1 /*****************************************************************************\
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** reading interface.conf file and filling structure **
10 \*****************************************************************************/
14 struct interface *interface_first = NULL; /* first interface is current list */
15 struct interface *interface_newlist = NULL; /* first interface in new list */
18 /* set default out_channel */
19 void default_out_channel(struct interface_port *ifport)
21 struct select_channel *selchannel, **selchannelp;
23 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
26 if (ifport->mISDNport->ntmode)
27 selchannel->channel = CHANNEL_FREE;
29 selchannel->channel = CHANNEL_ANY;
31 ifport->out_channel = selchannel;
33 /* additional channel selection for multipoint NT ports */
34 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode) {
35 selchannelp = &(selchannel->next);
36 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
38 selchannel->channel = CHANNEL_NO; // call waiting
39 *selchannelp = selchannel;
44 /* set default in_channel */
45 void default_in_channel(struct interface_port *ifport)
47 struct select_channel *selchannel;
49 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
52 selchannel->channel = CHANNEL_FREE;
54 ifport->in_channel = selchannel;
58 /* parse string for a positive number */
59 static int get_number(char *value)
66 SPRINT(text, "%d", val);
68 if (!strcmp(value, text))
75 /* remove element from buffer
76 * and return pointer to next element in buffer */
77 static char *get_seperated(char *buffer)
80 if (*buffer==',' || *buffer<=32) { /* seperate */
82 while((*buffer>'\0' && *buffer<=32) || *buffer==',')
92 * parameter processing
94 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
96 struct interface_port *ifport;
99 if (!interface->ifport) {
100 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
103 /* goto end of chain */
104 ifport = interface->ifport;
106 ifport = ifport->next;
109 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
115 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
117 if (interface->external) {
118 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is external interface.\n", filename, line, parameter);
122 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
125 interface->extension = 1;
128 static int inter_extern(struct interface *interface, char *filename, int line, char *parameter, char *value)
130 if (interface->extension) {
131 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is an extension.\n", filename, line, parameter);
135 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
138 interface->external = 1;
141 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
143 struct interface_port *ifport;
145 /* port in chain ? */
146 if (!interface->ifport) {
147 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
150 if (interface->ifport->ptmp) {
151 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
154 /* goto end of chain */
155 ifport = interface->ifport;
157 ifport = ifport->next;
160 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
167 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
169 struct interface_port *ifport;
171 /* port in chain ? */
172 if (!interface->ifport) {
173 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
176 if (interface->ifport->ptp) {
177 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
180 /* goto end of chain */
181 ifport = interface->ifport;
183 ifport = ifport->next;
186 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
193 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
195 struct interface_port *ifport;
197 /* port in chain ? */
198 if (!interface->ifport) {
199 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
202 /* goto end of chain */
203 ifport = interface->ifport;
205 ifport = ifport->next;
208 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
214 static int inter_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
216 struct interface_port *ifport;
218 /* port in chain ? */
219 if (!interface->ifport) {
220 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
223 /* goto end of chain */
224 ifport = interface->ifport;
226 ifport = ifport->next;
229 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
232 ifport->tespecial = 1;
235 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
237 if (!strcasecmp(value, "yes")) {
238 interface->is_tones = IS_YES;
240 if (!strcasecmp(value, "no")) {
241 interface->is_tones = IS_NO;
243 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
248 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
250 if (!strcasecmp(value, "yes")) {
251 interface->is_earlyb = IS_YES;
253 if (!strcasecmp(value, "no")) {
254 interface->is_earlyb = IS_NO;
256 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
261 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
263 if (!strcasecmp(value, "linear")) {
264 interface->hunt = HUNT_LINEAR;
266 if (!strcasecmp(value, "roundrobin")) {
267 interface->hunt = HUNT_ROUNDROBIN;
269 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
274 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
276 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);
279 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
281 struct interface_port *ifport, **ifportp;
282 struct interface *searchif;
285 val = get_number(value);
287 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
290 /* check for port already assigned */
291 searchif = interface_newlist;
293 ifport = searchif->ifport;
295 if (ifport->portnum == val) {
296 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
299 ifport = ifport->next;
301 searchif = searchif->next;
303 /* alloc port substructure */
304 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
306 ifport->interface = interface;
308 ifport->portnum = val;
310 ifportp = &interface->ifport;
312 ifportp = &((*ifportp)->next);
316 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
318 struct interface_port *ifport, **ifportp;
319 struct interface *searchif;
321 /* goto end of chain */
322 ifport = interface->ifport;
325 ifport = ifport->next;
328 /* check for port already assigned, but not for shared loop interface */
329 searchif = interface_newlist;
330 if (!!strcmp(value, options.loopback_lcr))
333 ifport = searchif->ifport;
335 if (!strcasecmp(ifport->portname, value)) {
336 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
339 ifport = ifport->next;
341 searchif = searchif->next;
344 /* alloc port substructure */
345 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
347 ifport->interface = interface;
349 ifport->portnum = -1; // disable until resolved
350 SCPY(ifport->portname, value);
352 ifportp = &interface->ifport;
354 ifportp = &((*ifportp)->next);
358 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
360 struct interface_port *ifport;
362 /* port in chain ? */
363 if (!interface->ifport) {
364 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
367 /* goto end of chain */
368 ifport = interface->ifport;
370 ifport = ifport->next;
371 if (!strcmp(value, "yes")) {
374 if (!strcmp(value, "no")) {
377 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
382 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
384 struct interface_port *ifport;
386 /* port in chain ? */
387 if (!interface->ifport) {
388 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
391 /* goto end of chain */
392 ifport = interface->ifport;
394 ifport = ifport->next;
395 if (!strcmp(value, "yes")) {
398 if (!strcmp(value, "no")) {
401 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
406 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
408 struct interface_port *ifport;
409 struct select_channel *selchannel, **selchannelp;
413 /* port in chain ? */
414 if (!interface->ifport) {
415 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
418 /* goto end of chain */
419 ifport = interface->ifport;
421 ifport = ifport->next;
425 p = get_seperated(p);
426 if (!strcasecmp(el, "force")) {
427 ifport->channel_force = 1;
428 if (ifport->out_channel) {
429 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
433 if (!strcasecmp(el, "any")) {
437 if (!strcasecmp(el, "free")) {
441 if (!strcasecmp(el, "no")) {
445 val = get_number(el);
447 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);
451 if (val<1 || val==16 || val>126) {
452 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
456 /* add to select-channel list */
457 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
460 selchannel->channel = val;
462 selchannelp = &ifport->out_channel;
464 selchannelp = &((*selchannelp)->next);
465 *selchannelp = selchannel;
470 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
472 struct interface_port *ifport;
473 struct select_channel *selchannel, **selchannelp;
477 /* port in chain ? */
478 if (!interface->ifport) {
479 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
482 /* goto end of chain */
483 ifport = interface->ifport;
485 ifport = ifport->next;
489 p = get_seperated(p);
490 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE) {
491 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
494 if (!strcasecmp(el, "free")) {
498 val = get_number(el);
500 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
504 if (val<1 || val==16 || val>126) {
505 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
509 /* add to select-channel list */
510 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
513 selchannel->channel = val;
515 selchannelp = &ifport->in_channel;
517 selchannelp = &((*selchannelp)->next);
518 *selchannelp = selchannel;
523 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
525 struct interface_port *ifport;
526 // struct select_channel *selchannel, **selchannelp;
530 /* port in chain ? */
531 if (!interface->ifport) {
532 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
535 /* goto end of chain */
536 ifport = interface->ifport;
538 ifport = ifport->next;
542 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
546 p = get_seperated(p);
547 ifport->tout_setup = atoi(el);
551 p = get_seperated(p);
552 ifport->tout_dialing = atoi(el);
556 p = get_seperated(p);
557 ifport->tout_proceeding = atoi(el);
561 p = get_seperated(p);
562 ifport->tout_alerting = atoi(el);
566 p = get_seperated(p);
567 ifport->tout_disconnect = atoi(el);
570 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
572 struct interface_msn *ifmsn, **ifmsnp;
576 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
579 if (interface->ifscreen_in) {
580 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
588 p = get_seperated(p);
589 /* add MSN to list */
590 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
593 SCPY(ifmsn->msn, el);
595 ifmsnp = &interface->ifmsn;
597 ifmsnp = &((*ifmsnp)->next);
602 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
604 struct interface_screen *ifscreen;
608 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
611 /* add screen entry to list*/
612 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
614 ifscreen->match_type = -1; /* unchecked */
615 ifscreen->match_present = -1; /* unchecked */
616 ifscreen->result_type = -1; /* unchanged */
617 ifscreen->result_present = -1; /* unchanged */
620 ifscreenp = &((*ifscreenp)->next);
621 *ifscreenp = ifscreen;
622 // printf("interface=%s\n", interface->name);
627 p = get_seperated(p);
628 if (!strcasecmp(el, "unknown")) {
629 if (ifscreen->match_type != -1) {
631 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
634 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
636 if (!strcasecmp(el, "subscriber")) {
637 if (ifscreen->match_type != -1)
639 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
641 if (!strcasecmp(el, "national")) {
642 if (ifscreen->match_type != -1)
644 ifscreen->match_type = INFO_NTYPE_NATIONAL;
646 if (!strcasecmp(el, "international")) {
647 if (ifscreen->match_type != -1)
649 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
651 if (!strcasecmp(el, "allowed")) {
652 if (ifscreen->match_present != -1) {
654 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
657 ifscreen->match_present = INFO_PRESENT_ALLOWED;
659 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
660 if (ifscreen->match_present != -1)
662 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
664 SCPY(ifscreen->match, el);
665 /* check for % at the end */
666 if (strchr(el, '%')) {
667 if (strchr(el, '%') != el+strlen(el)-1) {
668 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
675 if (ifscreen->match[0] == '\0') {
676 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
682 p = get_seperated(p);
683 if (!strcasecmp(el, "unknown")) {
684 if (ifscreen->result_type != -1)
686 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
688 if (!strcasecmp(el, "subscriber")) {
689 if (ifscreen->result_type != -1)
691 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
693 if (!strcasecmp(el, "national")) {
694 if (ifscreen->result_type != -1)
696 ifscreen->result_type = INFO_NTYPE_NATIONAL;
698 if (!strcasecmp(el, "international")) {
699 if (ifscreen->result_type != -1)
701 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
703 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
704 if (ifscreen->result_present != -1)
706 ifscreen->result_present = INFO_PRESENT_ALLOWED;
708 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
709 if (ifscreen->result_present != -1)
711 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
713 SCPY(ifscreen->result, el);
714 /* check for % at the end */
715 if (strchr(el, '%')) {
716 if (strchr(el, '%') != el+strlen(el)-1) {
717 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
724 if (ifscreen->result[0] == '\0') {
725 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
730 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
732 if (interface->ifmsn) {
733 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
737 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
739 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
741 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
743 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
745 struct interface_port *ifport;
747 /* port in chain ? */
748 if (!interface->ifport) {
749 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
752 /* goto end of chain */
753 ifport = interface->ifport;
755 ifport = ifport->next;
759 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
763 /* seperate parameter from filter */
769 while(*p > 0 && *p <= 32)
773 if (!strcasecmp(value, "gain")) {
779 while(*q > 0 && *q <= 32)
782 if (*p == 0 || *q == 0) {
783 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
786 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
787 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
790 interface->tx_gain = atoi(p);
791 interface->rx_gain = atoi(q);
793 if (!strcasecmp(value, "pipeline")) {
795 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
798 SCPY(interface->pipeline, p);
800 if (!strcasecmp(value, "blowfish")) {
801 unsigned char key[56];
804 if (!!strncmp(p, "0x", 2)) {
805 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
812 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
815 if (*p >= '0' && *p <= '9')
816 key[l] = (*p-'0')<<4;
817 else if (*p >= 'a' && *p <= 'f')
818 key[l] = (*p-'a'+10)<<4;
819 else if (*p >= 'A' && *p <= 'F')
820 key[l] = (*p-'A'+10)<<4;
823 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);
828 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);
831 if (*p >= '0' && *p <= '9')
832 key[l] = (*p-'0')<<4;
833 else if (*p >= 'a' && *p <= 'f')
834 key[l] = (*p-'a'+10)<<4;
835 else if (*p >= 'A' && *p <= 'F')
836 key[l] = (*p-'A'+10)<<4;
843 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);
846 memcpy(interface->bf_key, key, l);
847 interface->bf_len = l;
849 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
854 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
856 struct interface_port *ifport;
858 /* port in chain ? */
859 if (!interface->ifport) {
860 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
863 /* goto end of chain */
864 ifport = interface->ifport;
866 ifport = ifport->next;
867 ifport->dialmax = atoi(value);
870 static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
872 struct interface_port *ifport;
874 /* port in chain ? */
875 if (!interface->ifport) {
876 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
879 /* goto end of chain */
880 ifport = interface->ifport;
882 ifport = ifport->next;
883 SCPY(ifport->tones_dir, value);
886 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
888 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);
891 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
894 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
897 struct interface *searchif;
899 searchif = interface_newlist;
901 if (searchif->gsm_bs) {
902 SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses gsm BS side.\n", filename, line, searchif->name);
905 searchif = searchif->next;
908 /* goto end of chain again to set gsmflag */
909 interface->gsm_bs = 1;
914 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
917 SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
920 struct interface *searchif;
922 interface->gsm_ms = 1;
925 if (!value || !value[0]) {
926 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
929 SCPY(interface->gsm_ms_name, value);
931 /* check if name is used multiple times */
932 searchif = interface_newlist;
934 if (!strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
935 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);
938 searchif = searchif->next;
944 static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
947 SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
955 if (!value || !value[0]) {
956 SPRINT(interface_error, "Error in %s (line %d): Missing SIP local IP.\n", filename, line);
959 p = get_seperated(value);
961 SPRINT(interface_error, "Error in %s (line %d): Missing SIP remote IP.\n", filename, line);
964 SCPY(interface->sip_local_ip, value);
965 SCPY(interface->sip_remote_ip, p);
970 static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
972 interface->rtp_bridge = 1;
976 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
978 struct interface_port *ifport;
980 /* port in chain ? */
981 if (!interface->ifport) {
982 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
985 /* goto end of chain */
986 ifport = interface->ifport;
988 ifport = ifport->next;
989 ifport->nonotify = 1;
993 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
995 struct interface_port *ifport;
998 /* port in chain ? */
999 if (!interface->ifport) {
1000 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1003 /* goto end of chain */
1004 ifport = interface->ifport;
1006 ifport = ifport->next;
1007 ifport->ss5 |= SS5_ENABLE;
1008 while((element = strsep(&value, " "))) {
1009 if (element[0] == '\0')
1011 if (!strcasecmp(element, "connect"))
1012 ifport->ss5 |= SS5_FEATURE_CONNECT;
1014 if (!strcasecmp(element, "nodisconnect"))
1015 ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1017 if (!strcasecmp(element, "releaseguardtimer"))
1018 ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1020 if (!strcasecmp(element, "bell"))
1021 ifport->ss5 |= SS5_FEATURE_BELL;
1023 if (!strcasecmp(element, "pulsedialing"))
1024 ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1026 if (!strcasecmp(element, "delay"))
1027 ifport->ss5 |= SS5_FEATURE_DELAY;
1029 if (!strcasecmp(element, "starrelease"))
1030 ifport->ss5 |= SS5_FEATURE_STAR_RELEASE;
1032 if (!strcasecmp(element, "suppress"))
1033 ifport->ss5 |= SS5_FEATURE_SUPPRESS;
1035 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1042 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1044 struct interface_port *ifport;
1045 struct interface *searchif;
1048 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1051 searchif = interface_newlist;
1053 ifport = searchif->ifport;
1055 if (ifport->remote && !strcmp(ifport->remote_app, value)) {
1056 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses remote application '%s'.\n", filename, line, ifport->portname, value);
1059 ifport = ifport->next;
1061 searchif = searchif->next;
1065 if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
1068 /* goto end of chain again to set application name */
1069 ifport = interface->ifport;
1071 ifport = ifport->next;
1073 SCPY(ifport->remote_app, value);
1077 static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
1079 interface->shutdown = 1;
1083 static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1085 if (!value || !value[0]) {
1086 SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
1089 interface->app = EAPP_TYPE_BRIDGE;
1090 SCPY(interface->bridge_if, value);
1097 * structure of parameters
1099 struct interface_param interface_param[] = {
1100 { "extension", &inter_extension, "",
1101 "If keyword is given, calls to interface are handled as internal extensions."},
1103 { "extern", &inter_extern, "",
1104 "If keyword is given, this interface will be used for external calls.\n"
1105 "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1106 "Calls forwarded by extension's 'settings' also require an external interface."},
1108 {"tones", &inter_tones, "yes | no",
1109 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1111 {"earlyb", &inter_earlyb, "yes | no",
1112 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1114 {"hunt", &inter_hunt, "linear | roundrobin",
1115 "Select the algorithm for selecting port with free channel."},
1117 {"port", &inter_port, "<number>",
1119 {"portnum", &inter_portnum, "<number>",
1120 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1121 {"portname", &inter_portname, "<name>",
1122 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1124 {"block", &inter_block, "",
1125 "If keyword is given, calls on this interface are blocked.\n"
1126 "This parameter must follow a 'port' parameter."},
1128 {"ptp", &inter_ptp, "",
1129 "The given port above is opened as point-to-point.\n"
1130 "This is required on NT-mode ports that are multipoint by default.\n"
1131 "This parameter must follow a 'port' parameter."},
1134 {"ptmp", &inter_ptmp, "",
1135 "The given port above is opened as point-to-multipoint.\n"
1136 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1137 "This parameter must follow a 'port' parameter."},
1140 {"nt", &inter_nt, "",
1141 "The given port above is opened in NT-mode.\n"
1142 "This is required on interfaces that support both NT-mode and TE-mode.\n"
1143 "This parameter must follow a 'port' parameter."},
1145 {"te-special", &inter_tespecial, "",
1146 "The given port uses a modified TE-mode.\n"
1147 "All information elements that are allowed Network->User will then be\n"
1148 "transmitted User->Network also. This is usefull to pass all informations\n"
1149 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1150 "Note that this is not compliant with ISDN protocol.\n"
1151 "This parameter must follow a 'port' parameter."},
1153 {"layer1hold", &inter_l1hold, "yes | no",
1154 "The given port will not release layer 1 after layer 2 is down.\n"
1155 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1156 "This parameter must follow a 'port' parameter."},
1158 {"layer2hold", &inter_l2hold, "yes | no",
1159 "The given port will continuously try to establish layer 2 link and hold it.\n"
1160 "It is required for PTP links in most cases, therefore it is default.\n"
1161 "This parameter must follow a 'port' parameter."},
1163 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1164 "Channel selection list for all outgoing calls to the interface.\n"
1165 "A free channels is searched in order of appearance.\n"
1166 "This parameter must follow a 'port' parameter.\n"
1167 " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1168 " -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1169 " <number>[,...] - List of channels to search.\n"
1170 " free - Select any free channel\n"
1171 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1172 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1174 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1175 "Channel selection list for all incoming calls from the interface.\n"
1176 "A free channels is accepted if in the list.\n"
1177 "If any channel was requested, the first free channel found is selected.\n"
1178 "This parameter must follow a 'port' parameter.\n"
1179 " <number>[,...] - List of channels to accept.\n"
1180 " free - Accept any free channel"},
1182 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1183 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1184 "The default is 120 seconds for all states. Use 0 to disable.\n"
1185 "This parameter must follow a 'port' parameter.\n"},
1187 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1188 "Incoming caller ID is checked against given MSN numbers.\n"
1189 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1191 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1192 "Adds an entry for incoming calls to the caller ID screen list.\n"
1193 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1194 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1195 "additional digits.\n"
1196 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1199 " unknown | subsciber | national | international - Change caller ID type.\n"
1200 " present | restrict - Change presentation of caller ID."},
1202 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1203 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1204 "See 'screen-in' for help."},
1206 {"nodtmf", &inter_nodtmf, "",
1207 "Disables DTMF detection for this interface.\n"
1208 "This parameter must follow a 'port' parameter."},
1210 {"filter", &inter_filter, "<filter> <parameters>",
1211 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1212 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1213 "pipeline <string> - Sets echo cancelation pipeline.\n"
1214 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1216 {"dialmax", &inter_dialmax, "<digits>",
1217 "Limits the number of digits in setup/information message."},
1219 {"tones_dir", &inter_tones_dir, "<path>",
1220 "Overrides the given tone_dir in options.conf.\n"
1221 "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1223 {"gsm", &inter_gsm, "",
1225 {"gsm-bs", &inter_gsm_bs, "",
1226 "Sets up GSM base station interface for using OpenBSC."},
1227 {"gsm-ms", &inter_gsm_ms, "<socket>",
1228 "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1229 "The name of the MS folows the interface name.\n"
1230 "The socket is /tmp/osmocom_l2 by default and need to be changed when multiple\n"
1231 "MS interfaces are used."},
1232 {"sip", &inter_sip, "<local IP> <remote IP>",
1233 "Sets up SIP interface that represents one SIP endpoint.\n"
1234 "Give SIP configuration file."},
1235 {"rtp-bridge", &inter_rtp_bridge, "",
1236 "Sets up SIP interface that represents one SIP endpoint.\n"
1237 "Give SIP configuration file."},
1238 {"nonotify", &inter_nonotify, "",
1239 "Prevents sending notify messages to this interface. A call placed on hold will\n"
1240 "Not affect the remote end (phone or telcom switch).\n"
1241 "This parameter must follow a 'port' parameter."},
1242 {"bridge", &inter_bridge, "<destination interface>",
1243 "Define bridge application for this interface. All calls received on this\n"
1244 "interface will be directly bridged to the given destination interface.\n"
1245 "There will be no PBX application, nor routing."},
1248 {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1249 "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1250 "This feature causes CPU load to rise and has no practical intend.\n"
1251 "If you don't know what it is, you don't need it.\n"
1252 "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1253 " connect - Connect incomming call to throughconnect audio, if required.\n"
1254 " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1255 " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1256 " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1257 " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1258 " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1259 " starrelease - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1260 " suppress - Suppress received tones, as they will be recognized."},
1263 {"remote", &inter_remote, "<application>",
1264 "Sets up an interface that communicates with the remote application.\n"
1265 "Use \"asterisk\" to use chan_lcr as remote application."},
1267 {"shutdown", &inter_shutdown, "",
1268 "Interface will not be loaded when processing interface.conf"},
1270 {NULL, NULL, NULL, NULL}
1275 * read settings from interface.conf
1277 char interface_error[256];
1278 struct interface *read_interfaces(void)
1283 unsigned int line, i;
1285 struct interface *interface = NULL, /* in case no interface */
1286 **interfacep = &interface_newlist;
1287 char parameter[128];
1289 int expecting = 1; /* expecting new interface */
1290 struct interface_param *ifparam;
1292 if (interface_newlist != NULL)
1293 FATAL("list is not empty.\n");
1294 interface_error[0] = '\0';
1295 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1297 if (!(fp = fopen(filename,"r"))) {
1298 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1303 while((GETLINE(buffer, fp))) {
1307 while(*p <= 32) { /* skip spaces */
1312 if (*p==0 || *p=='#') /* ignore comments and empty line */
1317 i=0; /* read parameter */
1319 if (i+1 >= sizeof(parameter)) {
1320 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1323 parameter[i+1] = '\0';
1324 parameter[i++] = *p++;
1327 while(*p <= 32) { /* skip spaces */
1333 if (*p!=0 && *p!='#') { /* missing name */
1334 i=0; /* read until end */
1335 while(*p!=0 && *p!='#') {
1336 if (i+1 >= sizeof(value)) {
1337 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1344 /* remove trailing spaces from value */
1346 if (value[i-1]==0 || value[i-1]>32)
1353 /* check for interface name as first statement */
1354 if (expecting && parameter[0]!='[') {
1355 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1360 /* check for new interface */
1361 if (parameter[0] == '[') {
1362 if (parameter[strlen(parameter)-1] != ']') {
1363 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1366 parameter[strlen(parameter)-1] = '\0';
1368 /* check if interface name already exists */
1369 interface = interface_newlist;
1371 if (!strcasecmp(interface->name, parameter+1)) {
1372 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1375 interface = interface->next;
1378 /* append interface to new list */
1379 interface = (struct interface *)MALLOC(sizeof(struct interface));
1382 /* name interface */
1383 SCPY(interface->name, parameter+1);
1386 *interfacep = interface;
1387 interfacep = &interface->next;
1392 ifparam = interface_param;
1393 while(ifparam->name) {
1394 if (!strcasecmp(parameter, ifparam->name)) {
1395 if (ifparam->func(interface, filename, line, parameter, value))
1404 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1409 return(interface_newlist);
1411 PERROR_RUNTIME("%s", interface_error);
1413 free_interfaces(interface_newlist);
1414 interface_newlist = NULL;
1420 * freeing chain of interfaces
1422 void free_interfaces(struct interface *interface)
1425 struct interface_port *ifport;
1426 struct select_channel *selchannel;
1427 struct interface_msn *ifmsn;
1428 struct interface_screen *ifscreen;
1431 ifport = interface->ifport;
1433 selchannel = ifport->in_channel;
1436 selchannel = selchannel->next;
1437 FREE(temp, sizeof(struct select_channel));
1440 selchannel = ifport->out_channel;
1443 selchannel = selchannel->next;
1444 FREE(temp, sizeof(struct select_channel));
1448 ifport = ifport->next;
1449 FREE(temp, sizeof(struct interface_port));
1452 ifmsn = interface->ifmsn;
1455 ifmsn = ifmsn->next;
1456 FREE(temp, sizeof(struct interface_msn));
1459 ifscreen = interface->ifscreen_in;
1462 ifscreen = ifscreen->next;
1463 FREE(temp, sizeof(struct interface_screen));
1466 ifscreen = interface->ifscreen_out;
1469 ifscreen = ifscreen->next;
1470 FREE(temp, sizeof(struct interface_screen));
1474 interface = interface->next;
1475 FREE(temp, sizeof(struct interface));
1481 * defaults of ports if not specified by config
1483 static void set_defaults(struct interface_port *ifport)
1485 /* default channel selection list */
1486 if (!ifport->out_channel)
1487 default_out_channel(ifport);
1488 if (!ifport->in_channel)
1489 default_in_channel(ifport);
1490 /* must force the channel on PTMP/NT ports */
1491 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1492 ifport->channel_force = 1;
1493 /* default is_tones */
1494 if (ifport->interface->is_tones)
1495 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1497 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1498 /* default is_earlyb */
1499 if (ifport->interface->is_earlyb)
1500 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1502 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1503 /* set locally flag */
1504 if (ifport->interface->extension)
1505 ifport->mISDNport->locally = 1;
1507 ifport->mISDNport->locally = 0;
1512 * all links between mISDNport and interface are made
1513 * unused mISDNports are closed, new mISDNports are opened
1514 * also set default select_channel lists
1516 void relink_interfaces(void)
1518 struct mISDNport *mISDNport;
1519 struct interface *interface, *temp;
1520 struct interface_port *ifport;
1523 interface = interface_first;
1526 temp = interface_newlist;
1528 if (!strcmp(temp->name, interface->name))
1534 if (interface->gsm_ms)
1535 gsm_ms_delete(interface->gsm_ms_name);
1538 if (interface->gsm_bs)
1543 sip_exit_inst(interface);
1546 interface = interface->next;
1549 interface = interface_newlist;
1552 temp = interface_first;
1554 if (!strcmp(temp->name, interface->name))
1560 if (interface->gsm_ms)
1561 gsm_ms_new(interface);
1564 if (interface->gsm_bs)
1565 gsm_bs_init(interface);
1569 sip_init_inst(interface);
1572 interface = interface->next;
1575 /* unlink all mISDNports */
1576 mISDNport = mISDNport_first;
1578 mISDNport->ifport = NULL;
1579 mISDNport = mISDNport->next;
1582 /* relink existing mISDNports */
1583 interface = interface_newlist;
1585 ifport = interface->ifport;
1587 mISDNport = mISDNport_first;
1589 if (!strcmp(mISDNport->name, ifport->portname))
1590 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1591 if (mISDNport->portnum == ifport->portnum) {
1592 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1593 ifport->mISDNport = mISDNport;
1594 mISDNport->ifport = ifport;
1595 set_defaults(ifport);
1597 mISDNport = mISDNport->next;
1599 ifport = ifport->next;
1601 interface = interface->next;
1604 /* close unused mISDNports */
1606 mISDNport = mISDNport_first;
1608 if (mISDNport->ifport == NULL) {
1609 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1611 mISDNport_close(mISDNport);
1614 mISDNport = mISDNport->next;
1617 /* open and link new mISDNports */
1618 interface = interface_newlist;
1620 ifport = interface->ifport;
1622 if (!ifport->mISDNport) {
1623 if (!interface->shutdown) {
1629 ifport = ifport->next;
1631 interface = interface->next;
1640 void load_port(struct interface_port *ifport)
1642 struct mISDNport *mISDNport;
1645 mISDNport = mISDNport_open(ifport);
1648 ifport->mISDNport = mISDNport;
1649 mISDNport->ifport = ifport;
1650 /* set number and name */
1651 ifport->portnum = mISDNport->portnum;
1652 SCPY(ifport->portname, mISDNport->name);
1654 set_defaults(ifport);
1655 /* load static port instances */
1656 mISDNport_static(mISDNport);
1658 ifport->block = 2; /* not available */
1663 * give summary of interface syntax
1665 void doc_interface(void)
1667 struct interface_param *ifparam;
1669 printf("Syntax overview\n");
1670 printf("---------------\n\n");
1672 printf("[<name>]\n");
1673 ifparam = interface_param;
1674 while(ifparam->name) {
1675 if (ifparam->name[0])
1676 printf("%s %s\n", ifparam->name, ifparam->usage);
1680 ifparam = interface_param;
1681 while(ifparam->name) {
1682 if (ifparam->name[0]) {
1683 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1684 printf("%s\n", ifparam->help);
1692 * out==0: incoming caller id, out==1: outgoing caller id
1694 void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
1697 struct interface_msn *ifmsn;
1698 struct interface_screen *ifscreen;
1700 struct interface *interface = interface_first;
1703 if (!strcmp(interface->name, interface_name))
1705 interface = interface->next;
1710 /* screen incoming caller id */
1712 /* check for MSN numbers, use first MSN if no match */
1714 ifmsn = interface->ifmsn;
1718 if (!strcmp(ifmsn->msn, id)) {
1721 ifmsn = ifmsn->next;
1724 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1725 add_trace("msn", NULL, "%s", id);
1728 if (!ifmsn && msn1) { // not in list, first msn given
1729 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1730 add_trace("msn", "given", "%s", id);
1731 add_trace("msn", "used", "%s", msn1);
1733 UNCPY(id, msn1, idsize);
1734 id[idsize-1] = '\0';
1738 /* check screen list */
1740 ifscreen = interface->ifscreen_out;
1742 ifscreen = interface->ifscreen_in;
1744 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1745 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
1746 if (strchr(ifscreen->match,'%')) {
1747 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1750 if (!strcmp(ifscreen->match, id))
1754 ifscreen = ifscreen->next;
1756 if (ifscreen) { // match
1757 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)");
1759 case INFO_NTYPE_UNKNOWN:
1760 add_trace("given", "type", "unknown");
1762 case INFO_NTYPE_SUBSCRIBER:
1763 add_trace("given", "type", "subscriber");
1765 case INFO_NTYPE_NATIONAL:
1766 add_trace("given", "type", "national");
1768 case INFO_NTYPE_INTERNATIONAL:
1769 add_trace("given", "type", "international");
1773 case INFO_PRESENT_ALLOWED:
1774 add_trace("given", "present", "allowed");
1776 case INFO_PRESENT_RESTRICTED:
1777 add_trace("given", "present", "restricted");
1779 case INFO_PRESENT_NOTAVAIL:
1780 add_trace("given", "present", "not available");
1783 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1784 if (ifscreen->result_type != -1) {
1785 *type = ifscreen->result_type;
1787 case INFO_NTYPE_UNKNOWN:
1788 add_trace("used", "type", "unknown");
1790 case INFO_NTYPE_SUBSCRIBER:
1791 add_trace("used", "type", "subscriber");
1793 case INFO_NTYPE_NATIONAL:
1794 add_trace("used", "type", "national");
1796 case INFO_NTYPE_INTERNATIONAL:
1797 add_trace("used", "type", "international");
1801 if (ifscreen->result_present != -1) {
1802 *present = ifscreen->result_present;
1804 case INFO_PRESENT_ALLOWED:
1805 add_trace("used", "present", "allowed");
1807 case INFO_PRESENT_RESTRICTED:
1808 add_trace("used", "present", "restricted");
1810 case INFO_PRESENT_NOTAVAIL:
1811 add_trace("used", "present", "not available");
1815 if (strchr(ifscreen->match,'%')) {
1816 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1817 UNCPY(id, ifscreen->result, idsize);
1818 id[idsize-1] = '\0';
1819 if (strchr(id,'%')) {
1820 *strchr(id,'%') = '\0';
1821 UNCAT(id, suffix, idsize);
1822 id[idsize-1] = '\0';
1825 UNCPY(id, ifscreen->result, idsize);
1826 id[idsize-1] = '\0';
1828 add_trace("used", "id", "%s", id[0]?id:"<empty>");