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_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
213 struct interface_port *ifport;
215 /* port in chain ? */
216 if (!interface->ifport)
218 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
221 /* goto end of chain */
222 ifport = interface->ifport;
224 ifport = ifport->next;
228 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
231 ifport->tespecial = 1;
234 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
236 if (!strcasecmp(value, "yes"))
238 interface->is_tones = IS_YES;
240 if (!strcasecmp(value, "no"))
242 interface->is_tones = IS_NO;
245 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
250 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
252 if (!strcasecmp(value, "yes"))
254 interface->is_earlyb = IS_YES;
256 if (!strcasecmp(value, "no"))
258 interface->is_earlyb = IS_NO;
261 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
266 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
268 if (!strcasecmp(value, "linear"))
270 interface->hunt = HUNT_LINEAR;
272 if (!strcasecmp(value, "roundrobin"))
274 interface->hunt = HUNT_ROUNDROBIN;
277 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
282 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
284 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);
287 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
289 struct interface_port *ifport, **ifportp;
290 struct interface *searchif;
293 val = get_number(value);
296 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
299 /* check for port already assigned */
300 searchif = interface_newlist;
303 ifport = searchif->ifport;
306 if (ifport->portnum == val)
308 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
311 ifport = ifport->next;
313 searchif = searchif->next;
315 /* alloc port substructure */
316 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
318 ifport->interface = interface;
320 ifport->portnum = val;
322 ifportp = &interface->ifport;
324 ifportp = &((*ifportp)->next);
328 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
330 struct interface_port *ifport, **ifportp;
331 struct interface *searchif;
333 /* check for port already assigned */
334 searchif = interface_newlist;
337 ifport = searchif->ifport;
340 if (!strcasecmp(ifport->portname, value))
342 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
345 /* check for use as GSM */
348 SPRINT(interface_error, "Error in %s (line %d): Interface already used for GSM.\n", filename, line);
351 ifport = ifport->next;
353 searchif = searchif->next;
355 /* alloc port substructure */
356 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
358 ifport->interface = interface;
360 ifport->portnum = -1; // disable until resolved
361 SCPY(ifport->portname, value);
363 ifportp = &interface->ifport;
365 ifportp = &((*ifportp)->next);
369 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
371 struct interface_port *ifport;
373 /* port in chain ? */
374 if (!interface->ifport)
376 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
379 /* goto end of chain */
380 ifport = interface->ifport;
382 ifport = ifport->next;
383 if (!strcmp(value, "yes"))
387 if (!strcmp(value, "no"))
392 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
397 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
399 struct interface_port *ifport;
401 /* port in chain ? */
402 if (!interface->ifport)
404 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
407 /* goto end of chain */
408 ifport = interface->ifport;
410 ifport = ifport->next;
411 if (!strcmp(value, "yes"))
415 if (!strcmp(value, "no"))
420 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
425 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
427 struct interface_port *ifport;
428 struct select_channel *selchannel, **selchannelp;
432 /* port in chain ? */
433 if (!interface->ifport)
435 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
438 /* goto end of chain */
439 ifport = interface->ifport;
441 ifport = ifport->next;
446 p = get_seperated(p);
447 if (!strcasecmp(el, "force"))
449 ifport->channel_force = 1;
450 if (ifport->out_channel)
452 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
456 if (!strcasecmp(el, "any"))
461 if (!strcasecmp(el, "free"))
466 if (!strcasecmp(el, "no"))
472 val = get_number(el);
475 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);
479 if (val<1 || val==16 || val>126)
481 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
485 /* add to select-channel list */
486 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
489 selchannel->channel = val;
491 selchannelp = &ifport->out_channel;
493 selchannelp = &((*selchannelp)->next);
494 *selchannelp = selchannel;
499 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
501 struct interface_port *ifport;
502 struct select_channel *selchannel, **selchannelp;
506 /* port in chain ? */
507 if (!interface->ifport)
509 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
512 /* goto end of chain */
513 ifport = interface->ifport;
515 ifport = ifport->next;
520 p = get_seperated(p);
521 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
523 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
526 if (!strcasecmp(el, "free"))
532 val = get_number(el);
535 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
539 if (val<1 || val==16 || val>126)
541 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
545 /* add to select-channel list */
546 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
549 selchannel->channel = val;
551 selchannelp = &ifport->in_channel;
553 selchannelp = &((*selchannelp)->next);
554 *selchannelp = selchannel;
559 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
561 struct interface_port *ifport;
562 // struct select_channel *selchannel, **selchannelp;
566 /* port in chain ? */
567 if (!interface->ifport)
569 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
572 /* goto end of chain */
573 ifport = interface->ifport;
575 ifport = ifport->next;
580 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
584 p = get_seperated(p);
585 ifport->tout_setup = atoi(el);
589 p = get_seperated(p);
590 ifport->tout_dialing = atoi(el);
594 p = get_seperated(p);
595 ifport->tout_proceeding = atoi(el);
599 p = get_seperated(p);
600 ifport->tout_alerting = atoi(el);
604 p = get_seperated(p);
605 ifport->tout_disconnect = atoi(el);
608 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
610 struct interface_msn *ifmsn, **ifmsnp;
615 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
618 if (interface->ifscreen_in)
620 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
629 p = get_seperated(p);
630 /* add MSN to list */
631 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
634 SCPY(ifmsn->msn, el);
636 ifmsnp = &interface->ifmsn;
638 ifmsnp = &((*ifmsnp)->next);
643 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
645 struct interface_screen *ifscreen;
650 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
653 /* add screen entry to list*/
654 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
656 ifscreen->match_type = -1; /* unchecked */
657 ifscreen->match_present = -1; /* unchecked */
658 ifscreen->result_type = -1; /* unchanged */
659 ifscreen->result_present = -1; /* unchanged */
662 ifscreenp = &((*ifscreenp)->next);
663 *ifscreenp = ifscreen;
664 // printf("interface=%s\n", interface->name);
670 p = get_seperated(p);
671 if (!strcasecmp(el, "unknown"))
673 if (ifscreen->match_type != -1)
676 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
679 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
681 if (!strcasecmp(el, "subscriber"))
683 if (ifscreen->match_type != -1)
685 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
687 if (!strcasecmp(el, "national"))
689 if (ifscreen->match_type != -1)
691 ifscreen->match_type = INFO_NTYPE_NATIONAL;
693 if (!strcasecmp(el, "international"))
695 if (ifscreen->match_type != -1)
697 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
699 if (!strcasecmp(el, "allowed"))
701 if (ifscreen->match_present != -1)
704 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
707 ifscreen->match_present = INFO_PRESENT_ALLOWED;
709 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
711 if (ifscreen->match_present != -1)
713 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
715 SCPY(ifscreen->match, el);
716 /* check for % at the end */
719 if (strchr(el, '%') != el+strlen(el)-1)
721 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
728 if (ifscreen->match[0] == '\0')
730 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
737 p = get_seperated(p);
738 if (!strcasecmp(el, "unknown"))
740 if (ifscreen->result_type != -1)
742 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
744 if (!strcasecmp(el, "subscriber"))
746 if (ifscreen->result_type != -1)
748 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
750 if (!strcasecmp(el, "national"))
752 if (ifscreen->result_type != -1)
754 ifscreen->result_type = INFO_NTYPE_NATIONAL;
756 if (!strcasecmp(el, "international"))
758 if (ifscreen->result_type != -1)
760 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
762 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
764 if (ifscreen->result_present != -1)
766 ifscreen->result_present = INFO_PRESENT_ALLOWED;
768 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
770 if (ifscreen->result_present != -1)
772 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
774 SCPY(ifscreen->result, el);
775 /* check for % at the end */
778 if (strchr(el, '%') != el+strlen(el)-1)
780 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
787 if (ifscreen->result[0] == '\0')
789 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
794 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
796 if (interface->ifmsn)
798 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
802 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
804 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
806 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
808 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
810 struct interface_port *ifport;
812 /* port in chain ? */
813 if (!interface->ifport)
815 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
818 /* goto end of chain */
819 ifport = interface->ifport;
821 ifport = ifport->next;
825 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
829 /* seperate parameter from filter */
836 while(*p > 0 && *p <= 32)
840 if (!strcasecmp(value, "gain"))
848 while(*q > 0 && *q <= 32)
851 if (*p == 0 || *q == 0)
853 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
856 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
858 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
861 interface->tx_gain = atoi(p);
862 interface->rx_gain = atoi(q);
864 if (!strcasecmp(value, "pipeline"))
868 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
871 SCPY(interface->pipeline, p);
873 if (!strcasecmp(value, "blowfish"))
875 unsigned char key[56];
878 if (!!strncmp(p, "0x", 2))
880 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
889 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
892 if (*p >= '0' && *p <= '9')
893 key[l] = (*p-'0')<<4;
894 else if (*p >= 'a' && *p <= 'f')
895 key[l] = (*p-'a'+10)<<4;
896 else if (*p >= 'A' && *p <= 'F')
897 key[l] = (*p-'A'+10)<<4;
901 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);
907 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);
910 if (*p >= '0' && *p <= '9')
911 key[l] = (*p-'0')<<4;
912 else if (*p >= 'a' && *p <= 'f')
913 key[l] = (*p-'a'+10)<<4;
914 else if (*p >= 'A' && *p <= 'F')
915 key[l] = (*p-'A'+10)<<4;
923 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);
926 memcpy(interface->bf_key, key, l);
927 interface->bf_len = l;
930 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
935 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
937 struct interface_port *ifport;
939 /* port in chain ? */
940 if (!interface->ifport)
942 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
945 /* goto end of chain */
946 ifport = interface->ifport;
948 ifport = ifport->next;
949 ifport->dialmax = atoi(value);
952 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
955 SPRINT(interface_error, "Error in %s (line %d): GSM not compiled in.\n", filename, line);
958 struct interface_port *ifport;
959 struct interface *searchif;
964 SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
967 searchif = interface_newlist;
970 ifport = searchif->ifport;
975 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm\n", filename, line, value);
978 ifport = ifport->next;
980 searchif = searchif->next;
984 if (inter_portname(interface, filename, line, "portname", gsm->conf.interface_lcr))
986 /* goto end of chain again to set gsmflag*/
987 ifport = interface->ifport;
989 ifport = ifport->next;
997 * structure of parameters
999 struct interface_param interface_param[] = {
1000 { "extension", &inter_extension, "",
1001 "If keyword is given, calls to interface are handled as internal extensions."},
1002 {"tones", &inter_tones, "yes | no",
1003 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1005 {"earlyb", &inter_earlyb, "yes | no",
1006 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1008 {"hunt", &inter_hunt, "linear | roundrobin",
1009 "Select the algorithm for selecting port with free channel."},
1011 {"port", &inter_port, "<number>",
1013 {"portnum", &inter_portnum, "<number>",
1014 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1015 {"portname", &inter_portname, "<name>",
1016 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1018 {"block", &inter_block, "",
1019 "If keyword is given, calls on this interface are blocked.\n"
1020 "This parameter must follow a 'port' parameter."},
1022 {"ptp", &inter_ptp, "",
1023 "The given port above is opened as point-to-point.\n"
1024 "This is required on NT-mode ports that are multipoint by default.\n"
1025 "This parameter must follow a 'port' parameter."},
1028 {"ptmp", &inter_ptmp, "",
1029 "The given port above is opened as point-to-multipoint.\n"
1030 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1031 "This parameter must follow a 'port' parameter."},
1034 {"nt", &inter_nt, "",
1035 "The given port above is opened in NT-mode.\n"
1036 "This is required on interfaces that support both NT-mode and TE-mode.\n"
1037 "This parameter must follow a 'port' parameter."},
1039 {"te-special", &inter_tespecial, "",
1040 "The given port uses a modified TE-mode.\n"
1041 "All information elements that are allowed Network->User will then be\n"
1042 "transmitted User->Network also. This is usefull to pass all informations\n"
1043 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1044 "Note that this is not compliant with ISDN protocol.\n"
1045 "This parameter must follow a 'port' parameter."},
1047 {"layer1hold", &inter_l1hold, "yes | no",
1048 "The given port will not release layer 1 after layer 2 is down.\n"
1049 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1050 "This parameter must follow a 'port' parameter."},
1052 {"layer2hold", &inter_l2hold, "yes | no",
1053 "The given port will continuously try to establish layer 2 link and hold it.\n"
1054 "It is required for PTP links in most cases, therefore it is default.\n"
1055 "This parameter must follow a 'port' parameter."},
1057 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1058 "Channel selection list for all outgoing calls to the interface.\n"
1059 "A free channels is searched in order of appearance.\n"
1060 "This parameter must follow a 'port' parameter.\n"
1061 " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
1062 " <number>[,...] - List of channels to search.\n"
1063 " free - Select any free channel\n"
1064 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1065 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1067 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1068 "Channel selection list for all incoming calls from the interface.\n"
1069 "A free channels is accepted if in the list.\n"
1070 "If any channel was requested, the first free channel found is selected.\n"
1071 "This parameter must follow a 'port' parameter.\n"
1072 " <number>[,...] - List of channels to accept.\n"
1073 " free - Accept any free channel"},
1075 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1076 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1077 "The default is 120 seconds for all states. Use 0 to disable.\n"
1078 "This parameter must follow a 'port' parameter.\n"},
1080 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1081 "Incoming caller ID is checked against given MSN numbers.\n"
1082 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1084 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1085 "Adds an entry for incoming calls to the caller ID screen list.\n"
1086 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1087 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1088 "additional digits.\n"
1089 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1092 " unknown | subsciber | national | international - Change caller ID type.\n"
1093 " present | restrict - Change presentation of caller ID."},
1095 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1096 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1097 "See 'screen-in' for help."},
1099 {"nodtmf", &inter_nodtmf, "",
1100 "Disables DTMF detection for this interface.\n"
1101 "This parameter must follow a 'port' parameter."},
1103 {"filter", &inter_filter, "<filter> <parameters>",
1104 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1105 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1106 "pipeline <string> - Sets echo cancelation pipeline.\n"
1107 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1109 {"dialmax", &inter_dialmax, "<digits>",
1110 "Limits the number of digits in setup/information message."},
1112 {"gsm", &inter_gsm, "",
1113 "Sets up GSM interface for using OpenBSC.\n"
1114 "This interface must be a loopback interface. The second loopback interface\n"
1115 "must be assigned to OpenBSC"},
1117 {NULL, NULL, NULL, NULL}
1122 * read settings from interface.conf
1124 char interface_error[256];
1125 struct interface *read_interfaces(void)
1130 unsigned int line, i;
1132 struct interface *interface = NULL, /* in case no interface */
1133 **interfacep = &interface_newlist;
1134 char parameter[128];
1136 int expecting = 1; /* expecting new interface */
1137 struct interface_param *ifparam;
1139 if (interface_newlist != NULL)
1140 FATAL("list is not empty.\n");
1141 interface_error[0] = '\0';
1142 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1144 if (!(fp = fopen(filename,"r")))
1146 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1151 while((fgets(buffer,sizeof(buffer),fp)))
1153 buffer[sizeof(buffer)-1]=0;
1154 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1158 while(*p <= 32) /* skip spaces */
1164 if (*p==0 || *p=='#') /* ignore comments and empty line */
1169 i=0; /* read parameter */
1172 if (i+1 >= sizeof(parameter))
1174 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1177 parameter[i+1] = '\0';
1178 parameter[i++] = *p++;
1181 while(*p <= 32) /* skip spaces */
1188 if (*p!=0 && *p!='#') /* missing name */
1190 i=0; /* read until end */
1191 while(*p!=0 && *p!='#')
1193 if (i+1 >= sizeof(value))
1195 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1202 /* remove trailing spaces from value */
1205 if (value[i-1]==0 || value[i-1]>32)
1212 /* check for interface name as first statement */
1213 if (expecting && parameter[0]!='[')
1215 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1220 /* check for new interface */
1221 if (parameter[0] == '[')
1223 if (parameter[strlen(parameter)-1] != ']')
1225 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1228 parameter[strlen(parameter)-1] = '\0';
1230 /* check if interface name already exists */
1231 interface = interface_newlist;
1234 if (!strcasecmp(interface->name, parameter+1))
1236 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1239 interface = interface->next;
1242 /* append interface to new list */
1243 interface = (struct interface *)MALLOC(sizeof(struct interface));
1246 /* name interface */
1247 SCPY(interface->name, parameter+1);
1250 *interfacep = interface;
1251 interfacep = &interface->next;
1256 ifparam = interface_param;
1257 while(ifparam->name)
1259 if (!strcasecmp(parameter, ifparam->name))
1261 if (ifparam->func(interface, filename, line, parameter, value))
1270 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1275 return(interface_newlist);
1277 PERROR_RUNTIME("%s", interface_error);
1279 free_interfaces(interface_newlist);
1280 interface_newlist = NULL;
1286 * freeing chain of interfaces
1288 void free_interfaces(struct interface *interface)
1291 struct interface_port *ifport;
1292 struct select_channel *selchannel;
1293 struct interface_msn *ifmsn;
1294 struct interface_screen *ifscreen;
1298 ifport = interface->ifport;
1301 selchannel = ifport->in_channel;
1305 selchannel = selchannel->next;
1306 FREE(temp, sizeof(struct select_channel));
1309 selchannel = ifport->out_channel;
1313 selchannel = selchannel->next;
1314 FREE(temp, sizeof(struct select_channel));
1318 ifport = ifport->next;
1319 FREE(temp, sizeof(struct interface_port));
1322 ifmsn = interface->ifmsn;
1326 ifmsn = ifmsn->next;
1327 FREE(temp, sizeof(struct interface_msn));
1330 ifscreen = interface->ifscreen_in;
1334 ifscreen = ifscreen->next;
1335 FREE(temp, sizeof(struct interface_screen));
1338 ifscreen = interface->ifscreen_out;
1342 ifscreen = ifscreen->next;
1343 FREE(temp, sizeof(struct interface_screen));
1347 interface = interface->next;
1348 FREE(temp, sizeof(struct interface));
1354 * defaults of ports if not specified by config
1356 static void set_defaults(struct interface_port *ifport)
1358 /* default channel selection list */
1359 if (!ifport->out_channel)
1360 default_out_channel(ifport);
1361 if (!ifport->in_channel)
1362 default_in_channel(ifport);
1363 /* default is_tones */
1364 if (ifport->interface->is_tones)
1365 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1367 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1368 /* default is_earlyb */
1369 if (ifport->interface->is_earlyb)
1370 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1372 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1373 /* set locally flag */
1374 if (ifport->interface->extension)
1375 ifport->mISDNport->locally = 1;
1377 ifport->mISDNport->locally = 0;
1382 * all links between mISDNport and interface are made
1383 * unused mISDNports are closed, new mISDNports are opened
1384 * also set default select_channel lists
1386 void relink_interfaces(void)
1388 struct mISDNport *mISDNport;
1389 struct interface *interface;
1390 struct interface_port *ifport;
1392 /* unlink all mISDNports */
1393 mISDNport = mISDNport_first;
1396 mISDNport->ifport = NULL;
1397 mISDNport = mISDNport->next;
1400 /* relink existing mISDNports */
1401 interface = interface_newlist;
1404 ifport = interface->ifport;
1407 mISDNport = mISDNport_first;
1410 if (!strcmp(mISDNport->name, ifport->portname))
1411 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1412 if (mISDNport->portnum == ifport->portnum)
1414 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", mISDNport->portnum);
1415 ifport->mISDNport = mISDNport;
1416 mISDNport->ifport = ifport;
1417 set_defaults(ifport);
1419 mISDNport = mISDNport->next;
1421 ifport = ifport->next;
1423 interface = interface->next;
1426 /* close unused mISDNports */
1428 mISDNport = mISDNport_first;
1431 if (mISDNport->ifport == NULL)
1433 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1434 /* remove all port objects and destroy port */
1435 mISDNport_close(mISDNport);
1438 mISDNport = mISDNport->next;
1441 /* open and link new mISDNports */
1442 interface = interface_newlist;
1445 ifport = interface->ifport;
1448 if (!ifport->mISDNport)
1452 ifport = ifport->next;
1454 interface = interface->next;
1463 void load_port(struct interface_port *ifport)
1465 struct mISDNport *mISDNport;
1468 mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface, ifport->gsm);
1472 ifport->mISDNport = mISDNport;
1473 mISDNport->ifport = ifport;
1474 /* set number and name */
1475 ifport->portnum = mISDNport->portnum;
1476 SCPY(ifport->portname, mISDNport->name);
1478 set_defaults(ifport);
1481 ifport->block = 2; /* not available */
1486 * give summary of interface syntax
1488 void doc_interface(void)
1490 struct interface_param *ifparam;
1492 printf("Syntax overview\n");
1493 printf("---------------\n\n");
1495 printf("[<name>]\n");
1496 ifparam = interface_param;
1497 while(ifparam->name)
1499 if (ifparam->name[0])
1500 printf("%s %s\n", ifparam->name, ifparam->usage);
1504 ifparam = interface_param;
1505 while(ifparam->name)
1507 if (ifparam->name[0])
1509 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1510 printf("%s\n", ifparam->help);
1518 * out==0: incoming caller id, out==1: outgoing caller id
1520 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1523 struct interface_msn *ifmsn;
1524 struct interface_screen *ifscreen;
1527 /* screen incoming caller id */
1530 /* check for MSN numbers, use first MSN if no match */
1532 ifmsn = interface->ifmsn;
1537 if (!strcmp(ifmsn->msn, id))
1541 ifmsn = ifmsn->next;
1545 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1546 add_trace("msn", NULL, "%s", id);
1549 if (!ifmsn && msn1) // not in list, first msn given
1551 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1552 add_trace("msn", "given", "%s", id);
1553 add_trace("msn", "used", "%s", msn1);
1555 UNCPY(id, msn1, idsize);
1556 id[idsize-1] = '\0';
1560 /* check screen list */
1562 ifscreen = interface->ifscreen_out;
1564 ifscreen = interface->ifscreen_in;
1567 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1568 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1570 if (strchr(ifscreen->match,'%'))
1572 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1576 if (!strcmp(ifscreen->match, id))
1580 ifscreen = ifscreen->next;
1582 if (ifscreen) // match
1584 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
1587 case INFO_NTYPE_UNKNOWN:
1588 add_trace("given", "type", "unknown");
1590 case INFO_NTYPE_SUBSCRIBER:
1591 add_trace("given", "type", "subscriber");
1593 case INFO_NTYPE_NATIONAL:
1594 add_trace("given", "type", "national");
1596 case INFO_NTYPE_INTERNATIONAL:
1597 add_trace("given", "type", "international");
1602 case INFO_PRESENT_ALLOWED:
1603 add_trace("given", "present", "allowed");
1605 case INFO_PRESENT_RESTRICTED:
1606 add_trace("given", "present", "restricted");
1608 case INFO_PRESENT_NOTAVAIL:
1609 add_trace("given", "present", "not available");
1612 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1613 if (ifscreen->result_type != -1)
1615 *type = ifscreen->result_type;
1618 case INFO_NTYPE_UNKNOWN:
1619 add_trace("used", "type", "unknown");
1621 case INFO_NTYPE_SUBSCRIBER:
1622 add_trace("used", "type", "subscriber");
1624 case INFO_NTYPE_NATIONAL:
1625 add_trace("used", "type", "national");
1627 case INFO_NTYPE_INTERNATIONAL:
1628 add_trace("used", "type", "international");
1632 if (ifscreen->result_present != -1)
1634 *present = ifscreen->result_present;
1637 case INFO_PRESENT_ALLOWED:
1638 add_trace("used", "present", "allowed");
1640 case INFO_PRESENT_RESTRICTED:
1641 add_trace("used", "present", "restricted");
1643 case INFO_PRESENT_NOTAVAIL:
1644 add_trace("used", "present", "not available");
1648 if (strchr(ifscreen->match,'%'))
1650 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1651 UNCPY(id, ifscreen->result, idsize);
1652 id[idsize-1] = '\0';
1655 *strchr(id,'%') = '\0';
1656 UNCAT(id, suffix, idsize);
1657 id[idsize-1] = '\0';
1661 UNCPY(id, ifscreen->result, idsize);
1662 id[idsize-1] = '\0';
1664 add_trace("used", "id", "%s", id[0]?id:"<empty>");