1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** reading interface.conf file and filling structure **
10 \*****************************************************************************/
14 struct interface *interface_first = NULL; /* first interface is current list */
15 struct interface *interface_newlist = NULL; /* first interface in new list */
18 /* set default out_channel */
19 void default_out_channel(struct interface_port *ifport)
21 struct select_channel *selchannel, **selchannelp;
23 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
26 if (ifport->mISDNport->ntmode)
27 selchannel->channel = CHANNEL_FREE;
29 selchannel->channel = CHANNEL_ANY;
31 ifport->out_channel = selchannel;
33 /* additional channel selection for multipoint NT ports */
34 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
36 selchannelp = &(selchannel->next);
37 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
39 selchannel->channel = CHANNEL_NO; // call waiting
40 *selchannelp = selchannel;
45 /* set default in_channel */
46 void default_in_channel(struct interface_port *ifport)
48 struct select_channel *selchannel;
50 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
53 selchannel->channel = CHANNEL_FREE;
55 ifport->in_channel = selchannel;
59 /* parse string for a positive number */
60 static int get_number(char *value)
67 SPRINT(text, "%d", val);
69 if (!strcmp(value, text))
76 /* remove element from buffer
77 * and return pointer to next element in buffer */
78 static char *get_seperated(char *buffer)
82 if (*buffer==',' || *buffer<=32) /* seperate */
85 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
95 * parameter processing
97 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
99 struct interface_port *ifport;
101 /* port in chain ? */
102 if (!interface->ifport)
104 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
107 /* goto end of chain */
108 ifport = interface->ifport;
110 ifport = ifport->next;
114 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
120 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
124 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
127 interface->extension = 1;
130 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
132 struct interface_port *ifport;
134 /* port in chain ? */
135 if (!interface->ifport)
137 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
140 if (interface->ifport->ptmp)
142 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
145 /* goto end of chain */
146 ifport = interface->ifport;
148 ifport = ifport->next;
152 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
159 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
161 struct interface_port *ifport;
163 /* port in chain ? */
164 if (!interface->ifport)
166 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
169 if (interface->ifport->ptp)
171 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
174 /* goto end of chain */
175 ifport = interface->ifport;
177 ifport = ifport->next;
181 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
188 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
190 struct interface_port *ifport;
192 /* port in chain ? */
193 if (!interface->ifport)
195 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
198 /* goto end of chain */
199 ifport = interface->ifport;
201 ifport = ifport->next;
205 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
211 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
213 if (!strcasecmp(value, "yes"))
215 interface->is_tones = IS_YES;
217 if (!strcasecmp(value, "no"))
219 interface->is_tones = IS_NO;
222 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
227 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
229 if (!strcasecmp(value, "yes"))
231 interface->is_earlyb = IS_YES;
233 if (!strcasecmp(value, "no"))
235 interface->is_earlyb = IS_NO;
238 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
243 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
245 if (!strcasecmp(value, "linear"))
247 interface->hunt = HUNT_LINEAR;
249 if (!strcasecmp(value, "roundrobin"))
251 interface->hunt = HUNT_ROUNDROBIN;
254 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
259 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
261 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'portnum' and decrease port number by 1! Ports are counted from 0 now.\n", filename, line, parameter);
264 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
266 struct interface_port *ifport, **ifportp;
267 struct interface *searchif;
270 val = get_number(value);
273 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
276 /* check for port already assigned */
277 searchif = interface_newlist;
280 ifport = searchif->ifport;
283 if (ifport->portnum == val)
285 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
288 ifport = ifport->next;
290 searchif = searchif->next;
292 /* alloc port substructure */
293 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
295 ifport->interface = interface;
297 ifport->portnum = val;
299 ifportp = &interface->ifport;
301 ifportp = &((*ifportp)->next);
305 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
307 struct interface_port *ifport, **ifportp;
308 struct interface *searchif;
310 /* check for port already assigned */
311 searchif = interface_newlist;
314 ifport = searchif->ifport;
317 if (!strcasecmp(ifport->portname, value))
319 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
322 ifport = ifport->next;
324 searchif = searchif->next;
326 /* alloc port substructure */
327 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
329 ifport->interface = interface;
331 ifport->portnum = -1; // disable until resolved
332 SCPY(ifport->portname, value);
334 ifportp = &interface->ifport;
336 ifportp = &((*ifportp)->next);
340 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
342 struct interface_port *ifport;
344 /* port in chain ? */
345 if (!interface->ifport)
347 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
350 /* goto end of chain */
351 ifport = interface->ifport;
353 ifport = ifport->next;
354 if (!strcmp(value, "yes"))
358 if (!strcmp(value, "no"))
363 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
368 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
370 struct interface_port *ifport;
371 struct select_channel *selchannel, **selchannelp;
375 /* port in chain ? */
376 if (!interface->ifport)
378 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
381 /* goto end of chain */
382 ifport = interface->ifport;
384 ifport = ifport->next;
389 p = get_seperated(p);
390 if (!strcasecmp(el, "force"))
392 ifport->channel_force = 1;
393 if (ifport->out_channel)
395 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
399 if (!strcasecmp(el, "any"))
404 if (!strcasecmp(el, "free"))
409 if (!strcasecmp(el, "no"))
415 val = get_number(el);
418 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of 'force', 'any', 'free', 'no' and any channel number.\n", filename, line, parameter);
422 if (val<1 || val==16 || val>126)
424 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
428 /* add to select-channel list */
429 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
432 selchannel->channel = val;
434 selchannelp = &ifport->out_channel;
436 selchannelp = &((*selchannelp)->next);
437 *selchannelp = selchannel;
442 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
444 struct interface_port *ifport;
445 struct select_channel *selchannel, **selchannelp;
449 /* port in chain ? */
450 if (!interface->ifport)
452 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
455 /* goto end of chain */
456 ifport = interface->ifport;
458 ifport = ifport->next;
463 p = get_seperated(p);
464 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
466 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
469 if (!strcasecmp(el, "free"))
475 val = get_number(el);
478 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
482 if (val<1 || val==16 || val>126)
484 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
488 /* add to select-channel list */
489 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
492 selchannel->channel = val;
494 selchannelp = &ifport->in_channel;
496 selchannelp = &((*selchannelp)->next);
497 *selchannelp = selchannel;
502 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
504 struct interface_port *ifport;
505 // struct select_channel *selchannel, **selchannelp;
509 /* port in chain ? */
510 if (!interface->ifport)
512 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
515 /* goto end of chain */
516 ifport = interface->ifport;
518 ifport = ifport->next;
523 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
527 p = get_seperated(p);
528 ifport->tout_setup = atoi(el);
532 p = get_seperated(p);
533 ifport->tout_dialing = atoi(el);
537 p = get_seperated(p);
538 ifport->tout_proceeding = atoi(el);
542 p = get_seperated(p);
543 ifport->tout_alerting = atoi(el);
547 p = get_seperated(p);
548 ifport->tout_disconnect = atoi(el);
551 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
553 struct interface_msn *ifmsn, **ifmsnp;
558 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
561 if (interface->ifscreen_in)
563 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
572 p = get_seperated(p);
573 /* add MSN to list */
574 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
577 SCPY(ifmsn->msn, el);
579 ifmsnp = &interface->ifmsn;
581 ifmsnp = &((*ifmsnp)->next);
586 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
588 struct interface_screen *ifscreen;
593 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
596 /* add screen entry to list*/
597 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
599 ifscreen->match_type = -1; /* unchecked */
600 ifscreen->match_present = -1; /* unchecked */
601 ifscreen->result_type = -1; /* unchanged */
602 ifscreen->result_present = -1; /* unchanged */
605 ifscreenp = &((*ifscreenp)->next);
606 *ifscreenp = ifscreen;
607 // printf("interface=%s\n", interface->name);
613 p = get_seperated(p);
614 if (!strcasecmp(el, "unknown"))
616 if (ifscreen->match_type != -1)
619 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
622 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
624 if (!strcasecmp(el, "subscriber"))
626 if (ifscreen->match_type != -1)
628 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
630 if (!strcasecmp(el, "national"))
632 if (ifscreen->match_type != -1)
634 ifscreen->match_type = INFO_NTYPE_NATIONAL;
636 if (!strcasecmp(el, "international"))
638 if (ifscreen->match_type != -1)
640 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
642 if (!strcasecmp(el, "allowed"))
644 if (ifscreen->match_present != -1)
647 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
650 ifscreen->match_present = INFO_PRESENT_ALLOWED;
652 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
654 if (ifscreen->match_present != -1)
656 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
658 SCPY(ifscreen->match, el);
659 /* check for % at the end */
662 if (strchr(el, '%') != el+strlen(el)-1)
664 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
671 if (ifscreen->match[0] == '\0')
673 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
680 p = get_seperated(p);
681 if (!strcasecmp(el, "unknown"))
683 if (ifscreen->result_type != -1)
685 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
687 if (!strcasecmp(el, "subscriber"))
689 if (ifscreen->result_type != -1)
691 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
693 if (!strcasecmp(el, "national"))
695 if (ifscreen->result_type != -1)
697 ifscreen->result_type = INFO_NTYPE_NATIONAL;
699 if (!strcasecmp(el, "international"))
701 if (ifscreen->result_type != -1)
703 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
705 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
707 if (ifscreen->result_present != -1)
709 ifscreen->result_present = INFO_PRESENT_ALLOWED;
711 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
713 if (ifscreen->result_present != -1)
715 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
717 SCPY(ifscreen->result, el);
718 /* check for % at the end */
721 if (strchr(el, '%') != el+strlen(el)-1)
723 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
730 if (ifscreen->result[0] == '\0')
732 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
737 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
739 if (interface->ifmsn)
741 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
745 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
747 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
749 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
751 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
753 struct interface_port *ifport;
755 /* port in chain ? */
756 if (!interface->ifport)
758 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
761 /* goto end of chain */
762 ifport = interface->ifport;
764 ifport = ifport->next;
768 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
772 /* seperate parameter from filter */
779 while(*p > 0 && *p <= 32)
783 if (!strcasecmp(value, "gain"))
791 while(*q > 0 && *q <= 32)
794 if (*p == 0 || *q == 0)
796 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
799 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
801 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
804 interface->tx_gain = atoi(p);
805 interface->rx_gain = atoi(q);
807 if (!strcasecmp(value, "pipeline"))
811 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
814 SCPY(interface->pipeline, p);
816 if (!strcasecmp(value, "blowfish"))
818 unsigned char key[56];
821 if (!!strncmp(p, "0x", 2))
823 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
832 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
835 if (*p >= '0' && *p <= '9')
836 key[l] = (*p-'0')<<4;
837 else if (*p >= 'a' && *p <= 'f')
838 key[l] = (*p-'a'+10)<<4;
839 else if (*p >= 'A' && *p <= 'F')
840 key[l] = (*p-'A'+10)<<4;
844 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key has digits out of range. (0...9, a...f)\n", filename, line, parameter, value);
850 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must end on an 8 bit boundary (two character boundary).\n", filename, line, parameter, value);
853 if (*p >= '0' && *p <= '9')
854 key[l] = (*p-'0')<<4;
855 else if (*p >= 'a' && *p <= 'f')
856 key[l] = (*p-'a'+10)<<4;
857 else if (*p >= 'A' && *p <= 'F')
858 key[l] = (*p-'A'+10)<<4;
866 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must be at least 4 bytes (8 characters).\n", filename, line, parameter, value);
869 memcpy(interface->bf_key, key, l);
870 interface->bf_len = l;
873 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
881 * structure of parameters
883 struct interface_param interface_param[] = {
884 { "extension", &inter_extension, "",
885 "If keyword is given, calls to interface are handled as internal extensions."},
886 {"tones", &inter_tones, "yes | no",
887 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
889 {"earlyb", &inter_earlyb, "yes | no",
890 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
892 {"hunt", &inter_hunt, "linear | roundrobin",
893 "Select the algorithm for selecting port with free channel."},
895 {"port", &inter_port, "<number>",
897 {"portnum", &inter_portnum, "<number>",
898 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
899 {"portname", &inter_portname, "<name>",
900 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
902 {"block", &inter_block, "",
903 "If keyword is given, calls on this interface are blocked.\n"
904 "This parameter must follow a 'port' parameter."},
906 {"ptp", &inter_ptp, "",
907 "The given port above is opened as point-to-point.\n"
908 "This is required on NT-mode ports that are multipoint by default.\n"
909 "This parameter must follow a 'port' parameter."},
912 {"ptmp", &inter_ptmp, "",
913 "The given port above is opened as point-to-multipoint.\n"
914 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
915 "This parameter must follow a 'port' parameter."},
918 {"nt", &inter_nt, "",
919 "The given port above is opened in NT-mode.\n"
920 "This is required on interfaces that support both NT-mode and TE-mode.\n"
921 "This parameter must follow a 'port' parameter."},
923 {"layer2hold", &inter_l2hold, "yes | no",
924 "The given port will continuously try to establish layer 2 link and hold it.\n"
925 "It is required for PTP links in most cases, therefore it is default.\n"
926 "This parameter must follow a 'port' parameter."},
928 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
929 "Channel selection list for all outgoing calls to the interface.\n"
930 "A free channels is searched in order of appearance.\n"
931 "This parameter must follow a 'port' parameter.\n"
932 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
933 " <number>[,...] - List of channels to search.\n"
934 " free - Select any free channel\n"
935 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
936 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
938 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
939 "Channel selection list for all incoming calls from the interface.\n"
940 "A free channels is accepted if in the list.\n"
941 "If any channel was requested, the first free channel found is selected.\n"
942 "This parameter must follow a 'port' parameter.\n"
943 " <number>[,...] - List of channels to accept.\n"
944 " free - Accept any free channel"},
946 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
947 "Timeout values for call states. They are both for incoming and outgoing states.\n"
948 "The default is 120 seconds for all states. Use 0 to disable.\n"
949 "This parameter must follow a 'port' parameter.\n"},
951 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
952 "Incoming caller ID is checked against given MSN numbers.\n"
953 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
955 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
956 "Adds an entry for incoming calls to the caller ID screen list.\n"
957 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
958 "If '%' is given after old caller ID, it matches even if caller ID has\n"
959 "additional digits.\n"
960 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
963 " unknown | subsciber | national | international - Change caller ID type.\n"
964 " present | restrict - Change presentation of caller ID."},
966 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
967 "Adds an entry for outgoing calls to the caller ID screen list.\n"
968 "See 'screen-in' for help."},
970 {"nodtmf", &inter_nodtmf, "",
971 "Disables DTMF detection for this interface.\n"
972 "This parameter must follow a 'port' parameter."},
974 {"filter", &inter_filter, "<filter> <parameters>",
975 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
976 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
977 "pipeline <string> - Sets echo cancelation pipeline.\n"
978 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
980 {NULL, NULL, NULL, NULL}
985 * read settings from interface.conf
987 char interface_error[256];
988 struct interface *read_interfaces(void)
993 unsigned int line, i;
995 struct interface *interface = NULL, /* in case no interface */
996 **interfacep = &interface_newlist;
999 int expecting = 1; /* expecting new interface */
1000 struct interface_param *ifparam;
1002 if (interface_newlist != NULL)
1003 FATAL("list is not empty.\n");
1004 interface_error[0] = '\0';
1005 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
1007 if (!(fp = fopen(filename,"r")))
1009 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1014 while((fgets(buffer,sizeof(buffer),fp)))
1016 buffer[sizeof(buffer)-1]=0;
1017 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1021 while(*p <= 32) /* skip spaces */
1027 if (*p==0 || *p=='#') /* ignore comments and empty line */
1032 i=0; /* read parameter */
1035 if (i+1 >= sizeof(parameter))
1037 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1040 parameter[i+1] = '\0';
1041 parameter[i++] = *p++;
1044 while(*p <= 32) /* skip spaces */
1051 if (*p!=0 && *p!='#') /* missing name */
1053 i=0; /* read until end */
1054 while(*p!=0 && *p!='#')
1056 if (i+1 >= sizeof(value))
1058 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1065 /* remove trailing spaces from value */
1068 if (value[i-1]==0 || value[i-1]>32)
1075 /* check for interface name as first statement */
1076 if (expecting && parameter[0]!='[')
1078 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1083 /* check for new interface */
1084 if (parameter[0] == '[')
1086 if (parameter[strlen(parameter)-1] != ']')
1088 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1091 parameter[strlen(parameter)-1] = '\0';
1093 /* check if interface name already exists */
1094 interface = interface_newlist;
1097 if (!strcasecmp(interface->name, parameter+1))
1099 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1102 interface = interface->next;
1105 /* append interface to new list */
1106 interface = (struct interface *)MALLOC(sizeof(struct interface));
1109 /* name interface */
1110 SCPY(interface->name, parameter+1);
1113 *interfacep = interface;
1114 interfacep = &interface->next;
1119 ifparam = interface_param;
1120 while(ifparam->name)
1122 if (!strcasecmp(parameter, ifparam->name))
1124 if (ifparam->func(interface, filename, line, parameter, value))
1133 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1138 return(interface_newlist);
1140 PERROR_RUNTIME("%s", interface_error);
1142 free_interfaces(interface_newlist);
1143 interface_newlist = NULL;
1149 * freeing chain of interfaces
1151 void free_interfaces(struct interface *interface)
1154 struct interface_port *ifport;
1155 struct select_channel *selchannel;
1156 struct interface_msn *ifmsn;
1157 struct interface_screen *ifscreen;
1161 ifport = interface->ifport;
1164 selchannel = ifport->in_channel;
1168 selchannel = selchannel->next;
1169 FREE(temp, sizeof(struct select_channel));
1172 selchannel = ifport->out_channel;
1176 selchannel = selchannel->next;
1177 FREE(temp, sizeof(struct select_channel));
1181 ifport = ifport->next;
1182 FREE(temp, sizeof(struct interface_port));
1185 ifmsn = interface->ifmsn;
1189 ifmsn = ifmsn->next;
1190 FREE(temp, sizeof(struct interface_msn));
1193 ifscreen = interface->ifscreen_in;
1197 ifscreen = ifscreen->next;
1198 FREE(temp, sizeof(struct interface_screen));
1201 ifscreen = interface->ifscreen_out;
1205 ifscreen = ifscreen->next;
1206 FREE(temp, sizeof(struct interface_screen));
1210 interface = interface->next;
1211 FREE(temp, sizeof(struct interface));
1217 * defaults of ports if not specified by config
1219 static void set_defaults(struct interface_port *ifport)
1221 /* default channel selection list */
1222 if (!ifport->out_channel)
1223 default_out_channel(ifport);
1224 if (!ifport->in_channel)
1225 default_in_channel(ifport);
1226 /* default is_tones */
1227 if (ifport->interface->is_tones)
1228 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1230 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1231 /* default is_earlyb */
1232 if (ifport->interface->is_earlyb)
1233 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1235 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1236 /* set locally flag */
1237 if (ifport->interface->extension)
1238 ifport->mISDNport->locally = 1;
1240 ifport->mISDNport->locally = 0;
1245 * all links between mISDNport and interface are made
1246 * unused mISDNports are closed, new mISDNports are opened
1247 * also set default select_channel lists
1249 void relink_interfaces(void)
1251 struct mISDNport *mISDNport;
1252 struct interface *interface;
1253 struct interface_port *ifport;
1255 /* unlink all mISDNports */
1256 mISDNport = mISDNport_first;
1259 mISDNport->ifport = NULL;
1260 mISDNport = mISDNport->next;
1263 /* relink existing mISDNports */
1264 interface = interface_newlist;
1267 ifport = interface->ifport;
1270 mISDNport = mISDNport_first;
1273 if (mISDNport->portnum == ifport->portnum)
1275 ifport->mISDNport = mISDNport;
1276 mISDNport->ifport = ifport;
1277 set_defaults(ifport);
1279 mISDNport = mISDNport->next;
1281 ifport = ifport->next;
1283 interface = interface->next;
1286 /* close unused mISDNports */
1288 mISDNport = mISDNport_first;
1291 if (mISDNport->ifport == NULL)
1293 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1294 /* remove all port objects and destroy port */
1295 mISDNport_close(mISDNport);
1298 mISDNport = mISDNport->next;
1301 /* open and link new mISDNports */
1302 interface = interface_newlist;
1305 ifport = interface->ifport;
1308 if (!ifport->mISDNport)
1312 ifport = ifport->next;
1314 interface = interface->next;
1323 void load_port(struct interface_port *ifport)
1325 struct mISDNport *mISDNport;
1328 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->l2hold, ifport->interface);
1332 ifport->mISDNport = mISDNport;
1333 mISDNport->ifport = ifport;
1334 /* set number and name */
1335 ifport->portnum = mISDNport->portnum;
1336 SCPY(ifport->portname, mISDNport->name);
1338 set_defaults(ifport);
1341 ifport->block = 2; /* not available */
1346 * give summary of interface syntax
1348 void doc_interface(void)
1350 struct interface_param *ifparam;
1352 printf("Syntax overview\n");
1353 printf("---------------\n\n");
1355 printf("[<name>]\n");
1356 ifparam = interface_param;
1357 while(ifparam->name)
1359 if (ifparam->name[0])
1360 printf("%s %s\n", ifparam->name, ifparam->usage);
1364 ifparam = interface_param;
1365 while(ifparam->name)
1367 if (ifparam->name[0])
1369 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1370 printf("%s\n", ifparam->help);
1378 * out==0: incoming caller id, out==1: outgoing caller id
1380 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1383 struct interface_msn *ifmsn;
1384 struct interface_screen *ifscreen;
1387 /* screen incoming caller id */
1390 /* check for MSN numbers, use first MSN if no match */
1392 ifmsn = interface->ifmsn;
1397 if (!strcmp(ifmsn->msn, id))
1401 ifmsn = ifmsn->next;
1405 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1406 add_trace("msn", NULL, "%s", id);
1409 if (!ifmsn && msn1) // not in list, first msn given
1411 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1412 add_trace("msn", "given", "%s", id);
1413 add_trace("msn", "used", "%s", msn1);
1415 UNCPY(id, msn1, idsize);
1416 id[idsize-1] = '\0';
1420 /* check screen list */
1422 ifscreen = interface->ifscreen_out;
1424 ifscreen = interface->ifscreen_in;
1427 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1428 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1430 if (strchr(ifscreen->match,'%'))
1432 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1436 if (!strcmp(ifscreen->match, id))
1440 ifscreen = ifscreen->next;
1442 if (ifscreen) // match
1444 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1447 case INFO_NTYPE_UNKNOWN:
1448 add_trace("given", "type", "unknown");
1450 case INFO_NTYPE_SUBSCRIBER:
1451 add_trace("given", "type", "subscriber");
1453 case INFO_NTYPE_NATIONAL:
1454 add_trace("given", "type", "national");
1456 case INFO_NTYPE_INTERNATIONAL:
1457 add_trace("given", "type", "international");
1462 case INFO_PRESENT_ALLOWED:
1463 add_trace("given", "present", "allowed");
1465 case INFO_PRESENT_RESTRICTED:
1466 add_trace("given", "present", "restricted");
1468 case INFO_PRESENT_NOTAVAIL:
1469 add_trace("given", "present", "not available");
1472 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1473 if (ifscreen->result_type != -1)
1475 *type = ifscreen->result_type;
1478 case INFO_NTYPE_UNKNOWN:
1479 add_trace("used", "type", "unknown");
1481 case INFO_NTYPE_SUBSCRIBER:
1482 add_trace("used", "type", "subscriber");
1484 case INFO_NTYPE_NATIONAL:
1485 add_trace("used", "type", "national");
1487 case INFO_NTYPE_INTERNATIONAL:
1488 add_trace("used", "type", "international");
1492 if (ifscreen->result_present != -1)
1494 *present = ifscreen->result_present;
1497 case INFO_PRESENT_ALLOWED:
1498 add_trace("used", "present", "allowed");
1500 case INFO_PRESENT_RESTRICTED:
1501 add_trace("used", "present", "restricted");
1503 case INFO_PRESENT_NOTAVAIL:
1504 add_trace("used", "present", "not available");
1508 if (strchr(ifscreen->match,'%'))
1510 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1511 UNCPY(id, ifscreen->result, idsize);
1512 id[idsize-1] = '\0';
1515 *strchr(id,'%') = '\0';
1516 UNCAT(id, suffix, idsize);
1517 id[idsize-1] = '\0';
1521 UNCPY(id, ifscreen->result, idsize);
1522 id[idsize-1] = '\0';
1524 add_trace("used", "id", "%s", id[0]?id:"<empty>");