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_l1hold(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_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
393 struct interface_port *ifport;
395 /* port in chain ? */
396 if (!interface->ifport)
398 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
401 /* goto end of chain */
402 ifport = interface->ifport;
404 ifport = ifport->next;
405 if (!strcmp(value, "yes"))
409 if (!strcmp(value, "no"))
414 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
419 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
421 struct interface_port *ifport;
422 struct select_channel *selchannel, **selchannelp;
426 /* port in chain ? */
427 if (!interface->ifport)
429 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
432 /* goto end of chain */
433 ifport = interface->ifport;
435 ifport = ifport->next;
440 p = get_seperated(p);
441 if (!strcasecmp(el, "force"))
443 ifport->channel_force = 1;
444 if (ifport->out_channel)
446 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
450 if (!strcasecmp(el, "any"))
455 if (!strcasecmp(el, "free"))
460 if (!strcasecmp(el, "no"))
466 val = get_number(el);
469 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);
473 if (val<1 || val==16 || val>126)
475 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
479 /* add to select-channel list */
480 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
483 selchannel->channel = val;
485 selchannelp = &ifport->out_channel;
487 selchannelp = &((*selchannelp)->next);
488 *selchannelp = selchannel;
493 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
495 struct interface_port *ifport;
496 struct select_channel *selchannel, **selchannelp;
500 /* port in chain ? */
501 if (!interface->ifport)
503 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
506 /* goto end of chain */
507 ifport = interface->ifport;
509 ifport = ifport->next;
514 p = get_seperated(p);
515 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
517 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
520 if (!strcasecmp(el, "free"))
526 val = get_number(el);
529 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
533 if (val<1 || val==16 || val>126)
535 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
539 /* add to select-channel list */
540 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
543 selchannel->channel = val;
545 selchannelp = &ifport->in_channel;
547 selchannelp = &((*selchannelp)->next);
548 *selchannelp = selchannel;
553 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
555 struct interface_port *ifport;
556 // struct select_channel *selchannel, **selchannelp;
560 /* port in chain ? */
561 if (!interface->ifport)
563 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
566 /* goto end of chain */
567 ifport = interface->ifport;
569 ifport = ifport->next;
574 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
578 p = get_seperated(p);
579 ifport->tout_setup = atoi(el);
583 p = get_seperated(p);
584 ifport->tout_dialing = atoi(el);
588 p = get_seperated(p);
589 ifport->tout_proceeding = atoi(el);
593 p = get_seperated(p);
594 ifport->tout_alerting = atoi(el);
598 p = get_seperated(p);
599 ifport->tout_disconnect = atoi(el);
602 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
604 struct interface_msn *ifmsn, **ifmsnp;
609 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
612 if (interface->ifscreen_in)
614 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
623 p = get_seperated(p);
624 /* add MSN to list */
625 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
628 SCPY(ifmsn->msn, el);
630 ifmsnp = &interface->ifmsn;
632 ifmsnp = &((*ifmsnp)->next);
637 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
639 struct interface_screen *ifscreen;
644 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
647 /* add screen entry to list*/
648 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
650 ifscreen->match_type = -1; /* unchecked */
651 ifscreen->match_present = -1; /* unchecked */
652 ifscreen->result_type = -1; /* unchanged */
653 ifscreen->result_present = -1; /* unchanged */
656 ifscreenp = &((*ifscreenp)->next);
657 *ifscreenp = ifscreen;
658 // printf("interface=%s\n", interface->name);
664 p = get_seperated(p);
665 if (!strcasecmp(el, "unknown"))
667 if (ifscreen->match_type != -1)
670 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
673 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
675 if (!strcasecmp(el, "subscriber"))
677 if (ifscreen->match_type != -1)
679 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
681 if (!strcasecmp(el, "national"))
683 if (ifscreen->match_type != -1)
685 ifscreen->match_type = INFO_NTYPE_NATIONAL;
687 if (!strcasecmp(el, "international"))
689 if (ifscreen->match_type != -1)
691 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
693 if (!strcasecmp(el, "allowed"))
695 if (ifscreen->match_present != -1)
698 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
701 ifscreen->match_present = INFO_PRESENT_ALLOWED;
703 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
705 if (ifscreen->match_present != -1)
707 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
709 SCPY(ifscreen->match, el);
710 /* check for % at the end */
713 if (strchr(el, '%') != el+strlen(el)-1)
715 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
722 if (ifscreen->match[0] == '\0')
724 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
731 p = get_seperated(p);
732 if (!strcasecmp(el, "unknown"))
734 if (ifscreen->result_type != -1)
736 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
738 if (!strcasecmp(el, "subscriber"))
740 if (ifscreen->result_type != -1)
742 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
744 if (!strcasecmp(el, "national"))
746 if (ifscreen->result_type != -1)
748 ifscreen->result_type = INFO_NTYPE_NATIONAL;
750 if (!strcasecmp(el, "international"))
752 if (ifscreen->result_type != -1)
754 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
756 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
758 if (ifscreen->result_present != -1)
760 ifscreen->result_present = INFO_PRESENT_ALLOWED;
762 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
764 if (ifscreen->result_present != -1)
766 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
768 SCPY(ifscreen->result, el);
769 /* check for % at the end */
772 if (strchr(el, '%') != el+strlen(el)-1)
774 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
781 if (ifscreen->result[0] == '\0')
783 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
788 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
790 if (interface->ifmsn)
792 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
796 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
798 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
800 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
802 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
804 struct interface_port *ifport;
806 /* port in chain ? */
807 if (!interface->ifport)
809 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
812 /* goto end of chain */
813 ifport = interface->ifport;
815 ifport = ifport->next;
819 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
823 /* seperate parameter from filter */
830 while(*p > 0 && *p <= 32)
834 if (!strcasecmp(value, "gain"))
842 while(*q > 0 && *q <= 32)
845 if (*p == 0 || *q == 0)
847 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
850 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
852 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
855 interface->tx_gain = atoi(p);
856 interface->rx_gain = atoi(q);
858 if (!strcasecmp(value, "pipeline"))
862 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
865 SCPY(interface->pipeline, p);
867 if (!strcasecmp(value, "blowfish"))
869 unsigned char key[56];
872 if (!!strncmp(p, "0x", 2))
874 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
883 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
886 if (*p >= '0' && *p <= '9')
887 key[l] = (*p-'0')<<4;
888 else if (*p >= 'a' && *p <= 'f')
889 key[l] = (*p-'a'+10)<<4;
890 else if (*p >= 'A' && *p <= 'F')
891 key[l] = (*p-'A'+10)<<4;
895 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);
901 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);
904 if (*p >= '0' && *p <= '9')
905 key[l] = (*p-'0')<<4;
906 else if (*p >= 'a' && *p <= 'f')
907 key[l] = (*p-'a'+10)<<4;
908 else if (*p >= 'A' && *p <= 'F')
909 key[l] = (*p-'A'+10)<<4;
917 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);
920 memcpy(interface->bf_key, key, l);
921 interface->bf_len = l;
924 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
929 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
931 struct interface_port *ifport;
933 /* port in chain ? */
934 if (!interface->ifport)
936 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
939 /* goto end of chain */
940 ifport = interface->ifport;
942 ifport = ifport->next;
943 ifport->dialmax = atoi(value);
949 * structure of parameters
951 struct interface_param interface_param[] = {
952 { "extension", &inter_extension, "",
953 "If keyword is given, calls to interface are handled as internal extensions."},
954 {"tones", &inter_tones, "yes | no",
955 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
957 {"earlyb", &inter_earlyb, "yes | no",
958 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
960 {"hunt", &inter_hunt, "linear | roundrobin",
961 "Select the algorithm for selecting port with free channel."},
963 {"port", &inter_port, "<number>",
965 {"portnum", &inter_portnum, "<number>",
966 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
967 {"portname", &inter_portname, "<name>",
968 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
970 {"block", &inter_block, "",
971 "If keyword is given, calls on this interface are blocked.\n"
972 "This parameter must follow a 'port' parameter."},
974 {"ptp", &inter_ptp, "",
975 "The given port above is opened as point-to-point.\n"
976 "This is required on NT-mode ports that are multipoint by default.\n"
977 "This parameter must follow a 'port' parameter."},
980 {"ptmp", &inter_ptmp, "",
981 "The given port above is opened as point-to-multipoint.\n"
982 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
983 "This parameter must follow a 'port' parameter."},
986 {"nt", &inter_nt, "",
987 "The given port above is opened in NT-mode.\n"
988 "This is required on interfaces that support both NT-mode and TE-mode.\n"
989 "This parameter must follow a 'port' parameter."},
991 {"te-special", &inter_tespecial, "",
992 "The given port uses a modified TE-mode.\n"
993 "All information elements that are allowed Network->User will then be\n"
994 "transmitted User->Network also. This is usefull to pass all informations\n"
995 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
996 "Note that this is not compliant with ISDN protocol.\n"
997 "This parameter must follow a 'port' parameter."},
999 {"layer1hold", &inter_l1hold, "yes | no",
1000 "The given port will not release layer 1 after layer 2 is down.\n"
1001 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1002 "This parameter must follow a 'port' parameter."},
1004 {"layer2hold", &inter_l2hold, "yes | no",
1005 "The given port will continuously try to establish layer 2 link and hold it.\n"
1006 "It is required for PTP links in most cases, therefore it is default.\n"
1007 "This parameter must follow a 'port' parameter."},
1009 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1010 "Channel selection list for all outgoing calls to the interface.\n"
1011 "A free channels is searched in order of appearance.\n"
1012 "This parameter must follow a 'port' parameter.\n"
1013 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
1014 " <number>[,...] - List of channels to search.\n"
1015 " free - Select any free channel\n"
1016 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1017 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1019 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1020 "Channel selection list for all incoming calls from the interface.\n"
1021 "A free channels is accepted if in the list.\n"
1022 "If any channel was requested, the first free channel found is selected.\n"
1023 "This parameter must follow a 'port' parameter.\n"
1024 " <number>[,...] - List of channels to accept.\n"
1025 " free - Accept any free channel"},
1027 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1028 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1029 "The default is 120 seconds for all states. Use 0 to disable.\n"
1030 "This parameter must follow a 'port' parameter.\n"},
1032 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1033 "Incoming caller ID is checked against given MSN numbers.\n"
1034 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1036 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1037 "Adds an entry for incoming calls to the caller ID screen list.\n"
1038 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1039 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1040 "additional digits.\n"
1041 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1044 " unknown | subsciber | national | international - Change caller ID type.\n"
1045 " present | restrict - Change presentation of caller ID."},
1047 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1048 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1049 "See 'screen-in' for help."},
1051 {"nodtmf", &inter_nodtmf, "",
1052 "Disables DTMF detection for this interface.\n"
1053 "This parameter must follow a 'port' parameter."},
1055 {"filter", &inter_filter, "<filter> <parameters>",
1056 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1057 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1058 "pipeline <string> - Sets echo cancelation pipeline.\n"
1059 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1061 {"dialmax", &inter_dialmax, "<digits>",
1062 "Limits the number of digits in setup/information message."},
1064 {NULL, NULL, NULL, NULL}
1069 * read settings from interface.conf
1071 char interface_error[256];
1072 struct interface *read_interfaces(void)
1077 unsigned int line, i;
1079 struct interface *interface = NULL, /* in case no interface */
1080 **interfacep = &interface_newlist;
1081 char parameter[128];
1083 int expecting = 1; /* expecting new interface */
1084 struct interface_param *ifparam;
1086 if (interface_newlist != NULL)
1087 FATAL("list is not empty.\n");
1088 interface_error[0] = '\0';
1089 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1091 if (!(fp = fopen(filename,"r")))
1093 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1098 while((fgets(buffer,sizeof(buffer),fp)))
1100 buffer[sizeof(buffer)-1]=0;
1101 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1105 while(*p <= 32) /* skip spaces */
1111 if (*p==0 || *p=='#') /* ignore comments and empty line */
1116 i=0; /* read parameter */
1119 if (i+1 >= sizeof(parameter))
1121 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1124 parameter[i+1] = '\0';
1125 parameter[i++] = *p++;
1128 while(*p <= 32) /* skip spaces */
1135 if (*p!=0 && *p!='#') /* missing name */
1137 i=0; /* read until end */
1138 while(*p!=0 && *p!='#')
1140 if (i+1 >= sizeof(value))
1142 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1149 /* remove trailing spaces from value */
1152 if (value[i-1]==0 || value[i-1]>32)
1159 /* check for interface name as first statement */
1160 if (expecting && parameter[0]!='[')
1162 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1167 /* check for new interface */
1168 if (parameter[0] == '[')
1170 if (parameter[strlen(parameter)-1] != ']')
1172 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1175 parameter[strlen(parameter)-1] = '\0';
1177 /* check if interface name already exists */
1178 interface = interface_newlist;
1181 if (!strcasecmp(interface->name, parameter+1))
1183 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1186 interface = interface->next;
1189 /* append interface to new list */
1190 interface = (struct interface *)MALLOC(sizeof(struct interface));
1193 /* name interface */
1194 SCPY(interface->name, parameter+1);
1197 *interfacep = interface;
1198 interfacep = &interface->next;
1203 ifparam = interface_param;
1204 while(ifparam->name)
1206 if (!strcasecmp(parameter, ifparam->name))
1208 if (ifparam->func(interface, filename, line, parameter, value))
1217 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1222 return(interface_newlist);
1224 PERROR_RUNTIME("%s", interface_error);
1226 free_interfaces(interface_newlist);
1227 interface_newlist = NULL;
1233 * freeing chain of interfaces
1235 void free_interfaces(struct interface *interface)
1238 struct interface_port *ifport;
1239 struct select_channel *selchannel;
1240 struct interface_msn *ifmsn;
1241 struct interface_screen *ifscreen;
1245 ifport = interface->ifport;
1248 selchannel = ifport->in_channel;
1252 selchannel = selchannel->next;
1253 FREE(temp, sizeof(struct select_channel));
1256 selchannel = ifport->out_channel;
1260 selchannel = selchannel->next;
1261 FREE(temp, sizeof(struct select_channel));
1265 ifport = ifport->next;
1266 FREE(temp, sizeof(struct interface_port));
1269 ifmsn = interface->ifmsn;
1273 ifmsn = ifmsn->next;
1274 FREE(temp, sizeof(struct interface_msn));
1277 ifscreen = interface->ifscreen_in;
1281 ifscreen = ifscreen->next;
1282 FREE(temp, sizeof(struct interface_screen));
1285 ifscreen = interface->ifscreen_out;
1289 ifscreen = ifscreen->next;
1290 FREE(temp, sizeof(struct interface_screen));
1294 interface = interface->next;
1295 FREE(temp, sizeof(struct interface));
1301 * defaults of ports if not specified by config
1303 static void set_defaults(struct interface_port *ifport)
1305 /* default channel selection list */
1306 if (!ifport->out_channel)
1307 default_out_channel(ifport);
1308 if (!ifport->in_channel)
1309 default_in_channel(ifport);
1310 /* default is_tones */
1311 if (ifport->interface->is_tones)
1312 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1314 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1315 /* default is_earlyb */
1316 if (ifport->interface->is_earlyb)
1317 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1319 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1320 /* set locally flag */
1321 if (ifport->interface->extension)
1322 ifport->mISDNport->locally = 1;
1324 ifport->mISDNport->locally = 0;
1329 * all links between mISDNport and interface are made
1330 * unused mISDNports are closed, new mISDNports are opened
1331 * also set default select_channel lists
1333 void relink_interfaces(void)
1335 struct mISDNport *mISDNport;
1336 struct interface *interface;
1337 struct interface_port *ifport;
1339 /* unlink all mISDNports */
1340 mISDNport = mISDNport_first;
1343 mISDNport->ifport = NULL;
1344 mISDNport = mISDNport->next;
1347 /* relink existing mISDNports */
1348 interface = interface_newlist;
1351 ifport = interface->ifport;
1354 mISDNport = mISDNport_first;
1357 if (!strcmp(mISDNport->name, ifport->portname))
1358 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1359 if (mISDNport->portnum == ifport->portnum)
1361 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", mISDNport->portnum);
1362 ifport->mISDNport = mISDNport;
1363 mISDNport->ifport = ifport;
1364 set_defaults(ifport);
1366 mISDNport = mISDNport->next;
1368 ifport = ifport->next;
1370 interface = interface->next;
1373 /* close unused mISDNports */
1375 mISDNport = mISDNport_first;
1378 if (mISDNport->ifport == NULL)
1380 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1381 /* remove all port objects and destroy port */
1382 mISDNport_close(mISDNport);
1385 mISDNport = mISDNport->next;
1388 /* open and link new mISDNports */
1389 interface = interface_newlist;
1392 ifport = interface->ifport;
1395 if (!ifport->mISDNport)
1399 ifport = ifport->next;
1401 interface = interface->next;
1410 void load_port(struct interface_port *ifport)
1412 struct mISDNport *mISDNport;
1415 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface);
1419 ifport->mISDNport = mISDNport;
1420 mISDNport->ifport = ifport;
1421 /* set number and name */
1422 ifport->portnum = mISDNport->portnum;
1423 SCPY(ifport->portname, mISDNport->name);
1425 set_defaults(ifport);
1428 ifport->block = 2; /* not available */
1433 * give summary of interface syntax
1435 void doc_interface(void)
1437 struct interface_param *ifparam;
1439 printf("Syntax overview\n");
1440 printf("---------------\n\n");
1442 printf("[<name>]\n");
1443 ifparam = interface_param;
1444 while(ifparam->name)
1446 if (ifparam->name[0])
1447 printf("%s %s\n", ifparam->name, ifparam->usage);
1451 ifparam = interface_param;
1452 while(ifparam->name)
1454 if (ifparam->name[0])
1456 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1457 printf("%s\n", ifparam->help);
1465 * out==0: incoming caller id, out==1: outgoing caller id
1467 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1470 struct interface_msn *ifmsn;
1471 struct interface_screen *ifscreen;
1474 /* screen incoming caller id */
1477 /* check for MSN numbers, use first MSN if no match */
1479 ifmsn = interface->ifmsn;
1484 if (!strcmp(ifmsn->msn, id))
1488 ifmsn = ifmsn->next;
1492 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1493 add_trace("msn", NULL, "%s", id);
1496 if (!ifmsn && msn1) // not in list, first msn given
1498 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1499 add_trace("msn", "given", "%s", id);
1500 add_trace("msn", "used", "%s", msn1);
1502 UNCPY(id, msn1, idsize);
1503 id[idsize-1] = '\0';
1507 /* check screen list */
1509 ifscreen = interface->ifscreen_out;
1511 ifscreen = interface->ifscreen_in;
1514 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1515 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1517 if (strchr(ifscreen->match,'%'))
1519 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1523 if (!strcmp(ifscreen->match, id))
1527 ifscreen = ifscreen->next;
1529 if (ifscreen) // match
1531 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)");
1534 case INFO_NTYPE_UNKNOWN:
1535 add_trace("given", "type", "unknown");
1537 case INFO_NTYPE_SUBSCRIBER:
1538 add_trace("given", "type", "subscriber");
1540 case INFO_NTYPE_NATIONAL:
1541 add_trace("given", "type", "national");
1543 case INFO_NTYPE_INTERNATIONAL:
1544 add_trace("given", "type", "international");
1549 case INFO_PRESENT_ALLOWED:
1550 add_trace("given", "present", "allowed");
1552 case INFO_PRESENT_RESTRICTED:
1553 add_trace("given", "present", "restricted");
1555 case INFO_PRESENT_NOTAVAIL:
1556 add_trace("given", "present", "not available");
1559 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1560 if (ifscreen->result_type != -1)
1562 *type = ifscreen->result_type;
1565 case INFO_NTYPE_UNKNOWN:
1566 add_trace("used", "type", "unknown");
1568 case INFO_NTYPE_SUBSCRIBER:
1569 add_trace("used", "type", "subscriber");
1571 case INFO_NTYPE_NATIONAL:
1572 add_trace("used", "type", "national");
1574 case INFO_NTYPE_INTERNATIONAL:
1575 add_trace("used", "type", "international");
1579 if (ifscreen->result_present != -1)
1581 *present = ifscreen->result_present;
1584 case INFO_PRESENT_ALLOWED:
1585 add_trace("used", "present", "allowed");
1587 case INFO_PRESENT_RESTRICTED:
1588 add_trace("used", "present", "restricted");
1590 case INFO_PRESENT_NOTAVAIL:
1591 add_trace("used", "present", "not available");
1595 if (strchr(ifscreen->match,'%'))
1597 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1598 UNCPY(id, ifscreen->result, idsize);
1599 id[idsize-1] = '\0';
1602 *strchr(id,'%') = '\0';
1603 UNCAT(id, suffix, idsize);
1604 id[idsize-1] = '\0';
1608 UNCPY(id, ifscreen->result, idsize);
1609 id[idsize-1] = '\0';
1611 add_trace("used", "id", "%s", id[0]?id:"<empty>");