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 */
19 /* set default out_channel */
20 void default_out_channel(struct interface_port *ifport)
22 struct select_channel *selchannel, **selchannelp;
24 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
27 if (ifport->mISDNport->ntmode)
28 selchannel->channel = CHANNEL_FREE;
30 selchannel->channel = CHANNEL_ANY;
32 ifport->out_channel = selchannel;
34 /* additional channel selection for multipoint NT ports */
35 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;
60 /* parse string for a positive number */
61 static int get_number(char *value)
68 SPRINT(text, "%d", val);
70 if (!strcmp(value, text))
77 /* remove element from buffer
78 * and return pointer to next element in buffer */
79 static char *get_seperated(char *buffer)
82 if (*buffer==',' || *buffer<=32) { /* seperate */
84 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
94 * parameter processing
96 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
98 struct interface_port *ifport;
100 /* port in chain ? */
101 if (!interface->ifport) {
102 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
105 /* goto end of chain */
106 ifport = interface->ifport;
108 ifport = ifport->next;
111 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
117 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
119 if (interface->external) {
120 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is external interface.\n", filename, line, parameter);
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_extern(struct interface *interface, char *filename, int line, char *parameter, char *value)
132 if (interface->extension) {
133 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is an extension.\n", filename, line, parameter);
137 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
140 interface->external = 1;
143 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
145 struct interface_port *ifport;
147 /* port in chain ? */
148 if (!interface->ifport) {
149 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
152 if (interface->ifport->ptmp) {
153 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
156 /* goto end of chain */
157 ifport = interface->ifport;
159 ifport = ifport->next;
162 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
169 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
171 struct interface_port *ifport;
173 /* port in chain ? */
174 if (!interface->ifport) {
175 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
178 if (interface->ifport->ptp) {
179 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
182 /* goto end of chain */
183 ifport = interface->ifport;
185 ifport = ifport->next;
188 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
195 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
197 struct interface_port *ifport;
199 /* port in chain ? */
200 if (!interface->ifport) {
201 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
204 /* goto end of chain */
205 ifport = interface->ifport;
207 ifport = ifport->next;
210 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
216 static int inter_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
218 struct interface_port *ifport;
220 /* port in chain ? */
221 if (!interface->ifport) {
222 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
225 /* goto end of chain */
226 ifport = interface->ifport;
228 ifport = ifport->next;
231 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
234 ifport->tespecial = 1;
237 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
239 if (!strcasecmp(value, "yes")) {
240 interface->is_tones = IS_YES;
242 if (!strcasecmp(value, "no")) {
243 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")) {
253 interface->is_earlyb = IS_YES;
255 if (!strcasecmp(value, "no")) {
256 interface->is_earlyb = IS_NO;
258 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
263 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
265 if (!strcasecmp(value, "linear")) {
266 interface->hunt = HUNT_LINEAR;
268 if (!strcasecmp(value, "roundrobin")) {
269 interface->hunt = HUNT_ROUNDROBIN;
271 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
276 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
278 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);
281 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
284 SPRINT(interface_error, "Error in %s (line %d): mISDN support is not compiled in.\n", filename, line);
287 struct interface_port *ifport, **ifportp;
288 struct interface *searchif;
291 val = get_number(value);
293 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
296 /* check for port already assigned */
297 searchif = interface_newlist;
299 ifport = searchif->ifport;
301 if (ifport->portnum == val) {
302 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
305 ifport = ifport->next;
307 searchif = searchif->next;
309 /* alloc port substructure */
310 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
312 ifport->interface = interface;
314 ifport->portnum = val;
316 ifportp = &interface->ifport;
318 ifportp = &((*ifportp)->next);
323 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
326 SPRINT(interface_error, "Error in %s (line %d): mISDN support is not compiled in.\n", filename, line);
329 struct interface_port *ifport, **ifportp;
331 /* goto end of chain */
332 ifport = interface->ifport;
335 ifport = ifport->next;
338 /* alloc port substructure */
339 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
341 ifport->interface = interface;
343 ifport->portnum = -1; // disable until resolved
344 SCPY(ifport->portname, value);
346 ifportp = &interface->ifport;
348 ifportp = &((*ifportp)->next);
353 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
355 struct interface_port *ifport;
357 /* port in chain ? */
358 if (!interface->ifport) {
359 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
362 /* goto end of chain */
363 ifport = interface->ifport;
365 ifport = ifport->next;
366 if (!strcmp(value, "yes")) {
369 if (!strcmp(value, "no")) {
372 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
377 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
379 struct interface_port *ifport;
381 /* port in chain ? */
382 if (!interface->ifport) {
383 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
386 /* goto end of chain */
387 ifport = interface->ifport;
389 ifport = ifport->next;
390 if (!strcmp(value, "yes")) {
393 if (!strcmp(value, "no")) {
396 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
401 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
403 struct interface_port *ifport;
404 struct select_channel *selchannel, **selchannelp;
408 /* port in chain ? */
409 if (!interface->ifport) {
410 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
413 /* goto end of chain */
414 ifport = interface->ifport;
416 ifport = ifport->next;
420 p = get_seperated(p);
421 if (!strcasecmp(el, "force")) {
422 ifport->channel_force = 1;
423 if (ifport->out_channel) {
424 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
428 if (!strcasecmp(el, "any")) {
432 if (!strcasecmp(el, "free")) {
436 if (!strcasecmp(el, "no")) {
440 val = get_number(el);
442 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);
446 if (val<1 || val==16 || val>126) {
447 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
451 /* add to select-channel list */
452 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
455 selchannel->channel = val;
457 selchannelp = &ifport->out_channel;
459 selchannelp = &((*selchannelp)->next);
460 *selchannelp = selchannel;
465 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
467 struct interface_port *ifport;
468 struct select_channel *selchannel, **selchannelp;
472 /* port in chain ? */
473 if (!interface->ifport) {
474 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
477 /* goto end of chain */
478 ifport = interface->ifport;
480 ifport = ifport->next;
484 p = get_seperated(p);
485 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE) {
486 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
489 if (!strcasecmp(el, "free")) {
493 val = get_number(el);
495 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
499 if (val<1 || val==16 || val>126) {
500 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
504 /* add to select-channel list */
505 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
508 selchannel->channel = val;
510 selchannelp = &ifport->in_channel;
512 selchannelp = &((*selchannelp)->next);
513 *selchannelp = selchannel;
518 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
520 struct interface_port *ifport;
521 // struct select_channel *selchannel, **selchannelp;
525 /* port in chain ? */
526 if (!interface->ifport) {
527 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
530 /* goto end of chain */
531 ifport = interface->ifport;
533 ifport = ifport->next;
537 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
541 p = get_seperated(p);
542 ifport->tout_setup = atoi(el);
546 p = get_seperated(p);
547 ifport->tout_dialing = atoi(el);
551 p = get_seperated(p);
552 ifport->tout_proceeding = atoi(el);
556 p = get_seperated(p);
557 ifport->tout_alerting = atoi(el);
561 p = get_seperated(p);
562 ifport->tout_disconnect = atoi(el);
565 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
567 struct interface_msn *ifmsn, **ifmsnp;
571 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
574 if (interface->ifscreen_in) {
575 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
583 p = get_seperated(p);
584 /* add MSN to list */
585 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
588 SCPY(ifmsn->msn, el);
590 ifmsnp = &interface->ifmsn;
592 ifmsnp = &((*ifmsnp)->next);
597 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
599 struct interface_screen *ifscreen;
603 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
606 /* add screen entry to list*/
607 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
609 ifscreen->match_type = -1; /* unchecked */
610 ifscreen->match_present = -1; /* unchecked */
611 ifscreen->result_type = -1; /* unchanged */
612 ifscreen->result_present = -1; /* unchanged */
615 ifscreenp = &((*ifscreenp)->next);
616 *ifscreenp = ifscreen;
617 // printf("interface=%s\n", interface->name);
622 p = get_seperated(p);
623 if (!strcasecmp(el, "unknown")) {
624 if (ifscreen->match_type != -1) {
626 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
629 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
631 if (!strcasecmp(el, "subscriber")) {
632 if (ifscreen->match_type != -1)
634 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
636 if (!strcasecmp(el, "national")) {
637 if (ifscreen->match_type != -1)
639 ifscreen->match_type = INFO_NTYPE_NATIONAL;
641 if (!strcasecmp(el, "international")) {
642 if (ifscreen->match_type != -1)
644 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
646 if (!strcasecmp(el, "allowed")) {
647 if (ifscreen->match_present != -1) {
649 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
652 ifscreen->match_present = INFO_PRESENT_ALLOWED;
654 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
655 if (ifscreen->match_present != -1)
657 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
659 SCPY(ifscreen->match, el);
660 /* check for % at the end */
661 if (strchr(el, '%')) {
662 if (strchr(el, '%') != el+strlen(el)-1) {
663 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
670 if (ifscreen->match[0] == '\0') {
671 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
677 p = get_seperated(p);
678 if (!strcasecmp(el, "unknown")) {
679 if (ifscreen->result_type != -1)
681 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
683 if (!strcasecmp(el, "subscriber")) {
684 if (ifscreen->result_type != -1)
686 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
688 if (!strcasecmp(el, "national")) {
689 if (ifscreen->result_type != -1)
691 ifscreen->result_type = INFO_NTYPE_NATIONAL;
693 if (!strcasecmp(el, "international")) {
694 if (ifscreen->result_type != -1)
696 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
698 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
699 if (ifscreen->result_present != -1)
701 ifscreen->result_present = INFO_PRESENT_ALLOWED;
703 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
704 if (ifscreen->result_present != -1)
706 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
708 SCPY(ifscreen->result, el);
709 /* check for % at the end */
710 if (strchr(el, '%')) {
711 if (strchr(el, '%') != el+strlen(el)-1) {
712 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
719 if (ifscreen->result[0] == '\0') {
720 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
725 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
727 if (interface->ifmsn) {
728 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
732 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
734 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
736 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
738 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
740 struct interface_port *ifport;
742 /* port in chain ? */
743 if (!interface->ifport) {
744 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
747 /* goto end of chain */
748 ifport = interface->ifport;
750 ifport = ifport->next;
754 static int inter_dtmf_threshold(struct interface *interface, char *filename, int line, char *parameter, char *value)
756 struct interface_port *ifport;
758 /* port in chain ? */
759 if (!interface->ifport) {
760 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
763 /* goto end of chain */
764 ifport = interface->ifport;
766 ifport = ifport->next;
767 ifport->dtmf_threshold = atoi(value);
770 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
774 /* seperate parameter from filter */
780 while(*p > 0 && *p <= 32)
784 if (!strcasecmp(value, "gain")) {
790 while(*q > 0 && *q <= 32)
793 if (*p == 0 || *q == 0) {
794 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
797 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
798 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
801 interface->tx_gain = atoi(p);
802 interface->rx_gain = atoi(q);
804 if (!strcasecmp(value, "pipeline")) {
806 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
809 SCPY(interface->pipeline, p);
811 if (!strcasecmp(value, "blowfish")) {
812 unsigned char key[56];
815 if (!!strncmp(p, "0x", 2)) {
816 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
823 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
826 if (*p >= '0' && *p <= '9')
827 key[l] = (*p-'0')<<4;
828 else if (*p >= 'a' && *p <= 'f')
829 key[l] = (*p-'a'+10)<<4;
830 else if (*p >= 'A' && *p <= 'F')
831 key[l] = (*p-'A'+10)<<4;
834 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);
839 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);
842 if (*p >= '0' && *p <= '9')
843 key[l] = (*p-'0')<<4;
844 else if (*p >= 'a' && *p <= 'f')
845 key[l] = (*p-'a'+10)<<4;
846 else if (*p >= 'A' && *p <= 'F')
847 key[l] = (*p-'A'+10)<<4;
854 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);
857 memcpy(interface->bf_key, key, l);
858 interface->bf_len = l;
860 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
865 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
867 struct interface_port *ifport;
869 /* port in chain ? */
870 if (!interface->ifport) {
871 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
874 /* goto end of chain */
875 ifport = interface->ifport;
877 ifport = ifport->next;
878 ifport->dialmax = atoi(value);
881 static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
883 if (!value || !value[0]) {
884 SPRINT(interface_error, "Error in %s (line %d): Missing tones directory.\n", filename, line);
887 SCPY(interface->tones_dir, value);
891 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
893 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'gsm-bs' for base station or 'gsm-ms' for mobile station interface!\n", filename, line, parameter);
896 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
899 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
902 struct interface *searchif;
904 interface->gsm_bs = 1;
907 interface->gsm_bs_name[0] = '\0';
909 SCPY(interface->gsm_bs_name, value);
911 /* check if name is used multiple times */
912 searchif = interface_newlist;
914 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_bs_name, interface->gsm_bs_name)) {
915 SPRINT(interface_error, "Error in %s (line %d): network '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_bs_name, searchif->gsm_bs_name);
918 searchif = searchif->next;
924 static int inter_gsm_bs_hr(struct interface *interface, char *filename, int line, char *parameter, char *value)
927 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
930 interface->gsm_bs_hr = 1;
935 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
938 SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
941 struct interface *searchif;
943 interface->gsm_ms = 1;
946 if (!value || !value[0]) {
947 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
950 SCPY(interface->gsm_ms_name, value);
952 /* check if name is used multiple times */
953 searchif = interface_newlist;
955 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
956 SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_ms_name, searchif->gsm_ms_name);
959 searchif = searchif->next;
965 static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
968 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
976 if (!value || !value[0]) {
977 SPRINT(interface_error, "Error in %s (line %d): Missing SIP local peer.\n", filename, line);
980 p = get_seperated(value);
981 SCPY(interface->sip_local_peer, value);
982 SCPY(interface->sip_remote_peer, p);
987 static int inter_authenticate(struct interface *interface, char *filename, int line, char *parameter, char *value)
990 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
995 if (!interface->sip) {
996 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1001 if (!value || !value[0]) {
1002 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1005 p = get_seperated(value);
1007 SPRINT(interface_error, "Error in %s (line %d): Missing SIP password.\n", filename, line);
1010 q = get_seperated(p);
1011 SCPY(interface->sip_auth_user, value);
1012 SCPY(interface->sip_auth_password, p);
1014 SCPY(interface->sip_auth_realm, q);
1019 static int options_interval(struct interface *interface, char *filename, int line, char *parameter, char *value)
1022 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1025 if (!interface->sip) {
1026 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1030 if (!value || !value[0]) {
1031 SPRINT(interface_error, "Error in %s (line %d): Missing options interval.\n", filename, line);
1034 interface->sip_options_interval = atoi(value);
1039 static int options_asserted_id(struct interface *interface, char *filename, int line, char *parameter, char *value)
1042 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1045 if (!interface->sip) {
1046 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1050 if (!value || !value[0]) {
1051 SPRINT(interface_error, "Error in %s (line %d): Missing asserted caller ID.\n", filename, line);
1054 SCPY(interface->sip_asserted_id, value);
1059 static int options_public(struct interface *interface, char *filename, int line, char *parameter, char *value)
1062 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1065 if (!interface->sip) {
1066 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1069 if (interface->sip_stun_server[0]) {
1070 SPRINT(interface_error, "Error in %s (line %d): Don't specify STUN, if you want to define public IP.\n", filename, line);
1074 if (!value || !value[0]) {
1075 SPRINT(interface_error, "Error in %s (line %d): Missing public IP.\n", filename, line);
1078 SCPY(interface->sip_public_ip, value);
1083 static int options_stun(struct interface *interface, char *filename, int line, char *parameter, char *value)
1086 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1091 if (!interface->sip) {
1092 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1095 if (interface->sip_public_ip[0]) {
1096 SPRINT(interface_error, "Error in %s (line %d): Don't specify public IP, if you want to define STUN.\n", filename, line);
1100 if (!value || !value[0]) {
1101 SPRINT(interface_error, "Error in %s (line %d): Missing STUN server.\n", filename, line);
1104 p = get_seperated(value);
1106 SPRINT(interface_error, "Error in %s (line %d): Missing STUN timer.\n", filename, line);
1109 SCPY(interface->sip_stun_server, value);
1110 interface->sip_stun_interval = atoi(p);
1115 static int inter_rtp_ports(struct interface *interface, char *filename, int line, char *parameter, char *value)
1118 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1123 if (!interface->sip) {
1124 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1129 if (!value || !value[0]) {
1130 SPRINT(interface_error, "Error in %s (line %d): Missing 'from' port.\n", filename, line);
1133 p = get_seperated(value);
1135 SPRINT(interface_error, "Error in %s (line %d): Missing 'to' port.\n", filename, line);
1138 interface->rtp_port_from = atoi(value);
1139 interface->rtp_port_to = atoi(p);
1144 static int inter_register(struct interface *interface, char *filename, int line, char *parameter, char *value)
1147 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1152 if (!interface->sip) {
1153 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1158 if (!value || !value[0]) {
1159 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1162 p = get_seperated(value);
1164 SPRINT(interface_error, "Error in %s (line %d): Missing SIP host\n", filename, line);
1167 q = get_seperated(p);
1169 interface->sip_register_interval = 0;
1171 interface->sip_register_interval = atoi(q);
1172 interface->sip_register = 1;
1173 SCPY(interface->sip_register_user, value);
1174 SCPY(interface->sip_register_host, p);
1179 static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1184 if (interface->gsm_bs)
1192 SPRINT(interface_error, "Error in %s (line %d): Interface does not support RTP\n", filename, line);
1196 if (interface->app != EAPP_TYPE_BRIDGE) {
1197 SPRINT(interface_error, "Error in %s (line %d): '%s' requires previous 'bridge' parameter.\n", filename, line, parameter);
1201 interface->rtp_bridge = 1;
1206 static int inter_rtp_payload(struct interface *interface, char *filename, int line, char *parameter, char *value)
1209 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
1212 if (!interface->gsm_bs) {
1213 SPRINT(interface_error, "Error in %s (line %d): This parameter only works for GSM BS side interface\n", filename, line);
1216 if (!interface->rtp_bridge) {
1217 SPRINT(interface_error, "Error in %s (line %d): This parameter only works here, if RTP bridging is enabled\n", filename, line);
1221 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one payload type\n", filename, line, parameter);
1224 if (interface->gsm_bs_payloads == sizeof(interface->gsm_bs_payload_types)) {
1225 SPRINT(interface_error, "Error in %s (line %d): Too many payload types defined\n", filename, line);
1228 interface->gsm_bs_payload_types[interface->gsm_bs_payloads++] = atoi(value);
1234 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
1236 struct interface_port *ifport;
1238 /* port in chain ? */
1239 if (!interface->ifport) {
1240 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1243 /* goto end of chain */
1244 ifport = interface->ifport;
1246 ifport = ifport->next;
1247 ifport->nonotify = 1;
1251 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
1253 struct interface_port *ifport;
1256 /* port in chain ? */
1257 if (!interface->ifport) {
1258 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1261 /* goto end of chain */
1262 ifport = interface->ifport;
1264 ifport = ifport->next;
1265 ifport->ss5 |= SS5_ENABLE;
1266 while((element = strsep(&value, " "))) {
1267 if (element[0] == '\0')
1269 if (!strcasecmp(element, "connect"))
1270 ifport->ss5 |= SS5_FEATURE_CONNECT;
1272 if (!strcasecmp(element, "nodisconnect"))
1273 ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1275 if (!strcasecmp(element, "releaseguardtimer"))
1276 ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1278 if (!strcasecmp(element, "bell"))
1279 ifport->ss5 |= SS5_FEATURE_BELL;
1281 if (!strcasecmp(element, "pulsedialing"))
1282 ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1284 if (!strcasecmp(element, "delay"))
1285 ifport->ss5 |= SS5_FEATURE_DELAY;
1287 if (!strcasecmp(element, "release"))
1288 ifport->ss5 |= SS5_FEATURE_RELEASE;
1290 if (!strcasecmp(element, "mute-rx"))
1291 ifport->ss5 |= SS5_FEATURE_MUTE_RX;
1293 if (!strcasecmp(element, "mute-tx"))
1294 ifport->ss5 |= SS5_FEATURE_MUTE_TX;
1296 if (!strcasecmp(element, "quality"))
1297 ifport->ss5 |= SS5_FEATURE_QUALITY;
1299 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1306 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1308 struct interface *searchif;
1311 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1314 searchif = interface_newlist;
1316 if (interface->remote && !strcmp(interface->remote_app, value)) {
1317 SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses remote application '%s'.\n", filename, line, interface->name, value);
1320 searchif = searchif->next;
1323 /* goto end of chain again to set application name */
1324 interface->remote = 1;
1325 SCPY(interface->remote_app, value);
1329 static int inter_context(struct interface *interface, char *filename, int line, char *parameter, char *value)
1332 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application context as value.\n", filename, line, parameter);
1335 SCPY(interface->remote_context, value);
1339 static int inter_pots_flash(struct interface *interface, char *filename, int line, char *parameter, char *value)
1341 struct interface_port *ifport;
1343 /* port in chain ? */
1344 if (!interface->ifport) {
1345 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1348 /* goto end of chain */
1349 ifport = interface->ifport;
1351 ifport = ifport->next;
1353 ifport->pots_flash = 1;
1356 static int inter_pots_ring(struct interface *interface, char *filename, int line, char *parameter, char *value)
1358 struct interface_port *ifport;
1360 /* port in chain ? */
1361 if (!interface->ifport) {
1362 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1365 /* goto end of chain */
1366 ifport = interface->ifport;
1368 ifport = ifport->next;
1370 ifport->pots_ring = 1;
1373 static int inter_pots_transfer(struct interface *interface, char *filename, int line, char *parameter, char *value)
1375 struct interface_port *ifport;
1377 /* port in chain ? */
1378 if (!interface->ifport) {
1379 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1382 /* goto end of chain */
1383 ifport = interface->ifport;
1385 ifport = ifport->next;
1387 ifport->pots_transfer = 1;
1390 static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
1392 interface->shutdown = 1;
1396 static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1398 if (!value || !value[0]) {
1399 SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
1402 interface->app = EAPP_TYPE_BRIDGE;
1403 SCPY(interface->bridge_if, value);
1410 * structure of parameters
1412 struct interface_param interface_param[] = {
1413 { "extension", &inter_extension, "",
1414 "If keyword is given, calls to interface are handled as internal extensions."},
1416 { "extern", &inter_extern, "",
1417 "If keyword is given, this interface will be used for external calls.\n"
1418 "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1419 "Calls forwarded by extension's 'settings' also require an external interface."},
1421 {"tones", &inter_tones, "yes | no",
1422 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1424 {"earlyb", &inter_earlyb, "yes | no",
1425 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1427 {"hunt", &inter_hunt, "linear | roundrobin",
1428 "Select the algorithm for selecting port with free channel."},
1430 {"port", &inter_port, "<number>",
1432 {"portnum", &inter_portnum, "<number>",
1433 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1434 {"portname", &inter_portname, "<name>",
1435 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1437 {"block", &inter_block, "",
1438 "If keyword is given, calls on this interface are blocked.\n"
1439 "This parameter must follow a 'port' parameter."},
1441 {"ptp", &inter_ptp, "",
1442 "The given port above is opened as point-to-point.\n"
1443 "This is required on NT-mode ports that are multipoint by default.\n"
1444 "This parameter must follow a 'port' parameter."},
1447 {"ptmp", &inter_ptmp, "",
1448 "The given port above is opened as point-to-multipoint.\n"
1449 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1450 "This parameter must follow a 'port' parameter."},
1453 {"nt", &inter_nt, "",
1454 "The given port above is opened in NT-mode.\n"
1455 "This is required on interfaces that support both NT-mode and TE-mode.\n"
1456 "This parameter must follow a 'port' parameter."},
1458 {"te-special", &inter_tespecial, "",
1459 "The given port uses a modified TE-mode.\n"
1460 "All information elements that are allowed Network->User will then be\n"
1461 "transmitted User->Network also. This is usefull to pass all informations\n"
1462 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1463 "Note that this is not compliant with ISDN protocol.\n"
1464 "This parameter must follow a 'port' parameter."},
1466 {"layer1hold", &inter_l1hold, "yes | no",
1467 "The given port will not release layer 1 after layer 2 is down.\n"
1468 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1469 "This parameter must follow a 'port' parameter."},
1471 {"layer2hold", &inter_l2hold, "yes | no",
1472 "The given port will continuously try to establish layer 2 link and hold it.\n"
1473 "It is required for PTP links in most cases, therefore it is default.\n"
1474 "This parameter must follow a 'port' parameter."},
1476 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1477 "Channel selection list for all outgoing calls to the interface.\n"
1478 "A free channels is searched in order of appearance.\n"
1479 "This parameter must follow a 'port' parameter.\n"
1480 " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1481 " -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1482 " <number>[,...] - List of channels to search.\n"
1483 " free - Select any free channel\n"
1484 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1485 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1487 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1488 "Channel selection list for all incoming calls from the interface.\n"
1489 "A free channels is accepted if in the list.\n"
1490 "If any channel was requested, the first free channel found is selected.\n"
1491 "This parameter must follow a 'port' parameter.\n"
1492 " <number>[,...] - List of channels to accept.\n"
1493 " free - Accept any free channel"},
1495 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1496 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1497 "The default is 120 seconds for all states. Use 0 to disable.\n"
1498 "This parameter must follow a 'port' parameter."},
1500 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1501 "Incoming caller ID is checked against given MSN numbers.\n"
1502 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1504 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1505 "Adds an entry for incoming calls to the caller ID screen list.\n"
1506 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1507 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1508 "additional digits.\n"
1509 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1512 " unknown | subsciber | national | international - Change caller ID type.\n"
1513 " present | restrict - Change presentation of caller ID."},
1515 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1516 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1517 "See 'screen-in' for help."},
1519 {"nodtmf", &inter_nodtmf, "",
1520 "Disables DTMF detection for this interface.\n"
1521 "This parameter must follow a 'port' parameter."},
1523 {"dtmf-threshold", &inter_dtmf_threshold, "",
1524 "Set threshold value for minimum DTMF tone level.\n"
1525 "This parameter must follow a 'port' parameter."},
1527 {"filter", &inter_filter, "<filter> <parameters>",
1528 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1529 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1530 "pipeline <string> - Sets echo cancelation pipeline.\n"
1531 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1533 {"dialmax", &inter_dialmax, "<digits>",
1534 "Limits the number of digits in setup/information message."},
1536 {"tones-dir", &inter_tones_dir, "<path>",
1537 "Overrides the given tone_dir in options.conf.\n"
1538 "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1539 {"tones_dir", &inter_tones_dir, "<path>",
1540 "Same as tones-dir"},
1542 {"gsm", &inter_gsm, "",
1544 {"gsm-bs", &inter_gsm_bs, "[<socket name>]",
1545 "Sets up GSM base station interface for using OpenBSC.\n"
1546 "The socket is /tmp/bsc_mncc by default. If socket name is given, the socket will be\n"
1547 "extended to /tmp/bsc_mncc_<socket name>."},
1548 {"hr", &inter_gsm_bs_hr, "",
1549 "Enable and prefer half rate for mobile terminating calls."},
1550 {"gsm-ms", &inter_gsm_ms, "<socket name>",
1551 "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1552 "The socket will be /tmp/ms_mncc_<socket name>."},
1554 {"sip", &inter_sip, "<local IP/host>[:port] [<remote IP/host>[port]]",
1555 "Sets up SIP interface that represents one SIP endpoint.\n"
1556 "If the remote IP/host is omitted, a client must register first to us."},
1557 {"register", &inter_register, "<user> <host> [register-interval]",
1558 "Registers to given SIP registrar.\n"
1559 "Optionally give RE-REGISTER interval time in seconds.\n"
1560 "The exire value is set 60 seconds ahead this interval, then."},
1561 {"authenticate", &inter_authenticate, "<user> <password> [realm]",
1562 "Defines SIP user and password for authentication.\n"
1563 "If no remote IP was give, we are SIP gateway, so realm must be given also."},
1564 {"options-interval", &options_interval, "<interval> | 0",
1565 "Defines SIP timer to send OPTIONS messages to keepalive INVITE sessions."},
1566 {"asserted-id", &options_asserted_id, "<caller-id>",
1567 "Defines SIP's asserted-id in INVITE message."},
1568 {"public", &options_public, "<server> <interval>",
1569 "Defines public IP, if this endpoint is behind NAT firewall."},
1570 {"stun", &options_stun, "<server> <interval>",
1571 "Defines STUN server to resolv real local IP.\n"
1572 "The interval is used to check if IP has changed. (use 300)"},
1573 {"rtp-ports", &inter_rtp_ports, "<port from> <port to>",
1574 "Defines the range of ports to be used for RTP. This overrides the default."},
1576 {"rtp-bridge", &inter_rtp_bridge, "",
1577 "Enables RTP bridging directly from this interface.\n"
1578 "This only works if both bridged interfaces use RTP, e.g. between gsm-bs and sip.\n"
1579 "This parameter must follow a 'bridge' parameter."},
1581 not needed, since ms defines what is supports and remote (sip) tells what is selected
1582 {"rtp-payload", &inter_rtp_payload, "<codec>",
1583 "Define RTP payload to use. Only valid in conjuntion with gsm-bs!\n"
1584 "If multiple payloads are defined, the first has highest priority.\n"
1585 "If none are defined, GSM fullrate V1 (type 3) is assumed."},
1588 {"nonotify", &inter_nonotify, "",
1589 "Prevents sending notify messages to this interface. A call placed on hold will\n"
1590 "Not affect the remote end (phone or telcom switch).\n"
1591 "This parameter must follow a 'port' parameter."},
1593 {"bridge", &inter_bridge, "<destination interface>",
1594 "Define bridge application for this interface. All calls received on this\n"
1595 "interface will be directly bridged to the given destination interface.\n"
1596 "There will be no PBX application, nor routing."},
1599 {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1600 "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1601 "This feature causes CPU load to rise and has no practical intend.\n"
1602 "If you don't know what it is, you don't need it.\n"
1603 "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1604 " connect - Connect incomming call to throughconnect audio, if required.\n"
1605 " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1606 " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1607 " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1608 " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1609 " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1610 " release - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1611 " mutes-rx - Mute received 2600 and 2400 Hz tones when detected. (more realistic)\n"
1612 " mutes-tx - Mute received 2600 and 2400 Hz tones while transmitting reply tone. (more hackable)"},
1615 {"remote", &inter_remote, "<application>",
1616 "Sets up an interface that communicates with the remote application.\n"
1617 "Use \"asterisk\" to use chan_lcr as remote application."},
1618 {"context", &inter_context, "<context>",
1619 "Give context for calls to application."},
1621 {"pots-flash", &inter_pots_flash, "",
1622 "Allow flash button to hold an active call and setup a new call.\n"
1623 "Ihis parameter only appies to POTS type of interfaces\n"
1624 "This parameter must follow a 'port' parameter."},
1625 {"pots-ring-after-hangup", &inter_pots_ring, "",
1626 "Allow ringing of last hold call after hangup. Other calls on hold will not be\n"
1628 "Ihis parameter only appies to POTS type of interfaces\n"
1629 "This parameter must follow a 'port' parameter."},
1630 {"pots-transfer-after-hangup", &inter_pots_transfer, "",
1631 "If two calls on hold, both are connected after hangup.\n"
1632 "If one call is on hold and another one alerting, call on hold is tranfered.\n"
1633 "Ihis parameter only appies to POTS type of interfaces\n"
1634 "This parameter must follow a 'port' parameter."},
1636 {"shutdown", &inter_shutdown, "",
1637 "Interface will not be loaded when processing interface.conf"},
1639 {NULL, NULL, NULL, NULL}
1644 * read settings from interface.conf
1646 char interface_error[256];
1647 struct interface *read_interfaces(void)
1652 unsigned int line, i;
1654 struct interface *interface = NULL, /* in case no interface */
1655 **interfacep = &interface_newlist;
1656 char parameter[128];
1658 int expecting = 1; /* expecting new interface */
1659 struct interface_param *ifparam;
1661 if (interface_newlist != NULL)
1662 FATAL("list is not empty.\n");
1663 interface_error[0] = '\0';
1664 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1666 if (!(fp = fopen(filename,"r"))) {
1667 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1672 while((GETLINE(buffer, fp))) {
1676 while(*p <= 32) { /* skip spaces */
1681 if (*p==0 || *p=='#') /* ignore comments and empty line */
1686 i=0; /* read parameter */
1688 if (i+1 >= sizeof(parameter)) {
1689 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1692 parameter[i+1] = '\0';
1693 parameter[i++] = *p++;
1696 while(*p <= 32) { /* skip spaces */
1702 if (*p!=0 && *p!='#') { /* missing name */
1703 i=0; /* read until end */
1704 while(*p!=0 && *p!='#') {
1705 if (i+1 >= sizeof(value)) {
1706 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1713 /* remove trailing spaces from value */
1715 if (value[i-1]==0 || value[i-1]>32)
1722 /* check for interface name as first statement */
1723 if (expecting && parameter[0]!='[') {
1724 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1729 /* check for new interface */
1730 if (parameter[0] == '[') {
1731 if (parameter[strlen(parameter)-1] != ']') {
1732 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1735 parameter[strlen(parameter)-1] = '\0';
1737 /* check if interface name already exists */
1738 interface = interface_newlist;
1740 if (!strcasecmp(interface->name, parameter+1)) {
1741 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1744 interface = interface->next;
1747 /* append interface to new list */
1748 interface = (struct interface *)MALLOC(sizeof(struct interface));
1751 /* name interface */
1752 SCPY(interface->name, parameter+1);
1755 *interfacep = interface;
1756 interfacep = &interface->next;
1761 ifparam = interface_param;
1762 while(ifparam->name) {
1763 if (!strcasecmp(parameter, ifparam->name)) {
1764 if (ifparam->func(interface, filename, line, parameter, value))
1773 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1778 return(interface_newlist);
1780 PERROR_RUNTIME("%s", interface_error);
1782 free_interfaces(interface_newlist);
1783 interface_newlist = NULL;
1789 * freeing chain of interfaces
1791 void free_interfaces(struct interface *interface)
1794 struct interface_port *ifport;
1795 struct select_channel *selchannel;
1796 struct interface_msn *ifmsn;
1797 struct interface_screen *ifscreen;
1800 ifport = interface->ifport;
1802 selchannel = ifport->in_channel;
1805 selchannel = selchannel->next;
1806 FREE(temp, sizeof(struct select_channel));
1809 selchannel = ifport->out_channel;
1812 selchannel = selchannel->next;
1813 FREE(temp, sizeof(struct select_channel));
1817 ifport = ifport->next;
1818 FREE(temp, sizeof(struct interface_port));
1821 ifmsn = interface->ifmsn;
1824 ifmsn = ifmsn->next;
1825 FREE(temp, sizeof(struct interface_msn));
1828 ifscreen = interface->ifscreen_in;
1831 ifscreen = ifscreen->next;
1832 FREE(temp, sizeof(struct interface_screen));
1835 ifscreen = interface->ifscreen_out;
1838 ifscreen = ifscreen->next;
1839 FREE(temp, sizeof(struct interface_screen));
1843 interface = interface->next;
1844 FREE(temp, sizeof(struct interface));
1851 * defaults of ports if not specified by config
1853 static void set_mISDN_defaults(struct interface_port *ifport)
1855 /* default channel selection list */
1856 if (!ifport->out_channel)
1857 default_out_channel(ifport);
1858 if (!ifport->in_channel)
1859 default_in_channel(ifport);
1860 /* must force the channel on PTMP/NT ports */
1861 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1862 ifport->channel_force = 1;
1863 /* default is_tones */
1864 if (ifport->interface->is_tones)
1865 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1867 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1868 /* default is_earlyb */
1869 if (ifport->interface->is_earlyb)
1870 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1872 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1873 /* set locally flag */
1874 if (ifport->interface->extension)
1875 ifport->mISDNport->locally = 1;
1877 ifport->mISDNport->locally = 0;
1883 * all links between mISDNport and interface are made
1884 * unused mISDNports are closed, new mISDNports are opened
1885 * also set default select_channel lists
1887 void relink_interfaces(void)
1890 struct mISDNport *mISDNport;
1891 struct interface_port *ifport;
1893 struct interface *interface, *temp, *found;
1895 interface = interface_first;
1898 temp = interface_newlist;
1900 if (!strcmp(temp->name, interface->name))
1906 if (interface->gsm_ms)
1907 gsm_ms_delete(interface->gsm_ms_name);
1910 if (interface->gsm_bs)
1911 gsm_bs_delete(interface->gsm_bs_name);
1915 sip_exit_inst(interface);
1919 if (interface->sip) {
1920 /* move sip instance, if we keep interface */
1921 found->sip_inst = interface->sip_inst;
1922 interface->sip_inst = NULL;
1927 interface = interface->next;
1930 interface = interface_newlist;
1933 temp = interface_first;
1935 if (!strcmp(temp->name, interface->name))
1941 if (interface->gsm_ms)
1942 gsm_ms_new(interface);
1945 if (interface->gsm_bs)
1946 gsm_bs_new(interface);
1950 sip_init_inst(interface);
1953 interface = interface->next;
1957 /* unlink all mISDNports */
1958 mISDNport = mISDNport_first;
1960 mISDNport->ifport = NULL;
1961 mISDNport = mISDNport->next;
1964 /* relink existing mISDNports */
1965 interface = interface_newlist;
1967 ifport = interface->ifport;
1969 mISDNport = mISDNport_first;
1971 if (!strcmp(mISDNport->name, ifport->portname))
1972 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1973 if (mISDNport->portnum == ifport->portnum) {
1974 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1975 ifport->mISDNport = mISDNport;
1976 mISDNport->ifport = ifport;
1977 set_mISDN_defaults(ifport);
1979 mISDNport = mISDNport->next;
1981 ifport = ifport->next;
1983 interface = interface->next;
1986 /* close unused mISDNports */
1988 mISDNport = mISDNport_first;
1990 if (mISDNport->ifport == NULL) {
1991 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1993 mISDNport_close(mISDNport);
1996 mISDNport = mISDNport->next;
1999 /* open and link new mISDNports */
2000 interface = interface_newlist;
2002 ifport = interface->ifport;
2004 if (!ifport->mISDNport) {
2005 if (!interface->shutdown) {
2006 load_mISDN_port(ifport);
2011 ifport = ifport->next;
2013 interface = interface->next;
2023 void load_mISDN_port(struct interface_port *ifport)
2025 struct mISDNport *mISDNport;
2028 mISDNport = mISDNport_open(ifport);
2031 ifport->mISDNport = mISDNport;
2032 mISDNport->ifport = ifport;
2033 /* set number and name */
2034 ifport->portnum = mISDNport->portnum;
2035 SCPY(ifport->portname, mISDNport->name);
2037 set_mISDN_defaults(ifport);
2038 /* load static port instances */
2039 mISDNport_static(mISDNport);
2041 ifport->block = 2; /* not available */
2047 * give summary of interface syntax
2049 void doc_interface(void)
2051 struct interface_param *ifparam;
2053 printf("Syntax overview\n");
2054 printf("---------------\n\n");
2056 printf("[<name>]\n");
2057 ifparam = interface_param;
2058 while(ifparam->name) {
2059 if (ifparam->name[0])
2060 printf("%s %s\n", ifparam->name, ifparam->usage);
2064 ifparam = interface_param;
2065 while(ifparam->name) {
2066 if (ifparam->name[0]) {
2067 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
2068 printf("%s\n", ifparam->help);
2076 * out==0: incoming caller id, out==1: outgoing caller id
2078 void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
2081 struct interface_msn *ifmsn;
2082 struct interface_screen *ifscreen;
2084 struct interface *interface = interface_first;
2086 interface = getinterfacebyname(interface_name);
2090 /* screen incoming caller id */
2092 /* check for MSN numbers, use first MSN if no match */
2094 ifmsn = interface->ifmsn;
2098 if (!strcmp(ifmsn->msn, id)) {
2101 ifmsn = ifmsn->next;
2104 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
2105 add_trace("msn", NULL, "%s", id);
2108 if (!ifmsn && msn1) { // not in list, first msn given
2109 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
2110 add_trace("msn", "given", "%s", id);
2111 add_trace("msn", "used", "%s", msn1);
2113 UNCPY(id, msn1, idsize);
2114 id[idsize-1] = '\0';
2118 /* check screen list */
2120 ifscreen = interface->ifscreen_out;
2122 ifscreen = interface->ifscreen_in;
2124 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
2125 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
2126 if (strchr(ifscreen->match,'%')) {
2127 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
2130 if (!strcmp(ifscreen->match, id))
2134 ifscreen = ifscreen->next;
2136 if (ifscreen) { // match
2137 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)");
2139 case INFO_NTYPE_UNKNOWN:
2140 add_trace("given", "type", "unknown");
2142 case INFO_NTYPE_SUBSCRIBER:
2143 add_trace("given", "type", "subscriber");
2145 case INFO_NTYPE_NATIONAL:
2146 add_trace("given", "type", "national");
2148 case INFO_NTYPE_INTERNATIONAL:
2149 add_trace("given", "type", "international");
2153 case INFO_PRESENT_ALLOWED:
2154 add_trace("given", "present", "allowed");
2156 case INFO_PRESENT_RESTRICTED:
2157 add_trace("given", "present", "restricted");
2159 case INFO_PRESENT_NOTAVAIL:
2160 add_trace("given", "present", "not available");
2163 add_trace("given", "id", "%s", id[0]?id:"<empty>");
2164 if (ifscreen->result_type != -1) {
2165 *type = ifscreen->result_type;
2167 case INFO_NTYPE_UNKNOWN:
2168 add_trace("used", "type", "unknown");
2170 case INFO_NTYPE_SUBSCRIBER:
2171 add_trace("used", "type", "subscriber");
2173 case INFO_NTYPE_NATIONAL:
2174 add_trace("used", "type", "national");
2176 case INFO_NTYPE_INTERNATIONAL:
2177 add_trace("used", "type", "international");
2181 if (ifscreen->result_present != -1) {
2182 *present = ifscreen->result_present;
2184 case INFO_PRESENT_ALLOWED:
2185 add_trace("used", "present", "allowed");
2187 case INFO_PRESENT_RESTRICTED:
2188 add_trace("used", "present", "restricted");
2190 case INFO_PRESENT_NOTAVAIL:
2191 add_trace("used", "present", "not available");
2195 if (strchr(ifscreen->match,'%')) {
2196 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
2197 UNCPY(id, ifscreen->result, idsize);
2198 id[idsize-1] = '\0';
2199 if (strchr(id,'%')) {
2200 *strchr(id,'%') = '\0';
2201 UNCAT(id, suffix, idsize);
2202 id[idsize-1] = '\0';
2205 UNCPY(id, ifscreen->result, idsize);
2206 id[idsize-1] = '\0';
2208 add_trace("used", "id", "%s", id[0]?id:"<empty>");
2213 struct interface *getinterfacebyname(const char *name)
2215 struct interface *interface = interface_first;
2218 if (!strcmp(interface->name, name))
2220 interface = interface->next;