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 gsm interface */
329 searchif = interface_newlist;
330 #if defined WITH_GSM_BS || defined WITH_GSM_MS
331 if (options.gsm && !strcmp(value, gsm->conf.interface_lcr))
335 ifport = searchif->ifport;
337 if (!strcasecmp(ifport->portname, value)) {
338 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
341 ifport = ifport->next;
343 searchif = searchif->next;
346 /* alloc port substructure */
347 ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
349 ifport->interface = interface;
351 ifport->portnum = -1; // disable until resolved
352 SCPY(ifport->portname, value);
354 ifportp = &interface->ifport;
356 ifportp = &((*ifportp)->next);
360 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
362 struct interface_port *ifport;
364 /* port in chain ? */
365 if (!interface->ifport) {
366 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
369 /* goto end of chain */
370 ifport = interface->ifport;
372 ifport = ifport->next;
373 if (!strcmp(value, "yes")) {
376 if (!strcmp(value, "no")) {
379 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
384 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
386 struct interface_port *ifport;
388 /* port in chain ? */
389 if (!interface->ifport) {
390 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
393 /* goto end of chain */
394 ifport = interface->ifport;
396 ifport = ifport->next;
397 if (!strcmp(value, "yes")) {
400 if (!strcmp(value, "no")) {
403 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
408 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
410 struct interface_port *ifport;
411 struct select_channel *selchannel, **selchannelp;
415 /* port in chain ? */
416 if (!interface->ifport) {
417 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
420 /* goto end of chain */
421 ifport = interface->ifport;
423 ifport = ifport->next;
427 p = get_seperated(p);
428 if (!strcasecmp(el, "force")) {
429 ifport->channel_force = 1;
430 if (ifport->out_channel) {
431 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
435 if (!strcasecmp(el, "any")) {
439 if (!strcasecmp(el, "free")) {
443 if (!strcasecmp(el, "no")) {
447 val = get_number(el);
449 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);
453 if (val<1 || val==16 || val>126) {
454 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
458 /* add to select-channel list */
459 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
462 selchannel->channel = val;
464 selchannelp = &ifport->out_channel;
466 selchannelp = &((*selchannelp)->next);
467 *selchannelp = selchannel;
472 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
474 struct interface_port *ifport;
475 struct select_channel *selchannel, **selchannelp;
479 /* port in chain ? */
480 if (!interface->ifport) {
481 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
484 /* goto end of chain */
485 ifport = interface->ifport;
487 ifport = ifport->next;
491 p = get_seperated(p);
492 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE) {
493 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
496 if (!strcasecmp(el, "free")) {
500 val = get_number(el);
502 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
506 if (val<1 || val==16 || val>126) {
507 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
511 /* add to select-channel list */
512 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
515 selchannel->channel = val;
517 selchannelp = &ifport->in_channel;
519 selchannelp = &((*selchannelp)->next);
520 *selchannelp = selchannel;
525 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
527 struct interface_port *ifport;
528 // struct select_channel *selchannel, **selchannelp;
532 /* port in chain ? */
533 if (!interface->ifport) {
534 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
537 /* goto end of chain */
538 ifport = interface->ifport;
540 ifport = ifport->next;
544 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
548 p = get_seperated(p);
549 ifport->tout_setup = atoi(el);
553 p = get_seperated(p);
554 ifport->tout_dialing = atoi(el);
558 p = get_seperated(p);
559 ifport->tout_proceeding = atoi(el);
563 p = get_seperated(p);
564 ifport->tout_alerting = atoi(el);
568 p = get_seperated(p);
569 ifport->tout_disconnect = atoi(el);
572 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
574 struct interface_msn *ifmsn, **ifmsnp;
578 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
581 if (interface->ifscreen_in) {
582 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
590 p = get_seperated(p);
591 /* add MSN to list */
592 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
595 SCPY(ifmsn->msn, el);
597 ifmsnp = &interface->ifmsn;
599 ifmsnp = &((*ifmsnp)->next);
604 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
606 struct interface_screen *ifscreen;
610 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
613 /* add screen entry to list*/
614 ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
616 ifscreen->match_type = -1; /* unchecked */
617 ifscreen->match_present = -1; /* unchecked */
618 ifscreen->result_type = -1; /* unchanged */
619 ifscreen->result_present = -1; /* unchanged */
622 ifscreenp = &((*ifscreenp)->next);
623 *ifscreenp = ifscreen;
624 // printf("interface=%s\n", interface->name);
629 p = get_seperated(p);
630 if (!strcasecmp(el, "unknown")) {
631 if (ifscreen->match_type != -1) {
633 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
636 ifscreen->match_type = INFO_NTYPE_UNKNOWN;
638 if (!strcasecmp(el, "subscriber")) {
639 if (ifscreen->match_type != -1)
641 ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
643 if (!strcasecmp(el, "national")) {
644 if (ifscreen->match_type != -1)
646 ifscreen->match_type = INFO_NTYPE_NATIONAL;
648 if (!strcasecmp(el, "international")) {
649 if (ifscreen->match_type != -1)
651 ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
653 if (!strcasecmp(el, "allowed")) {
654 if (ifscreen->match_present != -1) {
656 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
659 ifscreen->match_present = INFO_PRESENT_ALLOWED;
661 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
662 if (ifscreen->match_present != -1)
664 ifscreen->match_present = INFO_PRESENT_RESTRICTED;
666 SCPY(ifscreen->match, el);
667 /* check for % at the end */
668 if (strchr(el, '%')) {
669 if (strchr(el, '%') != el+strlen(el)-1) {
670 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
677 if (ifscreen->match[0] == '\0') {
678 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
684 p = get_seperated(p);
685 if (!strcasecmp(el, "unknown")) {
686 if (ifscreen->result_type != -1)
688 ifscreen->result_type = INFO_NTYPE_UNKNOWN;
690 if (!strcasecmp(el, "subscriber")) {
691 if (ifscreen->result_type != -1)
693 ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
695 if (!strcasecmp(el, "national")) {
696 if (ifscreen->result_type != -1)
698 ifscreen->result_type = INFO_NTYPE_NATIONAL;
700 if (!strcasecmp(el, "international")) {
701 if (ifscreen->result_type != -1)
703 ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
705 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
706 if (ifscreen->result_present != -1)
708 ifscreen->result_present = INFO_PRESENT_ALLOWED;
710 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
711 if (ifscreen->result_present != -1)
713 ifscreen->result_present = INFO_PRESENT_RESTRICTED;
715 SCPY(ifscreen->result, el);
716 /* check for % at the end */
717 if (strchr(el, '%')) {
718 if (strchr(el, '%') != el+strlen(el)-1) {
719 SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
726 if (ifscreen->result[0] == '\0') {
727 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
732 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
734 if (interface->ifmsn) {
735 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
739 return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
741 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
743 return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
745 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
747 struct interface_port *ifport;
749 /* port in chain ? */
750 if (!interface->ifport) {
751 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
754 /* goto end of chain */
755 ifport = interface->ifport;
757 ifport = ifport->next;
761 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
765 /* seperate parameter from filter */
771 while(*p > 0 && *p <= 32)
775 if (!strcasecmp(value, "gain")) {
781 while(*q > 0 && *q <= 32)
784 if (*p == 0 || *q == 0) {
785 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
788 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
789 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
792 interface->tx_gain = atoi(p);
793 interface->rx_gain = atoi(q);
795 if (!strcasecmp(value, "pipeline")) {
797 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
800 SCPY(interface->pipeline, p);
802 if (!strcasecmp(value, "blowfish")) {
803 unsigned char key[56];
806 if (!!strncmp(p, "0x", 2)) {
807 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
814 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
817 if (*p >= '0' && *p <= '9')
818 key[l] = (*p-'0')<<4;
819 else if (*p >= 'a' && *p <= 'f')
820 key[l] = (*p-'a'+10)<<4;
821 else if (*p >= 'A' && *p <= 'F')
822 key[l] = (*p-'A'+10)<<4;
825 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);
830 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);
833 if (*p >= '0' && *p <= '9')
834 key[l] = (*p-'0')<<4;
835 else if (*p >= 'a' && *p <= 'f')
836 key[l] = (*p-'a'+10)<<4;
837 else if (*p >= 'A' && *p <= 'F')
838 key[l] = (*p-'A'+10)<<4;
845 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);
848 memcpy(interface->bf_key, key, l);
849 interface->bf_len = l;
851 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
856 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
858 struct interface_port *ifport;
860 /* port in chain ? */
861 if (!interface->ifport) {
862 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
865 /* goto end of chain */
866 ifport = interface->ifport;
868 ifport = ifport->next;
869 ifport->dialmax = atoi(value);
872 static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
874 struct interface_port *ifport;
876 /* port in chain ? */
877 if (!interface->ifport) {
878 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
881 /* goto end of chain */
882 ifport = interface->ifport;
884 ifport = ifport->next;
885 SCPY(ifport->tones_dir, value);
888 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
890 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);
893 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
896 SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
899 struct interface_port *ifport;
900 struct interface *searchif;
904 SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
907 searchif = interface_newlist;
909 ifport = searchif->ifport;
911 if (ifport->gsm_bs) {
912 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm BS side.\n", filename, line, ifport->portname);
915 ifport = ifport->next;
917 searchif = searchif->next;
921 if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
924 /* goto end of chain again to set gsmflag */
925 ifport = interface->ifport;
927 ifport = ifport->next;
933 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
936 SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
939 struct interface_port *ifport, *searchifport;
940 struct interface *searchif;
945 SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
950 if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
953 /* goto end of chain again to set gsmflag and socket */
954 ifport = interface->ifport;
956 ifport = ifport->next;
960 element = strsep(&value, " ");
961 if (!element || !element[0]) {
962 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
965 SCPY(ifport->gsm_ms_name, element);
966 element = strsep(&value, " ");
967 if (!element || !element[0]) {
968 SPRINT(interface_error, "Error in %s (line %d): Missing socket name after MS name.\n", filename, line);
971 SCPY(ifport->gsm_ms_socket, element);
973 /* check if socket is used multiple times */
974 searchif = interface_newlist;
976 searchifport = searchif->ifport;
977 while(searchifport) {
978 if (searchifport != ifport
979 && !strcmp(searchifport->gsm_ms_socket, ifport->gsm_ms_socket)) {
980 SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given socket '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_socket);
983 searchifport = searchifport->next;
985 searchif = searchif->next;
991 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
993 struct interface_port *ifport;
995 /* port in chain ? */
996 if (!interface->ifport) {
997 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1000 /* goto end of chain */
1001 ifport = interface->ifport;
1003 ifport = ifport->next;
1004 ifport->nonotify = 1;
1008 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
1010 struct interface_port *ifport;
1013 /* port in chain ? */
1014 if (!interface->ifport) {
1015 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1018 /* goto end of chain */
1019 ifport = interface->ifport;
1021 ifport = ifport->next;
1022 ifport->ss5 |= SS5_ENABLE;
1023 while((element = strsep(&value, " "))) {
1024 if (element[0] == '\0')
1026 if (!strcasecmp(element, "connect"))
1027 ifport->ss5 |= SS5_FEATURE_CONNECT;
1029 if (!strcasecmp(element, "nodisconnect"))
1030 ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1032 if (!strcasecmp(element, "releaseguardtimer"))
1033 ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1035 if (!strcasecmp(element, "bell"))
1036 ifport->ss5 |= SS5_FEATURE_BELL;
1038 if (!strcasecmp(element, "pulsedialing"))
1039 ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1041 if (!strcasecmp(element, "delay"))
1042 ifport->ss5 |= SS5_FEATURE_DELAY;
1044 if (!strcasecmp(element, "starrelease"))
1045 ifport->ss5 |= SS5_FEATURE_STAR_RELEASE;
1047 if (!strcasecmp(element, "suppress"))
1048 ifport->ss5 |= SS5_FEATURE_SUPPRESS;
1050 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1057 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1059 struct interface_port *ifport;
1060 struct interface *searchif;
1063 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1066 searchif = interface_newlist;
1068 ifport = searchif->ifport;
1070 if (ifport->remote && !strcmp(ifport->remote_app, value)) {
1071 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses remote application '%s'.\n", filename, line, ifport->portname, value);
1074 ifport = ifport->next;
1076 searchif = searchif->next;
1080 if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
1083 /* goto end of chain again to set application name */
1084 ifport = interface->ifport;
1086 ifport = ifport->next;
1088 SCPY(ifport->remote_app, value);
1096 * structure of parameters
1098 struct interface_param interface_param[] = {
1099 { "extension", &inter_extension, "",
1100 "If keyword is given, calls to interface are handled as internal extensions."},
1102 { "extern", &inter_extern, "",
1103 "If keyword is given, this interface will be used for external calls.\n"
1104 "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1105 "Calls forwarded by extension's 'settings' also require an external interface."},
1107 {"tones", &inter_tones, "yes | no",
1108 "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1110 {"earlyb", &inter_earlyb, "yes | no",
1111 "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1113 {"hunt", &inter_hunt, "linear | roundrobin",
1114 "Select the algorithm for selecting port with free channel."},
1116 {"port", &inter_port, "<number>",
1118 {"portnum", &inter_portnum, "<number>",
1119 "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1120 {"portname", &inter_portname, "<name>",
1121 "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1123 {"block", &inter_block, "",
1124 "If keyword is given, calls on this interface are blocked.\n"
1125 "This parameter must follow a 'port' parameter."},
1127 {"ptp", &inter_ptp, "",
1128 "The given port above is opened as point-to-point.\n"
1129 "This is required on NT-mode ports that are multipoint by default.\n"
1130 "This parameter must follow a 'port' parameter."},
1133 {"ptmp", &inter_ptmp, "",
1134 "The given port above is opened as point-to-multipoint.\n"
1135 "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1136 "This parameter must follow a 'port' parameter."},
1139 {"nt", &inter_nt, "",
1140 "The given port above is opened in NT-mode.\n"
1141 "This is required on interfaces that support both NT-mode and TE-mode.\n"
1142 "This parameter must follow a 'port' parameter."},
1144 {"te-special", &inter_tespecial, "",
1145 "The given port uses a modified TE-mode.\n"
1146 "All information elements that are allowed Network->User will then be\n"
1147 "transmitted User->Network also. This is usefull to pass all informations\n"
1148 "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1149 "Note that this is not compliant with ISDN protocol.\n"
1150 "This parameter must follow a 'port' parameter."},
1152 {"layer1hold", &inter_l1hold, "yes | no",
1153 "The given port will not release layer 1 after layer 2 is down.\n"
1154 "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1155 "This parameter must follow a 'port' parameter."},
1157 {"layer2hold", &inter_l2hold, "yes | no",
1158 "The given port will continuously try to establish layer 2 link and hold it.\n"
1159 "It is required for PTP links in most cases, therefore it is default.\n"
1160 "This parameter must follow a 'port' parameter."},
1162 {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1163 "Channel selection list for all outgoing calls to the interface.\n"
1164 "A free channels is searched in order of appearance.\n"
1165 "This parameter must follow a 'port' parameter.\n"
1166 " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1167 " -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1168 " <number>[,...] - List of channels to search.\n"
1169 " free - Select any free channel\n"
1170 " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1171 " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1173 {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1174 "Channel selection list for all incoming calls from the interface.\n"
1175 "A free channels is accepted if in the list.\n"
1176 "If any channel was requested, the first free channel found is selected.\n"
1177 "This parameter must follow a 'port' parameter.\n"
1178 " <number>[,...] - List of channels to accept.\n"
1179 " free - Accept any free channel"},
1181 {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1182 "Timeout values for call states. They are both for incoming and outgoing states.\n"
1183 "The default is 120 seconds for all states. Use 0 to disable.\n"
1184 "This parameter must follow a 'port' parameter.\n"},
1186 {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1187 "Incoming caller ID is checked against given MSN numbers.\n"
1188 "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1190 {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1191 "Adds an entry for incoming calls to the caller ID screen list.\n"
1192 "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1193 "If '%' is given after old caller ID, it matches even if caller ID has\n"
1194 "additional digits.\n"
1195 "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1198 " unknown | subsciber | national | international - Change caller ID type.\n"
1199 " present | restrict - Change presentation of caller ID."},
1201 {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1202 "Adds an entry for outgoing calls to the caller ID screen list.\n"
1203 "See 'screen-in' for help."},
1205 {"nodtmf", &inter_nodtmf, "",
1206 "Disables DTMF detection for this interface.\n"
1207 "This parameter must follow a 'port' parameter."},
1209 {"filter", &inter_filter, "<filter> <parameters>",
1210 "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1211 "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1212 "pipeline <string> - Sets echo cancelation pipeline.\n"
1213 "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1215 {"dialmax", &inter_dialmax, "<digits>",
1216 "Limits the number of digits in setup/information message."},
1218 {"tones_dir", &inter_tones_dir, "<path>",
1219 "Overrides the given tone_dir in options.conf.\n"
1220 "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1222 {"gsm", &inter_gsm, "",
1224 {"gsm-bs", &inter_gsm_bs, "",
1225 "Sets up GSM base station interface for using OpenBSC.\n"
1226 "See the default/gsm.conf for configuration for this version."},
1227 {"gsm-ms", &inter_gsm_ms, "[<socket>]",
1228 "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1229 "See the default/gsm.conf for configuration for this version.\n"
1230 "The name of the MS folows the interface name.\n"
1231 "The socket is /tmp/osmocom_l2 by default and need to be changed when multiple\n"
1232 "MS interfaces are used."},
1233 {"nonotify", &inter_nonotify, "",
1234 "Prevents sending notify messages to this interface. A call placed on hold will\n"
1235 "Not affect the remote end (phone or telcom switch).\n"
1236 "This parameter must follow a 'port' parameter."},
1239 {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1240 "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1241 "This feature causes CPU load to rise and has no practical intend.\n"
1242 "If you don't know what it is, you don't need it.\n"
1243 "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1244 " connect - Connect incomming call to throughconnect audio, if required.\n"
1245 " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1246 " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1247 " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1248 " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1249 " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1250 " starrelease - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1251 " suppress - Suppress received tones, as they will be recognized."},
1254 {"remote", &inter_remote, "<application>",
1255 "Sets up an interface that communicates with the remote application.\n"
1256 "Use \"asterisk\" to use chan_lcr as remote application."},
1258 {NULL, NULL, NULL, NULL}
1263 * read settings from interface.conf
1265 char interface_error[256];
1266 struct interface *read_interfaces(void)
1271 unsigned int line, i;
1273 struct interface *interface = NULL, /* in case no interface */
1274 **interfacep = &interface_newlist;
1275 char parameter[128];
1277 int expecting = 1; /* expecting new interface */
1278 struct interface_param *ifparam;
1280 if (interface_newlist != NULL)
1281 FATAL("list is not empty.\n");
1282 interface_error[0] = '\0';
1283 SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1285 if (!(fp = fopen(filename,"r"))) {
1286 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1291 while((GETLINE(buffer, fp))) {
1295 while(*p <= 32) { /* skip spaces */
1300 if (*p==0 || *p=='#') /* ignore comments and empty line */
1305 i=0; /* read parameter */
1307 if (i+1 >= sizeof(parameter)) {
1308 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1311 parameter[i+1] = '\0';
1312 parameter[i++] = *p++;
1315 while(*p <= 32) { /* skip spaces */
1321 if (*p!=0 && *p!='#') { /* missing name */
1322 i=0; /* read until end */
1323 while(*p!=0 && *p!='#') {
1324 if (i+1 >= sizeof(value)) {
1325 SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1332 /* remove trailing spaces from value */
1334 if (value[i-1]==0 || value[i-1]>32)
1341 /* check for interface name as first statement */
1342 if (expecting && parameter[0]!='[') {
1343 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1348 /* check for new interface */
1349 if (parameter[0] == '[') {
1350 if (parameter[strlen(parameter)-1] != ']') {
1351 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1354 parameter[strlen(parameter)-1] = '\0';
1356 /* check if interface name already exists */
1357 interface = interface_newlist;
1359 if (!strcasecmp(interface->name, parameter+1)) {
1360 SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1363 interface = interface->next;
1366 /* append interface to new list */
1367 interface = (struct interface *)MALLOC(sizeof(struct interface));
1370 /* name interface */
1371 SCPY(interface->name, parameter+1);
1374 *interfacep = interface;
1375 interfacep = &interface->next;
1380 ifparam = interface_param;
1381 while(ifparam->name) {
1382 if (!strcasecmp(parameter, ifparam->name)) {
1383 if (ifparam->func(interface, filename, line, parameter, value))
1392 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1397 return(interface_newlist);
1399 PERROR_RUNTIME("%s", interface_error);
1401 free_interfaces(interface_newlist);
1402 interface_newlist = NULL;
1408 * freeing chain of interfaces
1410 void free_interfaces(struct interface *interface)
1413 struct interface_port *ifport;
1414 struct select_channel *selchannel;
1415 struct interface_msn *ifmsn;
1416 struct interface_screen *ifscreen;
1419 ifport = interface->ifport;
1421 selchannel = ifport->in_channel;
1424 selchannel = selchannel->next;
1425 FREE(temp, sizeof(struct select_channel));
1428 selchannel = ifport->out_channel;
1431 selchannel = selchannel->next;
1432 FREE(temp, sizeof(struct select_channel));
1436 ifport = ifport->next;
1437 FREE(temp, sizeof(struct interface_port));
1440 ifmsn = interface->ifmsn;
1443 ifmsn = ifmsn->next;
1444 FREE(temp, sizeof(struct interface_msn));
1447 ifscreen = interface->ifscreen_in;
1450 ifscreen = ifscreen->next;
1451 FREE(temp, sizeof(struct interface_screen));
1454 ifscreen = interface->ifscreen_out;
1457 ifscreen = ifscreen->next;
1458 FREE(temp, sizeof(struct interface_screen));
1462 interface = interface->next;
1463 FREE(temp, sizeof(struct interface));
1469 * defaults of ports if not specified by config
1471 static void set_defaults(struct interface_port *ifport)
1473 /* default channel selection list */
1474 if (!ifport->out_channel)
1475 default_out_channel(ifport);
1476 if (!ifport->in_channel)
1477 default_in_channel(ifport);
1478 /* must force the channel on PTMP/NT ports */
1479 if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1480 ifport->channel_force = 1;
1481 /* default is_tones */
1482 if (ifport->interface->is_tones)
1483 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1485 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1486 /* default is_earlyb */
1487 if (ifport->interface->is_earlyb)
1488 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1490 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1491 /* set locally flag */
1492 if (ifport->interface->extension)
1493 ifport->mISDNport->locally = 1;
1495 ifport->mISDNport->locally = 0;
1500 * all links between mISDNport and interface are made
1501 * unused mISDNports are closed, new mISDNports are opened
1502 * also set default select_channel lists
1504 void relink_interfaces(void)
1506 struct mISDNport *mISDNport;
1507 struct interface *interface;
1508 struct interface_port *ifport;
1510 /* unlink all mISDNports */
1511 mISDNport = mISDNport_first;
1513 mISDNport->ifport = NULL;
1514 mISDNport = mISDNport->next;
1517 /* relink existing mISDNports */
1518 interface = interface_newlist;
1520 ifport = interface->ifport;
1522 mISDNport = mISDNport_first;
1524 if (!strcmp(mISDNport->name, ifport->portname))
1525 ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1526 if (mISDNport->portnum == ifport->portnum) {
1527 PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1528 ifport->mISDNport = mISDNport;
1529 mISDNport->ifport = ifport;
1530 set_defaults(ifport);
1532 mISDNport = mISDNport->next;
1534 ifport = ifport->next;
1536 interface = interface->next;
1539 /* close unused mISDNports */
1541 mISDNport = mISDNport_first;
1543 if (mISDNport->ifport == NULL) {
1544 PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1545 /* remove all port objects and destroy port */
1548 gsm_ms_delete(ifport->gsm_ms_name);
1550 mISDNport_close(mISDNport);
1553 mISDNport = mISDNport->next;
1556 /* open and link new mISDNports */
1557 interface = interface_newlist;
1559 ifport = interface->ifport;
1561 if (!ifport->mISDNport) {
1564 ifport = ifport->next;
1566 interface = interface->next;
1575 void load_port(struct interface_port *ifport)
1577 struct mISDNport *mISDNport;
1580 mISDNport = mISDNport_open(ifport);
1583 ifport->mISDNport = mISDNport;
1584 mISDNport->ifport = ifport;
1585 /* set number and name */
1586 ifport->portnum = mISDNport->portnum;
1587 SCPY(ifport->portname, mISDNport->name);
1589 set_defaults(ifport);
1590 /* load static port instances */
1591 mISDNport_static(mISDNport);
1594 gsm_ms_new(ifport->gsm_ms_name, ifport->gsm_ms_socket);
1597 ifport->block = 2; /* not available */
1602 * give summary of interface syntax
1604 void doc_interface(void)
1606 struct interface_param *ifparam;
1608 printf("Syntax overview\n");
1609 printf("---------------\n\n");
1611 printf("[<name>]\n");
1612 ifparam = interface_param;
1613 while(ifparam->name) {
1614 if (ifparam->name[0])
1615 printf("%s %s\n", ifparam->name, ifparam->usage);
1619 ifparam = interface_param;
1620 while(ifparam->name) {
1621 if (ifparam->name[0]) {
1622 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1623 printf("%s\n", ifparam->help);
1631 * out==0: incoming caller id, out==1: outgoing caller id
1633 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1636 struct interface_msn *ifmsn;
1637 struct interface_screen *ifscreen;
1640 /* screen incoming caller id */
1642 /* check for MSN numbers, use first MSN if no match */
1644 ifmsn = interface->ifmsn;
1648 if (!strcmp(ifmsn->msn, id)) {
1651 ifmsn = ifmsn->next;
1654 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1655 add_trace("msn", NULL, "%s", id);
1658 if (!ifmsn && msn1) { // not in list, first msn given
1659 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1660 add_trace("msn", "given", "%s", id);
1661 add_trace("msn", "used", "%s", msn1);
1663 UNCPY(id, msn1, idsize);
1664 id[idsize-1] = '\0';
1668 /* check screen list */
1670 ifscreen = interface->ifscreen_out;
1672 ifscreen = interface->ifscreen_in;
1674 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1675 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
1676 if (strchr(ifscreen->match,'%')) {
1677 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1680 if (!strcmp(ifscreen->match, id))
1684 ifscreen = ifscreen->next;
1686 if (ifscreen) { // match
1687 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)");
1689 case INFO_NTYPE_UNKNOWN:
1690 add_trace("given", "type", "unknown");
1692 case INFO_NTYPE_SUBSCRIBER:
1693 add_trace("given", "type", "subscriber");
1695 case INFO_NTYPE_NATIONAL:
1696 add_trace("given", "type", "national");
1698 case INFO_NTYPE_INTERNATIONAL:
1699 add_trace("given", "type", "international");
1703 case INFO_PRESENT_ALLOWED:
1704 add_trace("given", "present", "allowed");
1706 case INFO_PRESENT_RESTRICTED:
1707 add_trace("given", "present", "restricted");
1709 case INFO_PRESENT_NOTAVAIL:
1710 add_trace("given", "present", "not available");
1713 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1714 if (ifscreen->result_type != -1) {
1715 *type = ifscreen->result_type;
1717 case INFO_NTYPE_UNKNOWN:
1718 add_trace("used", "type", "unknown");
1720 case INFO_NTYPE_SUBSCRIBER:
1721 add_trace("used", "type", "subscriber");
1723 case INFO_NTYPE_NATIONAL:
1724 add_trace("used", "type", "national");
1726 case INFO_NTYPE_INTERNATIONAL:
1727 add_trace("used", "type", "international");
1731 if (ifscreen->result_present != -1) {
1732 *present = ifscreen->result_present;
1734 case INFO_PRESENT_ALLOWED:
1735 add_trace("used", "present", "allowed");
1737 case INFO_PRESENT_RESTRICTED:
1738 add_trace("used", "present", "restricted");
1740 case INFO_PRESENT_NOTAVAIL:
1741 add_trace("used", "present", "not available");
1745 if (strchr(ifscreen->match,'%')) {
1746 SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1747 UNCPY(id, ifscreen->result, idsize);
1748 id[idsize-1] = '\0';
1749 if (strchr(id,'%')) {
1750 *strchr(id,'%') = '\0';
1751 UNCAT(id, suffix, idsize);
1752 id[idsize-1] = '\0';
1755 UNCPY(id, ifscreen->result, idsize);
1756 id[idsize-1] = '\0';
1758 add_trace("used", "id", "%s", id[0]?id:"<empty>");