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 (!strcmp(mISDNport->name, ifport->portname))
1325 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1326 if (mISDNport->portnum == ifport->portnum)
1328 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", mISDNport->portnum);
1329 ifport->mISDNport = mISDNport;
1330 mISDNport->ifport = ifport;
1331 set_defaults(ifport);
1333 mISDNport = mISDNport->next;
1335 ifport = ifport->next;
1337 interface = interface->next;
1340 /* close unused mISDNports */
1342 mISDNport = mISDNport_first;
1345 if (mISDNport->ifport == NULL)
1347 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1348 /* remove all port objects and destroy port */
1349 mISDNport_close(mISDNport);
1352 mISDNport = mISDNport->next;
1355 /* open and link new mISDNports */
1356 interface = interface_newlist;
1359 ifport = interface->ifport;
1362 if (!ifport->mISDNport)
1366 ifport = ifport->next;
1368 interface = interface->next;
1377 void load_port(struct interface_port *ifport)
1379 struct mISDNport *mISDNport;
1382 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l2hold, ifport->interface);
1386 ifport->mISDNport = mISDNport;
1387 mISDNport->ifport = ifport;
1388 /* set number and name */
1389 ifport->portnum = mISDNport->portnum;
1390 SCPY(ifport->portname, mISDNport->name);
1392 set_defaults(ifport);
1395 ifport->block = 2; /* not available */
1400 * give summary of interface syntax
1402 void doc_interface(void)
1404 struct interface_param *ifparam;
1406 printf("Syntax overview\n");
1407 printf("---------------\n\n");
1409 printf("[<name>]\n");
1410 ifparam = interface_param;
1411 while(ifparam->name)
1413 if (ifparam->name[0])
1414 printf("%s %s\n", ifparam->name, ifparam->usage);
1418 ifparam = interface_param;
1419 while(ifparam->name)
1421 if (ifparam->name[0])
1423 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1424 printf("%s\n", ifparam->help);
1432 * out==0: incoming caller id, out==1: outgoing caller id
1434 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1437 struct interface_msn *ifmsn;
1438 struct interface_screen *ifscreen;
1441 /* screen incoming caller id */
1444 /* check for MSN numbers, use first MSN if no match */
1446 ifmsn = interface->ifmsn;
1451 if (!strcmp(ifmsn->msn, id))
1455 ifmsn = ifmsn->next;
1459 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1460 add_trace("msn", NULL, "%s", id);
1463 if (!ifmsn && msn1) // not in list, first msn given
1465 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1466 add_trace("msn", "given", "%s", id);
1467 add_trace("msn", "used", "%s", msn1);
1469 UNCPY(id, msn1, idsize);
1470 id[idsize-1] = '\0';
1474 /* check screen list */
1476 ifscreen = interface->ifscreen_out;
1478 ifscreen = interface->ifscreen_in;
1481 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1482 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1484 if (strchr(ifscreen->match,'%'))
1486 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1490 if (!strcmp(ifscreen->match, id))
1494 ifscreen = ifscreen->next;
1496 if (ifscreen) // match
1498 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)");
1501 case INFO_NTYPE_UNKNOWN:
1502 add_trace("given", "type", "unknown");
1504 case INFO_NTYPE_SUBSCRIBER:
1505 add_trace("given", "type", "subscriber");
1507 case INFO_NTYPE_NATIONAL:
1508 add_trace("given", "type", "national");
1510 case INFO_NTYPE_INTERNATIONAL:
1511 add_trace("given", "type", "international");
1516 case INFO_PRESENT_ALLOWED:
1517 add_trace("given", "present", "allowed");
1519 case INFO_PRESENT_RESTRICTED:
1520 add_trace("given", "present", "restricted");
1522 case INFO_PRESENT_NOTAVAIL:
1523 add_trace("given", "present", "not available");
1526 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1527 if (ifscreen->result_type != -1)
1529 *type = ifscreen->result_type;
1532 case INFO_NTYPE_UNKNOWN:
1533 add_trace("used", "type", "unknown");
1535 case INFO_NTYPE_SUBSCRIBER:
1536 add_trace("used", "type", "subscriber");
1538 case INFO_NTYPE_NATIONAL:
1539 add_trace("used", "type", "national");
1541 case INFO_NTYPE_INTERNATIONAL:
1542 add_trace("used", "type", "international");
1546 if (ifscreen->result_present != -1)
1548 *present = ifscreen->result_present;
1551 case INFO_PRESENT_ALLOWED:
1552 add_trace("used", "present", "allowed");
1554 case INFO_PRESENT_RESTRICTED:
1555 add_trace("used", "present", "restricted");
1557 case INFO_PRESENT_NOTAVAIL:
1558 add_trace("used", "present", "not available");
1562 if (strchr(ifscreen->match,'%'))
1564 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1565 UNCPY(id, ifscreen->result, idsize);
1566 id[idsize-1] = '\0';
1569 *strchr(id,'%') = '\0';
1570 UNCAT(id, suffix, idsize);
1571 id[idsize-1] = '\0';
1575 UNCPY(id, ifscreen->result, idsize);
1576 id[idsize-1] = '\0';
1578 add_trace("used", "id", "%s", id[0]?id:"<empty>");