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);
158 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
160 struct interface_port *ifport;
162 /* port in chain ? */
163 if (!interface->ifport)
165 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
168 if (interface->ifport->ptp)
170 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
173 /* goto end of chain */
174 ifport = interface->ifport;
176 ifport = ifport->next;
180 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
186 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
189 struct interface_port *ifport;
191 /* port in chain ? */
192 if (!interface->ifport)
194 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
197 /* goto end of chain */
198 ifport = interface->ifport;
200 ifport = ifport->next;
204 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_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
302 struct interface_port *ifport;
303 struct select_channel *selchannel, **selchannelp;
307 /* port in chain ? */
308 if (!interface->ifport)
310 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
313 /* goto end of chain */
314 ifport = interface->ifport;
316 ifport = ifport->next;
321 p = get_seperated(p);
322 if (!strcasecmp(el, "force"))
324 ifport->channel_force = 1;
325 if (ifport->out_channel)
327 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
331 if (!strcasecmp(el, "any"))
336 if (!strcasecmp(el, "free"))
341 if (!strcasecmp(el, "no"))
347 val = get_number(el);
350 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);
354 if (val<1 || val==16 || val>126)
356 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
360 /* add to select-channel list */
361 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
364 selchannel->channel = val;
366 selchannelp = &ifport->out_channel;
368 selchannelp = &((*selchannelp)->next);
369 *selchannelp = selchannel;
374 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
376 struct interface_port *ifport;
377 struct select_channel *selchannel, **selchannelp;
381 /* port in chain ? */
382 if (!interface->ifport)
384 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
387 /* goto end of chain */
388 ifport = interface->ifport;
390 ifport = ifport->next;
395 p = get_seperated(p);
396 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
398 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
401 if (!strcasecmp(el, "free"))
407 val = get_number(el);
410 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
414 if (val<1 || val==16 || val>126)
416 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
420 /* add to select-channel list */
421 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
424 selchannel->channel = val;
426 selchannelp = &ifport->in_channel;
428 selchannelp = &((*selchannelp)->next);
429 *selchannelp = selchannel;
434 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
436 struct interface_port *ifport;
437 // struct select_channel *selchannel, **selchannelp;
441 /* port in chain ? */
442 if (!interface->ifport)
444 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
447 /* goto end of chain */
448 ifport = interface->ifport;
450 ifport = ifport->next;
455 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
459 p = get_seperated(p);
460 ifport->tout_setup = atoi(el);
464 p = get_seperated(p);
465 ifport->tout_dialing = atoi(el);
469 p = get_seperated(p);
470 ifport->tout_proceeding = atoi(el);
474 p = get_seperated(p);
475 ifport->tout_alerting = atoi(el);
479 p = get_seperated(p);
480 ifport->tout_disconnect = atoi(el);
483 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
485 struct interface_msn *ifmsn, **ifmsnp;
490 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
493 if (interface->ifscreen_in)
495 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
504 p = get_seperated(p);
505 /* add MSN to list */
506 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
509 SCPY(ifmsn->msn, el);
511 ifmsnp = &interface->ifmsn;
513 ifmsnp = &((*ifmsnp)->next);
518 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
520 struct interface_screen *ifscreen;
525 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
528 /* add screen entry to list*/
529 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
531 ifscreen->match_type = -1; /* unchecked */
532 ifscreen->match_present = -1; /* unchecked */
533 ifscreen->result_type = -1; /* unchanged */
534 ifscreen->result_present = -1; /* unchanged */
537 ifscreenp = &((*ifscreenp)->next);
538 *ifscreenp = ifscreen;
539 // printf("interface=%s\n", interface->name);
545 p = get_seperated(p);
546 if (!strcasecmp(el, "unknown"))
548 if (ifscreen->match_type != -1)
551 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
554 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
556 if (!strcasecmp(el, "subscriber"))
558 if (ifscreen->match_type != -1)
560 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
562 if (!strcasecmp(el, "national"))
564 if (ifscreen->match_type != -1)
566 ifscreen->match_type = INFO_NTYPE_NATIONAL;
568 if (!strcasecmp(el, "international"))
570 if (ifscreen->match_type != -1)
572 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
574 if (!strcasecmp(el, "allowed"))
576 if (ifscreen->match_present != -1)
579 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
582 ifscreen->match_present = INFO_PRESENT_ALLOWED;
584 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
586 if (ifscreen->match_present != -1)
588 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
590 SCPY(ifscreen->match, el);
591 /* check for % at the end */
594 if (strchr(el, '%') != el+strlen(el)-1)
596 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
603 if (ifscreen->match[0] == '\0')
605 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
612 p = get_seperated(p);
613 if (!strcasecmp(el, "unknown"))
615 if (ifscreen->result_type != -1)
617 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
619 if (!strcasecmp(el, "subscriber"))
621 if (ifscreen->result_type != -1)
623 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
625 if (!strcasecmp(el, "national"))
627 if (ifscreen->result_type != -1)
629 ifscreen->result_type = INFO_NTYPE_NATIONAL;
631 if (!strcasecmp(el, "international"))
633 if (ifscreen->result_type != -1)
635 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
637 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
639 if (ifscreen->result_present != -1)
641 ifscreen->result_present = INFO_PRESENT_ALLOWED;
643 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
645 if (ifscreen->result_present != -1)
647 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
649 SCPY(ifscreen->result, el);
650 /* check for % at the end */
653 if (strchr(el, '%') != el+strlen(el)-1)
655 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
662 if (ifscreen->result[0] == '\0')
664 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
669 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
671 if (interface->ifmsn)
673 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
677 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
679 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
681 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
683 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
685 struct interface_port *ifport;
687 /* port in chain ? */
688 if (!interface->ifport)
690 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
693 /* goto end of chain */
694 ifport = interface->ifport;
696 ifport = ifport->next;
700 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
704 /* seperate parameter from filter */
711 while(*p > 0 && *p <= 32)
715 if (!strcasecmp(value, "gain"))
723 while(*q > 0 && *q <= 32)
726 if (*p == 0 || *q == 0)
728 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
731 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
733 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
736 interface->tx_gain = atoi(p);
737 interface->rx_gain = atoi(q);
739 if (!strcasecmp(value, "pipeline"))
743 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
746 SCPY(interface->pipeline, p);
748 if (!strcasecmp(value, "blowfish"))
750 unsigned char key[56];
753 if (!!strncmp(p, "0x", 2))
755 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
764 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
767 if (*p >= '0' && *p <= '9')
768 key[l] = (*p-'0')<<4;
769 else if (*p >= 'a' && *p <= 'f')
770 key[l] = (*p-'a'+10)<<4;
771 else if (*p >= 'A' && *p <= 'F')
772 key[l] = (*p-'A'+10)<<4;
776 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);
782 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);
785 if (*p >= '0' && *p <= '9')
786 key[l] = (*p-'0')<<4;
787 else if (*p >= 'a' && *p <= 'f')
788 key[l] = (*p-'a'+10)<<4;
789 else if (*p >= 'A' && *p <= 'F')
790 key[l] = (*p-'A'+10)<<4;
798 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);
801 memcpy(interface->bf_key, key, l);
802 interface->bf_len = l;
805 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
813 * structure of parameters
815 struct interface_param interface_param[] = {
816 { "extension", &inter_extension, "",
817 "If keyword is given, calls to interface are handled as internal extensions."},
818 {"tones", &inter_tones, "yes | no",
819 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
821 {"earlyb", &inter_earlyb, "yes | no",
822 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
824 {"hunt", &inter_hunt, "linear | roundrobin",
825 "Select the algorithm for selecting port with free channel."},
827 {"port", &inter_port, "<number>",
828 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
830 {"block", &inter_block, "",
831 "If keyword is given, calls on this interface are blocked.\n"
832 "This parameter must follow a 'port' parameter."},
834 {"ptp", &inter_ptp, "",
835 "The given port above is opened as point-to-point.\n"
836 "This is required on NT-mode ports that are multipoint by default.\n"
837 "This parameter must follow a 'port' parameter."},
839 {"ptmp", &inter_ptmp, "",
840 "The given port above is opened as point-to-multipoint.\n"
841 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
842 "This parameter must follow a 'port' parameter."},
843 {"nt", &inter_nt, "",
844 "The given port above is opened in NT-mode.\n"
846 "This is required on interfaces that support both NT-mode and TE-mode.\n"
848 "This parameter is only required for socket based mISDN driver.\n"
850 "This parameter must follow a 'port' parameter."},
852 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
853 "Channel selection list for all outgoing calls to the interface.\n"
854 "A free channels is searched in order of appearance.\n"
855 "This parameter must follow a 'port' parameter.\n"
856 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
857 " <number>[,...] - List of channels to search.\n"
858 " free - Select any free channel\n"
859 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
860 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
862 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
863 "Channel selection list for all incoming calls from the interface.\n"
864 "A free channels is accepted if in the list.\n"
865 "If any channel was requested, the first free channel found is selected.\n"
866 "This parameter must follow a 'port' parameter.\n"
867 " <number>[,...] - List of channels to accept.\n"
868 " free - Accept any free channel"},
870 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
871 "Timeout values for call states. They are both for incoming and outgoing states.\n"
872 "The default is 120 seconds for all states. Use 0 to disable.\n"
873 "This parameter must follow a 'port' parameter.\n"},
875 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
876 "Incoming caller ID is checked against given MSN numbers.\n"
877 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
879 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
880 "Adds an entry for incoming calls to the caller ID screen list.\n"
881 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
882 "If '%' is given after old caller ID, it matches even if caller ID has\n"
883 "additional digits.\n"
884 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
887 " unknown | subsciber | national | international - Change caller ID type.\n"
888 " present | restrict - Change presentation of caller ID."},
890 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
891 "Adds an entry for outgoing calls to the caller ID screen list.\n"
892 "See 'screen-in' for help."},
894 {"nodtmf", &inter_nodtmf, "",
895 "Disables DTMF detection for this interface.\n"
896 "This parameter must follow a 'port' parameter."},
899 {"layer2keep", &inter_layer2keep, "yes | no",
900 "By default, layer 2 is establised and kept up on PTP interfaces.\n"
902 "This parameter must follow a 'port' parameter."},
905 {"filter", &inter_filter, "<filter> <parameters>",
906 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
907 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
908 "pipeline <string> - Sets echo cancelation pipeline.\n"
909 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
911 {NULL, NULL, NULL, NULL}
916 * read settings from interface.conf
918 char interface_error[256];
919 struct interface *read_interfaces(void)
924 unsigned int line, i;
926 struct interface *interface = NULL, /* in case no interface */
927 **interfacep = &interface_newlist;
930 int expecting = 1; /* expecting new interface */
931 struct interface_param *ifparam;
933 if (interface_newlist != NULL)
934 FATAL("list is not empty.\n");
935 interface_error[0] = '\0';
936 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
938 if (!(fp = fopen(filename,"r")))
940 SPRINT(interface_error, "Cannot open '%s'\n", filename);
945 while((fgets(buffer,sizeof(buffer),fp)))
947 buffer[sizeof(buffer)-1]=0;
948 if (buffer[0]) buffer[strlen(buffer)-1]=0;
952 while(*p <= 32) /* skip spaces */
958 if (*p==0 || *p=='#') /* ignore comments and empty line */
963 i=0; /* read parameter */
966 if (i+1 >= sizeof(parameter))
968 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
971 parameter[i+1] = '\0';
972 parameter[i++] = *p++;
975 while(*p <= 32) /* skip spaces */
982 if (*p!=0 && *p!='#') /* missing name */
984 i=0; /* read until end */
985 while(*p!=0 && *p!='#')
987 if (i+1 >= sizeof(value))
989 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
996 /* remove trailing spaces from value */
999 if (value[i-1]==0 || value[i-1]>32)
1006 /* check for interface name as first statement */
1007 if (expecting && parameter[0]!='[')
1009 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1014 /* check for new interface */
1015 if (parameter[0] == '[')
1017 if (parameter[strlen(parameter)-1] != ']')
1019 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1022 parameter[strlen(parameter)-1] = '\0';
1024 /* check if interface name already exists */
1025 interface = interface_newlist;
1028 if (!strcasecmp(interface->name, parameter+1))
1030 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1033 interface = interface->next;
1036 /* append interface to new list */
1037 interface = (struct interface *)MALLOC(sizeof(struct interface));
1040 /* name interface */
1041 SCPY(interface->name, parameter+1);
1044 *interfacep = interface;
1045 interfacep = &interface->next;
1050 ifparam = interface_param;
1051 while(ifparam->name)
1053 if (!strcasecmp(parameter, ifparam->name))
1055 if (ifparam->func(interface, filename, line, parameter, value))
1064 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1069 return(interface_newlist);
1071 PERROR_RUNTIME("%s", interface_error);
1073 free_interfaces(interface_newlist);
1074 interface_newlist = NULL;
1080 * freeing chain of interfaces
1082 void free_interfaces(struct interface *interface)
1085 struct interface_port *ifport;
1086 struct select_channel *selchannel;
1087 struct interface_msn *ifmsn;
1088 struct interface_screen *ifscreen;
1092 ifport = interface->ifport;
1095 selchannel = ifport->in_channel;
1099 selchannel = selchannel->next;
1100 FREE(temp, sizeof(struct select_channel));
1103 selchannel = ifport->out_channel;
1107 selchannel = selchannel->next;
1108 FREE(temp, sizeof(struct select_channel));
1112 ifport = ifport->next;
1113 FREE(temp, sizeof(struct interface_port));
1116 ifmsn = interface->ifmsn;
1120 ifmsn = ifmsn->next;
1121 FREE(temp, sizeof(struct interface_msn));
1124 ifscreen = interface->ifscreen_in;
1128 ifscreen = ifscreen->next;
1129 FREE(temp, sizeof(struct interface_screen));
1132 ifscreen = interface->ifscreen_out;
1136 ifscreen = ifscreen->next;
1137 FREE(temp, sizeof(struct interface_screen));
1141 interface = interface->next;
1142 FREE(temp, sizeof(struct interface));
1148 * defaults of ports if not specified by config
1150 static void set_defaults(struct interface_port *ifport)
1152 /* default channel selection list */
1153 if (!ifport->out_channel)
1154 default_out_channel(ifport);
1155 if (!ifport->in_channel)
1156 default_in_channel(ifport);
1157 /* default is_tones */
1158 if (ifport->interface->is_tones)
1159 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1161 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1162 /* default is_earlyb */
1163 if (ifport->interface->is_earlyb)
1164 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1166 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1167 /* set locally flag */
1168 if (ifport->interface->extension)
1169 ifport->mISDNport->locally = 1;
1171 ifport->mISDNport->locally = 0;
1176 * all links between mISDNport and interface are made
1177 * unused mISDNports are closed, new mISDNports are opened
1178 * also set default select_channel lists
1180 void relink_interfaces(void)
1182 struct mISDNport *mISDNport;
1183 struct interface *interface;
1184 struct interface_port *ifport;
1186 /* unlink all mISDNports */
1187 mISDNport = mISDNport_first;
1190 mISDNport->ifport = NULL;
1191 mISDNport = mISDNport->next;
1194 /* relink existing mISDNports */
1195 interface = interface_newlist;
1198 ifport = interface->ifport;
1201 mISDNport = mISDNport_first;
1204 if (mISDNport->portnum == ifport->portnum)
1206 ifport->mISDNport = mISDNport;
1207 mISDNport->ifport = ifport;
1208 set_defaults(ifport);
1210 mISDNport = mISDNport->next;
1212 ifport = ifport->next;
1214 interface = interface->next;
1217 /* close unused mISDNports */
1219 mISDNport = mISDNport_first;
1222 if (mISDNport->ifport == NULL)
1224 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1225 /* remove all port objects and destroy port */
1226 mISDNport_close(mISDNport);
1229 mISDNport = mISDNport->next;
1232 /* open and link new mISDNports */
1233 interface = interface_newlist;
1236 ifport = interface->ifport;
1239 if (!ifport->mISDNport)
1243 ifport = ifport->next;
1245 interface = interface->next;
1254 void load_port(struct interface_port *ifport)
1256 struct mISDNport *mISDNport;
1259 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
1263 ifport->mISDNport = mISDNport;
1264 mISDNport->ifport = ifport;
1265 set_defaults(ifport);
1268 ifport->block = 2; /* not available */
1273 * give summary of interface syntax
1275 void doc_interface(void)
1277 struct interface_param *ifparam;
1279 printf("Syntax overview\n");
1280 printf("---------------\n\n");
1282 printf("[<name>]\n");
1283 ifparam = interface_param;
1284 while(ifparam->name)
1286 printf("%s %s\n", ifparam->name, ifparam->usage);
1290 ifparam = interface_param;
1291 while(ifparam->name)
1293 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1294 printf("%s\n", ifparam->help);
1301 * out==0: incoming caller id, out==1: outgoing caller id
1303 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1306 struct interface_msn *ifmsn;
1307 struct interface_screen *ifscreen;
1310 /* screen incoming caller id */
1313 /* check for MSN numbers, use first MSN if no match */
1315 ifmsn = interface->ifmsn;
1320 if (!strcmp(ifmsn->msn, id))
1324 ifmsn = ifmsn->next;
1328 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1329 add_trace("msn", NULL, "%s", id);
1332 if (!ifmsn && msn1) // not in list, first msn given
1334 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1335 add_trace("msn", "given", "%s", id);
1336 add_trace("msn", "used", "%s", msn1);
1338 UNCPY(id, msn1, idsize);
1339 id[idsize-1] = '\0';
1343 /* check screen list */
1345 ifscreen = interface->ifscreen_out;
1347 ifscreen = interface->ifscreen_in;
1350 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1351 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1353 if (strchr(ifscreen->match,'%'))
1355 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1359 if (!strcmp(ifscreen->match, id))
1363 ifscreen = ifscreen->next;
1365 if (ifscreen) // match
1367 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1370 case INFO_NTYPE_UNKNOWN:
1371 add_trace("given", "type", "unknown");
1373 case INFO_NTYPE_SUBSCRIBER:
1374 add_trace("given", "type", "subscriber");
1376 case INFO_NTYPE_NATIONAL:
1377 add_trace("given", "type", "national");
1379 case INFO_NTYPE_INTERNATIONAL:
1380 add_trace("given", "type", "international");
1385 case INFO_PRESENT_ALLOWED:
1386 add_trace("given", "present", "allowed");
1388 case INFO_PRESENT_RESTRICTED:
1389 add_trace("given", "present", "restricted");
1391 case INFO_PRESENT_NOTAVAIL:
1392 add_trace("given", "present", "not available");
1395 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1396 if (ifscreen->result_type != -1)
1398 *type = ifscreen->result_type;
1401 case INFO_NTYPE_UNKNOWN:
1402 add_trace("used", "type", "unknown");
1404 case INFO_NTYPE_SUBSCRIBER:
1405 add_trace("used", "type", "subscriber");
1407 case INFO_NTYPE_NATIONAL:
1408 add_trace("used", "type", "national");
1410 case INFO_NTYPE_INTERNATIONAL:
1411 add_trace("used", "type", "international");
1415 if (ifscreen->result_present != -1)
1417 *present = ifscreen->result_present;
1420 case INFO_PRESENT_ALLOWED:
1421 add_trace("used", "present", "allowed");
1423 case INFO_PRESENT_RESTRICTED:
1424 add_trace("used", "present", "restricted");
1426 case INFO_PRESENT_NOTAVAIL:
1427 add_trace("used", "present", "not available");
1431 if (strchr(ifscreen->match,'%'))
1433 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1434 UNCPY(id, ifscreen->result, idsize);
1435 id[idsize-1] = '\0';
1438 *strchr(id,'%') = '\0';
1439 UNCAT(id, suffix, idsize);
1440 id[idsize-1] = '\0';
1444 UNCPY(id, ifscreen->result, idsize);
1445 id[idsize-1] = '\0';
1447 add_trace("used", "id", "%s", id[0]?id:"<empty>");