1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** reading interface.conf file and filling structure **
10 \*****************************************************************************/
17 struct interface *interface_first = NULL; /* first interface is current list */
18 struct interface *interface_newlist = NULL; /* first interface in new list */
21 /* set default out_channel */
22 void default_out_channel(struct interface_port *ifport)
24 struct select_channel *selchannel, **selchannelp;
26 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
29 if (ifport->mISDNport->ntmode)
30 selchannel->channel = CHANNEL_FREE;
32 selchannel->channel = CHANNEL_ANY;
34 ifport->out_channel = selchannel;
36 /* additional channel selection for multipoint NT ports */
37 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
39 selchannelp = &(selchannel->next);
40 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
42 selchannel->channel = CHANNEL_NO; // call waiting
43 *selchannelp = selchannel;
48 /* set default in_channel */
49 void default_in_channel(struct interface_port *ifport)
51 struct select_channel *selchannel;
53 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
56 selchannel->channel = CHANNEL_FREE;
58 ifport->in_channel = selchannel;
62 /* parse string for a positive number */
63 static int get_number(char *value)
70 SPRINT(text, "%d", val);
72 if (!strcmp(value, text))
79 /* remove element from buffer
80 * and return pointer to next element in buffer */
81 static char *get_seperated(char *buffer)
85 if (*buffer==',' || *buffer<=32) /* seperate */
88 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
98 * parameter processing
100 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
102 struct interface_port *ifport;
104 /* port in chain ? */
105 if (!interface->ifport)
107 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
110 /* goto end of chain */
111 ifport = interface->ifport;
113 ifport = ifport->next;
117 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
123 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
127 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
130 interface->extension = 1;
133 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
135 struct interface_port *ifport;
137 /* port in chain ? */
138 if (!interface->ifport)
140 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
143 if (interface->ifport->ptmp)
145 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
148 /* goto end of chain */
149 ifport = interface->ifport;
151 ifport = ifport->next;
155 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
161 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
163 struct interface_port *ifport;
165 /* port in chain ? */
166 if (!interface->ifport)
168 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
171 if (interface->ifport->ptp)
173 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
176 /* goto end of chain */
177 ifport = interface->ifport;
179 ifport = ifport->next;
183 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
189 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
192 struct interface_port *ifport;
194 /* port in chain ? */
195 if (!interface->ifport)
197 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
200 /* goto end of chain */
201 ifport = interface->ifport;
203 ifport = ifport->next;
207 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
214 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
216 if (!strcasecmp(value, "yes"))
218 interface->is_tones = IS_YES;
220 if (!strcasecmp(value, "no"))
222 interface->is_tones = IS_NO;
225 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
230 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
232 if (!strcasecmp(value, "yes"))
234 interface->is_earlyb = IS_YES;
236 if (!strcasecmp(value, "no"))
238 interface->is_earlyb = IS_NO;
241 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
246 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
248 if (!strcasecmp(value, "linear"))
250 interface->hunt = HUNT_LINEAR;
252 if (!strcasecmp(value, "roundrobin"))
254 interface->hunt = HUNT_ROUNDROBIN;
257 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
262 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
264 struct interface_port *ifport, **ifportp;
265 struct interface *searchif;
268 val = get_number(value);
271 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
274 /* check for port already assigned */
275 searchif = interface_newlist;
278 ifport = searchif->ifport;
281 if (ifport->portnum == val)
283 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
286 ifport = ifport->next;
288 searchif = searchif->next;
290 /* alloc port substructure */
291 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
293 ifport->interface = interface;
295 ifport->portnum = val;
297 ifportp = &interface->ifport;
299 ifportp = &((*ifportp)->next);
303 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
305 struct interface_port *ifport;
306 struct select_channel *selchannel, **selchannelp;
310 /* port in chain ? */
311 if (!interface->ifport)
313 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
316 /* goto end of chain */
317 ifport = interface->ifport;
319 ifport = ifport->next;
324 p = get_seperated(p);
325 if (!strcasecmp(el, "force"))
327 ifport->channel_force = 1;
328 if (ifport->out_channel)
330 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
334 if (!strcasecmp(el, "any"))
339 if (!strcasecmp(el, "free"))
344 if (!strcasecmp(el, "no"))
350 val = get_number(el);
353 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);
357 if (val<1 || val==16 || val>126)
359 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
363 /* add to select-channel list */
364 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
367 selchannel->channel = val;
369 selchannelp = &ifport->out_channel;
371 selchannelp = &((*selchannelp)->next);
372 *selchannelp = selchannel;
377 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
379 struct interface_port *ifport;
380 struct select_channel *selchannel, **selchannelp;
384 /* port in chain ? */
385 if (!interface->ifport)
387 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
390 /* goto end of chain */
391 ifport = interface->ifport;
393 ifport = ifport->next;
398 p = get_seperated(p);
399 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
401 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
404 if (!strcasecmp(el, "free"))
410 val = get_number(el);
413 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
417 if (val<1 || val==16 || val>126)
419 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
423 /* add to select-channel list */
424 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
427 selchannel->channel = val;
429 selchannelp = &ifport->in_channel;
431 selchannelp = &((*selchannelp)->next);
432 *selchannelp = selchannel;
437 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
439 struct interface_port *ifport;
440 // struct select_channel *selchannel, **selchannelp;
444 /* port in chain ? */
445 if (!interface->ifport)
447 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
450 /* goto end of chain */
451 ifport = interface->ifport;
453 ifport = ifport->next;
458 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
462 p = get_seperated(p);
463 ifport->tout_setup = atoi(el);
467 p = get_seperated(p);
468 ifport->tout_dialing = atoi(el);
472 p = get_seperated(p);
473 ifport->tout_proceeding = atoi(el);
477 p = get_seperated(p);
478 ifport->tout_alerting = atoi(el);
482 p = get_seperated(p);
483 ifport->tout_disconnect = atoi(el);
486 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
488 struct interface_msn *ifmsn, **ifmsnp;
493 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
496 if (interface->ifscreen_in)
498 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
507 p = get_seperated(p);
508 /* add MSN to list */
509 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
512 SCPY(ifmsn->msn, el);
514 ifmsnp = &interface->ifmsn;
516 ifmsnp = &((*ifmsnp)->next);
521 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
523 struct interface_screen *ifscreen;
528 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
531 /* add screen entry to list*/
532 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
534 ifscreen->match_type = -1; /* unchecked */
535 ifscreen->match_present = -1; /* unchecked */
536 ifscreen->result_type = -1; /* unchanged */
537 ifscreen->result_present = -1; /* unchanged */
540 ifscreenp = &((*ifscreenp)->next);
541 *ifscreenp = ifscreen;
542 // printf("interface=%s\n", interface->name);
548 p = get_seperated(p);
549 if (!strcasecmp(el, "unknown"))
551 if (ifscreen->match_type != -1)
554 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
557 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
559 if (!strcasecmp(el, "subscriber"))
561 if (ifscreen->match_type != -1)
563 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
565 if (!strcasecmp(el, "national"))
567 if (ifscreen->match_type != -1)
569 ifscreen->match_type = INFO_NTYPE_NATIONAL;
571 if (!strcasecmp(el, "international"))
573 if (ifscreen->match_type != -1)
575 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
577 if (!strcasecmp(el, "allowed"))
579 if (ifscreen->match_present != -1)
582 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
585 ifscreen->match_present = INFO_PRESENT_ALLOWED;
587 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
589 if (ifscreen->match_present != -1)
591 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
593 SCPY(ifscreen->match, el);
594 /* check for % at the end */
597 if (strchr(el, '%') != el+strlen(el)-1)
599 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
606 if (ifscreen->match[0] == '\0')
608 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
615 p = get_seperated(p);
616 if (!strcasecmp(el, "unknown"))
618 if (ifscreen->result_type != -1)
620 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
622 if (!strcasecmp(el, "subscriber"))
624 if (ifscreen->result_type != -1)
626 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
628 if (!strcasecmp(el, "national"))
630 if (ifscreen->result_type != -1)
632 ifscreen->result_type = INFO_NTYPE_NATIONAL;
634 if (!strcasecmp(el, "international"))
636 if (ifscreen->result_type != -1)
638 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
640 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
642 if (ifscreen->result_present != -1)
644 ifscreen->result_present = INFO_PRESENT_ALLOWED;
646 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
648 if (ifscreen->result_present != -1)
650 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
652 SCPY(ifscreen->result, el);
653 /* check for % at the end */
656 if (strchr(el, '%') != el+strlen(el)-1)
658 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
665 if (ifscreen->result[0] == '\0')
667 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
672 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
674 if (interface->ifmsn)
676 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
680 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
682 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
684 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
686 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
688 struct interface_port *ifport;
690 /* port in chain ? */
691 if (!interface->ifport)
693 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
696 /* goto end of chain */
697 ifport = interface->ifport;
699 ifport = ifport->next;
703 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
707 /* seperate parameter from filter */
714 while(*p > 0 && *p <= 32)
718 if (!strcasecmp(value, "gain"))
726 while(*q > 0 && *q <= 32)
729 if (*p == 0 || *q == 0)
731 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
734 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
736 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
739 interface->tx_gain = atoi(p);
740 interface->rx_gain = atoi(q);
742 if (!strcasecmp(value, "pipeline"))
746 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
749 SCPY(interface->pipeline, p);
751 if (!strcasecmp(value, "blowfish"))
753 unsigned char key[56];
756 if (!!strncmp(p, "0x", 2))
758 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
767 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
770 if (*p >= '0' && *p <= '9')
771 key[l] = (*p-'0')<<4;
772 else if (*p >= 'a' && *p <= 'f')
773 key[l] = (*p-'a'+10)<<4;
774 else if (*p >= 'A' && *p <= 'F')
775 key[l] = (*p-'A'+10)<<4;
779 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);
785 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);
788 if (*p >= '0' && *p <= '9')
789 key[l] = (*p-'0')<<4;
790 else if (*p >= 'a' && *p <= 'f')
791 key[l] = (*p-'a'+10)<<4;
792 else if (*p >= 'A' && *p <= 'F')
793 key[l] = (*p-'A'+10)<<4;
801 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);
804 memcpy(interface->bf_key, key, l);
805 interface->bf_len = l;
808 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
816 * structure of parameters
818 struct interface_param interface_param[] = {
819 { "extension", &inter_extension, "",
820 "If keyword is given, calls to interface are handled as internal extensions."},
821 {"tones", &inter_tones, "yes | no",
822 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
824 {"earlyb", &inter_earlyb, "yes | no",
825 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
827 {"hunt", &inter_hunt, "linear | roundrobin",
828 "Select the algorithm for selecting port with free channel."},
830 {"port", &inter_port, "<number>",
831 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
833 {"block", &inter_block, "",
834 "If keyword is given, calls on this interface are blocked.\n"
835 "This parameter must follow a 'port' parameter."},
837 {"ptp", &inter_ptp, "",
838 "The given port above is opened as point-to-point.\n"
839 "This is required on NT-mode ports that are multipoint by default.\n"
840 "This parameter must follow a 'port' parameter."},
842 {"ptmp", &inter_ptmp, "",
843 "The given port above is opened as point-to-multipoint.\n"
844 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
845 "This parameter must follow a 'port' parameter."},
846 {"nt", &inter_nt, "",
847 "The given port above is opened in NT-mode.\n"
849 "This is required on interfaces that support both NT-mode and TE-mode.\n"
851 "This parameter is only required for socket based mISDN driver.\n"
853 "This parameter must follow a 'port' parameter."},
855 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
856 "Channel selection list for all outgoing calls to the interface.\n"
857 "A free channels is searched in order of appearance.\n"
858 "This parameter must follow a 'port' parameter.\n"
859 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
860 " <number>[,...] - List of channels to search.\n"
861 " free - Select any free channel\n"
862 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
863 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
865 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
866 "Channel selection list for all incoming calls from the interface.\n"
867 "A free channels is accepted if in the list.\n"
868 "If any channel was requested, the first free channel found is selected.\n"
869 "This parameter must follow a 'port' parameter.\n"
870 " <number>[,...] - List of channels to accept.\n"
871 " free - Accept any free channel"},
873 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
874 "Timeout values for call states. They are both for incoming and outgoing states.\n"
875 "The default is 120 seconds for all states. Use 0 to disable.\n"
876 "This parameter must follow a 'port' parameter.\n"},
878 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
879 "Incoming caller ID is checked against given MSN numbers.\n"
880 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
882 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
883 "Adds an entry for incoming calls to the caller ID screen list.\n"
884 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
885 "If '%' is given after old caller ID, it matches even if caller ID has\n"
886 "additional digits.\n"
887 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
890 " unknown | subsciber | national | international - Change caller ID type.\n"
891 " present | restrict - Change presentation of caller ID."},
893 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
894 "Adds an entry for outgoing calls to the caller ID screen list.\n"
895 "See 'screen-in' for help."},
897 {"nodtmf", &inter_nodtmf, "",
898 "Disables DTMF detection for this interface.\n"
899 "This parameter must follow a 'port' parameter."},
902 {"layer2keep", &inter_layer2keep, "yes | no",
903 "By default, layer 2 is establised and kept up on PTP interfaces.\n"
905 "This parameter must follow a 'port' parameter."},
908 {"filter", &inter_filter, "<filter> <parameters>",
909 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
910 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
911 "pipeline <string> - Sets echo cancelation pipeline.\n"
912 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
914 {NULL, NULL, NULL, NULL}
919 * read settings from interface.conf
921 char interface_error[256];
922 struct interface *read_interfaces(void)
927 unsigned int line, i;
929 struct interface *interface = NULL, /* in case no interface */
930 **interfacep = &interface_newlist;
933 int expecting = 1; /* expecting new interface */
934 struct interface_param *ifparam;
936 if (interface_newlist != NULL)
937 FATAL("list is not empty.\n");
938 interface_error[0] = '\0';
939 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
941 if (!(fp = fopen(filename,"r")))
943 SPRINT(interface_error, "Cannot open '%s'\n", filename);
948 while((fgets(buffer,sizeof(buffer),fp)))
950 buffer[sizeof(buffer)-1]=0;
951 if (buffer[0]) buffer[strlen(buffer)-1]=0;
955 while(*p <= 32) /* skip spaces */
961 if (*p==0 || *p=='#') /* ignore comments and empty line */
966 i=0; /* read parameter */
969 if (i+1 >= sizeof(parameter))
971 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
974 parameter[i+1] = '\0';
975 parameter[i++] = *p++;
978 while(*p <= 32) /* skip spaces */
985 if (*p!=0 && *p!='#') /* missing name */
987 i=0; /* read until end */
988 while(*p!=0 && *p!='#')
990 if (i+1 >= sizeof(value))
992 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
999 /* remove trailing spaces from value */
1002 if (value[i-1]==0 || value[i-1]>32)
1009 /* check for interface name as first statement */
1010 if (expecting && parameter[0]!='[')
1012 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1017 /* check for new interface */
1018 if (parameter[0] == '[')
1020 if (parameter[strlen(parameter)-1] != ']')
1022 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1025 parameter[strlen(parameter)-1] = '\0';
1027 /* check if interface name already exists */
1028 interface = interface_newlist;
1031 if (!strcasecmp(interface->name, parameter+1))
1033 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1036 interface = interface->next;
1039 /* append interface to new list */
1040 interface = (struct interface *)MALLOC(sizeof(struct interface));
1043 /* name interface */
1044 SCPY(interface->name, parameter+1);
1047 *interfacep = interface;
1048 interfacep = &interface->next;
1053 ifparam = interface_param;
1054 while(ifparam->name)
1056 if (!strcasecmp(parameter, ifparam->name))
1058 if (ifparam->func(interface, filename, line, parameter, value))
1067 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1072 return(interface_newlist);
1074 PERROR_RUNTIME("%s", interface_error);
1076 free_interfaces(interface_newlist);
1077 interface_newlist = NULL;
1083 * freeing chain of interfaces
1085 void free_interfaces(struct interface *interface)
1088 struct interface_port *ifport;
1089 struct select_channel *selchannel;
1090 struct interface_msn *ifmsn;
1091 struct interface_screen *ifscreen;
1095 ifport = interface->ifport;
1098 selchannel = ifport->in_channel;
1102 selchannel = selchannel->next;
1103 FREE(temp, sizeof(struct select_channel));
1106 selchannel = ifport->out_channel;
1110 selchannel = selchannel->next;
1111 FREE(temp, sizeof(struct select_channel));
1115 ifport = ifport->next;
1116 FREE(temp, sizeof(struct interface_port));
1119 ifmsn = interface->ifmsn;
1123 ifmsn = ifmsn->next;
1124 FREE(temp, sizeof(struct interface_msn));
1127 ifscreen = interface->ifscreen_in;
1131 ifscreen = ifscreen->next;
1132 FREE(temp, sizeof(struct interface_screen));
1135 ifscreen = interface->ifscreen_out;
1139 ifscreen = ifscreen->next;
1140 FREE(temp, sizeof(struct interface_screen));
1144 interface = interface->next;
1145 FREE(temp, sizeof(struct interface));
1151 * defaults of ports if not specified by config
1153 static void set_defaults(struct interface_port *ifport)
1155 /* default channel selection list */
1156 if (!ifport->out_channel)
1157 default_out_channel(ifport);
1158 if (!ifport->in_channel)
1159 default_in_channel(ifport);
1160 /* default is_tones */
1161 if (ifport->interface->is_tones)
1162 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1164 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1165 /* default is_earlyb */
1166 if (ifport->interface->is_earlyb)
1167 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1169 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1170 /* set locally flag */
1171 if (ifport->interface->extension)
1172 ifport->mISDNport->locally = 1;
1174 ifport->mISDNport->locally = 0;
1179 * all links between mISDNport and interface are made
1180 * unused mISDNports are closed, new mISDNports are opened
1181 * also set default select_channel lists
1183 void relink_interfaces(void)
1185 struct mISDNport *mISDNport;
1186 struct interface *interface;
1187 struct interface_port *ifport;
1189 /* unlink all mISDNports */
1190 mISDNport = mISDNport_first;
1193 mISDNport->ifport = NULL;
1194 mISDNport = mISDNport->next;
1197 /* relink existing mISDNports */
1198 interface = interface_newlist;
1201 ifport = interface->ifport;
1204 mISDNport = mISDNport_first;
1207 if (mISDNport->portnum == ifport->portnum)
1209 ifport->mISDNport = mISDNport;
1210 mISDNport->ifport = ifport;
1211 set_defaults(ifport);
1213 mISDNport = mISDNport->next;
1215 ifport = ifport->next;
1217 interface = interface->next;
1220 /* close unused mISDNports */
1222 mISDNport = mISDNport_first;
1225 if (mISDNport->ifport == NULL)
1227 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1228 /* remove all port objects and destroy port */
1229 mISDNport_close(mISDNport);
1232 mISDNport = mISDNport->next;
1235 /* open and link new mISDNports */
1236 interface = interface_newlist;
1239 ifport = interface->ifport;
1242 if (!ifport->mISDNport)
1246 ifport = ifport->next;
1248 interface = interface->next;
1257 void load_port(struct interface_port *ifport)
1259 struct mISDNport *mISDNport;
1262 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
1266 ifport->mISDNport = mISDNport;
1267 mISDNport->ifport = ifport;
1268 set_defaults(ifport);
1271 ifport->block = 2; /* not available */
1276 * give summary of interface syntax
1278 void doc_interface(void)
1280 struct interface_param *ifparam;
1282 printf("Syntax overview\n");
1283 printf("---------------\n\n");
1285 printf("[<name>]\n");
1286 ifparam = interface_param;
1287 while(ifparam->name)
1289 printf("%s %s\n", ifparam->name, ifparam->usage);
1293 ifparam = interface_param;
1294 while(ifparam->name)
1296 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1297 printf("%s\n", ifparam->help);
1304 * out==0: incoming caller id, out==1: outgoing caller id
1306 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1309 struct interface_msn *ifmsn;
1310 struct interface_screen *ifscreen;
1313 /* screen incoming caller id */
1316 /* check for MSN numbers, use first MSN if no match */
1318 ifmsn = interface->ifmsn;
1323 if (!strcmp(ifmsn->msn, id))
1327 ifmsn = ifmsn->next;
1331 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1332 add_trace("msn", NULL, "%s", id);
1335 if (!ifmsn && msn1) // not in list, first msn given
1337 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1338 add_trace("msn", "given", "%s", id);
1339 add_trace("msn", "used", "%s", msn1);
1341 UNCPY(id, msn1, idsize);
1342 id[idsize-1] = '\0';
1346 /* check screen list */
1348 ifscreen = interface->ifscreen_out;
1350 ifscreen = interface->ifscreen_in;
1353 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1354 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1356 if (strchr(ifscreen->match,'%'))
1358 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1362 if (!strcmp(ifscreen->match, id))
1366 ifscreen = ifscreen->next;
1368 if (ifscreen) // match
1370 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1373 case INFO_NTYPE_UNKNOWN:
1374 add_trace("given", "type", "unknown");
1376 case INFO_NTYPE_SUBSCRIBER:
1377 add_trace("given", "type", "subscriber");
1379 case INFO_NTYPE_NATIONAL:
1380 add_trace("given", "type", "national");
1382 case INFO_NTYPE_INTERNATIONAL:
1383 add_trace("given", "type", "international");
1388 case INFO_PRESENT_ALLOWED:
1389 add_trace("given", "present", "allowed");
1391 case INFO_PRESENT_RESTRICTED:
1392 add_trace("given", "present", "restricted");
1394 case INFO_PRESENT_NOTAVAIL:
1395 add_trace("given", "present", "not available");
1398 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1399 if (ifscreen->result_type != -1)
1401 *type = ifscreen->result_type;
1404 case INFO_NTYPE_UNKNOWN:
1405 add_trace("used", "type", "unknown");
1407 case INFO_NTYPE_SUBSCRIBER:
1408 add_trace("used", "type", "subscriber");
1410 case INFO_NTYPE_NATIONAL:
1411 add_trace("used", "type", "national");
1413 case INFO_NTYPE_INTERNATIONAL:
1414 add_trace("used", "type", "international");
1418 if (ifscreen->result_present != -1)
1420 *present = ifscreen->result_present;
1423 case INFO_PRESENT_ALLOWED:
1424 add_trace("used", "present", "allowed");
1426 case INFO_PRESENT_RESTRICTED:
1427 add_trace("used", "present", "restricted");
1429 case INFO_PRESENT_NOTAVAIL:
1430 add_trace("used", "present", "not available");
1434 if (strchr(ifscreen->match,'%'))
1436 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1437 UNCPY(id, ifscreen->result, idsize);
1438 id[idsize-1] = '\0';
1441 *strchr(id,'%') = '\0';
1442 UNCAT(id, suffix, idsize);
1443 id[idsize-1] = '\0';
1447 UNCPY(id, ifscreen->result, idsize);
1448 id[idsize-1] = '\0';
1450 add_trace("used", "id", "%s", id[0]?id:"<empty>");