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)
191 struct interface_port *ifport;
193 /* port in chain ? */
194 if (!interface->ifport)
196 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
199 /* goto end of chain */
200 ifport = interface->ifport;
202 ifport = ifport->next;
206 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
213 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
215 if (!strcasecmp(value, "yes"))
217 interface->is_tones = IS_YES;
219 if (!strcasecmp(value, "no"))
221 interface->is_tones = IS_NO;
224 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
229 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
231 if (!strcasecmp(value, "yes"))
233 interface->is_earlyb = IS_YES;
235 if (!strcasecmp(value, "no"))
237 interface->is_earlyb = IS_NO;
240 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
245 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
247 if (!strcasecmp(value, "linear"))
249 interface->hunt = HUNT_LINEAR;
251 if (!strcasecmp(value, "roundrobin"))
253 interface->hunt = HUNT_ROUNDROBIN;
256 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
261 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
263 struct interface_port *ifport, **ifportp;
264 struct interface *searchif;
267 val = get_number(value);
270 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
273 /* check for port already assigned */
274 searchif = interface_newlist;
277 ifport = searchif->ifport;
280 if (ifport->portnum == val)
282 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
285 ifport = ifport->next;
287 searchif = searchif->next;
289 /* alloc port substructure */
290 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
292 ifport->interface = interface;
294 ifport->portnum = val;
296 ifportp = &interface->ifport;
298 ifportp = &((*ifportp)->next);
302 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
304 struct interface_port *ifport;
306 /* port in chain ? */
307 if (!interface->ifport)
309 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
312 /* goto end of chain */
313 ifport = interface->ifport;
315 ifport = ifport->next;
316 if (!strcmp(value, "yes"))
320 if (!strcmp(value, "no"))
325 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
330 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
332 struct interface_port *ifport;
333 struct select_channel *selchannel, **selchannelp;
337 /* port in chain ? */
338 if (!interface->ifport)
340 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
343 /* goto end of chain */
344 ifport = interface->ifport;
346 ifport = ifport->next;
351 p = get_seperated(p);
352 if (!strcasecmp(el, "force"))
354 ifport->channel_force = 1;
355 if (ifport->out_channel)
357 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
361 if (!strcasecmp(el, "any"))
366 if (!strcasecmp(el, "free"))
371 if (!strcasecmp(el, "no"))
377 val = get_number(el);
380 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);
384 if (val<1 || val==16 || val>126)
386 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
390 /* add to select-channel list */
391 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
394 selchannel->channel = val;
396 selchannelp = &ifport->out_channel;
398 selchannelp = &((*selchannelp)->next);
399 *selchannelp = selchannel;
404 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
406 struct interface_port *ifport;
407 struct select_channel *selchannel, **selchannelp;
411 /* port in chain ? */
412 if (!interface->ifport)
414 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
417 /* goto end of chain */
418 ifport = interface->ifport;
420 ifport = ifport->next;
425 p = get_seperated(p);
426 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
428 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
431 if (!strcasecmp(el, "free"))
437 val = get_number(el);
440 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
444 if (val<1 || val==16 || val>126)
446 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
450 /* add to select-channel list */
451 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
454 selchannel->channel = val;
456 selchannelp = &ifport->in_channel;
458 selchannelp = &((*selchannelp)->next);
459 *selchannelp = selchannel;
464 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
466 struct interface_port *ifport;
467 // struct select_channel *selchannel, **selchannelp;
471 /* port in chain ? */
472 if (!interface->ifport)
474 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
477 /* goto end of chain */
478 ifport = interface->ifport;
480 ifport = ifport->next;
485 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
489 p = get_seperated(p);
490 ifport->tout_setup = atoi(el);
494 p = get_seperated(p);
495 ifport->tout_dialing = atoi(el);
499 p = get_seperated(p);
500 ifport->tout_proceeding = atoi(el);
504 p = get_seperated(p);
505 ifport->tout_alerting = atoi(el);
509 p = get_seperated(p);
510 ifport->tout_disconnect = atoi(el);
513 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
515 struct interface_msn *ifmsn, **ifmsnp;
520 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
523 if (interface->ifscreen_in)
525 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
534 p = get_seperated(p);
535 /* add MSN to list */
536 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
539 SCPY(ifmsn->msn, el);
541 ifmsnp = &interface->ifmsn;
543 ifmsnp = &((*ifmsnp)->next);
548 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
550 struct interface_screen *ifscreen;
555 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
558 /* add screen entry to list*/
559 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
561 ifscreen->match_type = -1; /* unchecked */
562 ifscreen->match_present = -1; /* unchecked */
563 ifscreen->result_type = -1; /* unchanged */
564 ifscreen->result_present = -1; /* unchanged */
567 ifscreenp = &((*ifscreenp)->next);
568 *ifscreenp = ifscreen;
569 // printf("interface=%s\n", interface->name);
575 p = get_seperated(p);
576 if (!strcasecmp(el, "unknown"))
578 if (ifscreen->match_type != -1)
581 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
584 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
586 if (!strcasecmp(el, "subscriber"))
588 if (ifscreen->match_type != -1)
590 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
592 if (!strcasecmp(el, "national"))
594 if (ifscreen->match_type != -1)
596 ifscreen->match_type = INFO_NTYPE_NATIONAL;
598 if (!strcasecmp(el, "international"))
600 if (ifscreen->match_type != -1)
602 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
604 if (!strcasecmp(el, "allowed"))
606 if (ifscreen->match_present != -1)
609 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
612 ifscreen->match_present = INFO_PRESENT_ALLOWED;
614 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
616 if (ifscreen->match_present != -1)
618 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
620 SCPY(ifscreen->match, el);
621 /* check for % at the end */
624 if (strchr(el, '%') != el+strlen(el)-1)
626 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
633 if (ifscreen->match[0] == '\0')
635 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
642 p = get_seperated(p);
643 if (!strcasecmp(el, "unknown"))
645 if (ifscreen->result_type != -1)
647 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
649 if (!strcasecmp(el, "subscriber"))
651 if (ifscreen->result_type != -1)
653 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
655 if (!strcasecmp(el, "national"))
657 if (ifscreen->result_type != -1)
659 ifscreen->result_type = INFO_NTYPE_NATIONAL;
661 if (!strcasecmp(el, "international"))
663 if (ifscreen->result_type != -1)
665 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
667 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
669 if (ifscreen->result_present != -1)
671 ifscreen->result_present = INFO_PRESENT_ALLOWED;
673 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
675 if (ifscreen->result_present != -1)
677 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
679 SCPY(ifscreen->result, el);
680 /* check for % at the end */
683 if (strchr(el, '%') != el+strlen(el)-1)
685 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
692 if (ifscreen->result[0] == '\0')
694 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
699 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
701 if (interface->ifmsn)
703 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
707 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
709 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
711 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
713 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
715 struct interface_port *ifport;
717 /* port in chain ? */
718 if (!interface->ifport)
720 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
723 /* goto end of chain */
724 ifport = interface->ifport;
726 ifport = ifport->next;
730 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
734 /* seperate parameter from filter */
741 while(*p > 0 && *p <= 32)
745 if (!strcasecmp(value, "gain"))
753 while(*q > 0 && *q <= 32)
756 if (*p == 0 || *q == 0)
758 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
761 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
763 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
766 interface->tx_gain = atoi(p);
767 interface->rx_gain = atoi(q);
769 if (!strcasecmp(value, "pipeline"))
773 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
776 SCPY(interface->pipeline, p);
778 if (!strcasecmp(value, "blowfish"))
780 unsigned char key[56];
783 if (!!strncmp(p, "0x", 2))
785 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
794 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
797 if (*p >= '0' && *p <= '9')
798 key[l] = (*p-'0')<<4;
799 else if (*p >= 'a' && *p <= 'f')
800 key[l] = (*p-'a'+10)<<4;
801 else if (*p >= 'A' && *p <= 'F')
802 key[l] = (*p-'A'+10)<<4;
806 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);
812 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);
815 if (*p >= '0' && *p <= '9')
816 key[l] = (*p-'0')<<4;
817 else if (*p >= 'a' && *p <= 'f')
818 key[l] = (*p-'a'+10)<<4;
819 else if (*p >= 'A' && *p <= 'F')
820 key[l] = (*p-'A'+10)<<4;
828 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);
831 memcpy(interface->bf_key, key, l);
832 interface->bf_len = l;
835 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
843 * structure of parameters
845 struct interface_param interface_param[] = {
846 { "extension", &inter_extension, "",
847 "If keyword is given, calls to interface are handled as internal extensions."},
848 {"tones", &inter_tones, "yes | no",
849 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
851 {"earlyb", &inter_earlyb, "yes | no",
852 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
854 {"hunt", &inter_hunt, "linear | roundrobin",
855 "Select the algorithm for selecting port with free channel."},
857 {"port", &inter_port, "<number>",
858 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
860 {"block", &inter_block, "",
861 "If keyword is given, calls on this interface are blocked.\n"
862 "This parameter must follow a 'port' parameter."},
864 {"ptp", &inter_ptp, "",
865 "The given port above is opened as point-to-point.\n"
866 "This is required on NT-mode ports that are multipoint by default.\n"
867 "This parameter must follow a 'port' parameter."},
870 {"ptmp", &inter_ptmp, "",
871 "The given port above is opened as point-to-multipoint.\n"
872 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
873 "This parameter must follow a 'port' parameter."},
876 {"nt", &inter_nt, "",
877 "The given port above is opened in NT-mode.\n"
879 "This is required on interfaces that support both NT-mode and TE-mode.\n"
881 "This parameter is only required for socket based mISDN driver.\n"
883 "This parameter must follow a 'port' parameter."},
885 {"layer2hold", &inter_l2hold, "yes | no",
886 "The given port will continuously try to establish layer 2 link and hold it.\n"
887 "It is required for PTP links in most cases, therefore it is default.\n"
888 "This parameter must follow a 'port' parameter."},
890 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
891 "Channel selection list for all outgoing calls to the interface.\n"
892 "A free channels is searched in order of appearance.\n"
893 "This parameter must follow a 'port' parameter.\n"
894 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
895 " <number>[,...] - List of channels to search.\n"
896 " free - Select any free channel\n"
897 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
898 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
900 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
901 "Channel selection list for all incoming calls from the interface.\n"
902 "A free channels is accepted if in the list.\n"
903 "If any channel was requested, the first free channel found is selected.\n"
904 "This parameter must follow a 'port' parameter.\n"
905 " <number>[,...] - List of channels to accept.\n"
906 " free - Accept any free channel"},
908 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
909 "Timeout values for call states. They are both for incoming and outgoing states.\n"
910 "The default is 120 seconds for all states. Use 0 to disable.\n"
911 "This parameter must follow a 'port' parameter.\n"},
913 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
914 "Incoming caller ID is checked against given MSN numbers.\n"
915 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
917 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
918 "Adds an entry for incoming calls to the caller ID screen list.\n"
919 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
920 "If '%' is given after old caller ID, it matches even if caller ID has\n"
921 "additional digits.\n"
922 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
925 " unknown | subsciber | national | international - Change caller ID type.\n"
926 " present | restrict - Change presentation of caller ID."},
928 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
929 "Adds an entry for outgoing calls to the caller ID screen list.\n"
930 "See 'screen-in' for help."},
932 {"nodtmf", &inter_nodtmf, "",
933 "Disables DTMF detection for this interface.\n"
934 "This parameter must follow a 'port' parameter."},
936 {"filter", &inter_filter, "<filter> <parameters>",
937 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
938 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
939 "pipeline <string> - Sets echo cancelation pipeline.\n"
940 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
942 {NULL, NULL, NULL, NULL}
947 * read settings from interface.conf
949 char interface_error[256];
950 struct interface *read_interfaces(void)
955 unsigned int line, i;
957 struct interface *interface = NULL, /* in case no interface */
958 **interfacep = &interface_newlist;
961 int expecting = 1; /* expecting new interface */
962 struct interface_param *ifparam;
964 if (interface_newlist != NULL)
965 FATAL("list is not empty.\n");
966 interface_error[0] = '\0';
967 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
969 if (!(fp = fopen(filename,"r")))
971 SPRINT(interface_error, "Cannot open '%s'\n", filename);
976 while((fgets(buffer,sizeof(buffer),fp)))
978 buffer[sizeof(buffer)-1]=0;
979 if (buffer[0]) buffer[strlen(buffer)-1]=0;
983 while(*p <= 32) /* skip spaces */
989 if (*p==0 || *p=='#') /* ignore comments and empty line */
994 i=0; /* read parameter */
997 if (i+1 >= sizeof(parameter))
999 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1002 parameter[i+1] = '\0';
1003 parameter[i++] = *p++;
1006 while(*p <= 32) /* skip spaces */
1013 if (*p!=0 && *p!='#') /* missing name */
1015 i=0; /* read until end */
1016 while(*p!=0 && *p!='#')
1018 if (i+1 >= sizeof(value))
1020 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1027 /* remove trailing spaces from value */
1030 if (value[i-1]==0 || value[i-1]>32)
1037 /* check for interface name as first statement */
1038 if (expecting && parameter[0]!='[')
1040 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1045 /* check for new interface */
1046 if (parameter[0] == '[')
1048 if (parameter[strlen(parameter)-1] != ']')
1050 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1053 parameter[strlen(parameter)-1] = '\0';
1055 /* check if interface name already exists */
1056 interface = interface_newlist;
1059 if (!strcasecmp(interface->name, parameter+1))
1061 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1064 interface = interface->next;
1067 /* append interface to new list */
1068 interface = (struct interface *)MALLOC(sizeof(struct interface));
1071 /* name interface */
1072 SCPY(interface->name, parameter+1);
1075 *interfacep = interface;
1076 interfacep = &interface->next;
1081 ifparam = interface_param;
1082 while(ifparam->name)
1084 if (!strcasecmp(parameter, ifparam->name))
1086 if (ifparam->func(interface, filename, line, parameter, value))
1095 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1100 return(interface_newlist);
1102 PERROR_RUNTIME("%s", interface_error);
1104 free_interfaces(interface_newlist);
1105 interface_newlist = NULL;
1111 * freeing chain of interfaces
1113 void free_interfaces(struct interface *interface)
1116 struct interface_port *ifport;
1117 struct select_channel *selchannel;
1118 struct interface_msn *ifmsn;
1119 struct interface_screen *ifscreen;
1123 ifport = interface->ifport;
1126 selchannel = ifport->in_channel;
1130 selchannel = selchannel->next;
1131 FREE(temp, sizeof(struct select_channel));
1134 selchannel = ifport->out_channel;
1138 selchannel = selchannel->next;
1139 FREE(temp, sizeof(struct select_channel));
1143 ifport = ifport->next;
1144 FREE(temp, sizeof(struct interface_port));
1147 ifmsn = interface->ifmsn;
1151 ifmsn = ifmsn->next;
1152 FREE(temp, sizeof(struct interface_msn));
1155 ifscreen = interface->ifscreen_in;
1159 ifscreen = ifscreen->next;
1160 FREE(temp, sizeof(struct interface_screen));
1163 ifscreen = interface->ifscreen_out;
1167 ifscreen = ifscreen->next;
1168 FREE(temp, sizeof(struct interface_screen));
1172 interface = interface->next;
1173 FREE(temp, sizeof(struct interface));
1179 * defaults of ports if not specified by config
1181 static void set_defaults(struct interface_port *ifport)
1183 /* default channel selection list */
1184 if (!ifport->out_channel)
1185 default_out_channel(ifport);
1186 if (!ifport->in_channel)
1187 default_in_channel(ifport);
1188 /* default is_tones */
1189 if (ifport->interface->is_tones)
1190 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1192 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1193 /* default is_earlyb */
1194 if (ifport->interface->is_earlyb)
1195 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1197 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1198 /* set locally flag */
1199 if (ifport->interface->extension)
1200 ifport->mISDNport->locally = 1;
1202 ifport->mISDNport->locally = 0;
1207 * all links between mISDNport and interface are made
1208 * unused mISDNports are closed, new mISDNports are opened
1209 * also set default select_channel lists
1211 void relink_interfaces(void)
1213 struct mISDNport *mISDNport;
1214 struct interface *interface;
1215 struct interface_port *ifport;
1217 /* unlink all mISDNports */
1218 mISDNport = mISDNport_first;
1221 mISDNport->ifport = NULL;
1222 mISDNport = mISDNport->next;
1225 /* relink existing mISDNports */
1226 interface = interface_newlist;
1229 ifport = interface->ifport;
1232 mISDNport = mISDNport_first;
1235 if (mISDNport->portnum == ifport->portnum)
1237 ifport->mISDNport = mISDNport;
1238 mISDNport->ifport = ifport;
1239 set_defaults(ifport);
1241 mISDNport = mISDNport->next;
1243 ifport = ifport->next;
1245 interface = interface->next;
1248 /* close unused mISDNports */
1250 mISDNport = mISDNport_first;
1253 if (mISDNport->ifport == NULL)
1255 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1256 /* remove all port objects and destroy port */
1257 mISDNport_close(mISDNport);
1260 mISDNport = mISDNport->next;
1263 /* open and link new mISDNports */
1264 interface = interface_newlist;
1267 ifport = interface->ifport;
1270 if (!ifport->mISDNport)
1274 ifport = ifport->next;
1276 interface = interface->next;
1285 void load_port(struct interface_port *ifport)
1287 struct mISDNport *mISDNport;
1290 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->nt, ifport->l2hold, ifport->interface);
1294 ifport->mISDNport = mISDNport;
1295 mISDNport->ifport = ifport;
1296 set_defaults(ifport);
1299 ifport->block = 2; /* not available */
1304 * give summary of interface syntax
1306 void doc_interface(void)
1308 struct interface_param *ifparam;
1310 printf("Syntax overview\n");
1311 printf("---------------\n\n");
1313 printf("[<name>]\n");
1314 ifparam = interface_param;
1315 while(ifparam->name)
1317 printf("%s %s\n", ifparam->name, ifparam->usage);
1321 ifparam = interface_param;
1322 while(ifparam->name)
1324 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1325 printf("%s\n", ifparam->help);
1332 * out==0: incoming caller id, out==1: outgoing caller id
1334 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1337 struct interface_msn *ifmsn;
1338 struct interface_screen *ifscreen;
1341 /* screen incoming caller id */
1344 /* check for MSN numbers, use first MSN if no match */
1346 ifmsn = interface->ifmsn;
1351 if (!strcmp(ifmsn->msn, id))
1355 ifmsn = ifmsn->next;
1359 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1360 add_trace("msn", NULL, "%s", id);
1363 if (!ifmsn && msn1) // not in list, first msn given
1365 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1366 add_trace("msn", "given", "%s", id);
1367 add_trace("msn", "used", "%s", msn1);
1369 UNCPY(id, msn1, idsize);
1370 id[idsize-1] = '\0';
1374 /* check screen list */
1376 ifscreen = interface->ifscreen_out;
1378 ifscreen = interface->ifscreen_in;
1381 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1382 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1384 if (strchr(ifscreen->match,'%'))
1386 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1390 if (!strcmp(ifscreen->match, id))
1394 ifscreen = ifscreen->next;
1396 if (ifscreen) // match
1398 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1401 case INFO_NTYPE_UNKNOWN:
1402 add_trace("given", "type", "unknown");
1404 case INFO_NTYPE_SUBSCRIBER:
1405 add_trace("given", "type", "subscriber");
1407 case INFO_NTYPE_NATIONAL:
1408 add_trace("given", "type", "national");
1410 case INFO_NTYPE_INTERNATIONAL:
1411 add_trace("given", "type", "international");
1416 case INFO_PRESENT_ALLOWED:
1417 add_trace("given", "present", "allowed");
1419 case INFO_PRESENT_RESTRICTED:
1420 add_trace("given", "present", "restricted");
1422 case INFO_PRESENT_NOTAVAIL:
1423 add_trace("given", "present", "not available");
1426 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1427 if (ifscreen->result_type != -1)
1429 *type = ifscreen->result_type;
1432 case INFO_NTYPE_UNKNOWN:
1433 add_trace("used", "type", "unknown");
1435 case INFO_NTYPE_SUBSCRIBER:
1436 add_trace("used", "type", "subscriber");
1438 case INFO_NTYPE_NATIONAL:
1439 add_trace("used", "type", "national");
1441 case INFO_NTYPE_INTERNATIONAL:
1442 add_trace("used", "type", "international");
1446 if (ifscreen->result_present != -1)
1448 *present = ifscreen->result_present;
1451 case INFO_PRESENT_ALLOWED:
1452 add_trace("used", "present", "allowed");
1454 case INFO_PRESENT_RESTRICTED:
1455 add_trace("used", "present", "restricted");
1457 case INFO_PRESENT_NOTAVAIL:
1458 add_trace("used", "present", "not available");
1462 if (strchr(ifscreen->match,'%'))
1464 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1465 UNCPY(id, ifscreen->result, idsize);
1466 id[idsize-1] = '\0';
1469 *strchr(id,'%') = '\0';
1470 UNCAT(id, suffix, idsize);
1471 id[idsize-1] = '\0';
1475 UNCPY(id, ifscreen->result, idsize);
1476 id[idsize-1] = '\0';
1478 add_trace("used", "id", "%s", id[0]?id:"<empty>");