1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** reading interface.conf file and filling structure **
10 \*****************************************************************************/
17 struct interface *interface_first = NULL; /* first interface is current list */
18 struct interface *interface_newlist = NULL; /* first interface in new list */
21 /* set default selchannel */
22 void default_selchannel(struct interface_port *ifport)
24 struct select_channel *selchannel, **selchannelp;
26 /* channel selection for TE-ports */
27 if (!ifport->mISDNport->ntmode)
29 selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
36 memset(*selchannelp, 0, sizeof(struct select_channel));
37 *selchannelp->channel = SEL_CHANNEL_ANY;
38 selchannelp = &ifport->selchannel;
40 selchannelp = &((*selchannelp)->next);
41 *selchannelp = selchannel;
45 /* channel selection for NT-ports */
46 selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
53 memset(*selchannelp, 0, sizeof(struct select_channel));
54 *selchannelp->channel = SEL_CHANNEL_FREE;
55 selchannelp = &ifport->selchannel;
57 selchannelp = &((*selchannelp)->next);
58 *selchannelp = selchannel;
60 /* additional channel selection for multipoint ports */
61 if (!ifport->mISDNport->ptp)
63 selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
70 memset(*selchannelp, 0, sizeof(struct select_channel));
71 *selchannelp->channel = SEL_CHANNEL_NO; // call waiting
72 selchannelp = &ifport->selchannel;
74 selchannelp = &((*selchannelp)->next);
75 *selchannelp = selchannel;
80 /* parse string for a positive number */
81 static int get_number(char *value)
88 SPRINT(text, "%d", val);
90 if (!strcmp(value, text))
97 /* remove element from buffer
98 * and return pointer to next element in buffer */
99 static char *get_seperated(char *buffer)
103 if (*buffer==',' || *buffer<=32) /* seperate */
106 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
116 * parameter processing
118 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
120 struct interface_port *ifport;
122 /* port in chain ? */
123 if (!interface->ifport)
125 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
128 /* goto end of chain */
129 ifport = interface->ifport;
131 ifport = ifport->next;
135 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
141 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
145 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
148 interface->extension = 1;
151 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
153 struct interface_port *ifport;
155 /* port in chain ? */
156 if (!interface->ifport)
158 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
161 /* goto end of chain */
162 ifport = interface->ifport;
164 ifport = ifport->next;
168 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
174 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
176 if (!strcasecmp(value, "yes"))
178 interface->is_tones = IS_YES;
180 if (!strcasecmp(value, "no"))
182 interface->is_tones = IS_NO;
185 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
190 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
192 if (!strcasecmp(value, "yes"))
194 interface->is_earlyb = IS_YES;
196 if (!strcasecmp(value, "no"))
198 interface->is_earlyb = IS_NO;
201 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
206 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
208 if (!strcasecmp(value, "linear"))
210 interface->hunt = HUNT_LINEAR;
212 if (!strcasecmp(value, "roundrobin"))
214 interface->hunt = HUNT_ROUNDROBIN;
217 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
222 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
224 struct interface_port *ifport, **ifportp;
225 struct interface *searchif;
226 struct interface_port *searchport;
229 val = get_number(value);
232 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
235 /* check for port already assigned */
236 searchif = interface_newlist;
239 searchport = searchif->ifport;
242 if (ifport->portnum == val)
244 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
247 ifport = ifport->next;
249 searchif = searchif->next;
251 /* alloc port substructure */
252 ifport = (struct interface_port *)malloc(sizeof(struct interface_port));
255 SPRINT(interface_error, "No memory!");
259 memset(ifport, 0, sizeof(struct interface_port));
260 ifport->interface = interface;
262 ifport->portnum = val;
264 ifportp = &interface->ifport;
266 ifportp = &((*ifportp)->next);
270 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
272 struct interface_port *ifport;
273 struct select_channel *selchannel, **selchannelp;
277 /* port in chain ? */
278 if (!interface->ifport)
280 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
283 /* goto end of chain */
284 ifport = interface->ifport;
286 ifport = ifport->next;
291 p = get_seperated(p);
292 if (!strcasecmp(el, "force"))
294 ifport->channel_force = 1;
295 if (ifport->selchannel)
297 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
301 if (!strcasecmp(el, "any"))
303 val = SEL_CHANNEL_ANY;
306 if (!strcasecmp(el, "free"))
308 val = SEL_CHANNEL_FREE;
311 if (!strcasecmp(el, "no"))
313 val = SEL_CHANNEL_NO;
317 val = get_number(el);
320 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);
324 if (val<1 || val==16 || val>126)
326 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
330 /* add to select-channel list */
331 selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
334 SPRINT(interface_error, "No memory!");
338 memset(selchannel, 0, sizeof(struct select_channel));
340 selchannel->channel = val;
342 selchannelp = &ifport->selchannel;
344 selchannelp = &((*selchannelp)->next);
345 *selchannelp = selchannel;
350 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
352 struct interface_port *ifport;
353 struct select_channel *selchannel, **selchannelp;
357 /* port in chain ? */
358 if (!interface->ifport)
360 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
363 /* goto end of chain */
364 ifport = interface->ifport;
366 ifport = ifport->next;
371 p = get_seperated(p);
372 if (ifport->in_select) if (ifport->in_select->channel == SEL_CHANNEL_FREE)
374 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
377 if (!strcasecmp(el, "free"))
379 val = SEL_CHANNEL_FREE;
383 val = get_number(el);
386 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
390 if (val<1 || val==16 || val>126)
392 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
396 /* add to select-channel list */
397 selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
400 SPRINT(interface_error, "No memory!");
404 memset(selchannel, 0, sizeof(struct select_channel));
406 selchannel->channel = val;
408 selchannelp = &ifport->in_select;
410 selchannelp = &((*selchannelp)->next);
411 *selchannelp = selchannel;
416 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
418 struct interface_msn *ifmsn, **ifmsnp;
423 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
426 if (interface->ifscreen_in)
428 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
437 p = get_seperated(p);
438 /* add MSN to list */
439 ifmsn = (struct interface_msn *)malloc(sizeof(struct interface_msn));
442 SPRINT(interface_error, "No memory!");
446 memset(ifmsn, 0, sizeof(struct interface_msn));
448 SCPY(ifmsn->msn, el);
450 ifmsnp = &interface->ifmsn;
452 ifmsnp = &((*ifmsnp)->next);
457 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
459 struct interface_screen *ifscreen;
464 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
469 p = get_seperated(p);
470 /* add screen entry to list*/
471 ifscreen = (struct interface_screen *)malloc(sizeof(struct interface_screen));
474 SPRINT(interface_error, "No memory!");
478 memset(ifscreen, 0, sizeof(struct interface_screen));
479 #warning handle unchanged as unchanged!!
480 ifscreen->result_type = -1; /* unchanged */
481 ifscreen->result_present = -1; /* unchanged */
484 ifscreenp = &((*ifscreenp)->next);
485 *ifscreenp = ifscreen;
490 p = get_seperated(p);
491 if (!strcasecmp(el, "unknown"))
493 if (ifscreen->match_type != -1)
496 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
499 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
501 if (!strcasecmp(el, "subscriber"))
503 if (ifscreen->match_type != -1)
505 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
507 if (!strcasecmp(el, "national"))
509 if (ifscreen->match_type != -1)
511 ifscreen->match_type = INFO_NTYPE_NATIONAL;
513 if (!strcasecmp(el, "international"))
515 if (ifscreen->match_type != -1)
517 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
519 if (!strcasecmp(el, "allowed"))
521 if (ifscreen->match_present != -1)
524 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line, parameter);
527 ifscreen->match_present = INFO_PRESENT_ALLOWED;
529 if (!strcasecmp(el, "restricted"))
531 if (ifscreen->match_present != -1)
533 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
535 SCPY(ifscreen->match, el);
539 if (ifscreen->match[0] == '\0')
541 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
548 p = get_seperated(p);
549 if (!strcasecmp(el, "unknown"))
551 if (ifscreen->result_type != -1)
553 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
555 if (!strcasecmp(el, "subscriber"))
557 if (ifscreen->result_type != -1)
559 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
561 if (!strcasecmp(el, "national"))
563 if (ifscreen->result_type != -1)
565 ifscreen->result_type = INFO_NTYPE_NATIONAL;
567 if (!strcasecmp(el, "international"))
569 if (ifscreen->result_type != -1)
571 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
573 if (!strcasecmp(el, "allowed"))
575 if (ifscreen->result_present != -1)
577 ifscreen->result_present = INFO_PRESENT_ALLOWED;
579 if (!strcasecmp(el, "restricted"))
581 if (ifscreen->result_present != -1)
583 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
585 SCPY(ifscreen->result, el);
589 if (ifscreen->result[0] == '\0')
591 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
596 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
598 if (interface->ifmsn)
600 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
604 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
606 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
608 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
610 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
612 #warning filter to be done
618 * structure of parameters
620 struct interface_param interface_param[] = {
621 { "extension", &inter_extension, "",
622 "If keyword is given, calls to interface are handled as internal extensions."},
623 {"tones", &inter_tones, "yes | no",
624 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode interfaces generate tones."},
626 {"earlyb", &inter_earlyb, "yes | no",
627 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode interfaces receive tones."},
629 {"hunt", &inter_hunt, "linear | roundrobin",
630 "Select the algorithm for selecting port with free channel."},
632 {"port", &inter_port, "<number>",
633 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
635 {"block", &inter_block, "",
636 "If keyword is given, calls on this interface are blocked.\n"
637 "This parameter must follow a 'port' parameter."},
639 {"ptp", &inter_ptp, "",
640 "The given port above is opened as point-to-point.\n"
641 "This is required on NT-mode ports that are multipoint by default.\n"
642 "This parameter must follow a 'port' parameter."},
644 {"channel_out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
645 "Channel selection list for all outgoing calls to the interface.\n"
646 "A free channels is searched in order of appearance.\n"
647 "This parameter must follow a 'port' parameter.\n"
648 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
649 " <number>[,...] - List of channels to search.\n"
650 " free - Select any free channel\n"
651 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
652 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
654 {"channel_in", &inter_channel_in, "[force,][<number>][,...][,free][,any][,no]",
655 "Channel selection list for all incomming calls from the interface.\n"
656 "A free channels is accepted if in the list.\n"
657 "If no channel was requested, the first free channel found is selected.\n"
658 "This parameter must follow a 'port' parameter.\n"
659 " <number>[,...] - List of channels to accept.\n"
660 " free - Accept any free channel\n"
662 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
663 "Incomming caller ID is checked against given MSN numbers.\n"
664 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
666 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%%] [options] <new caller ID>[%%]",
667 "Adds an entry for incomming calls to the caller ID screen list.\n"
668 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
669 "If '%%' is given after old caller ID, it matches even if caller ID has\n"
670 "additional digits.\n"
671 "If '%%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
674 " unknown | subsciber | national | international - Change caller ID type.\n"
675 " present | restrict - Change presentation of caller ID."},
677 {"screen-out", &inter_screen_out, "<old caller ID> <new caller ID> [options]",
678 "Adds an entry for outgoing calls to the caller ID screen list.\n"
679 "See 'screen-in' for help."},
681 {"filter", &inter_filter, "<filter> [parameters]",
682 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
683 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
684 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
686 {NULL, NULL, NULL, NULL}
691 * read settings from interface.conf
693 char interface_error[256];
694 struct interface *read_interfaces(void)
699 unsigned int line, i;
701 struct interface *interface = NULL, /* in case no interface */
702 **interfacep = &interface_newlist;
705 int expecting = 1; /* expecting new interface */
706 struct interface_param *ifparam;
708 if (interface_newlist != NULL)
710 PERROR("software error, list is not empty.\n");
713 interface_error[0] = '\0';
714 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
716 if (!(fp = fopen(filename,"r")))
718 SPRINT(interface_error, "Cannot open '%s'\n", filename);
723 while((fgets(buffer,sizeof(buffer),fp)))
725 buffer[sizeof(buffer)-1]=0;
726 if (buffer[0]) buffer[strlen(buffer)-1]=0;
730 while(*p <= 32) /* skip spaces */
736 if (*p==0 || *p=='#') /* ignore comments and empty line */
741 i=0; /* read parameter */
744 if (i+1 >= sizeof(parameter))
746 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
749 parameter[i+1] = '\0';
750 parameter[i++] = *p++;
753 while(*p <= 32) /* skip spaces */
760 if (*p!=0 && *p!='#') /* missing name */
762 i=0; /* read until end */
763 while(*p!=0 && *p!='#')
765 if (i+1 >= sizeof(value))
767 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
774 /* remove trailing spaces from value */
777 if (value[i-1]==0 || value[i-1]>32)
784 /* check for interface name as first statement */
785 if (expecting && parameter[0]!='[')
787 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
792 /* check for new interface */
793 if (parameter[0] == '[')
795 if (parameter[strlen(parameter)-1] != ']')
797 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
800 parameter[strlen(parameter)-1] = '\0';
802 /* check if interface name already exists */
803 interface = interface_first;
806 if (!strcasecmp(interface->name, parameter+1))
808 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
811 interface = interface->next;
814 /* append interface to new list */
815 interface = (struct interface *)malloc(sizeof(struct interface));
818 SPRINT(interface_error, "No memory!");
822 memset(interface, 0, sizeof(struct interface));
825 SCPY(interface->name, parameter+1);
828 *interfacep = interface;
829 interfacep = &interface->next;
834 ifparam = interface_param;
837 if (!strcasecmp(parameter, ifparam->name))
839 if (ifparam->func(interface, filename, line, parameter, value))
846 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
851 return(interface_newlist);
853 PERROR_RUNTIME("%s", interface_error);
855 free_interfaces(interface_newlist);
856 interface_newlist = NULL;
862 * freeing chain of interfaces
864 void free_interfaces(struct interface *interface)
867 struct interface_port *ifport;
868 struct select_channel *selchannel;
869 struct interface_msn *ifmsn;
870 struct interface_screen *ifscreen;
871 struct interface_filter *iffilter;
875 ifport = interface->ifport;
878 selchannel = ifport->in_channel;
882 selchannel = selchannel->next;
883 memset(temp, 0, sizeof(struct select_channel));
887 selchannel = ifport->out_channel;
891 selchannel = selchannel->next;
892 memset(temp, 0, sizeof(struct select_channel));
897 ifport = ifport->next;
898 memset(temp, 0, sizeof(struct interface_port));
902 ifmsn = interface->ifmsn;
907 memset(temp, 0, sizeof(struct interface_msn));
911 ifscreen = interface->ifscreen_in;
915 ifscreen = ifscreen->next;
916 memset(temp, 0, sizeof(struct interface_screen));
920 ifscreen = interface->ifscreen_out;
924 ifscreen = ifscreen->next;
925 memset(temp, 0, sizeof(struct interface_screen));
929 iffilter = interface->iffilter;
933 iffilter = iffilter->next;
934 memset(temp, 0, sizeof(struct interface_filter));
939 interface = interface->next;
940 memset(temp, 0, sizeof(struct interface));
948 * all links between mISDNport and interface are made
949 * unused mISDNports are closed, new mISDNports are opened
950 * also set default select_channel lists
952 void relink_interfaces(void)
954 struct mISDNport *mISDNport;
955 struct interface *interface;
956 struct interface_port *ifport;
958 /* unlink all mISDNports */
959 mISDNport = mISDNport_first;
962 mISDNport->ifport = NULL;
963 mISDNport = mISDNport->next;
966 /* relink existing mISDNports */
967 interface = interface_newlist;
970 ifport = interface->ifport;
973 mISDNport = mISDNport_first;
976 if (mISDNport->portnum == ifport->portnum)
978 ifport->mISDNport = mISDNport;
979 mISDNport->ifport = ifport;
981 mISDNport = mISDNport->next;
983 ifport = ifport->next;
985 interface = interface->next;
988 /* close unused mISDNports */
990 mISDNport = mISDNport_first;
993 if (mISDNport->ifport == NULL)
995 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
996 /* remove all port objects and destroy port */
997 mISDNport_close(mISDNport);
1000 mISDNport = mISDNport->next;
1003 /* open and link new mISDNports */
1004 interface = interface_newlist;
1007 ifport = interface->ifport;
1010 if (!ifport->mISDNport)
1013 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp);
1016 ifport->mISDNport = mISDNport;
1017 mISDNport->ifport = ifport;
1020 if (ifport->mISDNport && !ifport->selchannel)
1021 default_selchannel(ifport);
1023 interface = interface->next;
1029 * give summary of interface syntax
1031 void doc_interface(void)
1033 struct interface_param *ifparam;
1035 printf("Syntax overview\n");
1036 printf("---------------\n\n");
1038 printf("[<name>]\n");
1039 ifparam = interface_param;
1040 while(ifparam->name)
1042 printf("%s %s\n", ifparam->name, ifparam->usage);
1046 ifparam = interface_param;
1047 while(ifparam->name)
1049 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1050 printf("%s\n", ifparam->help);