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 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'portnum' and decrease port number by 1! Ports are counted from 0 now.\n", filename, line, parameter);
264 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
266 struct interface_port *ifport, **ifportp;
267 struct interface *searchif;
270 val = get_number(value);
273 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
276 /* check for port already assigned */
277 searchif = interface_newlist;
280 ifport = searchif->ifport;
283 if (ifport->portnum == val)
285 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
288 ifport = ifport->next;
290 searchif = searchif->next;
292 /* alloc port substructure */
293 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
295 ifport->interface = interface;
297 ifport->portnum = val;
299 ifportp = &interface->ifport;
301 ifportp = &((*ifportp)->next);
305 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
307 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not implemented yet.\n", filename, line, parameter);
310 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
312 struct interface_port *ifport;
314 /* port in chain ? */
315 if (!interface->ifport)
317 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
320 /* goto end of chain */
321 ifport = interface->ifport;
323 ifport = ifport->next;
324 if (!strcmp(value, "yes"))
328 if (!strcmp(value, "no"))
333 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
338 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
340 struct interface_port *ifport;
341 struct select_channel *selchannel, **selchannelp;
345 /* port in chain ? */
346 if (!interface->ifport)
348 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
351 /* goto end of chain */
352 ifport = interface->ifport;
354 ifport = ifport->next;
359 p = get_seperated(p);
360 if (!strcasecmp(el, "force"))
362 ifport->channel_force = 1;
363 if (ifport->out_channel)
365 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
369 if (!strcasecmp(el, "any"))
374 if (!strcasecmp(el, "free"))
379 if (!strcasecmp(el, "no"))
385 val = get_number(el);
388 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);
392 if (val<1 || val==16 || val>126)
394 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
398 /* add to select-channel list */
399 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
402 selchannel->channel = val;
404 selchannelp = &ifport->out_channel;
406 selchannelp = &((*selchannelp)->next);
407 *selchannelp = selchannel;
412 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
414 struct interface_port *ifport;
415 struct select_channel *selchannel, **selchannelp;
419 /* port in chain ? */
420 if (!interface->ifport)
422 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
425 /* goto end of chain */
426 ifport = interface->ifport;
428 ifport = ifport->next;
433 p = get_seperated(p);
434 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
436 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
439 if (!strcasecmp(el, "free"))
445 val = get_number(el);
448 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
452 if (val<1 || val==16 || val>126)
454 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
458 /* add to select-channel list */
459 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
462 selchannel->channel = val;
464 selchannelp = &ifport->in_channel;
466 selchannelp = &((*selchannelp)->next);
467 *selchannelp = selchannel;
472 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
474 struct interface_port *ifport;
475 // struct select_channel *selchannel, **selchannelp;
479 /* port in chain ? */
480 if (!interface->ifport)
482 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
485 /* goto end of chain */
486 ifport = interface->ifport;
488 ifport = ifport->next;
493 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
497 p = get_seperated(p);
498 ifport->tout_setup = atoi(el);
502 p = get_seperated(p);
503 ifport->tout_dialing = atoi(el);
507 p = get_seperated(p);
508 ifport->tout_proceeding = atoi(el);
512 p = get_seperated(p);
513 ifport->tout_alerting = atoi(el);
517 p = get_seperated(p);
518 ifport->tout_disconnect = atoi(el);
521 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
523 struct interface_msn *ifmsn, **ifmsnp;
528 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
531 if (interface->ifscreen_in)
533 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
542 p = get_seperated(p);
543 /* add MSN to list */
544 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
547 SCPY(ifmsn->msn, el);
549 ifmsnp = &interface->ifmsn;
551 ifmsnp = &((*ifmsnp)->next);
556 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
558 struct interface_screen *ifscreen;
563 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
566 /* add screen entry to list*/
567 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
569 ifscreen->match_type = -1; /* unchecked */
570 ifscreen->match_present = -1; /* unchecked */
571 ifscreen->result_type = -1; /* unchanged */
572 ifscreen->result_present = -1; /* unchanged */
575 ifscreenp = &((*ifscreenp)->next);
576 *ifscreenp = ifscreen;
577 // printf("interface=%s\n", interface->name);
583 p = get_seperated(p);
584 if (!strcasecmp(el, "unknown"))
586 if (ifscreen->match_type != -1)
589 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
592 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
594 if (!strcasecmp(el, "subscriber"))
596 if (ifscreen->match_type != -1)
598 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
600 if (!strcasecmp(el, "national"))
602 if (ifscreen->match_type != -1)
604 ifscreen->match_type = INFO_NTYPE_NATIONAL;
606 if (!strcasecmp(el, "international"))
608 if (ifscreen->match_type != -1)
610 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
612 if (!strcasecmp(el, "allowed"))
614 if (ifscreen->match_present != -1)
617 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
620 ifscreen->match_present = INFO_PRESENT_ALLOWED;
622 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
624 if (ifscreen->match_present != -1)
626 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
628 SCPY(ifscreen->match, el);
629 /* check for % at the end */
632 if (strchr(el, '%') != el+strlen(el)-1)
634 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
641 if (ifscreen->match[0] == '\0')
643 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
650 p = get_seperated(p);
651 if (!strcasecmp(el, "unknown"))
653 if (ifscreen->result_type != -1)
655 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
657 if (!strcasecmp(el, "subscriber"))
659 if (ifscreen->result_type != -1)
661 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
663 if (!strcasecmp(el, "national"))
665 if (ifscreen->result_type != -1)
667 ifscreen->result_type = INFO_NTYPE_NATIONAL;
669 if (!strcasecmp(el, "international"))
671 if (ifscreen->result_type != -1)
673 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
675 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
677 if (ifscreen->result_present != -1)
679 ifscreen->result_present = INFO_PRESENT_ALLOWED;
681 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
683 if (ifscreen->result_present != -1)
685 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
687 SCPY(ifscreen->result, el);
688 /* check for % at the end */
691 if (strchr(el, '%') != el+strlen(el)-1)
693 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
700 if (ifscreen->result[0] == '\0')
702 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
707 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
709 if (interface->ifmsn)
711 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
715 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
717 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
719 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
721 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
723 struct interface_port *ifport;
725 /* port in chain ? */
726 if (!interface->ifport)
728 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
731 /* goto end of chain */
732 ifport = interface->ifport;
734 ifport = ifport->next;
738 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
742 /* seperate parameter from filter */
749 while(*p > 0 && *p <= 32)
753 if (!strcasecmp(value, "gain"))
761 while(*q > 0 && *q <= 32)
764 if (*p == 0 || *q == 0)
766 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
769 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
771 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
774 interface->tx_gain = atoi(p);
775 interface->rx_gain = atoi(q);
777 if (!strcasecmp(value, "pipeline"))
781 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
784 SCPY(interface->pipeline, p);
786 if (!strcasecmp(value, "blowfish"))
788 unsigned char key[56];
791 if (!!strncmp(p, "0x", 2))
793 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
802 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
805 if (*p >= '0' && *p <= '9')
806 key[l] = (*p-'0')<<4;
807 else if (*p >= 'a' && *p <= 'f')
808 key[l] = (*p-'a'+10)<<4;
809 else if (*p >= 'A' && *p <= 'F')
810 key[l] = (*p-'A'+10)<<4;
814 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);
820 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);
823 if (*p >= '0' && *p <= '9')
824 key[l] = (*p-'0')<<4;
825 else if (*p >= 'a' && *p <= 'f')
826 key[l] = (*p-'a'+10)<<4;
827 else if (*p >= 'A' && *p <= 'F')
828 key[l] = (*p-'A'+10)<<4;
836 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);
839 memcpy(interface->bf_key, key, l);
840 interface->bf_len = l;
843 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
851 * structure of parameters
853 struct interface_param interface_param[] = {
854 { "extension", &inter_extension, "",
855 "If keyword is given, calls to interface are handled as internal extensions."},
856 {"tones", &inter_tones, "yes | no",
857 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
859 {"earlyb", &inter_earlyb, "yes | no",
860 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
862 {"hunt", &inter_hunt, "linear | roundrobin",
863 "Select the algorithm for selecting port with free channel."},
865 {"port", &inter_port, "<number>",
867 {"portnum", &inter_portnum, "<number>",
868 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
869 {"portname", &inter_portname, "<number>",
870 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
872 {"block", &inter_block, "",
873 "If keyword is given, calls on this interface are blocked.\n"
874 "This parameter must follow a 'port' parameter."},
876 {"ptp", &inter_ptp, "",
877 "The given port above is opened as point-to-point.\n"
878 "This is required on NT-mode ports that are multipoint by default.\n"
879 "This parameter must follow a 'port' parameter."},
882 {"ptmp", &inter_ptmp, "",
883 "The given port above is opened as point-to-multipoint.\n"
884 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
885 "This parameter must follow a 'port' parameter."},
888 {"nt", &inter_nt, "",
889 "The given port above is opened in NT-mode.\n"
890 "This is required on interfaces that support both NT-mode and TE-mode.\n"
891 "This parameter must follow a 'port' parameter."},
893 {"layer2hold", &inter_l2hold, "yes | no",
894 "The given port will continuously try to establish layer 2 link and hold it.\n"
895 "It is required for PTP links in most cases, therefore it is default.\n"
896 "This parameter must follow a 'port' parameter."},
898 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
899 "Channel selection list for all outgoing calls to the interface.\n"
900 "A free channels is searched in order of appearance.\n"
901 "This parameter must follow a 'port' parameter.\n"
902 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
903 " <number>[,...] - List of channels to search.\n"
904 " free - Select any free channel\n"
905 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
906 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
908 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
909 "Channel selection list for all incoming calls from the interface.\n"
910 "A free channels is accepted if in the list.\n"
911 "If any channel was requested, the first free channel found is selected.\n"
912 "This parameter must follow a 'port' parameter.\n"
913 " <number>[,...] - List of channels to accept.\n"
914 " free - Accept any free channel"},
916 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
917 "Timeout values for call states. They are both for incoming and outgoing states.\n"
918 "The default is 120 seconds for all states. Use 0 to disable.\n"
919 "This parameter must follow a 'port' parameter.\n"},
921 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
922 "Incoming caller ID is checked against given MSN numbers.\n"
923 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
925 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
926 "Adds an entry for incoming calls to the caller ID screen list.\n"
927 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
928 "If '%' is given after old caller ID, it matches even if caller ID has\n"
929 "additional digits.\n"
930 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
933 " unknown | subsciber | national | international - Change caller ID type.\n"
934 " present | restrict - Change presentation of caller ID."},
936 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
937 "Adds an entry for outgoing calls to the caller ID screen list.\n"
938 "See 'screen-in' for help."},
940 {"nodtmf", &inter_nodtmf, "",
941 "Disables DTMF detection for this interface.\n"
942 "This parameter must follow a 'port' parameter."},
944 {"filter", &inter_filter, "<filter> <parameters>",
945 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
946 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
947 "pipeline <string> - Sets echo cancelation pipeline.\n"
948 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
950 {NULL, NULL, NULL, NULL}
955 * read settings from interface.conf
957 char interface_error[256];
958 struct interface *read_interfaces(void)
963 unsigned int line, i;
965 struct interface *interface = NULL, /* in case no interface */
966 **interfacep = &interface_newlist;
969 int expecting = 1; /* expecting new interface */
970 struct interface_param *ifparam;
972 if (interface_newlist != NULL)
973 FATAL("list is not empty.\n");
974 interface_error[0] = '\0';
975 SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
977 if (!(fp = fopen(filename,"r")))
979 SPRINT(interface_error, "Cannot open '%s'\n", filename);
984 while((fgets(buffer,sizeof(buffer),fp)))
986 buffer[sizeof(buffer)-1]=0;
987 if (buffer[0]) buffer[strlen(buffer)-1]=0;
991 while(*p <= 32) /* skip spaces */
997 if (*p==0 || *p=='#') /* ignore comments and empty line */
1002 i=0; /* read parameter */
1005 if (i+1 >= sizeof(parameter))
1007 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1010 parameter[i+1] = '\0';
1011 parameter[i++] = *p++;
1014 while(*p <= 32) /* skip spaces */
1021 if (*p!=0 && *p!='#') /* missing name */
1023 i=0; /* read until end */
1024 while(*p!=0 && *p!='#')
1026 if (i+1 >= sizeof(value))
1028 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1035 /* remove trailing spaces from value */
1038 if (value[i-1]==0 || value[i-1]>32)
1045 /* check for interface name as first statement */
1046 if (expecting && parameter[0]!='[')
1048 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1053 /* check for new interface */
1054 if (parameter[0] == '[')
1056 if (parameter[strlen(parameter)-1] != ']')
1058 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1061 parameter[strlen(parameter)-1] = '\0';
1063 /* check if interface name already exists */
1064 interface = interface_newlist;
1067 if (!strcasecmp(interface->name, parameter+1))
1069 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1072 interface = interface->next;
1075 /* append interface to new list */
1076 interface = (struct interface *)MALLOC(sizeof(struct interface));
1079 /* name interface */
1080 SCPY(interface->name, parameter+1);
1083 *interfacep = interface;
1084 interfacep = &interface->next;
1089 ifparam = interface_param;
1090 while(ifparam->name)
1092 if (!strcasecmp(parameter, ifparam->name))
1094 if (ifparam->func(interface, filename, line, parameter, value))
1103 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1108 return(interface_newlist);
1110 PERROR_RUNTIME("%s", interface_error);
1112 free_interfaces(interface_newlist);
1113 interface_newlist = NULL;
1119 * freeing chain of interfaces
1121 void free_interfaces(struct interface *interface)
1124 struct interface_port *ifport;
1125 struct select_channel *selchannel;
1126 struct interface_msn *ifmsn;
1127 struct interface_screen *ifscreen;
1131 ifport = interface->ifport;
1134 selchannel = ifport->in_channel;
1138 selchannel = selchannel->next;
1139 FREE(temp, sizeof(struct select_channel));
1142 selchannel = ifport->out_channel;
1146 selchannel = selchannel->next;
1147 FREE(temp, sizeof(struct select_channel));
1151 ifport = ifport->next;
1152 FREE(temp, sizeof(struct interface_port));
1155 ifmsn = interface->ifmsn;
1159 ifmsn = ifmsn->next;
1160 FREE(temp, sizeof(struct interface_msn));
1163 ifscreen = interface->ifscreen_in;
1167 ifscreen = ifscreen->next;
1168 FREE(temp, sizeof(struct interface_screen));
1171 ifscreen = interface->ifscreen_out;
1175 ifscreen = ifscreen->next;
1176 FREE(temp, sizeof(struct interface_screen));
1180 interface = interface->next;
1181 FREE(temp, sizeof(struct interface));
1187 * defaults of ports if not specified by config
1189 static void set_defaults(struct interface_port *ifport)
1191 /* default channel selection list */
1192 if (!ifport->out_channel)
1193 default_out_channel(ifport);
1194 if (!ifport->in_channel)
1195 default_in_channel(ifport);
1196 /* default is_tones */
1197 if (ifport->interface->is_tones)
1198 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1200 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1201 /* default is_earlyb */
1202 if (ifport->interface->is_earlyb)
1203 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1205 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1206 /* set locally flag */
1207 if (ifport->interface->extension)
1208 ifport->mISDNport->locally = 1;
1210 ifport->mISDNport->locally = 0;
1215 * all links between mISDNport and interface are made
1216 * unused mISDNports are closed, new mISDNports are opened
1217 * also set default select_channel lists
1219 void relink_interfaces(void)
1221 struct mISDNport *mISDNport;
1222 struct interface *interface;
1223 struct interface_port *ifport;
1225 /* unlink all mISDNports */
1226 mISDNport = mISDNport_first;
1229 mISDNport->ifport = NULL;
1230 mISDNport = mISDNport->next;
1233 /* relink existing mISDNports */
1234 interface = interface_newlist;
1237 ifport = interface->ifport;
1240 mISDNport = mISDNport_first;
1243 if (mISDNport->portnum == ifport->portnum)
1245 ifport->mISDNport = mISDNport;
1246 mISDNport->ifport = ifport;
1247 set_defaults(ifport);
1249 mISDNport = mISDNport->next;
1251 ifport = ifport->next;
1253 interface = interface->next;
1256 /* close unused mISDNports */
1258 mISDNport = mISDNport_first;
1261 if (mISDNport->ifport == NULL)
1263 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1264 /* remove all port objects and destroy port */
1265 mISDNport_close(mISDNport);
1268 mISDNport = mISDNport->next;
1271 /* open and link new mISDNports */
1272 interface = interface_newlist;
1275 ifport = interface->ifport;
1278 if (!ifport->mISDNport)
1282 ifport = ifport->next;
1284 interface = interface->next;
1293 void load_port(struct interface_port *ifport)
1295 struct mISDNport *mISDNport;
1298 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->nt, ifport->l2hold, ifport->interface);
1302 ifport->mISDNport = mISDNport;
1303 mISDNport->ifport = ifport;
1304 set_defaults(ifport);
1307 ifport->block = 2; /* not available */
1312 * give summary of interface syntax
1314 void doc_interface(void)
1316 struct interface_param *ifparam;
1318 printf("Syntax overview\n");
1319 printf("---------------\n\n");
1321 printf("[<name>]\n");
1322 ifparam = interface_param;
1323 while(ifparam->name)
1325 if (ifparam->name[0])
1326 printf("%s %s\n", ifparam->name, ifparam->usage);
1330 ifparam = interface_param;
1331 while(ifparam->name)
1333 if (ifparam->name[0])
1335 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1336 printf("%s\n", ifparam->help);
1344 * out==0: incoming caller id, out==1: outgoing caller id
1346 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1349 struct interface_msn *ifmsn;
1350 struct interface_screen *ifscreen;
1353 /* screen incoming caller id */
1356 /* check for MSN numbers, use first MSN if no match */
1358 ifmsn = interface->ifmsn;
1363 if (!strcmp(ifmsn->msn, id))
1367 ifmsn = ifmsn->next;
1371 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1372 add_trace("msn", NULL, "%s", id);
1375 if (!ifmsn && msn1) // not in list, first msn given
1377 start_trace(0, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1378 add_trace("msn", "given", "%s", id);
1379 add_trace("msn", "used", "%s", msn1);
1381 UNCPY(id, msn1, idsize);
1382 id[idsize-1] = '\0';
1386 /* check screen list */
1388 ifscreen = interface->ifscreen_out;
1390 ifscreen = interface->ifscreen_in;
1393 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1394 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1396 if (strchr(ifscreen->match,'%'))
1398 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1402 if (!strcmp(ifscreen->match, id))
1406 ifscreen = ifscreen->next;
1408 if (ifscreen) // match
1410 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)");
1413 case INFO_NTYPE_UNKNOWN:
1414 add_trace("given", "type", "unknown");
1416 case INFO_NTYPE_SUBSCRIBER:
1417 add_trace("given", "type", "subscriber");
1419 case INFO_NTYPE_NATIONAL:
1420 add_trace("given", "type", "national");
1422 case INFO_NTYPE_INTERNATIONAL:
1423 add_trace("given", "type", "international");
1428 case INFO_PRESENT_ALLOWED:
1429 add_trace("given", "present", "allowed");
1431 case INFO_PRESENT_RESTRICTED:
1432 add_trace("given", "present", "restricted");
1434 case INFO_PRESENT_NOTAVAIL:
1435 add_trace("given", "present", "not available");
1438 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1439 if (ifscreen->result_type != -1)
1441 *type = ifscreen->result_type;
1444 case INFO_NTYPE_UNKNOWN:
1445 add_trace("used", "type", "unknown");
1447 case INFO_NTYPE_SUBSCRIBER:
1448 add_trace("used", "type", "subscriber");
1450 case INFO_NTYPE_NATIONAL:
1451 add_trace("used", "type", "national");
1453 case INFO_NTYPE_INTERNATIONAL:
1454 add_trace("used", "type", "international");
1458 if (ifscreen->result_present != -1)
1460 *present = ifscreen->result_present;
1463 case INFO_PRESENT_ALLOWED:
1464 add_trace("used", "present", "allowed");
1466 case INFO_PRESENT_RESTRICTED:
1467 add_trace("used", "present", "restricted");
1469 case INFO_PRESENT_NOTAVAIL:
1470 add_trace("used", "present", "not available");
1474 if (strchr(ifscreen->match,'%'))
1476 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1477 UNCPY(id, ifscreen->result, idsize);
1478 id[idsize-1] = '\0';
1481 *strchr(id,'%') = '\0';
1482 UNCAT(id, suffix, idsize);
1483 id[idsize-1] = '\0';
1487 UNCPY(id, ifscreen->result, idsize);
1488 id[idsize-1] = '\0';
1490 add_trace("used", "id", "%s", id[0]?id:"<empty>");