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_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
213 struct interface_port *ifport;
215 /* port in chain ? */
216 if (!interface->ifport)
218 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
221 /* goto end of chain */
222 ifport = interface->ifport;
224 ifport = ifport->next;
228 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
231 ifport->tespecial = 1;
234 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
236 if (!strcasecmp(value, "yes"))
238 interface->is_tones = IS_YES;
240 if (!strcasecmp(value, "no"))
242 interface->is_tones = IS_NO;
245 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
250 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
252 if (!strcasecmp(value, "yes"))
254 interface->is_earlyb = IS_YES;
256 if (!strcasecmp(value, "no"))
258 interface->is_earlyb = IS_NO;
261 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
266 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
268 if (!strcasecmp(value, "linear"))
270 interface->hunt = HUNT_LINEAR;
272 if (!strcasecmp(value, "roundrobin"))
274 interface->hunt = HUNT_ROUNDROBIN;
277 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
282 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
284 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);
287 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
289 struct interface_port *ifport, **ifportp;
290 struct interface *searchif;
293 val = get_number(value);
296 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
299 /* check for port already assigned */
300 searchif = interface_newlist;
303 ifport = searchif->ifport;
306 if (ifport->portnum == val)
308 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
311 ifport = ifport->next;
313 searchif = searchif->next;
315 /* alloc port substructure */
316 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
318 ifport->interface = interface;
320 ifport->portnum = val;
322 ifportp = &interface->ifport;
324 ifportp = &((*ifportp)->next);
328 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
330 struct interface_port *ifport, **ifportp;
331 struct interface *searchif;
333 /* check for port already assigned */
334 searchif = interface_newlist;
337 ifport = searchif->ifport;
340 if (!strcasecmp(ifport->portname, value))
342 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
345 ifport = ifport->next;
347 searchif = searchif->next;
349 /* alloc port substructure */
350 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
352 ifport->interface = interface;
354 ifport->portnum = -1; // disable until resolved
355 SCPY(ifport->portname, value);
357 ifportp = &interface->ifport;
359 ifportp = &((*ifportp)->next);
363 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
365 struct interface_port *ifport;
367 /* port in chain ? */
368 if (!interface->ifport)
370 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
373 /* goto end of chain */
374 ifport = interface->ifport;
376 ifport = ifport->next;
377 if (!strcmp(value, "yes"))
381 if (!strcmp(value, "no"))
386 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
391 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
393 struct interface_port *ifport;
394 struct select_channel *selchannel, **selchannelp;
398 /* port in chain ? */
399 if (!interface->ifport)
401 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
404 /* goto end of chain */
405 ifport = interface->ifport;
407 ifport = ifport->next;
412 p = get_seperated(p);
413 if (!strcasecmp(el, "force"))
415 ifport->channel_force = 1;
416 if (ifport->out_channel)
418 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
422 if (!strcasecmp(el, "any"))
427 if (!strcasecmp(el, "free"))
432 if (!strcasecmp(el, "no"))
438 val = get_number(el);
441 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);
445 if (val<1 || val==16 || val>126)
447 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
451 /* add to select-channel list */
452 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
455 selchannel->channel = val;
457 selchannelp = &ifport->out_channel;
459 selchannelp = &((*selchannelp)->next);
460 *selchannelp = selchannel;
465 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
467 struct interface_port *ifport;
468 struct select_channel *selchannel, **selchannelp;
472 /* port in chain ? */
473 if (!interface->ifport)
475 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
478 /* goto end of chain */
479 ifport = interface->ifport;
481 ifport = ifport->next;
486 p = get_seperated(p);
487 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
489 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
492 if (!strcasecmp(el, "free"))
498 val = get_number(el);
501 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
505 if (val<1 || val==16 || val>126)
507 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
511 /* add to select-channel list */
512 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
515 selchannel->channel = val;
517 selchannelp = &ifport->in_channel;
519 selchannelp = &((*selchannelp)->next);
520 *selchannelp = selchannel;
525 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
527 struct interface_port *ifport;
528 // struct select_channel *selchannel, **selchannelp;
532 /* port in chain ? */
533 if (!interface->ifport)
535 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
538 /* goto end of chain */
539 ifport = interface->ifport;
541 ifport = ifport->next;
546 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
550 p = get_seperated(p);
551 ifport->tout_setup = atoi(el);
555 p = get_seperated(p);
556 ifport->tout_dialing = atoi(el);
560 p = get_seperated(p);
561 ifport->tout_proceeding = atoi(el);
565 p = get_seperated(p);
566 ifport->tout_alerting = atoi(el);
570 p = get_seperated(p);
571 ifport->tout_disconnect = atoi(el);
574 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
576 struct interface_msn *ifmsn, **ifmsnp;
581 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
584 if (interface->ifscreen_in)
586 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
595 p = get_seperated(p);
596 /* add MSN to list */
597 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
600 SCPY(ifmsn->msn, el);
602 ifmsnp = &interface->ifmsn;
604 ifmsnp = &((*ifmsnp)->next);
609 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
611 struct interface_screen *ifscreen;
616 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
619 /* add screen entry to list*/
620 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
622 ifscreen->match_type = -1; /* unchecked */
623 ifscreen->match_present = -1; /* unchecked */
624 ifscreen->result_type = -1; /* unchanged */
625 ifscreen->result_present = -1; /* unchanged */
628 ifscreenp = &((*ifscreenp)->next);
629 *ifscreenp = ifscreen;
630 // printf("interface=%s\n", interface->name);
636 p = get_seperated(p);
637 if (!strcasecmp(el, "unknown"))
639 if (ifscreen->match_type != -1)
642 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
645 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
647 if (!strcasecmp(el, "subscriber"))
649 if (ifscreen->match_type != -1)
651 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
653 if (!strcasecmp(el, "national"))
655 if (ifscreen->match_type != -1)
657 ifscreen->match_type = INFO_NTYPE_NATIONAL;
659 if (!strcasecmp(el, "international"))
661 if (ifscreen->match_type != -1)
663 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
665 if (!strcasecmp(el, "allowed"))
667 if (ifscreen->match_present != -1)
670 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
673 ifscreen->match_present = INFO_PRESENT_ALLOWED;
675 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
677 if (ifscreen->match_present != -1)
679 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
681 SCPY(ifscreen->match, el);
682 /* check for % at the end */
685 if (strchr(el, '%') != el+strlen(el)-1)
687 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
694 if (ifscreen->match[0] == '\0')
696 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
703 p = get_seperated(p);
704 if (!strcasecmp(el, "unknown"))
706 if (ifscreen->result_type != -1)
708 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
710 if (!strcasecmp(el, "subscriber"))
712 if (ifscreen->result_type != -1)
714 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
716 if (!strcasecmp(el, "national"))
718 if (ifscreen->result_type != -1)
720 ifscreen->result_type = INFO_NTYPE_NATIONAL;
722 if (!strcasecmp(el, "international"))
724 if (ifscreen->result_type != -1)
726 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
728 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
730 if (ifscreen->result_present != -1)
732 ifscreen->result_present = INFO_PRESENT_ALLOWED;
734 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
736 if (ifscreen->result_present != -1)
738 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
740 SCPY(ifscreen->result, el);
741 /* check for % at the end */
744 if (strchr(el, '%') != el+strlen(el)-1)
746 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
753 if (ifscreen->result[0] == '\0')
755 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
760 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
762 if (interface->ifmsn)
764 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
768 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
770 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
772 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
774 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
776 struct interface_port *ifport;
778 /* port in chain ? */
779 if (!interface->ifport)
781 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
784 /* goto end of chain */
785 ifport = interface->ifport;
787 ifport = ifport->next;
791 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
795 /* seperate parameter from filter */
802 while(*p > 0 && *p <= 32)
806 if (!strcasecmp(value, "gain"))
814 while(*q > 0 && *q <= 32)
817 if (*p == 0 || *q == 0)
819 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
822 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
824 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
827 interface->tx_gain = atoi(p);
828 interface->rx_gain = atoi(q);
830 if (!strcasecmp(value, "pipeline"))
834 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
837 SCPY(interface->pipeline, p);
839 if (!strcasecmp(value, "blowfish"))
841 unsigned char key[56];
844 if (!!strncmp(p, "0x", 2))
846 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
855 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
858 if (*p >= '0' && *p <= '9')
859 key[l] = (*p-'0')<<4;
860 else if (*p >= 'a' && *p <= 'f')
861 key[l] = (*p-'a'+10)<<4;
862 else if (*p >= 'A' && *p <= 'F')
863 key[l] = (*p-'A'+10)<<4;
867 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);
873 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);
876 if (*p >= '0' && *p <= '9')
877 key[l] = (*p-'0')<<4;
878 else if (*p >= 'a' && *p <= 'f')
879 key[l] = (*p-'a'+10)<<4;
880 else if (*p >= 'A' && *p <= 'F')
881 key[l] = (*p-'A'+10)<<4;
889 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);
892 memcpy(interface->bf_key, key, l);
893 interface->bf_len = l;
896 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
904 * structure of parameters
906 struct interface_param interface_param[] = {
907 { "extension", &inter_extension, "",
908 "If keyword is given, calls to interface are handled as internal extensions."},
909 {"tones", &inter_tones, "yes | no",
910 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
912 {"earlyb", &inter_earlyb, "yes | no",
913 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
915 {"hunt", &inter_hunt, "linear | roundrobin",
916 "Select the algorithm for selecting port with free channel."},
918 {"port", &inter_port, "<number>",
920 {"portnum", &inter_portnum, "<number>",
921 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
922 {"portname", &inter_portname, "<name>",
923 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
925 {"block", &inter_block, "",
926 "If keyword is given, calls on this interface are blocked.\n"
927 "This parameter must follow a 'port' parameter."},
929 {"ptp", &inter_ptp, "",
930 "The given port above is opened as point-to-point.\n"
931 "This is required on NT-mode ports that are multipoint by default.\n"
932 "This parameter must follow a 'port' parameter."},
935 {"ptmp", &inter_ptmp, "",
936 "The given port above is opened as point-to-multipoint.\n"
937 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
938 "This parameter must follow a 'port' parameter."},
941 {"nt", &inter_nt, "",
942 "The given port above is opened in NT-mode.\n"
943 "This is required on interfaces that support both NT-mode and TE-mode.\n"
944 "This parameter must follow a 'port' parameter."},
946 {"te-special", &inter_tespecial, "",
947 "The given port uses a modified TE-mode.\n"
948 "All information elements that are allowed Network->User will then be\n"
949 "transmitted User->Network also. This is usefull to pass all informations\n"
950 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
951 "Note that this is not compliant with ISDN protocol.\n"
952 "This parameter must follow a 'port' parameter."},
954 {"layer2hold", &inter_l2hold, "yes | no",
955 "The given port will continuously try to establish layer 2 link and hold it.\n"
956 "It is required for PTP links in most cases, therefore it is default.\n"
957 "This parameter must follow a 'port' parameter."},
959 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
960 "Channel selection list for all outgoing calls to the interface.\n"
961 "A free channels is searched in order of appearance.\n"
962 "This parameter must follow a 'port' parameter.\n"
963 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
964 " <number>[,...] - List of channels to search.\n"
965 " free - Select any free channel\n"
966 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
967 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
969 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
970 "Channel selection list for all incoming calls from the interface.\n"
971 "A free channels is accepted if in the list.\n"
972 "If any channel was requested, the first free channel found is selected.\n"
973 "This parameter must follow a 'port' parameter.\n"
974 " <number>[,...] - List of channels to accept.\n"
975 " free - Accept any free channel"},
977 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
978 "Timeout values for call states. They are both for incoming and outgoing states.\n"
979 "The default is 120 seconds for all states. Use 0 to disable.\n"
980 "This parameter must follow a 'port' parameter.\n"},
982 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
983 "Incoming caller ID is checked against given MSN numbers.\n"
984 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
986 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
987 "Adds an entry for incoming calls to the caller ID screen list.\n"
988 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
989 "If '%' is given after old caller ID, it matches even if caller ID has\n"
990 "additional digits.\n"
991 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
994 " unknown | subsciber | national | international - Change caller ID type.\n"
995 " present | restrict - Change presentation of caller ID."},
997 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
998 "Adds an entry for outgoing calls to the caller ID screen list.\n"
999 "See 'screen-in' for help."},
1001 {"nodtmf", &inter_nodtmf, "",
1002 "Disables DTMF detection for this interface.\n"
1003 "This parameter must follow a 'port' parameter."},
1005 {"filter", &inter_filter, "<filter> <parameters>",
1006 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1007 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1008 "pipeline <string> - Sets echo cancelation pipeline.\n"
1009 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1011 {NULL, NULL, NULL, NULL}
1016 * read settings from interface.conf
1018 char interface_error[256];
1019 struct interface *read_interfaces(void)
1024 unsigned int line, i;
1026 struct interface *interface = NULL, /* in case no interface */
1027 **interfacep = &interface_newlist;
1028 char parameter[128];
1030 int expecting = 1; /* expecting new interface */
1031 struct interface_param *ifparam;
1033 if (interface_newlist != NULL)
1034 FATAL("list is not empty.\n");
1035 interface_error[0] = '\0';
1036 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1038 if (!(fp = fopen(filename,"r")))
1040 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1045 while((fgets(buffer,sizeof(buffer),fp)))
1047 buffer[sizeof(buffer)-1]=0;
1048 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1052 while(*p <= 32) /* skip spaces */
1058 if (*p==0 || *p=='#') /* ignore comments and empty line */
1063 i=0; /* read parameter */
1066 if (i+1 >= sizeof(parameter))
1068 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1071 parameter[i+1] = '\0';
1072 parameter[i++] = *p++;
1075 while(*p <= 32) /* skip spaces */
1082 if (*p!=0 && *p!='#') /* missing name */
1084 i=0; /* read until end */
1085 while(*p!=0 && *p!='#')
1087 if (i+1 >= sizeof(value))
1089 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1096 /* remove trailing spaces from value */
1099 if (value[i-1]==0 || value[i-1]>32)
1106 /* check for interface name as first statement */
1107 if (expecting && parameter[0]!='[')
1109 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1114 /* check for new interface */
1115 if (parameter[0] == '[')
1117 if (parameter[strlen(parameter)-1] != ']')
1119 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1122 parameter[strlen(parameter)-1] = '\0';
1124 /* check if interface name already exists */
1125 interface = interface_newlist;
1128 if (!strcasecmp(interface->name, parameter+1))
1130 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1133 interface = interface->next;
1136 /* append interface to new list */
1137 interface = (struct interface *)MALLOC(sizeof(struct interface));
1140 /* name interface */
1141 SCPY(interface->name, parameter+1);
1144 *interfacep = interface;
1145 interfacep = &interface->next;
1150 ifparam = interface_param;
1151 while(ifparam->name)
1153 if (!strcasecmp(parameter, ifparam->name))
1155 if (ifparam->func(interface, filename, line, parameter, value))
1164 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1169 return(interface_newlist);
1171 PERROR_RUNTIME("%s", interface_error);
1173 free_interfaces(interface_newlist);
1174 interface_newlist = NULL;
1180 * freeing chain of interfaces
1182 void free_interfaces(struct interface *interface)
1185 struct interface_port *ifport;
1186 struct select_channel *selchannel;
1187 struct interface_msn *ifmsn;
1188 struct interface_screen *ifscreen;
1192 ifport = interface->ifport;
1195 selchannel = ifport->in_channel;
1199 selchannel = selchannel->next;
1200 FREE(temp, sizeof(struct select_channel));
1203 selchannel = ifport->out_channel;
1207 selchannel = selchannel->next;
1208 FREE(temp, sizeof(struct select_channel));
1212 ifport = ifport->next;
1213 FREE(temp, sizeof(struct interface_port));
1216 ifmsn = interface->ifmsn;
1220 ifmsn = ifmsn->next;
1221 FREE(temp, sizeof(struct interface_msn));
1224 ifscreen = interface->ifscreen_in;
1228 ifscreen = ifscreen->next;
1229 FREE(temp, sizeof(struct interface_screen));
1232 ifscreen = interface->ifscreen_out;
1236 ifscreen = ifscreen->next;
1237 FREE(temp, sizeof(struct interface_screen));
1241 interface = interface->next;
1242 FREE(temp, sizeof(struct interface));
1248 * defaults of ports if not specified by config
1250 static void set_defaults(struct interface_port *ifport)
1252 /* default channel selection list */
1253 if (!ifport->out_channel)
1254 default_out_channel(ifport);
1255 if (!ifport->in_channel)
1256 default_in_channel(ifport);
1257 /* default is_tones */
1258 if (ifport->interface->is_tones)
1259 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1261 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1262 /* default is_earlyb */
1263 if (ifport->interface->is_earlyb)
1264 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1266 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1267 /* set locally flag */
1268 if (ifport->interface->extension)
1269 ifport->mISDNport->locally = 1;
1271 ifport->mISDNport->locally = 0;
1276 * all links between mISDNport and interface are made
1277 * unused mISDNports are closed, new mISDNports are opened
1278 * also set default select_channel lists
1280 void relink_interfaces(void)
1282 struct mISDNport *mISDNport;
1283 struct interface *interface;
1284 struct interface_port *ifport;
1286 /* unlink all mISDNports */
1287 mISDNport = mISDNport_first;
1290 mISDNport->ifport = NULL;
1291 mISDNport = mISDNport->next;
1294 /* relink existing mISDNports */
1295 interface = interface_newlist;
1298 ifport = interface->ifport;
1301 mISDNport = mISDNport_first;
1304 if (mISDNport->portnum == ifport->portnum)
1306 ifport->mISDNport = mISDNport;
1307 mISDNport->ifport = ifport;
1308 set_defaults(ifport);
1310 mISDNport = mISDNport->next;
1312 ifport = ifport->next;
1314 interface = interface->next;
1317 /* close unused mISDNports */
1319 mISDNport = mISDNport_first;
1322 if (mISDNport->ifport == NULL)
1324 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1325 /* remove all port objects and destroy port */
1326 mISDNport_close(mISDNport);
1329 mISDNport = mISDNport->next;
1332 /* open and link new mISDNports */
1333 interface = interface_newlist;
1336 ifport = interface->ifport;
1339 if (!ifport->mISDNport)
1343 ifport = ifport->next;
1345 interface = interface->next;
1354 void load_port(struct interface_port *ifport)
1356 struct mISDNport *mISDNport;
1359 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l2hold, ifport->interface);
1363 ifport->mISDNport = mISDNport;
1364 mISDNport->ifport = ifport;
1365 /* set number and name */
1366 ifport->portnum = mISDNport->portnum;
1367 SCPY(ifport->portname, mISDNport->name);
1369 set_defaults(ifport);
1372 ifport->block = 2; /* not available */
1377 * give summary of interface syntax
1379 void doc_interface(void)
1381 struct interface_param *ifparam;
1383 printf("Syntax overview\n");
1384 printf("---------------\n\n");
1386 printf("[<name>]\n");
1387 ifparam = interface_param;
1388 while(ifparam->name)
1390 if (ifparam->name[0])
1391 printf("%s %s\n", ifparam->name, ifparam->usage);
1395 ifparam = interface_param;
1396 while(ifparam->name)
1398 if (ifparam->name[0])
1400 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1401 printf("%s\n", ifparam->help);
1409 * out==0: incoming caller id, out==1: outgoing caller id
1411 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1414 struct interface_msn *ifmsn;
1415 struct interface_screen *ifscreen;
1418 /* screen incoming caller id */
1421 /* check for MSN numbers, use first MSN if no match */
1423 ifmsn = interface->ifmsn;
1428 if (!strcmp(ifmsn->msn, id))
1432 ifmsn = ifmsn->next;
1436 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1437 add_trace("msn", NULL, "%s", id);
1440 if (!ifmsn && msn1) // not in list, first msn given
1442 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1443 add_trace("msn", "given", "%s", id);
1444 add_trace("msn", "used", "%s", msn1);
1446 UNCPY(id, msn1, idsize);
1447 id[idsize-1] = '\0';
1451 /* check screen list */
1453 ifscreen = interface->ifscreen_out;
1455 ifscreen = interface->ifscreen_in;
1458 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1459 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1461 if (strchr(ifscreen->match,'%'))
1463 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1467 if (!strcmp(ifscreen->match, id))
1471 ifscreen = ifscreen->next;
1473 if (ifscreen) // match
1475 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1478 case INFO_NTYPE_UNKNOWN:
1479 add_trace("given", "type", "unknown");
1481 case INFO_NTYPE_SUBSCRIBER:
1482 add_trace("given", "type", "subscriber");
1484 case INFO_NTYPE_NATIONAL:
1485 add_trace("given", "type", "national");
1487 case INFO_NTYPE_INTERNATIONAL:
1488 add_trace("given", "type", "international");
1493 case INFO_PRESENT_ALLOWED:
1494 add_trace("given", "present", "allowed");
1496 case INFO_PRESENT_RESTRICTED:
1497 add_trace("given", "present", "restricted");
1499 case INFO_PRESENT_NOTAVAIL:
1500 add_trace("given", "present", "not available");
1503 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1504 if (ifscreen->result_type != -1)
1506 *type = ifscreen->result_type;
1509 case INFO_NTYPE_UNKNOWN:
1510 add_trace("used", "type", "unknown");
1512 case INFO_NTYPE_SUBSCRIBER:
1513 add_trace("used", "type", "subscriber");
1515 case INFO_NTYPE_NATIONAL:
1516 add_trace("used", "type", "national");
1518 case INFO_NTYPE_INTERNATIONAL:
1519 add_trace("used", "type", "international");
1523 if (ifscreen->result_present != -1)
1525 *present = ifscreen->result_present;
1528 case INFO_PRESENT_ALLOWED:
1529 add_trace("used", "present", "allowed");
1531 case INFO_PRESENT_RESTRICTED:
1532 add_trace("used", "present", "restricted");
1534 case INFO_PRESENT_NOTAVAIL:
1535 add_trace("used", "present", "not available");
1539 if (strchr(ifscreen->match,'%'))
1541 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1542 UNCPY(id, ifscreen->result, idsize);
1543 id[idsize-1] = '\0';
1546 *strchr(id,'%') = '\0';
1547 UNCAT(id, suffix, idsize);
1548 id[idsize-1] = '\0';
1552 UNCPY(id, ifscreen->result, idsize);
1553 id[idsize-1] = '\0';
1555 add_trace("used", "id", "%s", id[0]?id:"<empty>");