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;
330 struct interface *searchif;
332 /* goto end of chain */
333 ifport = interface->ifport;
336 ifport = ifport->next;
339 /* check for port already assigned, but not for shared loop interface */
340 searchif = interface_newlist;
341 if (!!strcmp(value, options.loopback_lcr))
344 ifport = searchif->ifport;
346 if (!strcasecmp(ifport->portname, value)) {
347 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
350 ifport = ifport->next;
352 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);
370 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
372 struct interface_port *ifport;
374 /* port in chain ? */
375 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")) {
386 if (!strcmp(value, "no")) {
389 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
394 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
396 struct interface_port *ifport;
398 /* port in chain ? */
399 if (!interface->ifport) {
400 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
403 /* goto end of chain */
404 ifport = interface->ifport;
406 ifport = ifport->next;
407 if (!strcmp(value, "yes")) {
410 if (!strcmp(value, "no")) {
413 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
418 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
420 struct interface_port *ifport;
421 struct select_channel *selchannel, **selchannelp;
425 /* port in chain ? */
426 if (!interface->ifport) {
427 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
430 /* goto end of chain */
431 ifport = interface->ifport;
433 ifport = ifport->next;
437 p = get_seperated(p);
438 if (!strcasecmp(el, "force")) {
439 ifport->channel_force = 1;
440 if (ifport->out_channel) {
441 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
445 if (!strcasecmp(el, "any")) {
449 if (!strcasecmp(el, "free")) {
453 if (!strcasecmp(el, "no")) {
457 val = get_number(el);
459 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);
463 if (val<1 || val==16 || val>126) {
464 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
468 /* add to select-channel list */
469 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
472 selchannel->channel = val;
474 selchannelp = &ifport->out_channel;
476 selchannelp = &((*selchannelp)->next);
477 *selchannelp = selchannel;
482 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
484 struct interface_port *ifport;
485 struct select_channel *selchannel, **selchannelp;
489 /* port in chain ? */
490 if (!interface->ifport) {
491 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
494 /* goto end of chain */
495 ifport = interface->ifport;
497 ifport = ifport->next;
501 p = get_seperated(p);
502 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE) {
503 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
506 if (!strcasecmp(el, "free")) {
510 val = get_number(el);
512 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
516 if (val<1 || val==16 || val>126) {
517 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
521 /* add to select-channel list */
522 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
525 selchannel->channel = val;
527 selchannelp = &ifport->in_channel;
529 selchannelp = &((*selchannelp)->next);
530 *selchannelp = selchannel;
535 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
537 struct interface_port *ifport;
538 // struct select_channel *selchannel, **selchannelp;
542 /* port in chain ? */
543 if (!interface->ifport) {
544 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
547 /* goto end of chain */
548 ifport = interface->ifport;
550 ifport = ifport->next;
554 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
558 p = get_seperated(p);
559 ifport->tout_setup = atoi(el);
563 p = get_seperated(p);
564 ifport->tout_dialing = atoi(el);
568 p = get_seperated(p);
569 ifport->tout_proceeding = atoi(el);
573 p = get_seperated(p);
574 ifport->tout_alerting = atoi(el);
578 p = get_seperated(p);
579 ifport->tout_disconnect = atoi(el);
582 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
584 struct interface_msn *ifmsn, **ifmsnp;
588 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
591 if (interface->ifscreen_in) {
592 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
600 p = get_seperated(p);
601 /* add MSN to list */
602 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
605 SCPY(ifmsn->msn, el);
607 ifmsnp = &interface->ifmsn;
609 ifmsnp = &((*ifmsnp)->next);
614 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
616 struct interface_screen *ifscreen;
620 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
623 /* add screen entry to list*/
624 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
626 ifscreen->match_type = -1; /* unchecked */
627 ifscreen->match_present = -1; /* unchecked */
628 ifscreen->result_type = -1; /* unchanged */
629 ifscreen->result_present = -1; /* unchanged */
632 ifscreenp = &((*ifscreenp)->next);
633 *ifscreenp = ifscreen;
634 // printf("interface=%s\n", interface->name);
639 p = get_seperated(p);
640 if (!strcasecmp(el, "unknown")) {
641 if (ifscreen->match_type != -1) {
643 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
646 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
648 if (!strcasecmp(el, "subscriber")) {
649 if (ifscreen->match_type != -1)
651 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
653 if (!strcasecmp(el, "national")) {
654 if (ifscreen->match_type != -1)
656 ifscreen->match_type = INFO_NTYPE_NATIONAL;
658 if (!strcasecmp(el, "international")) {
659 if (ifscreen->match_type != -1)
661 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
663 if (!strcasecmp(el, "allowed")) {
664 if (ifscreen->match_present != -1) {
666 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
669 ifscreen->match_present = INFO_PRESENT_ALLOWED;
671 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
672 if (ifscreen->match_present != -1)
674 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
676 SCPY(ifscreen->match, el);
677 /* check for % at the end */
678 if (strchr(el, '%')) {
679 if (strchr(el, '%') != el+strlen(el)-1) {
680 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
687 if (ifscreen->match[0] == '\0') {
688 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
694 p = get_seperated(p);
695 if (!strcasecmp(el, "unknown")) {
696 if (ifscreen->result_type != -1)
698 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
700 if (!strcasecmp(el, "subscriber")) {
701 if (ifscreen->result_type != -1)
703 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
705 if (!strcasecmp(el, "national")) {
706 if (ifscreen->result_type != -1)
708 ifscreen->result_type = INFO_NTYPE_NATIONAL;
710 if (!strcasecmp(el, "international")) {
711 if (ifscreen->result_type != -1)
713 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
715 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
716 if (ifscreen->result_present != -1)
718 ifscreen->result_present = INFO_PRESENT_ALLOWED;
720 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
721 if (ifscreen->result_present != -1)
723 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
725 SCPY(ifscreen->result, el);
726 /* check for % at the end */
727 if (strchr(el, '%')) {
728 if (strchr(el, '%') != el+strlen(el)-1) {
729 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
736 if (ifscreen->result[0] == '\0') {
737 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
742 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
744 if (interface->ifmsn) {
745 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
749 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
751 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
753 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
755 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
757 struct interface_port *ifport;
759 /* port in chain ? */
760 if (!interface->ifport) {
761 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
764 /* goto end of chain */
765 ifport = interface->ifport;
767 ifport = ifport->next;
771 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
775 /* seperate parameter from filter */
781 while(*p > 0 && *p <= 32)
785 if (!strcasecmp(value, "gain")) {
791 while(*q > 0 && *q <= 32)
794 if (*p == 0 || *q == 0) {
795 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
798 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
799 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
802 interface->tx_gain = atoi(p);
803 interface->rx_gain = atoi(q);
805 if (!strcasecmp(value, "pipeline")) {
807 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
810 SCPY(interface->pipeline, p);
812 if (!strcasecmp(value, "blowfish")) {
813 unsigned char key[56];
816 if (!!strncmp(p, "0x", 2)) {
817 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
824 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
827 if (*p >= '0' && *p <= '9')
828 key[l] = (*p-'0')<<4;
829 else if (*p >= 'a' && *p <= 'f')
830 key[l] = (*p-'a'+10)<<4;
831 else if (*p >= 'A' && *p <= 'F')
832 key[l] = (*p-'A'+10)<<4;
835 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);
840 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);
843 if (*p >= '0' && *p <= '9')
844 key[l] = (*p-'0')<<4;
845 else if (*p >= 'a' && *p <= 'f')
846 key[l] = (*p-'a'+10)<<4;
847 else if (*p >= 'A' && *p <= 'F')
848 key[l] = (*p-'A'+10)<<4;
855 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);
858 memcpy(interface->bf_key, key, l);
859 interface->bf_len = l;
861 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
866 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
868 struct interface_port *ifport;
870 /* port in chain ? */
871 if (!interface->ifport) {
872 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
875 /* goto end of chain */
876 ifport = interface->ifport;
878 ifport = ifport->next;
879 ifport->dialmax = atoi(value);
882 static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
884 struct interface_port *ifport;
886 /* port in chain ? */
887 if (!interface->ifport) {
888 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
891 /* goto end of chain */
892 ifport = interface->ifport;
894 ifport = ifport->next;
895 SCPY(ifport->tones_dir, value);
898 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
900 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);
903 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
906 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
909 struct interface *searchif;
911 searchif = interface_newlist;
913 if (searchif->gsm_bs) {
914 SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses gsm BS side.\n", filename, line, searchif->name);
917 searchif = searchif->next;
920 /* goto end of chain again to set gsmflag */
921 interface->gsm_bs = 1;
926 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
929 SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
932 struct interface *searchif;
934 interface->gsm_ms = 1;
937 if (!value || !value[0]) {
938 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
941 SCPY(interface->gsm_ms_name, value);
943 /* check if name is used multiple times */
944 searchif = interface_newlist;
946 if (!strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
947 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);
950 searchif = searchif->next;
956 static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
959 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
967 if (!value || !value[0]) {
968 SPRINT(interface_error, "Error in %s (line %d): Missing SIP local IP.\n", filename, line);
971 p = get_seperated(value);
973 SPRINT(interface_error, "Error in %s (line %d): Missing SIP remote IP.\n", filename, line);
976 SCPY(interface->sip_local_peer, value);
977 SCPY(interface->sip_remote_peer, p);
982 static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
987 if (interface->gsm_bs)
995 SPRINT(interface_error, "Error in %s (line %d): Interface does not support RTP\n", filename, line);
998 interface->rtp_bridge = 1;
1003 static int inter_rtp_payload(struct interface *interface, char *filename, int line, char *parameter, char *value)
1006 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
1009 if (!interface->gsm_bs) {
1010 SPRINT(interface_error, "Error in %s (line %d): This parameter only works for GSM BS side interface\n", filename, line);
1013 if (!interface->rtp_bridge) {
1014 SPRINT(interface_error, "Error in %s (line %d): This parameter only works here, if RTP bridging is enabled\n", filename, line);
1018 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one payload type\n", filename, line, parameter);
1021 if (interface->gsm_bs_payloads == sizeof(interface->gsm_bs_payload_types)) {
1022 SPRINT(interface_error, "Error in %s (line %d): Too many payload types defined\n", filename, line);
1025 interface->gsm_bs_payload_types[interface->gsm_bs_payloads++] = atoi(value);
1031 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
1033 struct interface_port *ifport;
1035 /* port in chain ? */
1036 if (!interface->ifport) {
1037 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1040 /* goto end of chain */
1041 ifport = interface->ifport;
1043 ifport = ifport->next;
1044 ifport->nonotify = 1;
1048 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
1050 struct interface_port *ifport;
1053 /* port in chain ? */
1054 if (!interface->ifport) {
1055 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1058 /* goto end of chain */
1059 ifport = interface->ifport;
1061 ifport = ifport->next;
1062 ifport->ss5 |= SS5_ENABLE;
1063 while((element = strsep(&value, " "))) {
1064 if (element[0] == '\0')
1066 if (!strcasecmp(element, "connect"))
1067 ifport->ss5 |= SS5_FEATURE_CONNECT;
1069 if (!strcasecmp(element, "nodisconnect"))
1070 ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1072 if (!strcasecmp(element, "releaseguardtimer"))
1073 ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1075 if (!strcasecmp(element, "bell"))
1076 ifport->ss5 |= SS5_FEATURE_BELL;
1078 if (!strcasecmp(element, "pulsedialing"))
1079 ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1081 if (!strcasecmp(element, "delay"))
1082 ifport->ss5 |= SS5_FEATURE_DELAY;
1084 if (!strcasecmp(element, "starrelease"))
1085 ifport->ss5 |= SS5_FEATURE_STAR_RELEASE;
1087 if (!strcasecmp(element, "suppress"))
1088 ifport->ss5 |= SS5_FEATURE_SUPPRESS;
1090 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1097 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1099 struct interface_port *ifport;
1100 struct interface *searchif;
1103 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1106 searchif = interface_newlist;
1108 ifport = searchif->ifport;
1110 if (ifport->remote && !strcmp(ifport->remote_app, value)) {
1111 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses remote application '%s'.\n", filename, line, ifport->portname, value);
1114 ifport = ifport->next;
1116 searchif = searchif->next;
1120 if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
1123 /* goto end of chain again to set application name */
1124 ifport = interface->ifport;
1126 ifport = ifport->next;
1128 SCPY(ifport->remote_app, value);
1132 static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
1134 interface->shutdown = 1;
1138 static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1140 if (!value || !value[0]) {
1141 SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
1144 interface->app = EAPP_TYPE_BRIDGE;
1145 SCPY(interface->bridge_if, value);
1152 * structure of parameters
1154 struct interface_param interface_param[] = {
1155 { "extension", &inter_extension, "",
1156 "If keyword is given, calls to interface are handled as internal extensions."},
1158 { "extern", &inter_extern, "",
1159 "If keyword is given, this interface will be used for external calls.\n"
1160 "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1161 "Calls forwarded by extension's 'settings' also require an external interface."},
1163 {"tones", &inter_tones, "yes | no",
1164 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1166 {"earlyb", &inter_earlyb, "yes | no",
1167 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1169 {"hunt", &inter_hunt, "linear | roundrobin",
1170 "Select the algorithm for selecting port with free channel."},
1172 {"port", &inter_port, "<number>",
1174 {"portnum", &inter_portnum, "<number>",
1175 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1176 {"portname", &inter_portname, "<name>",
1177 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1179 {"block", &inter_block, "",
1180 "If keyword is given, calls on this interface are blocked.\n"
1181 "This parameter must follow a 'port' parameter."},
1183 {"ptp", &inter_ptp, "",
1184 "The given port above is opened as point-to-point.\n"
1185 "This is required on NT-mode ports that are multipoint by default.\n"
1186 "This parameter must follow a 'port' parameter."},
1189 {"ptmp", &inter_ptmp, "",
1190 "The given port above is opened as point-to-multipoint.\n"
1191 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1192 "This parameter must follow a 'port' parameter."},
1195 {"nt", &inter_nt, "",
1196 "The given port above is opened in NT-mode.\n"
1197 "This is required on interfaces that support both NT-mode and TE-mode.\n"
1198 "This parameter must follow a 'port' parameter."},
1200 {"te-special", &inter_tespecial, "",
1201 "The given port uses a modified TE-mode.\n"
1202 "All information elements that are allowed Network->User will then be\n"
1203 "transmitted User->Network also. This is usefull to pass all informations\n"
1204 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1205 "Note that this is not compliant with ISDN protocol.\n"
1206 "This parameter must follow a 'port' parameter."},
1208 {"layer1hold", &inter_l1hold, "yes | no",
1209 "The given port will not release layer 1 after layer 2 is down.\n"
1210 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1211 "This parameter must follow a 'port' parameter."},
1213 {"layer2hold", &inter_l2hold, "yes | no",
1214 "The given port will continuously try to establish layer 2 link and hold it.\n"
1215 "It is required for PTP links in most cases, therefore it is default.\n"
1216 "This parameter must follow a 'port' parameter."},
1218 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1219 "Channel selection list for all outgoing calls to the interface.\n"
1220 "A free channels is searched in order of appearance.\n"
1221 "This parameter must follow a 'port' parameter.\n"
1222 " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1223 " -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1224 " <number>[,...] - List of channels to search.\n"
1225 " free - Select any free channel\n"
1226 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1227 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1229 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1230 "Channel selection list for all incoming calls from the interface.\n"
1231 "A free channels is accepted if in the list.\n"
1232 "If any channel was requested, the first free channel found is selected.\n"
1233 "This parameter must follow a 'port' parameter.\n"
1234 " <number>[,...] - List of channels to accept.\n"
1235 " free - Accept any free channel"},
1237 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1238 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1239 "The default is 120 seconds for all states. Use 0 to disable.\n"
1240 "This parameter must follow a 'port' parameter.\n"},
1242 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1243 "Incoming caller ID is checked against given MSN numbers.\n"
1244 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1246 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1247 "Adds an entry for incoming calls to the caller ID screen list.\n"
1248 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1249 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1250 "additional digits.\n"
1251 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1254 " unknown | subsciber | national | international - Change caller ID type.\n"
1255 " present | restrict - Change presentation of caller ID."},
1257 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1258 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1259 "See 'screen-in' for help."},
1261 {"nodtmf", &inter_nodtmf, "",
1262 "Disables DTMF detection for this interface.\n"
1263 "This parameter must follow a 'port' parameter."},
1265 {"filter", &inter_filter, "<filter> <parameters>",
1266 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1267 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1268 "pipeline <string> - Sets echo cancelation pipeline.\n"
1269 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1271 {"dialmax", &inter_dialmax, "<digits>",
1272 "Limits the number of digits in setup/information message."},
1274 {"tones_dir", &inter_tones_dir, "<path>",
1275 "Overrides the given tone_dir in options.conf.\n"
1276 "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1278 {"gsm", &inter_gsm, "",
1280 {"gsm-bs", &inter_gsm_bs, "",
1281 "Sets up GSM base station interface for using OpenBSC."},
1282 {"gsm-ms", &inter_gsm_ms, "<socket>",
1283 "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1284 "The name of the MS folows the interface name.\n"
1285 "The socket is /tmp/osmocom_l2 by default and need to be changed when multiple\n"
1286 "MS interfaces are used."},
1287 {"sip", &inter_sip, "<local IP> <remote IP>",
1288 "Sets up SIP interface that represents one SIP endpoint.\n"
1289 "Give SIP configuration file."},
1290 {"rtp-bridge", &inter_rtp_bridge, "",
1291 "Enables RTP bridging directly from this interface.\n"
1292 "This only works, if both ends support RTP. (like gsm-bs and sip)"},
1294 not needed, since ms defines what is supports and remote (sip) tells what is selected
1295 {"rtp-payload", &inter_rtp_payload, "<codec>",
1296 "Define RTP payload to use. Only valid in conjuntion with gsm-bs!\n"
1297 "If multiple payloads are defined, the first has highest priority.\n"
1298 "If none are defined, GSM fullrate V1 (type 3) is assumed.\n"},
1300 {"nonotify", &inter_nonotify, "",
1301 "Prevents sending notify messages to this interface. A call placed on hold will\n"
1302 "Not affect the remote end (phone or telcom switch).\n"
1303 "This parameter must follow a 'port' parameter."},
1304 {"bridge", &inter_bridge, "<destination interface>",
1305 "Define bridge application for this interface. All calls received on this\n"
1306 "interface will be directly bridged to the given destination interface.\n"
1307 "There will be no PBX application, nor routing."},
1310 {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1311 "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1312 "This feature causes CPU load to rise and has no practical intend.\n"
1313 "If you don't know what it is, you don't need it.\n"
1314 "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1315 " connect - Connect incomming call to throughconnect audio, if required.\n"
1316 " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1317 " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1318 " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1319 " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1320 " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1321 " starrelease - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1322 " suppress - Suppress received tones, as they will be recognized."},
1325 {"remote", &inter_remote, "<application>",
1326 "Sets up an interface that communicates with the remote application.\n"
1327 "Use \"asterisk\" to use chan_lcr as remote application."},
1329 {"shutdown", &inter_shutdown, "",
1330 "Interface will not be loaded when processing interface.conf"},
1332 {NULL, NULL, NULL, NULL}
1337 * read settings from interface.conf
1339 char interface_error[256];
1340 struct interface *read_interfaces(void)
1345 unsigned int line, i;
1347 struct interface *interface = NULL, /* in case no interface */
1348 **interfacep = &interface_newlist;
1349 char parameter[128];
1351 int expecting = 1; /* expecting new interface */
1352 struct interface_param *ifparam;
1354 if (interface_newlist != NULL)
1355 FATAL("list is not empty.\n");
1356 interface_error[0] = '\0';
1357 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1359 if (!(fp = fopen(filename,"r"))) {
1360 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1365 while((GETLINE(buffer, fp))) {
1369 while(*p <= 32) { /* skip spaces */
1374 if (*p==0 || *p=='#') /* ignore comments and empty line */
1379 i=0; /* read parameter */
1381 if (i+1 >= sizeof(parameter)) {
1382 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1385 parameter[i+1] = '\0';
1386 parameter[i++] = *p++;
1389 while(*p <= 32) { /* skip spaces */
1395 if (*p!=0 && *p!='#') { /* missing name */
1396 i=0; /* read until end */
1397 while(*p!=0 && *p!='#') {
1398 if (i+1 >= sizeof(value)) {
1399 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1406 /* remove trailing spaces from value */
1408 if (value[i-1]==0 || value[i-1]>32)
1415 /* check for interface name as first statement */
1416 if (expecting && parameter[0]!='[') {
1417 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1422 /* check for new interface */
1423 if (parameter[0] == '[') {
1424 if (parameter[strlen(parameter)-1] != ']') {
1425 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1428 parameter[strlen(parameter)-1] = '\0';
1430 /* check if interface name already exists */
1431 interface = interface_newlist;
1433 if (!strcasecmp(interface->name, parameter+1)) {
1434 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1437 interface = interface->next;
1440 /* append interface to new list */
1441 interface = (struct interface *)MALLOC(sizeof(struct interface));
1444 /* name interface */
1445 SCPY(interface->name, parameter+1);
1448 *interfacep = interface;
1449 interfacep = &interface->next;
1454 ifparam = interface_param;
1455 while(ifparam->name) {
1456 if (!strcasecmp(parameter, ifparam->name)) {
1457 if (ifparam->func(interface, filename, line, parameter, value))
1466 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1471 return(interface_newlist);
1473 PERROR_RUNTIME("%s", interface_error);
1475 free_interfaces(interface_newlist);
1476 interface_newlist = NULL;
1482 * freeing chain of interfaces
1484 void free_interfaces(struct interface *interface)
1487 struct interface_port *ifport;
1488 struct select_channel *selchannel;
1489 struct interface_msn *ifmsn;
1490 struct interface_screen *ifscreen;
1493 ifport = interface->ifport;
1495 selchannel = ifport->in_channel;
1498 selchannel = selchannel->next;
1499 FREE(temp, sizeof(struct select_channel));
1502 selchannel = ifport->out_channel;
1505 selchannel = selchannel->next;
1506 FREE(temp, sizeof(struct select_channel));
1510 ifport = ifport->next;
1511 FREE(temp, sizeof(struct interface_port));
1514 ifmsn = interface->ifmsn;
1517 ifmsn = ifmsn->next;
1518 FREE(temp, sizeof(struct interface_msn));
1521 ifscreen = interface->ifscreen_in;
1524 ifscreen = ifscreen->next;
1525 FREE(temp, sizeof(struct interface_screen));
1528 ifscreen = interface->ifscreen_out;
1531 ifscreen = ifscreen->next;
1532 FREE(temp, sizeof(struct interface_screen));
1536 interface = interface->next;
1537 FREE(temp, sizeof(struct interface));
1544 * defaults of ports if not specified by config
1546 static void set_mISDN_defaults(struct interface_port *ifport)
1548 /* default channel selection list */
1549 if (!ifport->out_channel)
1550 default_out_channel(ifport);
1551 if (!ifport->in_channel)
1552 default_in_channel(ifport);
1553 /* must force the channel on PTMP/NT ports */
1554 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1555 ifport->channel_force = 1;
1556 /* default is_tones */
1557 if (ifport->interface->is_tones)
1558 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1560 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1561 /* default is_earlyb */
1562 if (ifport->interface->is_earlyb)
1563 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1565 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1566 /* set locally flag */
1567 if (ifport->interface->extension)
1568 ifport->mISDNport->locally = 1;
1570 ifport->mISDNport->locally = 0;
1576 * all links between mISDNport and interface are made
1577 * unused mISDNports are closed, new mISDNports are opened
1578 * also set default select_channel lists
1580 void relink_interfaces(void)
1583 struct mISDNport *mISDNport;
1584 struct interface_port *ifport;
1586 struct interface *interface, *temp;
1589 interface = interface_first;
1592 temp = interface_newlist;
1594 if (!strcmp(temp->name, interface->name))
1600 if (interface->gsm_ms)
1601 gsm_ms_delete(interface->gsm_ms_name);
1604 if (interface->gsm_bs)
1609 sip_exit_inst(interface);
1612 interface = interface->next;
1615 interface = interface_newlist;
1618 temp = interface_first;
1620 if (!strcmp(temp->name, interface->name))
1626 if (interface->gsm_ms)
1627 gsm_ms_new(interface);
1630 if (interface->gsm_bs)
1631 gsm_bs_init(interface);
1635 sip_init_inst(interface);
1638 interface = interface->next;
1642 /* unlink all mISDNports */
1643 mISDNport = mISDNport_first;
1645 mISDNport->ifport = NULL;
1646 mISDNport = mISDNport->next;
1649 /* relink existing mISDNports */
1650 interface = interface_newlist;
1652 ifport = interface->ifport;
1654 mISDNport = mISDNport_first;
1656 if (!strcmp(mISDNport->name, ifport->portname))
1657 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1658 if (mISDNport->portnum == ifport->portnum) {
1659 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1660 ifport->mISDNport = mISDNport;
1661 mISDNport->ifport = ifport;
1662 set_mISDN_defaults(ifport);
1664 mISDNport = mISDNport->next;
1666 ifport = ifport->next;
1668 interface = interface->next;
1671 /* close unused mISDNports */
1673 mISDNport = mISDNport_first;
1675 if (mISDNport->ifport == NULL) {
1676 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1678 mISDNport_close(mISDNport);
1681 mISDNport = mISDNport->next;
1684 /* open and link new mISDNports */
1685 interface = interface_newlist;
1687 ifport = interface->ifport;
1689 if (!ifport->mISDNport) {
1690 if (!interface->shutdown) {
1691 load_mISDN_port(ifport);
1696 ifport = ifport->next;
1698 interface = interface->next;
1708 void load_mISDN_port(struct interface_port *ifport)
1710 struct mISDNport *mISDNport;
1713 mISDNport = mISDNport_open(ifport);
1716 ifport->mISDNport = mISDNport;
1717 mISDNport->ifport = ifport;
1718 /* set number and name */
1719 ifport->portnum = mISDNport->portnum;
1720 SCPY(ifport->portname, mISDNport->name);
1722 set_mISDN_defaults(ifport);
1723 /* load static port instances */
1724 mISDNport_static(mISDNport);
1726 ifport->block = 2; /* not available */
1732 * give summary of interface syntax
1734 void doc_interface(void)
1736 struct interface_param *ifparam;
1738 printf("Syntax overview\n");
1739 printf("---------------\n\n");
1741 printf("[<name>]\n");
1742 ifparam = interface_param;
1743 while(ifparam->name) {
1744 if (ifparam->name[0])
1745 printf("%s %s\n", ifparam->name, ifparam->usage);
1749 ifparam = interface_param;
1750 while(ifparam->name) {
1751 if (ifparam->name[0]) {
1752 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1753 printf("%s\n", ifparam->help);
1761 * out==0: incoming caller id, out==1: outgoing caller id
1763 void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
1766 struct interface_msn *ifmsn;
1767 struct interface_screen *ifscreen;
1769 struct interface *interface = interface_first;
1771 interface = getinterfacebyname(interface_name);
1775 /* screen incoming caller id */
1777 /* check for MSN numbers, use first MSN if no match */
1779 ifmsn = interface->ifmsn;
1783 if (!strcmp(ifmsn->msn, id)) {
1786 ifmsn = ifmsn->next;
1789 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1790 add_trace("msn", NULL, "%s", id);
1793 if (!ifmsn && msn1) { // not in list, first msn given
1794 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1795 add_trace("msn", "given", "%s", id);
1796 add_trace("msn", "used", "%s", msn1);
1798 UNCPY(id, msn1, idsize);
1799 id[idsize-1] = '\0';
1803 /* check screen list */
1805 ifscreen = interface->ifscreen_out;
1807 ifscreen = interface->ifscreen_in;
1809 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1810 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
1811 if (strchr(ifscreen->match,'%')) {
1812 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1815 if (!strcmp(ifscreen->match, id))
1819 ifscreen = ifscreen->next;
1821 if (ifscreen) { // match
1822 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)");
1824 case INFO_NTYPE_UNKNOWN:
1825 add_trace("given", "type", "unknown");
1827 case INFO_NTYPE_SUBSCRIBER:
1828 add_trace("given", "type", "subscriber");
1830 case INFO_NTYPE_NATIONAL:
1831 add_trace("given", "type", "national");
1833 case INFO_NTYPE_INTERNATIONAL:
1834 add_trace("given", "type", "international");
1838 case INFO_PRESENT_ALLOWED:
1839 add_trace("given", "present", "allowed");
1841 case INFO_PRESENT_RESTRICTED:
1842 add_trace("given", "present", "restricted");
1844 case INFO_PRESENT_NOTAVAIL:
1845 add_trace("given", "present", "not available");
1848 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1849 if (ifscreen->result_type != -1) {
1850 *type = ifscreen->result_type;
1852 case INFO_NTYPE_UNKNOWN:
1853 add_trace("used", "type", "unknown");
1855 case INFO_NTYPE_SUBSCRIBER:
1856 add_trace("used", "type", "subscriber");
1858 case INFO_NTYPE_NATIONAL:
1859 add_trace("used", "type", "national");
1861 case INFO_NTYPE_INTERNATIONAL:
1862 add_trace("used", "type", "international");
1866 if (ifscreen->result_present != -1) {
1867 *present = ifscreen->result_present;
1869 case INFO_PRESENT_ALLOWED:
1870 add_trace("used", "present", "allowed");
1872 case INFO_PRESENT_RESTRICTED:
1873 add_trace("used", "present", "restricted");
1875 case INFO_PRESENT_NOTAVAIL:
1876 add_trace("used", "present", "not available");
1880 if (strchr(ifscreen->match,'%')) {
1881 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1882 UNCPY(id, ifscreen->result, idsize);
1883 id[idsize-1] = '\0';
1884 if (strchr(id,'%')) {
1885 *strchr(id,'%') = '\0';
1886 UNCAT(id, suffix, idsize);
1887 id[idsize-1] = '\0';
1890 UNCPY(id, ifscreen->result, idsize);
1891 id[idsize-1] = '\0';
1893 add_trace("used", "id", "%s", id[0]?id:"<empty>");
1898 struct interface *getinterfacebyname(const char *name)
1900 struct interface *interface = interface_first;
1903 if (!strcmp(interface->name, name))
1905 interface = interface->next;