SIP: Add DTMF support (receive INFO only)
[lcr.git] / interface.c
1 /*****************************************************************************\
2 **                                                                           **
3 ** LCR                                                                       **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** reading interface.conf file and filling structure                         **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12 #include "main.h"
13
14 struct interface *interface_first = NULL; /* first interface is current list */
15 struct interface *interface_newlist = NULL; /* first interface in new list */
16
17
18 #ifdef WITH_MISDN
19 /* set default out_channel */
20 void default_out_channel(struct interface_port *ifport)
21 {
22         struct select_channel *selchannel, **selchannelp;
23
24         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
25         memuse++;
26
27         if (ifport->mISDNport->ntmode)
28                 selchannel->channel = CHANNEL_FREE;
29         else
30                 selchannel->channel = CHANNEL_ANY;
31         
32         ifport->out_channel = selchannel;
33
34         /* additional channel selection for multipoint NT ports */
35         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode) {
36                 selchannelp = &(selchannel->next);
37                 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
38                 memuse++;
39                 selchannel->channel = CHANNEL_NO; // call waiting
40                 *selchannelp = selchannel;
41         }
42 }
43
44
45 /* set default in_channel */
46 void default_in_channel(struct interface_port *ifport)
47 {
48         struct select_channel *selchannel;
49
50         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
51         memuse++;
52         
53         selchannel->channel = CHANNEL_FREE;
54         
55         ifport->in_channel = selchannel;
56 }
57 #endif
58
59
60 /* parse string for a positive number */
61 static int get_number(char *value)
62 {
63         int val = 0;
64         char text[10];
65
66         val = atoi(value);
67         
68         SPRINT(text, "%d", val);
69
70         if (!strcmp(value, text))
71                 return(val);
72
73         return(-1);
74 }
75
76
77 /* remove element from buffer
78  * and return pointer to next element in buffer */
79 static char *get_seperated(char *buffer)
80 {
81         while(*buffer) {
82                 if (*buffer==',' || *buffer<=32) { /* seperate */
83                         *buffer++ = '\0';
84                         while((*buffer>'\0' && *buffer<=32) || *buffer==',')
85                                 buffer++;
86                         return(buffer);
87                 }
88                 buffer++;
89         }
90         return(buffer);
91 }
92
93 /*
94  * parameter processing
95  */
96 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
97 {
98         struct interface_port *ifport;
99
100         /* port in chain ? */
101         if (!interface->ifport) {
102                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
103                 return(-1);
104         }
105         /* goto end of chain */
106         ifport = interface->ifport;
107         while(ifport->next)
108                 ifport = ifport->next;
109         /* add value */
110         if (value[0]) {
111                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
112                 return(-1);
113         }
114         ifport->block = 1;
115         return(0);
116 }
117 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
118 {
119         if (interface->external) {
120                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is external interface.\n", filename, line, parameter);
121                 return(-1);
122         }
123         if (value[0]) {
124                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
125                 return(-1);
126         }
127         interface->extension = 1;
128         return(0);
129 }
130 static int inter_extern(struct interface *interface, char *filename, int line, char *parameter, char *value)
131 {
132         if (interface->extension) {
133                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed, because interface is an extension.\n", filename, line, parameter);
134                 return(-1);
135         }
136         if (value[0]) {
137                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
138                 return(-1);
139         }
140         interface->external = 1;
141         return(0);
142 }
143 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
144 {
145         struct interface_port *ifport;
146
147         /* port in chain ? */
148         if (!interface->ifport) {
149                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
150                 return(-1);
151         }
152         if (interface->ifport->ptmp) {
153                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
154                 return(-1);
155         }
156         /* goto end of chain */
157         ifport = interface->ifport;
158         while(ifport->next)
159                 ifport = ifport->next;
160         /* add value */
161         if (value[0]) {
162                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
163                 return(-1);
164         }
165         ifport->ptp = 1;
166         return(0);
167 }
168 #if 0
169 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
170 {
171         struct interface_port *ifport;
172
173         /* port in chain ? */
174         if (!interface->ifport) {
175                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
176                 return(-1);
177         }
178         if (interface->ifport->ptp) {
179                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
180                 return(-1);
181         }
182         /* goto end of chain */
183         ifport = interface->ifport;
184         while(ifport->next)
185                 ifport = ifport->next;
186         /* add value */
187         if (value[0]) {
188                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
189                 return(-1);
190         }
191         ifport->ptmp = 1;
192         return(0);
193 }
194 #endif
195 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
196 {
197         struct interface_port *ifport;
198
199         /* port in chain ? */
200         if (!interface->ifport) {
201                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
202                 return(-1);
203         }
204         /* goto end of chain */
205         ifport = interface->ifport;
206         while(ifport->next)
207                 ifport = ifport->next;
208         /* add value */
209         if (value[0]) {
210                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
211                 return(-1);
212         }
213         ifport->nt = 1;
214         return(0);
215 }
216 static int inter_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
217 {
218         struct interface_port *ifport;
219
220         /* port in chain ? */
221         if (!interface->ifport) {
222                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
223                 return(-1);
224         }
225         /* goto end of chain */
226         ifport = interface->ifport;
227         while(ifport->next)
228                 ifport = ifport->next;
229         /* add value */
230         if (value[0]) {
231                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
232                 return(-1);
233         }
234         ifport->tespecial = 1;
235         return(0);
236 }
237 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
238 {
239         if (!strcasecmp(value, "yes")) {
240                 interface->is_tones = IS_YES;
241         } else
242         if (!strcasecmp(value, "no")) {
243                 interface->is_tones = IS_NO;
244         } else {
245                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
246                 return(-1);
247         }
248         return(0);
249 }
250 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
251 {
252         if (!strcasecmp(value, "yes")) {
253                 interface->is_earlyb = IS_YES;
254         } else
255         if (!strcasecmp(value, "no")) {
256                 interface->is_earlyb = IS_NO;
257         } else {
258                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
259                 return(-1);
260         }
261         return(0);
262 }
263 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
264 {
265         if (!strcasecmp(value, "linear")) {
266                 interface->hunt = HUNT_LINEAR;
267         } else
268         if (!strcasecmp(value, "roundrobin")) {
269                 interface->hunt = HUNT_ROUNDROBIN;
270         } else {
271                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
272                 return(-1);
273         }
274         return(0);
275 }
276 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
277 {
278         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'portnum' and decrease port number by 1! Ports are counted from 0 now.\n", filename, line, parameter);
279         return(-1);
280 }
281 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
282 {
283 #ifndef WITH_MISDN
284         SPRINT(interface_error, "Error in %s (line %d): mISDN support is not compiled in.\n", filename, line);
285         return(-1);
286 #else
287         struct interface_port *ifport, **ifportp;
288         struct interface *searchif;
289         int val;
290
291         val = get_number(value);
292         if (val == -1) {
293                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
294                 return(-1);
295         }
296         /* check for port already assigned */
297         searchif = interface_newlist;
298         while(searchif) {
299                 ifport = searchif->ifport;
300                 while(ifport) {
301                         if (ifport->portnum == val) {
302                                 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
303                                 return(-1);
304                         }
305                         ifport = ifport->next;
306                 }
307                 searchif = searchif->next;
308         }
309         /* alloc port substructure */
310         ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
311         memuse++;
312         ifport->interface = interface;
313         /* set value */
314         ifport->portnum = val;
315         /* tail port */
316         ifportp = &interface->ifport;
317         while(*ifportp)
318                 ifportp = &((*ifportp)->next);
319         *ifportp = ifport;
320         return(0);
321 #endif
322 }
323 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
324 {
325 #ifndef WITH_MISDN
326         SPRINT(interface_error, "Error in %s (line %d): mISDN support is not compiled in.\n", filename, line);
327         return(-1);
328 #else
329         struct interface_port *ifport, **ifportp;
330
331         /* goto end of chain */
332         ifport = interface->ifport;
333         if (ifport) {
334                 while(ifport->next)
335                         ifport = ifport->next;
336         }
337
338         /* alloc port substructure */
339         ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
340         memuse++;
341         ifport->interface = interface;
342         /* set value */
343         ifport->portnum = -1; // disable until resolved
344         SCPY(ifport->portname, value);
345         /* tail port */
346         ifportp = &interface->ifport;
347         while(*ifportp)
348                 ifportp = &((*ifportp)->next);
349         *ifportp = ifport;
350         return(0);
351 #endif
352 }
353 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
354 {
355         struct interface_port *ifport;
356
357         /* port in chain ? */
358         if (!interface->ifport) {
359                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
360                 return(-1);
361         }
362         /* goto end of chain */
363         ifport = interface->ifport;
364         while(ifport->next)
365                 ifport = ifport->next;
366         if (!strcmp(value, "yes")) {
367                 ifport->l1hold = 1;
368         } else
369         if (!strcmp(value, "no")) {
370                 ifport->l1hold = 0;
371         } else {
372                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
373                 return(-1);
374         }
375         return(0);
376 }
377 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
378 {
379         struct interface_port *ifport;
380
381         /* port in chain ? */
382         if (!interface->ifport) {
383                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
384                 return(-1);
385         }
386         /* goto end of chain */
387         ifport = interface->ifport;
388         while(ifport->next)
389                 ifport = ifport->next;
390         if (!strcmp(value, "yes")) {
391                 ifport->l2hold = 1;
392         } else
393         if (!strcmp(value, "no")) {
394                 ifport->l2hold = -1;
395         } else {
396                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
397                 return(-1);
398         }
399         return(0);
400 }
401 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
402 {
403         struct interface_port *ifport;
404         struct select_channel *selchannel, **selchannelp;
405         int val;
406         char *p, *el;
407
408         /* port in chain ? */
409         if (!interface->ifport) {
410                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
411                 return(-1);
412         }
413         /* goto end of chain */
414         ifport = interface->ifport;
415         while(ifport->next)
416                 ifport = ifport->next;
417         p = value;
418         while(*p) {
419                 el = p;
420                 p = get_seperated(p);
421                 if (!strcasecmp(el, "force")) {
422                         ifport->channel_force = 1;
423                         if (ifport->out_channel) {
424                                 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
425                                 return(-1);
426                         }
427                 } else
428                 if (!strcasecmp(el, "any")) {
429                         val = CHANNEL_ANY;
430                         goto selchannel;
431                 } else
432                 if (!strcasecmp(el, "free")) {
433                         val = CHANNEL_FREE;
434                         goto selchannel;
435                 } else
436                 if (!strcasecmp(el, "no")) {
437                         val = CHANNEL_NO;
438                         goto selchannel;
439                 } else {
440                         val = get_number(el);
441                         if (val == -1) {
442                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of 'force', 'any', 'free', 'no' and any channel number.\n", filename, line, parameter);
443                                 return(-1);
444                         }
445
446                         if (val<1 || val==16 || val>126) {
447                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
448                                 return(-1);
449                         }
450                         selchannel:
451                         /* add to select-channel list */
452                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
453                         memuse++;
454                         /* set value */
455                         selchannel->channel = val;
456                         /* tail port */
457                         selchannelp = &ifport->out_channel;
458                         while(*selchannelp)
459                                 selchannelp = &((*selchannelp)->next);
460                         *selchannelp = selchannel;
461                 }
462         }
463         return(0);
464 }
465 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
466 {
467         struct interface_port *ifport;
468         struct select_channel *selchannel, **selchannelp;
469         int val;
470         char *p, *el;
471
472         /* port in chain ? */
473         if (!interface->ifport) {
474                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
475                 return(-1);
476         }
477         /* goto end of chain */
478         ifport = interface->ifport;
479         while(ifport->next)
480                 ifport = ifport->next;
481         p = value;
482         while(*p) {
483                 el = p;
484                 p = get_seperated(p);
485                 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE) {
486                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
487                                 return(-1);
488                 }
489                 if (!strcasecmp(el, "free")) {
490                         val = CHANNEL_FREE;
491                         goto selchannel;
492                 } else {
493                         val = get_number(el);
494                         if (val == -1) {
495                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
496                                 return(-1);
497                         }
498
499                         if (val<1 || val==16 || val>126) {
500                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
501                                 return(-1);
502                         }
503                         selchannel:
504                         /* add to select-channel list */
505                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
506                         memuse++;
507                         /* set value */
508                         selchannel->channel = val;
509                         /* tail port */
510                         selchannelp = &ifport->in_channel;
511                         while(*selchannelp)
512                                 selchannelp = &((*selchannelp)->next);
513                         *selchannelp = selchannel;
514                 }
515         }
516         return(0);
517 }
518 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
519 {
520         struct interface_port *ifport;
521 //      struct select_channel *selchannel, **selchannelp;
522 //      int val;
523         char *p, *el;
524
525         /* port in chain ? */
526         if (!interface->ifport) {
527                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
528                 return(-1);
529         }
530         /* goto end of chain */
531         ifport = interface->ifport;
532         while(ifport->next)
533                 ifport = ifport->next;
534         p = value;
535         if (!*p) {
536                 nofive:
537                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
538                 return(-1);
539         }
540         el = p;
541         p = get_seperated(p);
542         ifport->tout_setup = atoi(el);
543         if (!*p)
544                 goto nofive;
545         el = p;
546         p = get_seperated(p);
547         ifport->tout_dialing = atoi(el);
548         if (!*p)
549                 goto nofive;
550         el = p;
551         p = get_seperated(p);
552         ifport->tout_proceeding = atoi(el);
553         if (!*p)
554                 goto nofive;
555         el = p;
556         p = get_seperated(p);
557         ifport->tout_alerting = atoi(el);
558         if (!*p)
559                 goto nofive;
560         el = p;
561         p = get_seperated(p);
562         ifport->tout_disconnect = atoi(el);
563         return(0);
564 }
565 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
566 {
567         struct interface_msn *ifmsn, **ifmsnp;
568         char *p, *el;
569
570         if (!value[0]) {
571                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
572                 return(-1);
573         }
574         if (interface->ifscreen_in) {
575                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
576                 return(-1);
577         }
578
579         /* process list */
580         p = value;
581         while(*p) {
582                 el = p;
583                 p = get_seperated(p);
584                 /* add MSN to list */
585                 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
586                 memuse++;
587                 /* set value */
588                 SCPY(ifmsn->msn, el);
589                 /* tail port */
590                 ifmsnp = &interface->ifmsn;
591                 while(*ifmsnp)
592                         ifmsnp = &((*ifmsnp)->next);
593                 *ifmsnp = ifmsn;
594         }
595         return(0);
596 }
597 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
598 {
599         struct interface_screen *ifscreen;
600         char *p, *el;
601
602         if (!value[0]) {
603                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
604                 return(-1);
605         }
606         /* add screen entry to list*/
607         ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
608         memuse++;
609         ifscreen->match_type = -1; /* unchecked */
610         ifscreen->match_present = -1; /* unchecked */
611         ifscreen->result_type = -1; /* unchanged */
612         ifscreen->result_present = -1; /* unchanged */
613         /* tail port */
614         while(*ifscreenp)
615                 ifscreenp = &((*ifscreenp)->next);
616         *ifscreenp = ifscreen;
617 //      printf("interface=%s\n", interface->name);
618         /* get match */
619         p = value;
620         while(*p) {
621                 el = p;
622                 p = get_seperated(p);
623                 if (!strcasecmp(el, "unknown")) {
624                         if (ifscreen->match_type != -1) {
625                                 typeerror:
626                                 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
627                                 return(-1);
628                         }
629                         ifscreen->match_type = INFO_NTYPE_UNKNOWN;
630                 } else
631                 if (!strcasecmp(el, "subscriber")) {
632                         if (ifscreen->match_type != -1)
633                                 goto typeerror;
634                         ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
635                 } else
636                 if (!strcasecmp(el, "national")) {
637                         if (ifscreen->match_type != -1)
638                                 goto typeerror;
639                         ifscreen->match_type = INFO_NTYPE_NATIONAL;
640                 } else
641                 if (!strcasecmp(el, "international")) {
642                         if (ifscreen->match_type != -1)
643                                 goto typeerror;
644                         ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
645                 } else
646                 if (!strcasecmp(el, "allowed")) {
647                         if (ifscreen->match_present != -1) {
648                                 presenterror:
649                                 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
650                                 return(-1);
651                         }
652                         ifscreen->match_present = INFO_PRESENT_ALLOWED;
653                 } else
654                 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted")) {
655                         if (ifscreen->match_present != -1)
656                                 goto presenterror;
657                         ifscreen->match_present = INFO_PRESENT_RESTRICTED;
658                 } else {
659                         SCPY(ifscreen->match, el);
660                         /* check for % at the end */
661                         if (strchr(el, '%')) {
662                                 if (strchr(el, '%') != el+strlen(el)-1) {
663                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
664                                         return(-1);
665                                 }
666                         }
667                         break;
668                 }
669         }
670         if (ifscreen->match[0] == '\0') {
671                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
672                 return(-1);
673         }
674         /* get result */
675         while(*p) {
676                 el = p;
677                 p = get_seperated(p);
678                 if (!strcasecmp(el, "unknown")) {
679                         if (ifscreen->result_type != -1)
680                                 goto typeerror;
681                         ifscreen->result_type = INFO_NTYPE_UNKNOWN;
682                 } else
683                 if (!strcasecmp(el, "subscriber")) {
684                         if (ifscreen->result_type != -1)
685                                 goto typeerror;
686                         ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
687                 } else
688                 if (!strcasecmp(el, "national")) {
689                         if (ifscreen->result_type != -1)
690                                 goto typeerror;
691                         ifscreen->result_type = INFO_NTYPE_NATIONAL;
692                 } else
693                 if (!strcasecmp(el, "international")) {
694                         if (ifscreen->result_type != -1)
695                                 goto typeerror;
696                         ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
697                 } else
698                 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow")) {
699                         if (ifscreen->result_present != -1)
700                                 goto presenterror;
701                         ifscreen->result_present = INFO_PRESENT_ALLOWED;
702                 } else
703                 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied")) {
704                         if (ifscreen->result_present != -1)
705                                 goto presenterror;
706                         ifscreen->result_present = INFO_PRESENT_RESTRICTED;
707                 } else {
708                         SCPY(ifscreen->result, el);
709                         /* check for % at the end */
710                         if (strchr(el, '%')) {
711                                 if (strchr(el, '%') != el+strlen(el)-1) {
712                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
713                                         return(-1);
714                                 }
715                         }
716                         break;
717                 }
718         }
719         if (ifscreen->result[0] == '\0') {
720                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
721                 return(-1);
722         }
723         return(0);
724 }
725 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
726 {
727         if (interface->ifmsn) {
728                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
729                 return(-1);
730         }
731
732         return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
733 }
734 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
735 {
736         return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
737 }
738 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
739 {
740         struct interface_port *ifport;
741
742         /* port in chain ? */
743         if (!interface->ifport) {
744                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
745                 return(-1);
746         }
747         /* goto end of chain */
748         ifport = interface->ifport;
749         while(ifport->next)
750                 ifport = ifport->next;
751         ifport->nodtmf = 1;
752         return(0);
753 }
754 static int inter_dtmf_threshold(struct interface *interface, char *filename, int line, char *parameter, char *value)
755 {
756         struct interface_port *ifport;
757
758         /* port in chain ? */
759         if (!interface->ifport) {
760                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
761                 return(-1);
762         }
763         /* goto end of chain */
764         ifport = interface->ifport;
765         while(ifport->next)
766                 ifport = ifport->next;
767         ifport->dtmf_threshold = atoi(value);
768         return(0);
769 }
770 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
771 {
772         char *p, *q;
773
774         /* seperate parameter from filter */
775         p = value;
776         while(*p > 32)
777                 p++;
778         if (*p) {
779                 *p++ = 0;
780                 while(*p > 0 && *p <= 32)
781                         p++;
782         }
783
784         if (!strcasecmp(value, "gain")) {
785                 q = p;
786                 while(*q > 32)
787                         q++;
788                 if (*q) {
789                         *q++ = 0;
790                         while(*q > 0 && *q <= 32)
791                                 q++;
792                 }
793                 if (*p == 0 || *q == 0) {
794                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
795                         return(-1);
796                 }
797                 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8) {
798                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
799                         return(-1);
800                 }
801                 interface->tx_gain = atoi(p);
802                 interface->rx_gain = atoi(q);
803         } else
804         if (!strcasecmp(value, "pipeline")) {
805                 if (*p == 0) {
806                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
807                         return(-1);
808                 }
809                 SCPY(interface->pipeline, p);
810         } else
811         if (!strcasecmp(value, "blowfish")) {
812                 unsigned char key[56];
813                 int l;
814                 
815                 if (!!strncmp(p, "0x", 2)) {
816                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
817                         return(-1);
818                 }
819                 p += 2;
820                 l = 0; 
821                 while(*p) {
822                         if (l == 56) {
823                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
824                                 return(-1);
825                         }
826                         if (*p >= '0' && *p <= '9')
827                                 key[l] = (*p-'0')<<4;
828                         else if (*p >= 'a' && *p <= 'f')
829                                 key[l] = (*p-'a'+10)<<4;
830                         else if (*p >= 'A' && *p <= 'F')
831                                 key[l] = (*p-'A'+10)<<4;
832                         else {
833                                 digout:
834                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key has digits out of range. (0...9, a...f)\n", filename, line, parameter, value);
835                                 return(-1);
836                         }
837                         p++;
838                         if (*p == 0) {
839                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must end on an 8 bit boundary (two character boundary).\n", filename, line, parameter, value);
840                                 return(-1);
841                         }
842                         if (*p >= '0' && *p <= '9')
843                                 key[l] = (*p-'0')<<4;
844                         else if (*p >= 'a' && *p <= 'f')
845                                 key[l] = (*p-'a'+10)<<4;
846                         else if (*p >= 'A' && *p <= 'F')
847                                 key[l] = (*p-'A'+10)<<4;
848                         else
849                                 goto digout;
850                         p++;
851                         l++;
852                 }
853                 if (l < 4) {
854                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key must be at least 4 bytes (8 characters).\n", filename, line, parameter, value);
855                         return(-1);
856                 }
857                 memcpy(interface->bf_key, key, l);
858                 interface->bf_len = l;
859         } else {
860                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
861                 return(-1);
862         }
863         return(0);
864 }
865 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
866 {
867         struct interface_port *ifport;
868
869         /* port in chain ? */
870         if (!interface->ifport) {
871                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
872                 return(-1);
873         }
874         /* goto end of chain */
875         ifport = interface->ifport;
876         while(ifport->next)
877                 ifport = ifport->next;
878         ifport->dialmax = atoi(value);
879         return(0);
880 }
881 static int inter_tones_dir(struct interface *interface, char *filename, int line, char *parameter, char *value)
882 {
883         if (!value || !value[0]) {
884                 SPRINT(interface_error, "Error in %s (line %d): Missing tones directory.\n", filename, line);
885                 return(-1);
886         }
887         SCPY(interface->tones_dir, value);
888
889         return(0);
890 }
891 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
892 {
893         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' is outdated.\nPlease use 'gsm-bs' for base station or 'gsm-ms' for mobile station interface!\n", filename, line, parameter);
894         return(-1);
895 }
896 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
897 {
898 #ifndef WITH_GSM_BS
899         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
900         return(-1);
901 #else
902         struct interface *searchif;
903
904         interface->gsm_bs = 1;
905
906         if (!value)
907                 interface->gsm_bs_name[0] = '\0';
908         else
909                 SCPY(interface->gsm_bs_name, value);
910
911         /* check if name is used multiple times */
912         searchif = interface_newlist;
913         while(searchif) {
914                 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_bs_name, interface->gsm_bs_name)) {
915                         SPRINT(interface_error, "Error in %s (line %d): network '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_bs_name, searchif->gsm_bs_name);
916                         return(-1);
917                 }
918                 searchif = searchif->next;
919         }
920
921         return(0);
922 #endif
923 }
924 static int inter_gsm_bs_hr(struct interface *interface, char *filename, int line, char *parameter, char *value)
925 {
926 #ifndef WITH_GSM_BS
927         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
928         return(-1);
929 #else
930         interface->gsm_bs_hr = 1;
931
932         return(0);
933 #endif
934 }
935 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
936 {
937 #ifndef WITH_GSM_MS
938         SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
939         return(-1);
940 #else
941         struct interface *searchif;
942
943         interface->gsm_ms = 1;
944
945         /* copy values */
946         if (!value || !value[0]) {
947                 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
948                 return(-1);
949         }
950         SCPY(interface->gsm_ms_name, value);
951
952         /* check if name is used multiple times */
953         searchif = interface_newlist;
954         while(searchif) {
955                 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
956                         SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_ms_name, searchif->gsm_ms_name);
957                         return(-1);
958                 }
959                 searchif = searchif->next;
960         }
961
962         return(0);
963 #endif
964 }
965 static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
966 {
967 #ifndef WITH_SIP
968         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
969         return(-1);
970 #else
971         char *p;
972
973         interface->sip = 1;
974
975         /* copy values */
976         if (!value || !value[0]) {
977                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP local peer.\n", filename, line);
978                 return(-1);
979         }
980         p = get_seperated(value);
981         SCPY(interface->sip_local_peer, value);
982         SCPY(interface->sip_remote_peer, p);
983
984         return(0);
985 #endif
986 }
987 static int inter_authenticate(struct interface *interface, char *filename, int line, char *parameter, char *value)
988 {
989 #ifndef WITH_SIP
990         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
991         return(-1);
992 #else
993         char *p, *q;
994
995         if (!interface->sip) {
996                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
997                 return(-1);
998         }
999
1000         /* copy values */
1001         if (!value || !value[0]) {
1002                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1003                 return(-1);
1004         }
1005         p = get_seperated(value);
1006         if (!p[0]) {
1007                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP password.\n", filename, line);
1008                 return(-1);
1009         }
1010         q = get_seperated(p);
1011         SCPY(interface->sip_auth_user, value);
1012         SCPY(interface->sip_auth_password, p);
1013         if (q[0])
1014                 SCPY(interface->sip_auth_realm, q);
1015
1016         return(0);
1017 #endif
1018 }
1019 static int options_interval(struct interface *interface, char *filename, int line, char *parameter, char *value)
1020 {
1021 #ifndef WITH_SIP
1022         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1023         return(-1);
1024 #else
1025         if (!interface->sip) {
1026                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1027                 return(-1);
1028         }
1029
1030         if (!value || !value[0]) {
1031                 SPRINT(interface_error, "Error in %s (line %d): Missing options interval.\n", filename, line);
1032                 return(-1);
1033         }
1034         interface->sip_options_interval = atoi(value);
1035
1036         return(0);
1037 #endif
1038 }
1039 static int options_asserted_id(struct interface *interface, char *filename, int line, char *parameter, char *value)
1040 {
1041 #ifndef WITH_SIP
1042         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1043         return(-1);
1044 #else
1045         if (!interface->sip) {
1046                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1047                 return(-1);
1048         }
1049
1050         if (!value || !value[0]) {
1051                 SPRINT(interface_error, "Error in %s (line %d): Missing asserted caller ID.\n", filename, line);
1052                 return(-1);
1053         }
1054         SCPY(interface->sip_asserted_id, value);
1055
1056         return(0);
1057 #endif
1058 }
1059 static int options_public(struct interface *interface, char *filename, int line, char *parameter, char *value)
1060 {
1061 #ifndef WITH_SIP
1062         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1063         return(-1);
1064 #else
1065         if (!interface->sip) {
1066                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1067                 return(-1);
1068         }
1069         if (interface->sip_stun_server[0]) {
1070                 SPRINT(interface_error, "Error in %s (line %d): Don't specify STUN, if you want to define public IP.\n", filename, line);
1071                 return(-1);
1072         }
1073
1074         if (!value || !value[0]) {
1075                 SPRINT(interface_error, "Error in %s (line %d): Missing public IP.\n", filename, line);
1076                 return(-1);
1077         }
1078         SCPY(interface->sip_public_ip, value);
1079
1080         return(0);
1081 #endif
1082 }
1083 static int options_stun(struct interface *interface, char *filename, int line, char *parameter, char *value)
1084 {
1085 #ifndef WITH_SIP
1086         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1087         return(-1);
1088 #else
1089         char *p;
1090
1091         if (!interface->sip) {
1092                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1093                 return(-1);
1094         }
1095         if (interface->sip_public_ip[0]) {
1096                 SPRINT(interface_error, "Error in %s (line %d): Don't specify public IP, if you want to define STUN.\n", filename, line);
1097                 return(-1);
1098         }
1099
1100         if (!value || !value[0]) {
1101                 SPRINT(interface_error, "Error in %s (line %d): Missing STUN server.\n", filename, line);
1102                 return(-1);
1103         }
1104         p = get_seperated(value);
1105         if (!p[0]) {
1106                 SPRINT(interface_error, "Error in %s (line %d): Missing STUN timer.\n", filename, line);
1107                 return(-1);
1108         }
1109         SCPY(interface->sip_stun_server, value);
1110         interface->sip_stun_interval = atoi(p);
1111
1112         return(0);
1113 #endif
1114 }
1115 static int inter_rtp_ports(struct interface *interface, char *filename, int line, char *parameter, char *value)
1116 {
1117 #ifndef WITH_SIP
1118         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1119         return(-1);
1120 #else
1121         char *p;
1122
1123         if (!interface->sip) {
1124                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1125                 return(-1);
1126         }
1127
1128         /* copy values */
1129         if (!value || !value[0]) {
1130                 SPRINT(interface_error, "Error in %s (line %d): Missing 'from' port.\n", filename, line);
1131                 return(-1);
1132         }
1133         p = get_seperated(value);
1134         if (!p[0]) {
1135                 SPRINT(interface_error, "Error in %s (line %d): Missing 'to' port.\n", filename, line);
1136                 return(-1);
1137         }
1138         interface->rtp_port_from = atoi(value);
1139         interface->rtp_port_to = atoi(p);
1140
1141         return(0);
1142 #endif
1143 }
1144 static int inter_register(struct interface *interface, char *filename, int line, char *parameter, char *value)
1145 {
1146 #ifndef WITH_SIP
1147         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1148         return(-1);
1149 #else
1150         char *p, *q;
1151
1152         if (!interface->sip) {
1153                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1154                 return(-1);
1155         }
1156
1157         /* copy values */
1158         if (!value || !value[0]) {
1159                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1160                 return(-1);
1161         }
1162         p = get_seperated(value);
1163         if (!p[0]) {
1164                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP host\n", filename, line);
1165                 return(-1);
1166         }
1167         q = get_seperated(p);
1168         if (!q[0])
1169                 interface->sip_register_interval = 0;
1170         else
1171                 interface->sip_register_interval = atoi(q);
1172         interface->sip_register = 1;
1173         SCPY(interface->sip_register_user, value);
1174         SCPY(interface->sip_register_host, p);
1175
1176         return(0);
1177 #endif
1178 }
1179 static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1180 {
1181         int supported = 0;
1182
1183 #ifdef WITH_GSM_BS
1184         if (interface->gsm_bs)
1185                 supported = 1;
1186 #endif
1187 #ifdef WITH_SIP
1188         if (interface->sip)
1189                 supported = 1;
1190 #endif
1191         if (!supported) {
1192                 SPRINT(interface_error, "Error in %s (line %d): Interface does not support RTP\n", filename, line);
1193                 return(-1);
1194         }
1195
1196         if (interface->app != EAPP_TYPE_BRIDGE) {
1197                 SPRINT(interface_error, "Error in %s (line %d): '%s' requires previous 'bridge' parameter.\n", filename, line, parameter);
1198                 return(-1);
1199         }
1200
1201         interface->rtp_bridge = 1;
1202
1203         return(0);
1204 }
1205 #if 0
1206 static int inter_rtp_payload(struct interface *interface, char *filename, int line, char *parameter, char *value)
1207 {
1208 #ifndef WITH_GSM_BS
1209         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
1210         return(-1);
1211 #else
1212         if (!interface->gsm_bs) {
1213                 SPRINT(interface_error, "Error in %s (line %d): This parameter only works for GSM BS side interface\n", filename, line);
1214                 return(-1);
1215         }
1216         if (!interface->rtp_bridge) {
1217                 SPRINT(interface_error, "Error in %s (line %d): This parameter only works here, if RTP bridging is enabled\n", filename, line);
1218                 return(-1);
1219         }
1220         if (!value[0]) {
1221                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one payload type\n", filename, line, parameter);
1222                 return(-1);
1223         }
1224         if (interface->gsm_bs_payloads == sizeof(interface->gsm_bs_payload_types)) {
1225                 SPRINT(interface_error, "Error in %s (line %d): Too many payload types defined\n", filename, line);
1226                 return(-1);
1227         }
1228         interface->gsm_bs_payload_types[interface->gsm_bs_payloads++] = atoi(value);
1229
1230         return(0);
1231 #endif
1232 }
1233 #endif
1234 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
1235 {
1236         struct interface_port *ifport;
1237
1238         /* port in chain ? */
1239         if (!interface->ifport) {
1240                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1241                 return(-1);
1242         }
1243         /* goto end of chain */
1244         ifport = interface->ifport;
1245         while(ifport->next)
1246                 ifport = ifport->next;
1247         ifport->nonotify = 1;
1248         return(0);
1249 }
1250 #ifdef WITH_SS5
1251 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
1252 {
1253         struct interface_port *ifport;
1254         char *element;
1255
1256         /* port in chain ? */
1257         if (!interface->ifport) {
1258                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1259                 return(-1);
1260         }
1261         /* goto end of chain */
1262         ifport = interface->ifport;
1263         while(ifport->next)
1264                 ifport = ifport->next;
1265         ifport->ss5 |= SS5_ENABLE;
1266         while((element = strsep(&value, " "))) {
1267                 if (element[0] == '\0')
1268                         continue;
1269                 if (!strcasecmp(element, "connect"))
1270                         ifport->ss5 |= SS5_FEATURE_CONNECT;
1271                 else
1272                 if (!strcasecmp(element, "nodisconnect"))
1273                         ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1274                 else
1275                 if (!strcasecmp(element, "releaseguardtimer"))
1276                         ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1277                 else
1278                 if (!strcasecmp(element, "bell"))
1279                         ifport->ss5 |= SS5_FEATURE_BELL;
1280                 else
1281                 if (!strcasecmp(element, "pulsedialing"))
1282                         ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1283                 else
1284                 if (!strcasecmp(element, "delay"))
1285                         ifport->ss5 |= SS5_FEATURE_DELAY;
1286                 else
1287                 if (!strcasecmp(element, "release"))
1288                         ifport->ss5 |= SS5_FEATURE_RELEASE;
1289                 else
1290                 if (!strcasecmp(element, "mute-rx"))
1291                         ifport->ss5 |= SS5_FEATURE_MUTE_RX;
1292                 else
1293                 if (!strcasecmp(element, "mute-tx"))
1294                         ifport->ss5 |= SS5_FEATURE_MUTE_TX;
1295                 else
1296                 if (!strcasecmp(element, "quality"))
1297                         ifport->ss5 |= SS5_FEATURE_QUALITY;
1298                 else {
1299                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1300                         return(-1);
1301                 }
1302         }
1303         return(0);
1304 }
1305 #endif
1306 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1307 {
1308         struct interface *searchif;
1309
1310         if (!value[0]) {
1311                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1312                 return(-1);
1313         }
1314         searchif = interface_newlist;
1315         while(searchif) {
1316                 if (interface->remote && !strcmp(interface->remote_app, value)) {
1317                         SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses remote application '%s'.\n", filename, line, interface->name, value);
1318                         return(-1);
1319                 }
1320                 searchif = searchif->next;
1321         }
1322
1323         /* goto end of chain again to set application name */
1324         interface->remote = 1;
1325         SCPY(interface->remote_app, value);
1326
1327         return(0);
1328 }
1329 static int inter_context(struct interface *interface, char *filename, int line, char *parameter, char *value)
1330 {
1331         if (!value[0]) {
1332                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application context as value.\n", filename, line, parameter);
1333                 return(-1);
1334         }
1335         SCPY(interface->remote_context, value);
1336
1337         return(0);
1338 }
1339 static int inter_pots_flash(struct interface *interface, char *filename, int line, char *parameter, char *value)
1340 {
1341         struct interface_port *ifport;
1342
1343         /* port in chain ? */
1344         if (!interface->ifport) {
1345                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1346                 return(-1);
1347         }
1348         /* goto end of chain */
1349         ifport = interface->ifport;
1350         while(ifport->next)
1351                 ifport = ifport->next;
1352
1353         ifport->pots_flash = 1;
1354         return(0);
1355 }
1356 static int inter_pots_ring(struct interface *interface, char *filename, int line, char *parameter, char *value)
1357 {
1358         struct interface_port *ifport;
1359
1360         /* port in chain ? */
1361         if (!interface->ifport) {
1362                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1363                 return(-1);
1364         }
1365         /* goto end of chain */
1366         ifport = interface->ifport;
1367         while(ifport->next)
1368                 ifport = ifport->next;
1369
1370         ifport->pots_ring = 1;
1371         return(0);
1372 }
1373 static int inter_pots_transfer(struct interface *interface, char *filename, int line, char *parameter, char *value)
1374 {
1375         struct interface_port *ifport;
1376
1377         /* port in chain ? */
1378         if (!interface->ifport) {
1379                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1380                 return(-1);
1381         }
1382         /* goto end of chain */
1383         ifport = interface->ifport;
1384         while(ifport->next)
1385                 ifport = ifport->next;
1386
1387         ifport->pots_transfer = 1;
1388         return(0);
1389 }
1390 static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
1391 {
1392         interface->shutdown = 1;
1393
1394         return(0);
1395 }
1396 static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1397 {
1398         if (!value || !value[0]) {
1399                 SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
1400                 return(-1);
1401         }
1402         interface->app = EAPP_TYPE_BRIDGE;
1403         SCPY(interface->bridge_if, value);
1404
1405         return(0);
1406 }
1407
1408
1409 /*
1410  * structure of parameters
1411  */
1412 struct interface_param interface_param[] = {
1413         { "extension", &inter_extension, "",
1414         "If keyword is given, calls to interface are handled as internal extensions."},
1415
1416         { "extern", &inter_extern, "",
1417         "If keyword is given, this interface will be used for external calls.\n"
1418         "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1419         "Calls forwarded by extension's 'settings' also require an external interface."},
1420
1421         {"tones", &inter_tones, "yes | no",
1422         "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1423
1424         {"earlyb", &inter_earlyb, "yes | no",
1425         "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1426
1427         {"hunt", &inter_hunt, "linear | roundrobin",
1428         "Select the algorithm for selecting port with free channel."},
1429
1430         {"port", &inter_port, "<number>",
1431         ""},
1432         {"portnum", &inter_portnum, "<number>",
1433         "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1434         {"portname", &inter_portname, "<name>",
1435         "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1436
1437         {"block", &inter_block, "",
1438         "If keyword is given, calls on this interface are blocked.\n"
1439         "This parameter must follow a 'port' parameter."},
1440
1441         {"ptp", &inter_ptp, "",
1442         "The given port above is opened as point-to-point.\n"
1443         "This is required on NT-mode ports that are multipoint by default.\n"
1444         "This parameter must follow a 'port' parameter."},
1445
1446 #if 0
1447         {"ptmp", &inter_ptmp, "",
1448         "The given port above is opened as point-to-multipoint.\n"
1449         "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1450         "This parameter must follow a 'port' parameter."},
1451 #endif
1452
1453         {"nt", &inter_nt, "",
1454         "The given port above is opened in NT-mode.\n"
1455         "This is required on interfaces that support both NT-mode and TE-mode.\n"
1456         "This parameter must follow a 'port' parameter."},
1457
1458         {"te-special", &inter_tespecial, "",
1459         "The given port uses a modified TE-mode.\n"
1460         "All information elements that are allowed Network->User will then be\n"
1461         "transmitted User->Network also. This is usefull to pass all informations\n"
1462         "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1463         "Note that this is not compliant with ISDN protocol.\n"
1464         "This parameter must follow a 'port' parameter."},
1465
1466         {"layer1hold", &inter_l1hold, "yes | no",
1467         "The given port will not release layer 1 after layer 2 is down.\n"
1468         "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1469         "This parameter must follow a 'port' parameter."},
1470
1471         {"layer2hold", &inter_l2hold, "yes | no",
1472         "The given port will continuously try to establish layer 2 link and hold it.\n"
1473         "It is required for PTP links in most cases, therefore it is default.\n"
1474         "This parameter must follow a 'port' parameter."},
1475
1476         {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1477         "Channel selection list for all outgoing calls to the interface.\n"
1478         "A free channels is searched in order of appearance.\n"
1479         "This parameter must follow a 'port' parameter.\n"
1480         " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1481         "  -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1482         " <number>[,...] - List of channels to search.\n"
1483         " free - Select any free channel\n"
1484         " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1485         " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1486
1487         {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1488         "Channel selection list for all incoming calls from the interface.\n"
1489         "A free channels is accepted if in the list.\n"
1490         "If any channel was requested, the first free channel found is selected.\n"
1491         "This parameter must follow a 'port' parameter.\n"
1492         " <number>[,...] - List of channels to accept.\n"
1493         " free - Accept any free channel"},
1494
1495         {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1496         "Timeout values for call states. They are both for incoming and outgoing states.\n"
1497         "The default is 120 seconds for all states. Use 0 to disable.\n"
1498         "This parameter must follow a 'port' parameter."},
1499
1500         {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1501         "Incoming caller ID is checked against given MSN numbers.\n"
1502         "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1503
1504         {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1505         "Adds an entry for incoming calls to the caller ID screen list.\n"
1506         "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1507         "If '%' is given after old caller ID, it matches even if caller ID has\n"
1508         "additional digits.\n"
1509         "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1510         "are added.\n"
1511         "Options can be:\n"
1512         " unknown | subsciber | national | international - Change caller ID type.\n"
1513         " present | restrict - Change presentation of caller ID."},
1514                 
1515         {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1516         "Adds an entry for outgoing calls to the caller ID screen list.\n"
1517         "See 'screen-in' for help."},
1518
1519         {"nodtmf", &inter_nodtmf, "",
1520         "Disables DTMF detection for this interface.\n"
1521         "This parameter must follow a 'port' parameter."},
1522
1523         {"dtmf-threshold", &inter_dtmf_threshold, "",
1524         "Set threshold value for minimum DTMF tone level.\n"
1525         "This parameter must follow a 'port' parameter."},
1526
1527         {"filter", &inter_filter, "<filter> <parameters>",
1528         "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1529         "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1530         "pipeline <string> - Sets echo cancelation pipeline.\n"
1531         "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1532
1533         {"dialmax", &inter_dialmax, "<digits>",
1534         "Limits the number of digits in setup/information message."},
1535
1536         {"tones-dir", &inter_tones_dir, "<path>",
1537         "Overrides the given tone_dir in options.conf.\n"
1538         "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1539         {"tones_dir", &inter_tones_dir, "<path>",
1540         "Same as tones-dir"},
1541
1542         {"gsm", &inter_gsm, "",
1543         ""},
1544         {"gsm-bs", &inter_gsm_bs, "[<socket name>]",
1545         "Sets up GSM base station interface for using OpenBSC.\n"
1546         "The socket is /tmp/bsc_mncc by default. If socket name is given, the socket will be\n"
1547         "extended to /tmp/bsc_mncc_<socket name>."},
1548         {"hr", &inter_gsm_bs_hr, "",
1549         "Enable and prefer half rate for mobile terminating calls."},
1550         {"gsm-ms", &inter_gsm_ms, "<socket name>",
1551         "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1552         "The socket will be /tmp/ms_mncc_<socket name>."},
1553
1554         {"sip", &inter_sip, "<local IP/host>[:port] [<remote IP/host>[port]]",
1555         "Sets up SIP interface that represents one SIP endpoint.\n"
1556         "If the remote IP/host is omitted, a client must register first to us."},
1557         {"register", &inter_register, "<user> <host> [register-interval]",
1558         "Registers to given SIP registrar.\n"
1559         "Optionally give RE-REGISTER interval time in seconds.\n"
1560         "The exire value is set 60 seconds ahead this interval, then."},
1561         {"authenticate", &inter_authenticate, "<user> <password> [realm]",
1562         "Defines SIP user and password for authentication.\n"
1563         "If no remote IP was give, we are SIP gateway, so realm must be given also."},
1564         {"options-interval", &options_interval, "<interval> | 0",
1565         "Defines SIP timer to send OPTIONS messages to keepalive INVITE sessions."},
1566         {"asserted-id", &options_asserted_id, "<caller-id>",
1567         "Defines SIP's asserted-id in INVITE message."},
1568         {"public", &options_public, "<server> <interval>",
1569         "Defines public IP, if this endpoint is behind NAT firewall."},
1570         {"stun", &options_stun, "<server> <interval>",
1571         "Defines STUN server to resolv real local IP.\n"
1572         "The interval is used to check if IP has changed. (use 300)"},
1573         {"rtp-ports", &inter_rtp_ports, "<port from> <port to>",
1574         "Defines the range of ports to be used for RTP. This overrides the default."},
1575
1576         {"rtp-bridge", &inter_rtp_bridge, "",
1577         "Enables RTP bridging directly from this interface.\n"
1578         "This only works if both bridged interfaces use RTP, e.g. between gsm-bs and sip.\n"
1579         "This parameter must follow a 'bridge' parameter."},
1580 #if 0
1581         not needed, since ms defines what is supports and remote (sip) tells what is selected
1582         {"rtp-payload", &inter_rtp_payload, "<codec>",
1583         "Define RTP payload to use. Only valid in conjuntion with gsm-bs!\n"
1584         "If multiple payloads are defined, the first has highest priority.\n"
1585         "If none are defined, GSM fullrate V1 (type 3) is assumed."},
1586 #endif
1587
1588         {"nonotify", &inter_nonotify, "",
1589         "Prevents sending notify messages to this interface. A call placed on hold will\n"
1590         "Not affect the remote end (phone or telcom switch).\n"
1591         "This parameter must follow a 'port' parameter."},
1592
1593         {"bridge", &inter_bridge, "<destination interface>",
1594         "Define bridge application for this interface. All calls received on this\n"
1595         "interface will be directly bridged to the given destination interface.\n"
1596         "There will be no PBX application, nor routing."},
1597
1598 #ifdef WITH_SS5
1599         {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1600         "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1601         "This feature causes CPU load to rise and has no practical intend.\n"
1602         "If you don't know what it is, you don't need it.\n"
1603         "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1604         " connect - Connect incomming call to throughconnect audio, if required.\n"
1605         " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1606         " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1607         " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1608         " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1609         " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1610         " release - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1611         " mutes-rx - Mute received 2600 and 2400 Hz tones when detected. (more realistic)\n"
1612         " mutes-tx - Mute received 2600 and 2400 Hz tones while transmitting reply tone. (more hackable)"},
1613 #endif
1614
1615         {"remote", &inter_remote, "<application>",
1616         "Sets up an interface that communicates with the remote application.\n"
1617         "Use \"asterisk\" to use chan_lcr as remote application."},
1618         {"context", &inter_context, "<context>",
1619         "Give context for calls to application."},
1620
1621         {"pots-flash", &inter_pots_flash, "",
1622         "Allow flash button to hold an active call and setup a new call.\n"
1623         "Ihis parameter only appies to POTS type of interfaces\n"
1624         "This parameter must follow a 'port' parameter."},
1625         {"pots-ring-after-hangup", &inter_pots_ring, "",
1626         "Allow ringing of last hold call after hangup. Other calls on hold will not be\n"
1627         "released.\n"
1628         "Ihis parameter only appies to POTS type of interfaces\n"
1629         "This parameter must follow a 'port' parameter."},
1630         {"pots-transfer-after-hangup", &inter_pots_transfer, "",
1631         "If two calls on hold, both are connected after hangup.\n"
1632         "If one call is on hold and another one alerting, call on hold is tranfered.\n"
1633         "Ihis parameter only appies to POTS type of interfaces\n"
1634         "This parameter must follow a 'port' parameter."},
1635
1636         {"shutdown", &inter_shutdown, "",
1637         "Interface will not be loaded when processing interface.conf"},
1638
1639         {NULL, NULL, NULL, NULL}
1640 };
1641
1642 /* read interfaces
1643  *
1644  * read settings from interface.conf
1645  */
1646 char interface_error[256];
1647 struct interface *read_interfaces(void)
1648 {
1649         FILE                    *fp = NULL;
1650         char                    filename[128];
1651         char                    *p;
1652         unsigned int            line, i;
1653         char                    buffer[256];
1654         struct interface        *interface = NULL, /* in case no interface */
1655                                 **interfacep = &interface_newlist;
1656         char                    parameter[128];
1657         char                    value[256];
1658         int                     expecting = 1; /* expecting new interface */
1659         struct interface_param  *ifparam;
1660
1661         if (interface_newlist != NULL)
1662                 FATAL("list is not empty.\n");
1663         interface_error[0] = '\0';
1664         SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1665
1666         if (!(fp = fopen(filename,"r"))) {
1667                 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1668                 goto error;
1669         }
1670
1671         line=0;
1672         while((GETLINE(buffer, fp))) {
1673                 p=buffer;
1674                 line++;
1675
1676                 while(*p <= 32) { /* skip spaces */
1677                         if (*p == 0)
1678                                 break;
1679                         p++;
1680                 }
1681                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1682                         continue;
1683
1684                 parameter[0]=0;
1685                 value[0]=0;
1686                 i=0; /* read parameter */
1687                 while(*p > 32) {
1688                         if (i+1 >= sizeof(parameter)) {
1689                                 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1690                                 goto error;
1691                         }
1692                         parameter[i+1] = '\0';
1693                         parameter[i++] = *p++;
1694                 }
1695
1696                 while(*p <= 32) { /* skip spaces */
1697                         if (*p == 0)
1698                                 break;
1699                         p++;
1700                 }
1701
1702                 if (*p!=0 && *p!='#') { /* missing name */
1703                         i=0; /* read until end */
1704                         while(*p!=0 && *p!='#') {
1705                                 if (i+1 >= sizeof(value)) {
1706                                         SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1707                                         goto error;
1708                                 }
1709                                 value[i+1] = '\0';
1710                                 value[i++] = *p++;
1711                         }
1712
1713                         /* remove trailing spaces from value */
1714                         while(i) {
1715                                 if (value[i-1]==0 || value[i-1]>32)
1716                                         break;
1717                                 value[i-1] = '\0';
1718                                 i--;
1719                         }
1720                 }
1721
1722                 /* check for interface name as first statement */
1723                 if (expecting && parameter[0]!='[') {
1724                         SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1725                         goto error;
1726                 }
1727                 expecting = 0;
1728
1729                 /* check for new interface */
1730                 if (parameter[0] == '[') {
1731                         if (parameter[strlen(parameter)-1] != ']') {
1732                                 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1733                                 goto error;
1734                         }
1735                         parameter[strlen(parameter)-1] = '\0';
1736
1737                         /* check if interface name already exists */
1738                         interface = interface_newlist;
1739                         while(interface) {
1740                                 if (!strcasecmp(interface->name, parameter+1)) {
1741                                         SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1742                                         goto error;
1743                                 }
1744                                 interface = interface->next;
1745                         }
1746
1747                         /* append interface to new list */
1748                         interface = (struct interface *)MALLOC(sizeof(struct interface));
1749                         memuse++;
1750
1751                         /* name interface */
1752                         SCPY(interface->name, parameter+1);
1753
1754                         /* attach */
1755                         *interfacep = interface;
1756                         interfacep = &interface->next;
1757
1758                         continue;
1759                 }
1760
1761                 ifparam = interface_param;
1762                 while(ifparam->name) {
1763                         if (!strcasecmp(parameter, ifparam->name)) {
1764                                 if (ifparam->func(interface, filename, line, parameter, value))
1765                                         goto error;
1766                                 break;
1767                         }
1768                         ifparam++;
1769                 }
1770                 if (ifparam->name)
1771                         continue;
1772
1773                 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1774                 goto error;
1775         }
1776
1777         if (fp) fclose(fp);
1778         return(interface_newlist);
1779 error:
1780         PERROR_RUNTIME("%s", interface_error);
1781         if (fp) fclose(fp);
1782         free_interfaces(interface_newlist);
1783         interface_newlist = NULL;
1784         return(NULL);
1785 }
1786
1787
1788 /*
1789  * freeing chain of interfaces
1790  */
1791 void free_interfaces(struct interface *interface)
1792 {
1793         void *temp;
1794         struct interface_port *ifport;
1795         struct select_channel *selchannel;
1796         struct interface_msn *ifmsn;
1797         struct interface_screen *ifscreen;
1798
1799         while(interface) {
1800                 ifport = interface->ifport;
1801                 while(ifport) {
1802                         selchannel = ifport->in_channel;
1803                         while(selchannel) {
1804                                 temp = selchannel;
1805                                 selchannel = selchannel->next;
1806                                 FREE(temp, sizeof(struct select_channel));
1807                                 memuse--;
1808                         }
1809                         selchannel = ifport->out_channel;
1810                         while(selchannel) {
1811                                 temp = selchannel;
1812                                 selchannel = selchannel->next;
1813                                 FREE(temp, sizeof(struct select_channel));
1814                                 memuse--;
1815                         }
1816                         temp = ifport;
1817                         ifport = ifport->next;
1818                         FREE(temp, sizeof(struct interface_port));
1819                         memuse--;
1820                 }
1821                 ifmsn = interface->ifmsn;
1822                 while(ifmsn) {
1823                         temp = ifmsn;
1824                         ifmsn = ifmsn->next;
1825                         FREE(temp, sizeof(struct interface_msn));
1826                         memuse--;
1827                 }
1828                 ifscreen = interface->ifscreen_in;
1829                 while(ifscreen) {
1830                         temp = ifscreen;
1831                         ifscreen = ifscreen->next;
1832                         FREE(temp, sizeof(struct interface_screen));
1833                         memuse--;
1834                 }
1835                 ifscreen = interface->ifscreen_out;
1836                 while(ifscreen) {
1837                         temp = ifscreen;
1838                         ifscreen = ifscreen->next;
1839                         FREE(temp, sizeof(struct interface_screen));
1840                         memuse--;
1841                 }
1842                 temp = interface;
1843                 interface = interface->next;
1844                 FREE(temp, sizeof(struct interface));
1845                 memuse--;
1846         }
1847 }
1848
1849 #ifdef WITH_MISDN
1850 /*
1851  * defaults of ports if not specified by config
1852  */
1853 static void set_mISDN_defaults(struct interface_port *ifport)
1854 {
1855         /* default channel selection list */
1856         if (!ifport->out_channel)
1857                 default_out_channel(ifport);
1858         if (!ifport->in_channel)
1859                 default_in_channel(ifport);
1860         /* must force the channel on PTMP/NT ports */
1861         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1862                 ifport->channel_force = 1;
1863         /* default is_tones */
1864         if (ifport->interface->is_tones)
1865                 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1866         else
1867                 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1868         /* default is_earlyb */
1869         if (ifport->interface->is_earlyb)
1870                 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1871         else
1872                 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1873         /* set locally flag */
1874         if (ifport->interface->extension)
1875                 ifport->mISDNport->locally = 1;
1876         else
1877                 ifport->mISDNport->locally = 0;
1878 }
1879 #endif
1880
1881
1882 /*
1883  * all links between mISDNport and interface are made
1884  * unused mISDNports are closed, new mISDNports are opened
1885  * also set default select_channel lists
1886  */
1887 void relink_interfaces(void)
1888 {
1889 #ifdef WITH_MISDN
1890         struct mISDNport *mISDNport;
1891         struct interface_port *ifport;
1892 #endif
1893         struct interface *interface, *temp, *found;
1894
1895         interface = interface_first;
1896         while(interface) {
1897                 found = NULL;
1898                 temp = interface_newlist;
1899                 while(temp) {
1900                         if (!strcmp(temp->name, interface->name))
1901                                 found = temp;
1902                         temp = temp->next;
1903                 }
1904                 if (!found) {
1905 #ifdef WITH_GSM_MS
1906                         if (interface->gsm_ms)
1907                                 gsm_ms_delete(interface->gsm_ms_name);
1908 #endif
1909 #ifdef WITH_GSM_BS
1910                         if (interface->gsm_bs)
1911                                 gsm_bs_delete(interface->gsm_bs_name);
1912 #endif
1913 #ifdef WITH_SIP
1914                         if (interface->sip)
1915                                 sip_exit_inst(interface);
1916 #endif
1917                 } else {
1918 #ifdef WITH_SIP
1919                         if (interface->sip) {
1920                                 /* move sip instance, if we keep interface */
1921                                 found->sip_inst = interface->sip_inst;
1922                                 interface->sip_inst = NULL;
1923                         }
1924 #endif
1925                         ;
1926                 }
1927                 interface = interface->next;
1928         }
1929
1930         interface = interface_newlist;
1931         while(interface) {
1932                 found = NULL;
1933                 temp = interface_first;
1934                 while(temp) {
1935                         if (!strcmp(temp->name, interface->name))
1936                                 found = temp;
1937                         temp = temp->next;
1938                 }
1939                 if (!found) {
1940 #ifdef WITH_GSM_MS
1941                         if (interface->gsm_ms)
1942                                 gsm_ms_new(interface);
1943 #endif
1944 #ifdef WITH_GSM_BS
1945                         if (interface->gsm_bs)
1946                                 gsm_bs_new(interface);
1947 #endif
1948 #ifdef WITH_SIP
1949                         if (interface->sip)
1950                                 sip_init_inst(interface);
1951 #endif
1952                 }
1953                 interface = interface->next;
1954         }
1955
1956 #ifdef WITH_MISDN
1957         /* unlink all mISDNports */
1958         mISDNport = mISDNport_first;
1959         while(mISDNport) {
1960                 mISDNport->ifport = NULL;
1961                 mISDNport = mISDNport->next;
1962         }
1963
1964         /* relink existing mISDNports */
1965         interface = interface_newlist;
1966         while(interface) {
1967                 ifport = interface->ifport;
1968                 while(ifport) {
1969                         mISDNport = mISDNport_first;
1970                         while(mISDNport) {
1971                                 if (!strcmp(mISDNport->name, ifport->portname))
1972                                         ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1973                                 if (mISDNport->portnum == ifport->portnum) {
1974                                         PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1975                                         ifport->mISDNport = mISDNport;
1976                                         mISDNport->ifport = ifport;
1977                                         set_mISDN_defaults(ifport);
1978                                 }
1979                                 mISDNport = mISDNport->next;
1980                         }
1981                         ifport = ifport->next;
1982                 }
1983                 interface = interface->next;
1984         }
1985
1986         /* close unused mISDNports */
1987         closeagain:
1988         mISDNport = mISDNport_first;
1989         while(mISDNport) {
1990                 if (mISDNport->ifport == NULL) {
1991                         PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1992                         /* destroy port */
1993                         mISDNport_close(mISDNport);
1994                         goto closeagain;
1995                 }
1996                 mISDNport = mISDNport->next;
1997         }
1998
1999         /* open and link new mISDNports */
2000         interface = interface_newlist;
2001         while(interface) {
2002                 ifport = interface->ifport;
2003                 while(ifport) {
2004                         if (!ifport->mISDNport) {
2005                                 if (!interface->shutdown) {
2006                                         load_mISDN_port(ifport);
2007                                 } else {
2008                                         ifport->block = 2;
2009                                 }
2010                         }
2011                         ifport = ifport->next;
2012                 }
2013                 interface = interface->next;
2014         }
2015 #endif
2016 }
2017
2018
2019 #ifdef WITH_MISDN
2020 /*
2021  * load port
2022  */
2023 void load_mISDN_port(struct interface_port *ifport)
2024 {
2025         struct mISDNport *mISDNport;
2026
2027         /* open new port */
2028         mISDNport = mISDNport_open(ifport);
2029         if (mISDNport) {
2030                 /* link port */
2031                 ifport->mISDNport = mISDNport;
2032                 mISDNport->ifport = ifport;
2033                 /* set number and name */
2034                 ifport->portnum = mISDNport->portnum;
2035                 SCPY(ifport->portname, mISDNport->name);
2036                 /* set defaults */
2037                 set_mISDN_defaults(ifport);
2038                 /* load static port instances */
2039                 mISDNport_static(mISDNport);
2040         } else {
2041                 ifport->block = 2; /* not available */
2042         }
2043 }
2044 #endif
2045
2046 /*
2047  * give summary of interface syntax
2048  */
2049 void doc_interface(void)
2050 {
2051         struct interface_param *ifparam;
2052         
2053         printf("Syntax overview\n");
2054         printf("---------------\n\n");
2055
2056         printf("[<name>]\n");
2057         ifparam = interface_param;
2058         while(ifparam->name) {
2059                 if (ifparam->name[0])
2060                         printf("%s %s\n", ifparam->name, ifparam->usage);
2061                 ifparam++;
2062         }
2063
2064         ifparam = interface_param;
2065         while(ifparam->name) {
2066                 if (ifparam->name[0]) {
2067                         printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
2068                         printf("%s\n", ifparam->help);
2069                 }
2070                 ifparam++;
2071         }
2072 }
2073
2074
2075 /* screen caller id
2076  * out==0: incoming caller id, out==1: outgoing caller id
2077  */
2078 void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
2079 {
2080         char                    *msn1;
2081         struct interface_msn    *ifmsn;
2082         struct interface_screen *ifscreen;
2083         char suffix[64];
2084         struct interface *interface = interface_first;
2085
2086         interface = getinterfacebyname(interface_name);
2087         if (!interface)
2088                 return;
2089
2090         /* screen incoming caller id */
2091         if (!out) {
2092                 /* check for MSN numbers, use first MSN if no match */
2093                 msn1 = NULL;
2094                 ifmsn = interface->ifmsn;
2095                 while(ifmsn) {
2096                         if (!msn1)
2097                                 msn1 = ifmsn->msn;
2098                         if (!strcmp(ifmsn->msn, id)) {
2099                                 break;
2100                         }
2101                         ifmsn = ifmsn->next;
2102                 }
2103                 if (ifmsn) {
2104                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
2105                         add_trace("msn", NULL, "%s", id);
2106                         end_trace();
2107                 }
2108                 if (!ifmsn && msn1) { // not in list, first msn given
2109                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
2110                         add_trace("msn", "given", "%s", id);
2111                         add_trace("msn", "used", "%s", msn1);
2112                         end_trace();
2113                         UNCPY(id, msn1, idsize);
2114                         id[idsize-1] = '\0';
2115                 }
2116         }
2117
2118         /* check screen list */
2119         if (out)
2120                 ifscreen = interface->ifscreen_out;
2121         else
2122                 ifscreen = interface->ifscreen_in;
2123         while (ifscreen) {
2124                 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
2125                 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
2126                         if (strchr(ifscreen->match,'%')) {
2127                                 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
2128                                         break;
2129                         } else {
2130                                 if (!strcmp(ifscreen->match, id))
2131                                         break;
2132                         }
2133                 }
2134                 ifscreen = ifscreen->next;
2135         }
2136         if (ifscreen) { // match
2137                 start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, out?DIRECTION_OUT:DIRECTION_IN, 0, 0, "SCREEN (found in screen list)");
2138                 switch(*type) {
2139                         case INFO_NTYPE_UNKNOWN:
2140                         add_trace("given", "type", "unknown");
2141                         break;
2142                         case INFO_NTYPE_SUBSCRIBER:
2143                         add_trace("given", "type", "subscriber");
2144                         break;
2145                         case INFO_NTYPE_NATIONAL:
2146                         add_trace("given", "type", "national");
2147                         break;
2148                         case INFO_NTYPE_INTERNATIONAL:
2149                         add_trace("given", "type", "international");
2150                         break;
2151                 }
2152                 switch(*present) {
2153                         case INFO_PRESENT_ALLOWED:
2154                         add_trace("given", "present", "allowed");
2155                         break;
2156                         case INFO_PRESENT_RESTRICTED:
2157                         add_trace("given", "present", "restricted");
2158                         break;
2159                         case INFO_PRESENT_NOTAVAIL:
2160                         add_trace("given", "present", "not available");
2161                         break;
2162                 }
2163                 add_trace("given", "id", "%s", id[0]?id:"<empty>");
2164                 if (ifscreen->result_type != -1) {
2165                         *type = ifscreen->result_type;
2166                         switch(*type) {
2167                                 case INFO_NTYPE_UNKNOWN:
2168                                 add_trace("used", "type", "unknown");
2169                                 break;
2170                                 case INFO_NTYPE_SUBSCRIBER:
2171                                 add_trace("used", "type", "subscriber");
2172                                 break;
2173                                 case INFO_NTYPE_NATIONAL:
2174                                 add_trace("used", "type", "national");
2175                                 break;
2176                                 case INFO_NTYPE_INTERNATIONAL:
2177                                 add_trace("used", "type", "international");
2178                                 break;
2179                         }
2180                 }
2181                 if (ifscreen->result_present != -1) {
2182                         *present = ifscreen->result_present;
2183                         switch(*present) {
2184                                 case INFO_PRESENT_ALLOWED:
2185                                 add_trace("used", "present", "allowed");
2186                                 break;
2187                                 case INFO_PRESENT_RESTRICTED:
2188                                 add_trace("used", "present", "restricted");
2189                                 break;
2190                                 case INFO_PRESENT_NOTAVAIL:
2191                                 add_trace("used", "present", "not available");
2192                                 break;
2193                         }
2194                 }
2195                 if (strchr(ifscreen->match,'%')) {
2196                         SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
2197                         UNCPY(id, ifscreen->result, idsize);
2198                         id[idsize-1] = '\0';
2199                         if (strchr(id,'%')) {
2200                                 *strchr(id,'%') = '\0';
2201                                 UNCAT(id, suffix, idsize);
2202                                 id[idsize-1] = '\0';
2203                         }
2204                 } else {
2205                         UNCPY(id, ifscreen->result, idsize);
2206                         id[idsize-1] = '\0';
2207                 }
2208                 add_trace("used", "id", "%s", id[0]?id:"<empty>");
2209                 end_trace();
2210         }
2211 }
2212
2213 struct interface *getinterfacebyname(const char *name)
2214 {
2215         struct interface *interface = interface_first;
2216
2217         while (interface) {
2218                 if (!strcmp(interface->name, name))
2219                         return interface;
2220                 interface = interface->next;
2221         }
2222
2223         return NULL;
2224 }
2225