1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** reading interface.conf file and filling structure **
10 \*****************************************************************************/
17 struct interface *interface_first = NULL; /* first interface is current list */
18 struct interface *interface_newlist = NULL; /* first interface in new list */
21 /* set default out_channel */
22 void default_out_channel(struct interface_port *ifport)
24 struct select_channel *selchannel, **selchannelp;
26 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
29 if (ifport->mISDNport->ntmode)
30 selchannel->channel = CHANNEL_FREE;
32 selchannel->channel = CHANNEL_ANY;
34 ifport->out_channel = selchannel;
36 /* additional channel selection for multipoint NT ports */
37 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
39 selchannelp = &(selchannel->next);
40 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
42 selchannel->channel = CHANNEL_NO; // call waiting
43 *selchannelp = selchannel;
48 /* set default in_channel */
49 void default_in_channel(struct interface_port *ifport)
51 struct select_channel *selchannel;
53 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
56 selchannel->channel = CHANNEL_FREE;
58 ifport->in_channel = selchannel;
62 /* parse string for a positive number */
63 static int get_number(char *value)
70 SPRINT(text, "%d", val);
72 if (!strcmp(value, text))
79 /* remove element from buffer
80 * and return pointer to next element in buffer */
81 static char *get_seperated(char *buffer)
85 if (*buffer==',' || *buffer<=32) /* seperate */
88 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
98 * parameter processing
100 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
102 struct interface_port *ifport;
104 /* port in chain ? */
105 if (!interface->ifport)
107 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
110 /* goto end of chain */
111 ifport = interface->ifport;
113 ifport = ifport->next;
117 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
123 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
127 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
130 interface->extension = 1;
133 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
135 struct interface_port *ifport;
137 /* port in chain ? */
138 if (!interface->ifport)
140 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
143 if (interface->ifport->ptmp)
145 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
148 /* goto end of chain */
149 ifport = interface->ifport;
151 ifport = ifport->next;
155 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
161 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
163 struct interface_port *ifport;
165 /* port in chain ? */
166 if (!interface->ifport)
168 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
171 if (interface->ifport->ptp)
173 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
176 /* goto end of chain */
177 ifport = interface->ifport;
179 ifport = ifport->next;
183 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
189 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
192 struct interface_port *ifport;
194 /* port in chain ? */
195 if (!interface->ifport)
197 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
200 /* goto end of chain */
201 ifport = interface->ifport;
203 ifport = ifport->next;
207 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
214 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
216 if (!strcasecmp(value, "yes"))
218 interface->is_tones = IS_YES;
220 if (!strcasecmp(value, "no"))
222 interface->is_tones = IS_NO;
225 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
230 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
232 if (!strcasecmp(value, "yes"))
234 interface->is_earlyb = IS_YES;
236 if (!strcasecmp(value, "no"))
238 interface->is_earlyb = IS_NO;
241 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
246 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
248 if (!strcasecmp(value, "linear"))
250 interface->hunt = HUNT_LINEAR;
252 if (!strcasecmp(value, "roundrobin"))
254 interface->hunt = HUNT_ROUNDROBIN;
257 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
262 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
264 struct interface_port *ifport, **ifportp;
265 struct interface *searchif;
268 val = get_number(value);
271 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
274 /* check for port already assigned */
275 searchif = interface_newlist;
278 ifport = searchif->ifport;
281 if (ifport->portnum == val)
283 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
286 ifport = ifport->next;
288 searchif = searchif->next;
290 /* alloc port substructure */
291 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
293 ifport->interface = interface;
295 ifport->portnum = val;
297 ifportp = &interface->ifport;
299 ifportp = &((*ifportp)->next);
303 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
305 struct interface_port *ifport;
306 struct select_channel *selchannel, **selchannelp;
310 /* port in chain ? */
311 if (!interface->ifport)
313 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
316 /* goto end of chain */
317 ifport = interface->ifport;
319 ifport = ifport->next;
324 p = get_seperated(p);
325 if (!strcasecmp(el, "force"))
327 ifport->channel_force = 1;
328 if (ifport->out_channel)
330 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
334 if (!strcasecmp(el, "any"))
339 if (!strcasecmp(el, "free"))
344 if (!strcasecmp(el, "no"))
350 val = get_number(el);
353 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of 'force', 'any', 'free', 'no' and any channel number.\n", filename, line, parameter);
357 if (val<1 || val==16 || val>126)
359 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
363 /* add to select-channel list */
364 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
367 selchannel->channel = val;
369 selchannelp = &ifport->out_channel;
371 selchannelp = &((*selchannelp)->next);
372 *selchannelp = selchannel;
377 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
379 struct interface_port *ifport;
380 struct select_channel *selchannel, **selchannelp;
384 /* port in chain ? */
385 if (!interface->ifport)
387 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
390 /* goto end of chain */
391 ifport = interface->ifport;
393 ifport = ifport->next;
398 p = get_seperated(p);
399 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
401 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
404 if (!strcasecmp(el, "free"))
410 val = get_number(el);
413 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
417 if (val<1 || val==16 || val>126)
419 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
423 /* add to select-channel list */
424 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
427 selchannel->channel = val;
429 selchannelp = &ifport->in_channel;
431 selchannelp = &((*selchannelp)->next);
432 *selchannelp = selchannel;
437 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
439 struct interface_msn *ifmsn, **ifmsnp;
444 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
447 if (interface->ifscreen_in)
449 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
458 p = get_seperated(p);
459 /* add MSN to list */
460 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
463 SCPY(ifmsn->msn, el);
465 ifmsnp = &interface->ifmsn;
467 ifmsnp = &((*ifmsnp)->next);
472 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
474 struct interface_screen *ifscreen;
479 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
482 /* add screen entry to list*/
483 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
485 ifscreen->match_type = -1; /* unchecked */
486 ifscreen->match_present = -1; /* unchecked */
487 ifscreen->result_type = -1; /* unchanged */
488 ifscreen->result_present = -1; /* unchanged */
491 ifscreenp = &((*ifscreenp)->next);
492 *ifscreenp = ifscreen;
493 // printf("interface=%s\n", interface->name);
499 p = get_seperated(p);
500 if (!strcasecmp(el, "unknown"))
502 if (ifscreen->match_type != -1)
505 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
508 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
510 if (!strcasecmp(el, "subscriber"))
512 if (ifscreen->match_type != -1)
514 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
516 if (!strcasecmp(el, "national"))
518 if (ifscreen->match_type != -1)
520 ifscreen->match_type = INFO_NTYPE_NATIONAL;
522 if (!strcasecmp(el, "international"))
524 if (ifscreen->match_type != -1)
526 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
528 if (!strcasecmp(el, "allowed"))
530 if (ifscreen->match_present != -1)
533 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
536 ifscreen->match_present = INFO_PRESENT_ALLOWED;
538 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
540 if (ifscreen->match_present != -1)
542 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
544 SCPY(ifscreen->match, el);
545 /* check for % at the end */
548 if (strchr(el, '%') != el+strlen(el)-1)
550 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
557 if (ifscreen->match[0] == '\0')
559 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
566 p = get_seperated(p);
567 if (!strcasecmp(el, "unknown"))
569 if (ifscreen->result_type != -1)
571 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
573 if (!strcasecmp(el, "subscriber"))
575 if (ifscreen->result_type != -1)
577 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
579 if (!strcasecmp(el, "national"))
581 if (ifscreen->result_type != -1)
583 ifscreen->result_type = INFO_NTYPE_NATIONAL;
585 if (!strcasecmp(el, "international"))
587 if (ifscreen->result_type != -1)
589 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
591 if (!strcasecmp(el, "allowed"))
593 if (ifscreen->result_present != -1)
595 ifscreen->result_present = INFO_PRESENT_ALLOWED;
597 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
599 if (ifscreen->result_present != -1)
601 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
603 SCPY(ifscreen->result, el);
604 /* check for % at the end */
607 if (strchr(el, '%') != el+strlen(el)-1)
609 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
616 if (ifscreen->result[0] == '\0')
618 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
623 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
625 if (interface->ifmsn)
627 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
631 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
633 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
635 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
637 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
639 struct interface_port *ifport;
641 /* port in chain ? */
642 if (!interface->ifport)
644 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
647 /* goto end of chain */
648 ifport = interface->ifport;
650 ifport = ifport->next;
654 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
658 /* seperate parameter from filter */
665 while(*p > 0 && *p <= 32)
669 if (!strcasecmp(value, "gain"))
677 while(*q > 0 && *q <= 32)
680 if (*p == 0 || *q == 0)
682 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
685 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
687 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
690 interface->gain_tx = atoi(p);
691 interface->gain_rx = atoi(q);
693 if (!strcasecmp(value, "pipeline"))
697 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
700 SCPY(interface->pipeline, p);
702 if (!strcasecmp(value, "blowfish"))
704 unsigned char key[56];
707 if (!!strncmp(p, "0x", 2))
709 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
718 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
721 if (*p >= '0' && *p <= '9')
722 key[l] = (*p-'0')<<4;
723 else if (*p >= 'a' && *p <= 'f')
724 key[l] = (*p-'a'+10)<<4;
725 else if (*p >= 'A' && *p <= 'F')
726 key[l] = (*p-'A'+10)<<4;
730 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);
736 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);
739 if (*p >= '0' && *p <= '9')
740 key[l] = (*p-'0')<<4;
741 else if (*p >= 'a' && *p <= 'f')
742 key[l] = (*p-'a'+10)<<4;
743 else if (*p >= 'A' && *p <= 'F')
744 key[l] = (*p-'A'+10)<<4;
752 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);
755 memcpy(interface->bf_key, key, l);
756 interface->bf_len = l;
759 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
767 * structure of parameters
769 struct interface_param interface_param[] = {
770 { "extension", &inter_extension, "",
771 "If keyword is given, calls to interface are handled as internal extensions."},
772 {"tones", &inter_tones, "yes | no",
773 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
775 {"earlyb", &inter_earlyb, "yes | no",
776 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
778 {"hunt", &inter_hunt, "linear | roundrobin",
779 "Select the algorithm for selecting port with free channel."},
781 {"port", &inter_port, "<number>",
782 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
784 {"block", &inter_block, "",
785 "If keyword is given, calls on this interface are blocked.\n"
786 "This parameter must follow a 'port' parameter."},
788 {"ptp", &inter_ptp, "",
789 "The given port above is opened as point-to-point.\n"
790 "This is required on NT-mode ports that are multipoint by default.\n"
791 "This parameter must follow a 'port' parameter."},
793 {"ptmp", &inter_ptmp, "",
794 "The given port above is opened as point-to-multipoint.\n"
795 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
796 "This parameter must follow a 'port' parameter."},
797 {"nt", &inter_nt, "",
798 "The given port above is opened in NT-mode.\n"
800 "This is required on interfaces that support both NT-mode and TE-mode.\n"
802 "This parameter is only required for socket based mISDN driver.\n"
804 "This parameter must follow a 'port' parameter."},
806 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
807 "Channel selection list for all outgoing calls to the interface.\n"
808 "A free channels is searched in order of appearance.\n"
809 "This parameter must follow a 'port' parameter.\n"
810 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
811 " <number>[,...] - List of channels to search.\n"
812 " free - Select any free channel\n"
813 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
814 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
816 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
817 "Channel selection list for all incomming calls from the interface.\n"
818 "A free channels is accepted if in the list.\n"
819 "If any channel was requested, the first free channel found is selected.\n"
820 "This parameter must follow a 'port' parameter.\n"
821 " <number>[,...] - List of channels to accept.\n"
822 " free - Accept any free channel"},
824 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
825 "Incomming caller ID is checked against given MSN numbers.\n"
826 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
828 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
829 "Adds an entry for incomming calls to the caller ID screen list.\n"
830 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
831 "If '%' is given after old caller ID, it matches even if caller ID has\n"
832 "additional digits.\n"
833 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
836 " unknown | subsciber | national | international - Change caller ID type.\n"
837 " present | restrict - Change presentation of caller ID."},
839 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
840 "Adds an entry for outgoing calls to the caller ID screen list.\n"
841 "See 'screen-in' for help."},
843 {"nodtmf", &inter_nodtmf, "",
844 "Disables DTMF detection for this interface.\n"
845 "This parameter must follow a 'port' parameter."},
848 {"layer2keep", &inter_layer2keep, "yes | no",
849 "By default, layer 2 is establised and kept up on PTP interfaces.\n"
851 "This parameter must follow a 'port' parameter."},
854 {"filter", &inter_filter, "<filter> <parameters>",
855 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
856 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
857 "pipeline <string> - Sets echo cancelation pipeline.\n"
858 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
860 {NULL, NULL, NULL, NULL}
865 * read settings from interface.conf
867 char interface_error[256];
868 struct interface *read_interfaces(void)
873 unsigned int line, i;
875 struct interface *interface = NULL, /* in case no interface */
876 **interfacep = &interface_newlist;
879 int expecting = 1; /* expecting new interface */
880 struct interface_param *ifparam;
882 if (interface_newlist != NULL)
883 FATAL("list is not empty.\n");
884 interface_error[0] = '\0';
885 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
887 if (!(fp = fopen(filename,"r")))
889 SPRINT(interface_error, "Cannot open '%s'\n", filename);
894 while((fgets(buffer,sizeof(buffer),fp)))
896 buffer[sizeof(buffer)-1]=0;
897 if (buffer[0]) buffer[strlen(buffer)-1]=0;
901 while(*p <= 32) /* skip spaces */
907 if (*p==0 || *p=='#') /* ignore comments and empty line */
912 i=0; /* read parameter */
915 if (i+1 >= sizeof(parameter))
917 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
920 parameter[i+1] = '\0';
921 parameter[i++] = *p++;
924 while(*p <= 32) /* skip spaces */
931 if (*p!=0 && *p!='#') /* missing name */
933 i=0; /* read until end */
934 while(*p!=0 && *p!='#')
936 if (i+1 >= sizeof(value))
938 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
945 /* remove trailing spaces from value */
948 if (value[i-1]==0 || value[i-1]>32)
955 /* check for interface name as first statement */
956 if (expecting && parameter[0]!='[')
958 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
963 /* check for new interface */
964 if (parameter[0] == '[')
966 if (parameter[strlen(parameter)-1] != ']')
968 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
971 parameter[strlen(parameter)-1] = '\0';
973 /* check if interface name already exists */
974 interface = interface_newlist;
977 if (!strcasecmp(interface->name, parameter+1))
979 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
982 interface = interface->next;
985 /* append interface to new list */
986 interface = (struct interface *)MALLOC(sizeof(struct interface));
990 SCPY(interface->name, parameter+1);
993 *interfacep = interface;
994 interfacep = &interface->next;
999 ifparam = interface_param;
1000 while(ifparam->name)
1002 if (!strcasecmp(parameter, ifparam->name))
1004 if (ifparam->func(interface, filename, line, parameter, value))
1013 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1018 return(interface_newlist);
1020 PERROR_RUNTIME("%s", interface_error);
1022 free_interfaces(interface_newlist);
1023 interface_newlist = NULL;
1029 * freeing chain of interfaces
1031 void free_interfaces(struct interface *interface)
1034 struct interface_port *ifport;
1035 struct select_channel *selchannel;
1036 struct interface_msn *ifmsn;
1037 struct interface_screen *ifscreen;
1041 ifport = interface->ifport;
1044 selchannel = ifport->in_channel;
1048 selchannel = selchannel->next;
1049 FREE(temp, sizeof(struct select_channel));
1052 selchannel = ifport->out_channel;
1056 selchannel = selchannel->next;
1057 FREE(temp, sizeof(struct select_channel));
1061 ifport = ifport->next;
1062 FREE(temp, sizeof(struct interface_port));
1065 ifmsn = interface->ifmsn;
1069 ifmsn = ifmsn->next;
1070 FREE(temp, sizeof(struct interface_msn));
1073 ifscreen = interface->ifscreen_in;
1077 ifscreen = ifscreen->next;
1078 FREE(temp, sizeof(struct interface_screen));
1081 ifscreen = interface->ifscreen_out;
1085 ifscreen = ifscreen->next;
1086 FREE(temp, sizeof(struct interface_screen));
1090 interface = interface->next;
1091 FREE(temp, sizeof(struct interface));
1097 * defaults of ports if not specified by config
1099 static void set_defaults(struct interface_port *ifport)
1101 /* default channel selection list */
1102 if (!ifport->out_channel)
1103 default_out_channel(ifport);
1104 if (!ifport->in_channel)
1105 default_in_channel(ifport);
1106 /* default is_tones */
1107 if (ifport->interface->is_tones)
1108 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1110 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1111 /* default is_earlyb */
1112 if (ifport->interface->is_earlyb)
1113 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1115 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1116 /* set locally flag */
1117 if (ifport->interface->extension)
1118 ifport->mISDNport->locally = 1;
1120 ifport->mISDNport->locally = 0;
1125 * all links between mISDNport and interface are made
1126 * unused mISDNports are closed, new mISDNports are opened
1127 * also set default select_channel lists
1129 void relink_interfaces(void)
1131 struct mISDNport *mISDNport;
1132 struct interface *interface;
1133 struct interface_port *ifport;
1135 /* unlink all mISDNports */
1136 mISDNport = mISDNport_first;
1139 mISDNport->ifport = NULL;
1140 mISDNport = mISDNport->next;
1143 /* relink existing mISDNports */
1144 interface = interface_newlist;
1147 ifport = interface->ifport;
1150 mISDNport = mISDNport_first;
1153 if (mISDNport->portnum == ifport->portnum)
1155 ifport->mISDNport = mISDNport;
1156 mISDNport->ifport = ifport;
1157 set_defaults(ifport);
1159 mISDNport = mISDNport->next;
1161 ifport = ifport->next;
1163 interface = interface->next;
1166 /* close unused mISDNports */
1168 mISDNport = mISDNport_first;
1171 if (mISDNport->ifport == NULL)
1173 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1174 /* remove all port objects and destroy port */
1175 mISDNport_close(mISDNport);
1178 mISDNport = mISDNport->next;
1181 /* open and link new mISDNports */
1182 interface = interface_newlist;
1185 ifport = interface->ifport;
1188 if (!ifport->mISDNport)
1192 ifport = ifport->next;
1194 interface = interface->next;
1203 void load_port(struct interface_port *ifport)
1205 struct mISDNport *mISDNport;
1208 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
1212 ifport->mISDNport = mISDNport;
1213 mISDNport->ifport = ifport;
1214 set_defaults(ifport);
1217 ifport->block = 2; /* not available */
1222 * give summary of interface syntax
1224 void doc_interface(void)
1226 struct interface_param *ifparam;
1228 printf("Syntax overview\n");
1229 printf("---------------\n\n");
1231 printf("[<name>]\n");
1232 ifparam = interface_param;
1233 while(ifparam->name)
1235 printf("%s %s\n", ifparam->name, ifparam->usage);
1239 ifparam = interface_param;
1240 while(ifparam->name)
1242 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1243 printf("%s\n", ifparam->help);
1250 * out==0: incomming caller id, out==1: outgoing caller id
1252 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1255 struct interface_msn *ifmsn;
1256 struct interface_screen *ifscreen;
1259 /* screen incoming caller id */
1262 /* check for MSN numbers, use first MSN if no match */
1264 ifmsn = interface->ifmsn;
1269 if (!strcmp(ifmsn->msn, id))
1273 ifmsn = ifmsn->next;
1277 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (fount in MSN list)");
1278 add_trace("msn", NULL, "%s", id);
1281 if (!ifmsn && msn1) // not in list, first msn given
1283 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, DIRECTION_IN, 0, 0, "SCREEN (not fount in MSN list)");
1284 add_trace("msn", "given", "%s", id);
1285 add_trace("msn", "used", "%s", msn1);
1287 UNCPY(id, msn1, idsize);
1288 id[idsize-1] = '\0';
1292 /* check screen list */
1294 ifscreen = interface->ifscreen_out;
1296 ifscreen = interface->ifscreen_in;
1299 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1300 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1302 if (strchr(ifscreen->match,'%'))
1304 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1308 if (!strcmp(ifscreen->match, id))
1312 ifscreen = ifscreen->next;
1314 if (ifscreen) // match
1316 start_trace(0, interface, numberrize_callerinfo(id, *type), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (fount in screen list)");
1319 case INFO_NTYPE_UNKNOWN:
1320 add_trace("given", "type", "unknown");
1322 case INFO_NTYPE_SUBSCRIBER:
1323 add_trace("given", "type", "subscriber");
1325 case INFO_NTYPE_NATIONAL:
1326 add_trace("given", "type", "national");
1328 case INFO_NTYPE_INTERNATIONAL:
1329 add_trace("given", "type", "international");
1334 case INFO_PRESENT_ALLOWED:
1335 add_trace("given", "present", "allowed");
1337 case INFO_PRESENT_RESTRICTED:
1338 add_trace("given", "present", "restricted");
1340 case INFO_PRESENT_NOTAVAIL:
1341 add_trace("given", "present", "not available");
1344 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1345 if (ifscreen->result_type != -1)
1347 *type = ifscreen->result_type;
1350 case INFO_NTYPE_UNKNOWN:
1351 add_trace("used", "type", "unknown");
1353 case INFO_NTYPE_SUBSCRIBER:
1354 add_trace("used", "type", "subscriber");
1356 case INFO_NTYPE_NATIONAL:
1357 add_trace("used", "type", "national");
1359 case INFO_NTYPE_INTERNATIONAL:
1360 add_trace("used", "type", "international");
1364 if (ifscreen->result_present != -1)
1366 *present = ifscreen->result_present;
1369 case INFO_PRESENT_ALLOWED:
1370 add_trace("used", "present", "allowed");
1372 case INFO_PRESENT_RESTRICTED:
1373 add_trace("used", "present", "restricted");
1375 case INFO_PRESENT_NOTAVAIL:
1376 add_trace("used", "present", "not available");
1380 if (strchr(ifscreen->match,'%'))
1382 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1383 UNCPY(id, ifscreen->result, idsize);
1384 id[idsize-1] = '\0';
1387 *strchr(id,'%') = '\0';
1388 UNCAT(id, suffix, idsize);
1389 id[idsize-1] = '\0';
1393 UNCPY(id, ifscreen->result, idsize);
1394 id[idsize-1] = '\0';
1396 add_trace("used", "id", "%s", id[0]?id:"<empty>");