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_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
213 if (!strcasecmp(value, "yes"))
215 interface->is_tones = IS_YES;
217 if (!strcasecmp(value, "no"))
219 interface->is_tones = IS_NO;
222 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
227 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
229 if (!strcasecmp(value, "yes"))
231 interface->is_earlyb = IS_YES;
233 if (!strcasecmp(value, "no"))
235 interface->is_earlyb = IS_NO;
238 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
243 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
245 if (!strcasecmp(value, "linear"))
247 interface->hunt = HUNT_LINEAR;
249 if (!strcasecmp(value, "roundrobin"))
251 interface->hunt = HUNT_ROUNDROBIN;
254 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
259 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
261 struct interface_port *ifport, **ifportp;
262 struct interface *searchif;
265 val = get_number(value);
268 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
271 /* check for port already assigned */
272 searchif = interface_newlist;
275 ifport = searchif->ifport;
278 if (ifport->portnum == val)
280 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
283 ifport = ifport->next;
285 searchif = searchif->next;
287 /* alloc port substructure */
288 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
290 ifport->interface = interface;
292 ifport->portnum = val;
294 ifportp = &interface->ifport;
296 ifportp = &((*ifportp)->next);
300 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
302 struct interface_port *ifport;
304 /* port in chain ? */
305 if (!interface->ifport)
307 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
310 /* goto end of chain */
311 ifport = interface->ifport;
313 ifport = ifport->next;
314 if (!strcmp(value, "yes"))
318 if (!strcmp(value, "no"))
323 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
328 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
330 struct interface_port *ifport;
331 struct select_channel *selchannel, **selchannelp;
335 /* port in chain ? */
336 if (!interface->ifport)
338 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
341 /* goto end of chain */
342 ifport = interface->ifport;
344 ifport = ifport->next;
349 p = get_seperated(p);
350 if (!strcasecmp(el, "force"))
352 ifport->channel_force = 1;
353 if (ifport->out_channel)
355 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
359 if (!strcasecmp(el, "any"))
364 if (!strcasecmp(el, "free"))
369 if (!strcasecmp(el, "no"))
375 val = get_number(el);
378 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);
382 if (val<1 || val==16 || val>126)
384 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
388 /* add to select-channel list */
389 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
392 selchannel->channel = val;
394 selchannelp = &ifport->out_channel;
396 selchannelp = &((*selchannelp)->next);
397 *selchannelp = selchannel;
402 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
404 struct interface_port *ifport;
405 struct select_channel *selchannel, **selchannelp;
409 /* port in chain ? */
410 if (!interface->ifport)
412 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
415 /* goto end of chain */
416 ifport = interface->ifport;
418 ifport = ifport->next;
423 p = get_seperated(p);
424 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
426 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
429 if (!strcasecmp(el, "free"))
435 val = get_number(el);
438 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
442 if (val<1 || val==16 || val>126)
444 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
448 /* add to select-channel list */
449 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
452 selchannel->channel = val;
454 selchannelp = &ifport->in_channel;
456 selchannelp = &((*selchannelp)->next);
457 *selchannelp = selchannel;
462 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
464 struct interface_port *ifport;
465 // struct select_channel *selchannel, **selchannelp;
469 /* port in chain ? */
470 if (!interface->ifport)
472 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
475 /* goto end of chain */
476 ifport = interface->ifport;
478 ifport = ifport->next;
483 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
487 p = get_seperated(p);
488 ifport->tout_setup = atoi(el);
492 p = get_seperated(p);
493 ifport->tout_dialing = atoi(el);
497 p = get_seperated(p);
498 ifport->tout_proceeding = atoi(el);
502 p = get_seperated(p);
503 ifport->tout_alerting = atoi(el);
507 p = get_seperated(p);
508 ifport->tout_disconnect = atoi(el);
511 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
513 struct interface_msn *ifmsn, **ifmsnp;
518 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
521 if (interface->ifscreen_in)
523 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
532 p = get_seperated(p);
533 /* add MSN to list */
534 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
537 SCPY(ifmsn->msn, el);
539 ifmsnp = &interface->ifmsn;
541 ifmsnp = &((*ifmsnp)->next);
546 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
548 struct interface_screen *ifscreen;
553 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
556 /* add screen entry to list*/
557 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
559 ifscreen->match_type = -1; /* unchecked */
560 ifscreen->match_present = -1; /* unchecked */
561 ifscreen->result_type = -1; /* unchanged */
562 ifscreen->result_present = -1; /* unchanged */
565 ifscreenp = &((*ifscreenp)->next);
566 *ifscreenp = ifscreen;
567 // printf("interface=%s\n", interface->name);
573 p = get_seperated(p);
574 if (!strcasecmp(el, "unknown"))
576 if (ifscreen->match_type != -1)
579 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
582 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
584 if (!strcasecmp(el, "subscriber"))
586 if (ifscreen->match_type != -1)
588 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
590 if (!strcasecmp(el, "national"))
592 if (ifscreen->match_type != -1)
594 ifscreen->match_type = INFO_NTYPE_NATIONAL;
596 if (!strcasecmp(el, "international"))
598 if (ifscreen->match_type != -1)
600 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
602 if (!strcasecmp(el, "allowed"))
604 if (ifscreen->match_present != -1)
607 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
610 ifscreen->match_present = INFO_PRESENT_ALLOWED;
612 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
614 if (ifscreen->match_present != -1)
616 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
618 SCPY(ifscreen->match, el);
619 /* check for % at the end */
622 if (strchr(el, '%') != el+strlen(el)-1)
624 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
631 if (ifscreen->match[0] == '\0')
633 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
640 p = get_seperated(p);
641 if (!strcasecmp(el, "unknown"))
643 if (ifscreen->result_type != -1)
645 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
647 if (!strcasecmp(el, "subscriber"))
649 if (ifscreen->result_type != -1)
651 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
653 if (!strcasecmp(el, "national"))
655 if (ifscreen->result_type != -1)
657 ifscreen->result_type = INFO_NTYPE_NATIONAL;
659 if (!strcasecmp(el, "international"))
661 if (ifscreen->result_type != -1)
663 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
665 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
667 if (ifscreen->result_present != -1)
669 ifscreen->result_present = INFO_PRESENT_ALLOWED;
671 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
673 if (ifscreen->result_present != -1)
675 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
677 SCPY(ifscreen->result, el);
678 /* check for % at the end */
681 if (strchr(el, '%') != el+strlen(el)-1)
683 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
690 if (ifscreen->result[0] == '\0')
692 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
697 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
699 if (interface->ifmsn)
701 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
705 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
707 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
709 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
711 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
713 struct interface_port *ifport;
715 /* port in chain ? */
716 if (!interface->ifport)
718 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
721 /* goto end of chain */
722 ifport = interface->ifport;
724 ifport = ifport->next;
728 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
732 /* seperate parameter from filter */
739 while(*p > 0 && *p <= 32)
743 if (!strcasecmp(value, "gain"))
751 while(*q > 0 && *q <= 32)
754 if (*p == 0 || *q == 0)
756 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
759 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
761 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
764 interface->tx_gain = atoi(p);
765 interface->rx_gain = atoi(q);
767 if (!strcasecmp(value, "pipeline"))
771 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
774 SCPY(interface->pipeline, p);
776 if (!strcasecmp(value, "blowfish"))
778 unsigned char key[56];
781 if (!!strncmp(p, "0x", 2))
783 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
792 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
795 if (*p >= '0' && *p <= '9')
796 key[l] = (*p-'0')<<4;
797 else if (*p >= 'a' && *p <= 'f')
798 key[l] = (*p-'a'+10)<<4;
799 else if (*p >= 'A' && *p <= 'F')
800 key[l] = (*p-'A'+10)<<4;
804 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);
810 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);
813 if (*p >= '0' && *p <= '9')
814 key[l] = (*p-'0')<<4;
815 else if (*p >= 'a' && *p <= 'f')
816 key[l] = (*p-'a'+10)<<4;
817 else if (*p >= 'A' && *p <= 'F')
818 key[l] = (*p-'A'+10)<<4;
826 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);
829 memcpy(interface->bf_key, key, l);
830 interface->bf_len = l;
833 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
841 * structure of parameters
843 struct interface_param interface_param[] = {
844 { "extension", &inter_extension, "",
845 "If keyword is given, calls to interface are handled as internal extensions."},
846 {"tones", &inter_tones, "yes | no",
847 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
849 {"earlyb", &inter_earlyb, "yes | no",
850 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
852 {"hunt", &inter_hunt, "linear | roundrobin",
853 "Select the algorithm for selecting port with free channel."},
855 {"port", &inter_port, "<number>",
856 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
858 {"block", &inter_block, "",
859 "If keyword is given, calls on this interface are blocked.\n"
860 "This parameter must follow a 'port' parameter."},
862 {"ptp", &inter_ptp, "",
863 "The given port above is opened as point-to-point.\n"
864 "This is required on NT-mode ports that are multipoint by default.\n"
865 "This parameter must follow a 'port' parameter."},
868 {"ptmp", &inter_ptmp, "",
869 "The given port above is opened as point-to-multipoint.\n"
870 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
871 "This parameter must follow a 'port' parameter."},
874 {"nt", &inter_nt, "",
875 "The given port above is opened in NT-mode.\n"
876 "This is required on interfaces that support both NT-mode and TE-mode.\n"
877 "This parameter must follow a 'port' parameter."},
879 {"layer2hold", &inter_l2hold, "yes | no",
880 "The given port will continuously try to establish layer 2 link and hold it.\n"
881 "It is required for PTP links in most cases, therefore it is default.\n"
882 "This parameter must follow a 'port' parameter."},
884 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
885 "Channel selection list for all outgoing calls to the interface.\n"
886 "A free channels is searched in order of appearance.\n"
887 "This parameter must follow a 'port' parameter.\n"
888 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
889 " <number>[,...] - List of channels to search.\n"
890 " free - Select any free channel\n"
891 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
892 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
894 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
895 "Channel selection list for all incoming calls from the interface.\n"
896 "A free channels is accepted if in the list.\n"
897 "If any channel was requested, the first free channel found is selected.\n"
898 "This parameter must follow a 'port' parameter.\n"
899 " <number>[,...] - List of channels to accept.\n"
900 " free - Accept any free channel"},
902 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
903 "Timeout values for call states. They are both for incoming and outgoing states.\n"
904 "The default is 120 seconds for all states. Use 0 to disable.\n"
905 "This parameter must follow a 'port' parameter.\n"},
907 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
908 "Incoming caller ID is checked against given MSN numbers.\n"
909 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
911 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
912 "Adds an entry for incoming calls to the caller ID screen list.\n"
913 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
914 "If '%' is given after old caller ID, it matches even if caller ID has\n"
915 "additional digits.\n"
916 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
919 " unknown | subsciber | national | international - Change caller ID type.\n"
920 " present | restrict - Change presentation of caller ID."},
922 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
923 "Adds an entry for outgoing calls to the caller ID screen list.\n"
924 "See 'screen-in' for help."},
926 {"nodtmf", &inter_nodtmf, "",
927 "Disables DTMF detection for this interface.\n"
928 "This parameter must follow a 'port' parameter."},
930 {"filter", &inter_filter, "<filter> <parameters>",
931 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
932 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
933 "pipeline <string> - Sets echo cancelation pipeline.\n"
934 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
936 {NULL, NULL, NULL, NULL}
941 * read settings from interface.conf
943 char interface_error[256];
944 struct interface *read_interfaces(void)
949 unsigned int line, i;
951 struct interface *interface = NULL, /* in case no interface */
952 **interfacep = &interface_newlist;
955 int expecting = 1; /* expecting new interface */
956 struct interface_param *ifparam;
958 if (interface_newlist != NULL)
959 FATAL("list is not empty.\n");
960 interface_error[0] = '\0';
961 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
963 if (!(fp = fopen(filename,"r")))
965 SPRINT(interface_error, "Cannot open '%s'\n", filename);
970 while((fgets(buffer,sizeof(buffer),fp)))
972 buffer[sizeof(buffer)-1]=0;
973 if (buffer[0]) buffer[strlen(buffer)-1]=0;
977 while(*p <= 32) /* skip spaces */
983 if (*p==0 || *p=='#') /* ignore comments and empty line */
988 i=0; /* read parameter */
991 if (i+1 >= sizeof(parameter))
993 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
996 parameter[i+1] = '\0';
997 parameter[i++] = *p++;
1000 while(*p <= 32) /* skip spaces */
1007 if (*p!=0 && *p!='#') /* missing name */
1009 i=0; /* read until end */
1010 while(*p!=0 && *p!='#')
1012 if (i+1 >= sizeof(value))
1014 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1021 /* remove trailing spaces from value */
1024 if (value[i-1]==0 || value[i-1]>32)
1031 /* check for interface name as first statement */
1032 if (expecting && parameter[0]!='[')
1034 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1039 /* check for new interface */
1040 if (parameter[0] == '[')
1042 if (parameter[strlen(parameter)-1] != ']')
1044 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1047 parameter[strlen(parameter)-1] = '\0';
1049 /* check if interface name already exists */
1050 interface = interface_newlist;
1053 if (!strcasecmp(interface->name, parameter+1))
1055 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1058 interface = interface->next;
1061 /* append interface to new list */
1062 interface = (struct interface *)MALLOC(sizeof(struct interface));
1065 /* name interface */
1066 SCPY(interface->name, parameter+1);
1069 *interfacep = interface;
1070 interfacep = &interface->next;
1075 ifparam = interface_param;
1076 while(ifparam->name)
1078 if (!strcasecmp(parameter, ifparam->name))
1080 if (ifparam->func(interface, filename, line, parameter, value))
1089 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1094 return(interface_newlist);
1096 PERROR_RUNTIME("%s", interface_error);
1098 free_interfaces(interface_newlist);
1099 interface_newlist = NULL;
1105 * freeing chain of interfaces
1107 void free_interfaces(struct interface *interface)
1110 struct interface_port *ifport;
1111 struct select_channel *selchannel;
1112 struct interface_msn *ifmsn;
1113 struct interface_screen *ifscreen;
1117 ifport = interface->ifport;
1120 selchannel = ifport->in_channel;
1124 selchannel = selchannel->next;
1125 FREE(temp, sizeof(struct select_channel));
1128 selchannel = ifport->out_channel;
1132 selchannel = selchannel->next;
1133 FREE(temp, sizeof(struct select_channel));
1137 ifport = ifport->next;
1138 FREE(temp, sizeof(struct interface_port));
1141 ifmsn = interface->ifmsn;
1145 ifmsn = ifmsn->next;
1146 FREE(temp, sizeof(struct interface_msn));
1149 ifscreen = interface->ifscreen_in;
1153 ifscreen = ifscreen->next;
1154 FREE(temp, sizeof(struct interface_screen));
1157 ifscreen = interface->ifscreen_out;
1161 ifscreen = ifscreen->next;
1162 FREE(temp, sizeof(struct interface_screen));
1166 interface = interface->next;
1167 FREE(temp, sizeof(struct interface));
1173 * defaults of ports if not specified by config
1175 static void set_defaults(struct interface_port *ifport)
1177 /* default channel selection list */
1178 if (!ifport->out_channel)
1179 default_out_channel(ifport);
1180 if (!ifport->in_channel)
1181 default_in_channel(ifport);
1182 /* default is_tones */
1183 if (ifport->interface->is_tones)
1184 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1186 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1187 /* default is_earlyb */
1188 if (ifport->interface->is_earlyb)
1189 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1191 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1192 /* set locally flag */
1193 if (ifport->interface->extension)
1194 ifport->mISDNport->locally = 1;
1196 ifport->mISDNport->locally = 0;
1201 * all links between mISDNport and interface are made
1202 * unused mISDNports are closed, new mISDNports are opened
1203 * also set default select_channel lists
1205 void relink_interfaces(void)
1207 struct mISDNport *mISDNport;
1208 struct interface *interface;
1209 struct interface_port *ifport;
1211 /* unlink all mISDNports */
1212 mISDNport = mISDNport_first;
1215 mISDNport->ifport = NULL;
1216 mISDNport = mISDNport->next;
1219 /* relink existing mISDNports */
1220 interface = interface_newlist;
1223 ifport = interface->ifport;
1226 mISDNport = mISDNport_first;
1229 if (mISDNport->portnum == ifport->portnum)
1231 ifport->mISDNport = mISDNport;
1232 mISDNport->ifport = ifport;
1233 set_defaults(ifport);
1235 mISDNport = mISDNport->next;
1237 ifport = ifport->next;
1239 interface = interface->next;
1242 /* close unused mISDNports */
1244 mISDNport = mISDNport_first;
1247 if (mISDNport->ifport == NULL)
1249 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1250 /* remove all port objects and destroy port */
1251 mISDNport_close(mISDNport);
1254 mISDNport = mISDNport->next;
1257 /* open and link new mISDNports */
1258 interface = interface_newlist;
1261 ifport = interface->ifport;
1264 if (!ifport->mISDNport)
1268 ifport = ifport->next;
1270 interface = interface->next;
1279 void load_port(struct interface_port *ifport)
1281 struct mISDNport *mISDNport;
1284 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->nt, ifport->l2hold, ifport->interface);
1288 ifport->mISDNport = mISDNport;
1289 mISDNport->ifport = ifport;
1290 set_defaults(ifport);
1293 ifport->block = 2; /* not available */
1298 * give summary of interface syntax
1300 void doc_interface(void)
1302 struct interface_param *ifparam;
1304 printf("Syntax overview\n");
1305 printf("---------------\n\n");
1307 printf("[<name>]\n");
1308 ifparam = interface_param;
1309 while(ifparam->name)
1311 printf("%s %s\n", ifparam->name, ifparam->usage);
1315 ifparam = interface_param;
1316 while(ifparam->name)
1318 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1319 printf("%s\n", ifparam->help);
1326 * out==0: incoming caller id, out==1: outgoing caller id
1328 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1331 struct interface_msn *ifmsn;
1332 struct interface_screen *ifscreen;
1335 /* screen incoming caller id */
1338 /* check for MSN numbers, use first MSN if no match */
1340 ifmsn = interface->ifmsn;
1345 if (!strcmp(ifmsn->msn, id))
1349 ifmsn = ifmsn->next;
1353 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1354 add_trace("msn", NULL, "%s", id);
1357 if (!ifmsn && msn1) // not in list, first msn given
1359 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1360 add_trace("msn", "given", "%s", id);
1361 add_trace("msn", "used", "%s", msn1);
1363 UNCPY(id, msn1, idsize);
1364 id[idsize-1] = '\0';
1368 /* check screen list */
1370 ifscreen = interface->ifscreen_out;
1372 ifscreen = interface->ifscreen_in;
1375 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1376 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1378 if (strchr(ifscreen->match,'%'))
1380 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1384 if (!strcmp(ifscreen->match, id))
1388 ifscreen = ifscreen->next;
1390 if (ifscreen) // match
1392 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1395 case INFO_NTYPE_UNKNOWN:
1396 add_trace("given", "type", "unknown");
1398 case INFO_NTYPE_SUBSCRIBER:
1399 add_trace("given", "type", "subscriber");
1401 case INFO_NTYPE_NATIONAL:
1402 add_trace("given", "type", "national");
1404 case INFO_NTYPE_INTERNATIONAL:
1405 add_trace("given", "type", "international");
1410 case INFO_PRESENT_ALLOWED:
1411 add_trace("given", "present", "allowed");
1413 case INFO_PRESENT_RESTRICTED:
1414 add_trace("given", "present", "restricted");
1416 case INFO_PRESENT_NOTAVAIL:
1417 add_trace("given", "present", "not available");
1420 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1421 if (ifscreen->result_type != -1)
1423 *type = ifscreen->result_type;
1426 case INFO_NTYPE_UNKNOWN:
1427 add_trace("used", "type", "unknown");
1429 case INFO_NTYPE_SUBSCRIBER:
1430 add_trace("used", "type", "subscriber");
1432 case INFO_NTYPE_NATIONAL:
1433 add_trace("used", "type", "national");
1435 case INFO_NTYPE_INTERNATIONAL:
1436 add_trace("used", "type", "international");
1440 if (ifscreen->result_present != -1)
1442 *present = ifscreen->result_present;
1445 case INFO_PRESENT_ALLOWED:
1446 add_trace("used", "present", "allowed");
1448 case INFO_PRESENT_RESTRICTED:
1449 add_trace("used", "present", "restricted");
1451 case INFO_PRESENT_NOTAVAIL:
1452 add_trace("used", "present", "not available");
1456 if (strchr(ifscreen->match,'%'))
1458 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1459 UNCPY(id, ifscreen->result, idsize);
1460 id[idsize-1] = '\0';
1463 *strchr(id,'%') = '\0';
1464 UNCAT(id, suffix, idsize);
1465 id[idsize-1] = '\0';
1469 UNCPY(id, ifscreen->result, idsize);
1470 id[idsize-1] = '\0';
1472 add_trace("used", "id", "%s", id[0]?id:"<empty>");