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);
901 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
903 struct interface_port *ifport;
905 /* port in chain ? */
906 if (!interface->ifport)
908 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
911 /* goto end of chain */
912 ifport = interface->ifport;
914 ifport = ifport->next;
915 ifport->dialmax = atoi(value);
921 * structure of parameters
923 struct interface_param interface_param[] = {
924 { "extension", &inter_extension, "",
925 "If keyword is given, calls to interface are handled as internal extensions."},
926 {"tones", &inter_tones, "yes | no",
927 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
929 {"earlyb", &inter_earlyb, "yes | no",
930 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
932 {"hunt", &inter_hunt, "linear | roundrobin",
933 "Select the algorithm for selecting port with free channel."},
935 {"port", &inter_port, "<number>",
937 {"portnum", &inter_portnum, "<number>",
938 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
939 {"portname", &inter_portname, "<name>",
940 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
942 {"block", &inter_block, "",
943 "If keyword is given, calls on this interface are blocked.\n"
944 "This parameter must follow a 'port' parameter."},
946 {"ptp", &inter_ptp, "",
947 "The given port above is opened as point-to-point.\n"
948 "This is required on NT-mode ports that are multipoint by default.\n"
949 "This parameter must follow a 'port' parameter."},
952 {"ptmp", &inter_ptmp, "",
953 "The given port above is opened as point-to-multipoint.\n"
954 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
955 "This parameter must follow a 'port' parameter."},
958 {"nt", &inter_nt, "",
959 "The given port above is opened in NT-mode.\n"
960 "This is required on interfaces that support both NT-mode and TE-mode.\n"
961 "This parameter must follow a 'port' parameter."},
963 {"te-special", &inter_tespecial, "",
964 "The given port uses a modified TE-mode.\n"
965 "All information elements that are allowed Network->User will then be\n"
966 "transmitted User->Network also. This is usefull to pass all informations\n"
967 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
968 "Note that this is not compliant with ISDN protocol.\n"
969 "This parameter must follow a 'port' parameter."},
971 {"layer2hold", &inter_l2hold, "yes | no",
972 "The given port will continuously try to establish layer 2 link and hold it.\n"
973 "It is required for PTP links in most cases, therefore it is default.\n"
974 "This parameter must follow a 'port' parameter."},
976 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
977 "Channel selection list for all outgoing calls to the interface.\n"
978 "A free channels is searched in order of appearance.\n"
979 "This parameter must follow a 'port' parameter.\n"
980 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
981 " <number>[,...] - List of channels to search.\n"
982 " free - Select any free channel\n"
983 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
984 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
986 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
987 "Channel selection list for all incoming calls from the interface.\n"
988 "A free channels is accepted if in the list.\n"
989 "If any channel was requested, the first free channel found is selected.\n"
990 "This parameter must follow a 'port' parameter.\n"
991 " <number>[,...] - List of channels to accept.\n"
992 " free - Accept any free channel"},
994 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
995 "Timeout values for call states. They are both for incoming and outgoing states.\n"
996 "The default is 120 seconds for all states. Use 0 to disable.\n"
997 "This parameter must follow a 'port' parameter.\n"},
999 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1000 "Incoming caller ID is checked against given MSN numbers.\n"
1001 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1003 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1004 "Adds an entry for incoming calls to the caller ID screen list.\n"
1005 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1006 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1007 "additional digits.\n"
1008 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1011 " unknown | subsciber | national | international - Change caller ID type.\n"
1012 " present | restrict - Change presentation of caller ID."},
1014 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1015 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1016 "See 'screen-in' for help."},
1018 {"nodtmf", &inter_nodtmf, "",
1019 "Disables DTMF detection for this interface.\n"
1020 "This parameter must follow a 'port' parameter."},
1022 {"filter", &inter_filter, "<filter> <parameters>",
1023 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1024 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1025 "pipeline <string> - Sets echo cancelation pipeline.\n"
1026 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1028 {"dialmax", &inter_dialmax, "<digits>",
1029 "Limits the number of digits in setup/information message."},
1031 {NULL, NULL, NULL, NULL}
1036 * read settings from interface.conf
1038 char interface_error[256];
1039 struct interface *read_interfaces(void)
1044 unsigned int line, i;
1046 struct interface *interface = NULL, /* in case no interface */
1047 **interfacep = &interface_newlist;
1048 char parameter[128];
1050 int expecting = 1; /* expecting new interface */
1051 struct interface_param *ifparam;
1053 if (interface_newlist != NULL)
1054 FATAL("list is not empty.\n");
1055 interface_error[0] = '\0';
1056 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1058 if (!(fp = fopen(filename,"r")))
1060 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1065 while((fgets(buffer,sizeof(buffer),fp)))
1067 buffer[sizeof(buffer)-1]=0;
1068 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1072 while(*p <= 32) /* skip spaces */
1078 if (*p==0 || *p=='#') /* ignore comments and empty line */
1083 i=0; /* read parameter */
1086 if (i+1 >= sizeof(parameter))
1088 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1091 parameter[i+1] = '\0';
1092 parameter[i++] = *p++;
1095 while(*p <= 32) /* skip spaces */
1102 if (*p!=0 && *p!='#') /* missing name */
1104 i=0; /* read until end */
1105 while(*p!=0 && *p!='#')
1107 if (i+1 >= sizeof(value))
1109 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1116 /* remove trailing spaces from value */
1119 if (value[i-1]==0 || value[i-1]>32)
1126 /* check for interface name as first statement */
1127 if (expecting && parameter[0]!='[')
1129 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1134 /* check for new interface */
1135 if (parameter[0] == '[')
1137 if (parameter[strlen(parameter)-1] != ']')
1139 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1142 parameter[strlen(parameter)-1] = '\0';
1144 /* check if interface name already exists */
1145 interface = interface_newlist;
1148 if (!strcasecmp(interface->name, parameter+1))
1150 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1153 interface = interface->next;
1156 /* append interface to new list */
1157 interface = (struct interface *)MALLOC(sizeof(struct interface));
1160 /* name interface */
1161 SCPY(interface->name, parameter+1);
1164 *interfacep = interface;
1165 interfacep = &interface->next;
1170 ifparam = interface_param;
1171 while(ifparam->name)
1173 if (!strcasecmp(parameter, ifparam->name))
1175 if (ifparam->func(interface, filename, line, parameter, value))
1184 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1189 return(interface_newlist);
1191 PERROR_RUNTIME("%s", interface_error);
1193 free_interfaces(interface_newlist);
1194 interface_newlist = NULL;
1200 * freeing chain of interfaces
1202 void free_interfaces(struct interface *interface)
1205 struct interface_port *ifport;
1206 struct select_channel *selchannel;
1207 struct interface_msn *ifmsn;
1208 struct interface_screen *ifscreen;
1212 ifport = interface->ifport;
1215 selchannel = ifport->in_channel;
1219 selchannel = selchannel->next;
1220 FREE(temp, sizeof(struct select_channel));
1223 selchannel = ifport->out_channel;
1227 selchannel = selchannel->next;
1228 FREE(temp, sizeof(struct select_channel));
1232 ifport = ifport->next;
1233 FREE(temp, sizeof(struct interface_port));
1236 ifmsn = interface->ifmsn;
1240 ifmsn = ifmsn->next;
1241 FREE(temp, sizeof(struct interface_msn));
1244 ifscreen = interface->ifscreen_in;
1248 ifscreen = ifscreen->next;
1249 FREE(temp, sizeof(struct interface_screen));
1252 ifscreen = interface->ifscreen_out;
1256 ifscreen = ifscreen->next;
1257 FREE(temp, sizeof(struct interface_screen));
1261 interface = interface->next;
1262 FREE(temp, sizeof(struct interface));
1268 * defaults of ports if not specified by config
1270 static void set_defaults(struct interface_port *ifport)
1272 /* default channel selection list */
1273 if (!ifport->out_channel)
1274 default_out_channel(ifport);
1275 if (!ifport->in_channel)
1276 default_in_channel(ifport);
1277 /* default is_tones */
1278 if (ifport->interface->is_tones)
1279 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1281 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1282 /* default is_earlyb */
1283 if (ifport->interface->is_earlyb)
1284 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1286 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1287 /* set locally flag */
1288 if (ifport->interface->extension)
1289 ifport->mISDNport->locally = 1;
1291 ifport->mISDNport->locally = 0;
1296 * all links between mISDNport and interface are made
1297 * unused mISDNports are closed, new mISDNports are opened
1298 * also set default select_channel lists
1300 void relink_interfaces(void)
1302 struct mISDNport *mISDNport;
1303 struct interface *interface;
1304 struct interface_port *ifport;
1306 /* unlink all mISDNports */
1307 mISDNport = mISDNport_first;
1310 mISDNport->ifport = NULL;
1311 mISDNport = mISDNport->next;
1314 /* relink existing mISDNports */
1315 interface = interface_newlist;
1318 ifport = interface->ifport;
1321 mISDNport = mISDNport_first;
1324 if (mISDNport->portnum == ifport->portnum)
1326 ifport->mISDNport = mISDNport;
1327 mISDNport->ifport = ifport;
1328 set_defaults(ifport);
1330 mISDNport = mISDNport->next;
1332 ifport = ifport->next;
1334 interface = interface->next;
1337 /* close unused mISDNports */
1339 mISDNport = mISDNport_first;
1342 if (mISDNport->ifport == NULL)
1344 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1345 /* remove all port objects and destroy port */
1346 mISDNport_close(mISDNport);
1349 mISDNport = mISDNport->next;
1352 /* open and link new mISDNports */
1353 interface = interface_newlist;
1356 ifport = interface->ifport;
1359 if (!ifport->mISDNport)
1363 ifport = ifport->next;
1365 interface = interface->next;
1374 void load_port(struct interface_port *ifport)
1376 struct mISDNport *mISDNport;
1379 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l2hold, ifport->interface);
1383 ifport->mISDNport = mISDNport;
1384 mISDNport->ifport = ifport;
1385 /* set number and name */
1386 ifport->portnum = mISDNport->portnum;
1387 SCPY(ifport->portname, mISDNport->name);
1389 set_defaults(ifport);
1392 ifport->block = 2; /* not available */
1397 * give summary of interface syntax
1399 void doc_interface(void)
1401 struct interface_param *ifparam;
1403 printf("Syntax overview\n");
1404 printf("---------------\n\n");
1406 printf("[<name>]\n");
1407 ifparam = interface_param;
1408 while(ifparam->name)
1410 if (ifparam->name[0])
1411 printf("%s %s\n", ifparam->name, ifparam->usage);
1415 ifparam = interface_param;
1416 while(ifparam->name)
1418 if (ifparam->name[0])
1420 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1421 printf("%s\n", ifparam->help);
1429 * out==0: incoming caller id, out==1: outgoing caller id
1431 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1434 struct interface_msn *ifmsn;
1435 struct interface_screen *ifscreen;
1438 /* screen incoming caller id */
1441 /* check for MSN numbers, use first MSN if no match */
1443 ifmsn = interface->ifmsn;
1448 if (!strcmp(ifmsn->msn, id))
1452 ifmsn = ifmsn->next;
1456 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1457 add_trace("msn", NULL, "%s", id);
1460 if (!ifmsn && msn1) // not in list, first msn given
1462 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1463 add_trace("msn", "given", "%s", id);
1464 add_trace("msn", "used", "%s", msn1);
1466 UNCPY(id, msn1, idsize);
1467 id[idsize-1] = '\0';
1471 /* check screen list */
1473 ifscreen = interface->ifscreen_out;
1475 ifscreen = interface->ifscreen_in;
1478 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1479 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1481 if (strchr(ifscreen->match,'%'))
1483 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1487 if (!strcmp(ifscreen->match, id))
1491 ifscreen = ifscreen->next;
1493 if (ifscreen) // match
1495 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)");
1498 case INFO_NTYPE_UNKNOWN:
1499 add_trace("given", "type", "unknown");
1501 case INFO_NTYPE_SUBSCRIBER:
1502 add_trace("given", "type", "subscriber");
1504 case INFO_NTYPE_NATIONAL:
1505 add_trace("given", "type", "national");
1507 case INFO_NTYPE_INTERNATIONAL:
1508 add_trace("given", "type", "international");
1513 case INFO_PRESENT_ALLOWED:
1514 add_trace("given", "present", "allowed");
1516 case INFO_PRESENT_RESTRICTED:
1517 add_trace("given", "present", "restricted");
1519 case INFO_PRESENT_NOTAVAIL:
1520 add_trace("given", "present", "not available");
1523 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1524 if (ifscreen->result_type != -1)
1526 *type = ifscreen->result_type;
1529 case INFO_NTYPE_UNKNOWN:
1530 add_trace("used", "type", "unknown");
1532 case INFO_NTYPE_SUBSCRIBER:
1533 add_trace("used", "type", "subscriber");
1535 case INFO_NTYPE_NATIONAL:
1536 add_trace("used", "type", "national");
1538 case INFO_NTYPE_INTERNATIONAL:
1539 add_trace("used", "type", "international");
1543 if (ifscreen->result_present != -1)
1545 *present = ifscreen->result_present;
1548 case INFO_PRESENT_ALLOWED:
1549 add_trace("used", "present", "allowed");
1551 case INFO_PRESENT_RESTRICTED:
1552 add_trace("used", "present", "restricted");
1554 case INFO_PRESENT_NOTAVAIL:
1555 add_trace("used", "present", "not available");
1559 if (strchr(ifscreen->match,'%'))
1561 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1562 UNCPY(id, ifscreen->result, idsize);
1563 id[idsize-1] = '\0';
1566 *strchr(id,'%') = '\0';
1567 UNCAT(id, suffix, idsize);
1568 id[idsize-1] = '\0';
1572 UNCPY(id, ifscreen->result, idsize);
1573 id[idsize-1] = '\0';
1575 add_trace("used", "id", "%s", id[0]?id:"<empty>");