SIP: Register, STUN and authentication support
[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         struct interface_port *ifport;
884
885         /* port in chain ? */
886         if (!interface->ifport) {
887                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
888                 return(-1);
889         }
890         /* goto end of chain */
891         ifport = interface->ifport;
892         while(ifport->next)
893                 ifport = ifport->next;
894         SCPY(ifport->tones_dir, value);
895         return(0);
896 }
897 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
898 {
899         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);
900         return(-1);
901 }
902 static int inter_gsm_bs(struct interface *interface, char *filename, int line, char *parameter, char *value)
903 {
904 #ifndef WITH_GSM_BS
905         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
906         return(-1);
907 #else
908         struct interface *searchif;
909
910         interface->gsm_bs = 1;
911
912         if (!value)
913                 interface->gsm_bs_name[0] = '\0';
914         else
915                 SCPY(interface->gsm_bs_name, value);
916
917         /* check if name is used multiple times */
918         searchif = interface_newlist;
919         while(searchif) {
920                 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_bs_name, interface->gsm_bs_name)) {
921                         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);
922                         return(-1);
923                 }
924                 searchif = searchif->next;
925         }
926
927         return(0);
928 #endif
929 }
930 static int inter_gsm_bs_hr(struct interface *interface, char *filename, int line, char *parameter, char *value)
931 {
932 #ifndef WITH_GSM_BS
933         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
934         return(-1);
935 #else
936         interface->gsm_bs_hr = 1;
937
938         return(0);
939 #endif
940 }
941 static int inter_gsm_ms(struct interface *interface, char *filename, int line, char *parameter, char *value)
942 {
943 #ifndef WITH_GSM_MS
944         SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
945         return(-1);
946 #else
947         struct interface *searchif;
948
949         interface->gsm_ms = 1;
950
951         /* copy values */
952         if (!value || !value[0]) {
953                 SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
954                 return(-1);
955         }
956         SCPY(interface->gsm_ms_name, value);
957
958         /* check if name is used multiple times */
959         searchif = interface_newlist;
960         while(searchif) {
961                 if (searchif != interface && searchif->gsm_bs && !strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
962                         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);
963                         return(-1);
964                 }
965                 searchif = searchif->next;
966         }
967
968         return(0);
969 #endif
970 }
971 static int inter_sip(struct interface *interface, char *filename, int line, char *parameter, char *value)
972 {
973 #ifndef WITH_SIP
974         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
975         return(-1);
976 #else
977         char *p;
978
979         interface->sip = 1;
980
981         /* copy values */
982         if (!value || !value[0]) {
983                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP local IP.\n", filename, line);
984                 return(-1);
985         }
986         p = get_seperated(value);
987         if (!p[0]) {
988                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP remote IP.\n", filename, line);
989                 return(-1);
990         }
991         SCPY(interface->sip_local_peer, value);
992         SCPY(interface->sip_remote_peer, p);
993
994         return(0);
995 #endif
996 }
997 static int inter_authenticate(struct interface *interface, char *filename, int line, char *parameter, char *value)
998 {
999 #ifndef WITH_SIP
1000         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1001         return(-1);
1002 #else
1003         char *p;
1004
1005         if (!interface->sip) {
1006                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1007                 return(-1);
1008         }
1009
1010         /* copy values */
1011         if (!value || !value[0]) {
1012                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1013                 return(-1);
1014         }
1015         p = get_seperated(value);
1016         if (!p[0]) {
1017                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP password.\n", filename, line);
1018                 return(-1);
1019         }
1020         SCPY(interface->sip_auth_user, value);
1021         SCPY(interface->sip_auth_password, p);
1022
1023         return(0);
1024 #endif
1025 }
1026 static int options_timer(struct interface *interface, char *filename, int line, char *parameter, char *value)
1027 {
1028 #ifndef WITH_SIP
1029         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1030         return(-1);
1031 #else
1032         if (!interface->sip) {
1033                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1034                 return(-1);
1035         }
1036
1037         if (value)
1038                 interface->sip_options_timer = atoi(value);
1039
1040         return(0);
1041 #endif
1042 }
1043 static int options_stun(struct interface *interface, char *filename, int line, char *parameter, char *value)
1044 {
1045 #ifndef WITH_SIP
1046         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1047         return(-1);
1048 #else
1049         char *p;
1050
1051         if (!interface->sip) {
1052                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1053                 return(-1);
1054         }
1055
1056         if (!value || !value[0]) {
1057                 SPRINT(interface_error, "Error in %s (line %d): Missing STUN server.\n", filename, line);
1058                 return(-1);
1059         }
1060         p = get_seperated(value);
1061         if (!p[0]) {
1062                 SPRINT(interface_error, "Error in %s (line %d): Missing STUN timer.\n", filename, line);
1063                 return(-1);
1064         }
1065         SCPY(interface->sip_stun_server, value);
1066         interface->sip_stun_interval = atoi(p);
1067
1068         return(0);
1069 #endif
1070 }
1071 static int inter_rtp_ports(struct interface *interface, char *filename, int line, char *parameter, char *value)
1072 {
1073 #ifndef WITH_SIP
1074         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1075         return(-1);
1076 #else
1077         char *p;
1078
1079         if (!interface->sip) {
1080                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1081                 return(-1);
1082         }
1083
1084         /* copy values */
1085         if (!value || !value[0]) {
1086                 SPRINT(interface_error, "Error in %s (line %d): Missing 'from' port.\n", filename, line);
1087                 return(-1);
1088         }
1089         p = get_seperated(value);
1090         if (!p[0]) {
1091                 SPRINT(interface_error, "Error in %s (line %d): Missing 'to' port.\n", filename, line);
1092                 return(-1);
1093         }
1094         interface->rtp_port_from = atoi(value);
1095         interface->rtp_port_to = atoi(p);
1096
1097         return(0);
1098 #endif
1099 }
1100 static int inter_register(struct interface *interface, char *filename, int line, char *parameter, char *value)
1101 {
1102 #ifndef WITH_SIP
1103         SPRINT(interface_error, "Error in %s (line %d): SIP not compiled in.\n", filename, line);
1104         return(-1);
1105 #else
1106         char *p;
1107
1108         if (!interface->sip) {
1109                 SPRINT(interface_error, "Error in %s (line %d): This is not a SIP interface.\n", filename, line);
1110                 return(-1);
1111         }
1112
1113         /* copy values */
1114         if (!value || !value[0]) {
1115                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP user.\n", filename, line);
1116                 return(-1);
1117         }
1118         p = get_seperated(value);
1119         if (!p[0]) {
1120                 SPRINT(interface_error, "Error in %s (line %d): Missing SIP host\n", filename, line);
1121                 return(-1);
1122         }
1123         interface->sip_register = 1;
1124         SCPY(interface->sip_register_user, value);
1125         SCPY(interface->sip_register_host, p);
1126
1127         return(0);
1128 #endif
1129 }
1130 static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1131 {
1132         int supported = 0;
1133
1134 #ifdef WITH_GSM_BS
1135         if (interface->gsm_bs)
1136                 supported = 1;
1137 #endif
1138 #ifdef WITH_SIP
1139         if (interface->sip)
1140                 supported = 1;
1141 #endif
1142         if (!supported) {
1143                 SPRINT(interface_error, "Error in %s (line %d): Interface does not support RTP\n", filename, line);
1144                 return(-1);
1145         }
1146
1147         if (interface->app != EAPP_TYPE_BRIDGE) {
1148                 SPRINT(interface_error, "Error in %s (line %d): '%s' requires previous 'bridge' parameter.\n", filename, line, parameter);
1149                 return(-1);
1150         }
1151
1152         interface->rtp_bridge = 1;
1153
1154         return(0);
1155 }
1156 #if 0
1157 static int inter_rtp_payload(struct interface *interface, char *filename, int line, char *parameter, char *value)
1158 {
1159 #ifndef WITH_GSM_BS
1160         SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
1161         return(-1);
1162 #else
1163         if (!interface->gsm_bs) {
1164                 SPRINT(interface_error, "Error in %s (line %d): This parameter only works for GSM BS side interface\n", filename, line);
1165                 return(-1);
1166         }
1167         if (!interface->rtp_bridge) {
1168                 SPRINT(interface_error, "Error in %s (line %d): This parameter only works here, if RTP bridging is enabled\n", filename, line);
1169                 return(-1);
1170         }
1171         if (!value[0]) {
1172                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one payload type\n", filename, line, parameter);
1173                 return(-1);
1174         }
1175         if (interface->gsm_bs_payloads == sizeof(interface->gsm_bs_payload_types)) {
1176                 SPRINT(interface_error, "Error in %s (line %d): Too many payload types defined\n", filename, line);
1177                 return(-1);
1178         }
1179         interface->gsm_bs_payload_types[interface->gsm_bs_payloads++] = atoi(value);
1180
1181         return(0);
1182 #endif
1183 }
1184 #endif
1185 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
1186 {
1187         struct interface_port *ifport;
1188
1189         /* port in chain ? */
1190         if (!interface->ifport) {
1191                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1192                 return(-1);
1193         }
1194         /* goto end of chain */
1195         ifport = interface->ifport;
1196         while(ifport->next)
1197                 ifport = ifport->next;
1198         ifport->nonotify = 1;
1199         return(0);
1200 }
1201 #ifdef WITH_SS5
1202 static int inter_ss5(struct interface *interface, char *filename, int line, char *parameter, char *value)
1203 {
1204         struct interface_port *ifport;
1205         char *element;
1206
1207         /* port in chain ? */
1208         if (!interface->ifport) {
1209                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1210                 return(-1);
1211         }
1212         /* goto end of chain */
1213         ifport = interface->ifport;
1214         while(ifport->next)
1215                 ifport = ifport->next;
1216         ifport->ss5 |= SS5_ENABLE;
1217         while((element = strsep(&value, " "))) {
1218                 if (element[0] == '\0')
1219                         continue;
1220                 if (!strcasecmp(element, "connect"))
1221                         ifport->ss5 |= SS5_FEATURE_CONNECT;
1222                 else
1223                 if (!strcasecmp(element, "nodisconnect"))
1224                         ifport->ss5 |= SS5_FEATURE_NODISCONNECT;
1225                 else
1226                 if (!strcasecmp(element, "releaseguardtimer"))
1227                         ifport->ss5 |= SS5_FEATURE_RELEASEGUARDTIMER;
1228                 else
1229                 if (!strcasecmp(element, "bell"))
1230                         ifport->ss5 |= SS5_FEATURE_BELL;
1231                 else
1232                 if (!strcasecmp(element, "pulsedialing"))
1233                         ifport->ss5 |= SS5_FEATURE_PULSEDIALING;
1234                 else
1235                 if (!strcasecmp(element, "delay"))
1236                         ifport->ss5 |= SS5_FEATURE_DELAY;
1237                 else
1238                 if (!strcasecmp(element, "release"))
1239                         ifport->ss5 |= SS5_FEATURE_RELEASE;
1240                 else
1241                 if (!strcasecmp(element, "mute-rx"))
1242                         ifport->ss5 |= SS5_FEATURE_MUTE_RX;
1243                 else
1244                 if (!strcasecmp(element, "mute-tx"))
1245                         ifport->ss5 |= SS5_FEATURE_MUTE_TX;
1246                 else
1247                 if (!strcasecmp(element, "quality"))
1248                         ifport->ss5 |= SS5_FEATURE_QUALITY;
1249                 else {
1250                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' does not allow value element '%s'.\n", filename, line, parameter, element);
1251                         return(-1);
1252                 }
1253         }
1254         return(0);
1255 }
1256 #endif
1257 static int inter_remote(struct interface *interface, char *filename, int line, char *parameter, char *value)
1258 {
1259         struct interface *searchif;
1260
1261         if (!value[0]) {
1262                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application name as value.\n", filename, line, parameter);
1263                 return(-1);
1264         }
1265         searchif = interface_newlist;
1266         while(searchif) {
1267                 if (interface->remote && !strcmp(interface->remote_app, value)) {
1268                         SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses remote application '%s'.\n", filename, line, interface->name, value);
1269                         return(-1);
1270                 }
1271                 searchif = searchif->next;
1272         }
1273
1274         /* goto end of chain again to set application name */
1275         interface->remote = 1;
1276         SCPY(interface->remote_app, value);
1277
1278         return(0);
1279 }
1280 static int inter_context(struct interface *interface, char *filename, int line, char *parameter, char *value)
1281 {
1282         if (!value[0]) {
1283                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects application context as value.\n", filename, line, parameter);
1284                 return(-1);
1285         }
1286         SCPY(interface->remote_context, value);
1287
1288         return(0);
1289 }
1290 static int inter_pots_flash(struct interface *interface, char *filename, int line, char *parameter, char *value)
1291 {
1292         struct interface_port *ifport;
1293
1294         /* port in chain ? */
1295         if (!interface->ifport) {
1296                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1297                 return(-1);
1298         }
1299         /* goto end of chain */
1300         ifport = interface->ifport;
1301         while(ifport->next)
1302                 ifport = ifport->next;
1303
1304         ifport->pots_flash = 1;
1305         return(0);
1306 }
1307 static int inter_pots_ring(struct interface *interface, char *filename, int line, char *parameter, char *value)
1308 {
1309         struct interface_port *ifport;
1310
1311         /* port in chain ? */
1312         if (!interface->ifport) {
1313                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1314                 return(-1);
1315         }
1316         /* goto end of chain */
1317         ifport = interface->ifport;
1318         while(ifport->next)
1319                 ifport = ifport->next;
1320
1321         ifport->pots_ring = 1;
1322         return(0);
1323 }
1324 static int inter_pots_transfer(struct interface *interface, char *filename, int line, char *parameter, char *value)
1325 {
1326         struct interface_port *ifport;
1327
1328         /* port in chain ? */
1329         if (!interface->ifport) {
1330                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
1331                 return(-1);
1332         }
1333         /* goto end of chain */
1334         ifport = interface->ifport;
1335         while(ifport->next)
1336                 ifport = ifport->next;
1337
1338         ifport->pots_transfer = 1;
1339         return(0);
1340 }
1341 static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
1342 {
1343         interface->shutdown = 1;
1344
1345         return(0);
1346 }
1347 static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
1348 {
1349         if (!value || !value[0]) {
1350                 SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
1351                 return(-1);
1352         }
1353         interface->app = EAPP_TYPE_BRIDGE;
1354         SCPY(interface->bridge_if, value);
1355
1356         return(0);
1357 }
1358
1359
1360 /*
1361  * structure of parameters
1362  */
1363 struct interface_param interface_param[] = {
1364         { "extension", &inter_extension, "",
1365         "If keyword is given, calls to interface are handled as internal extensions."},
1366
1367         { "extern", &inter_extern, "",
1368         "If keyword is given, this interface will be used for external calls.\n"
1369         "Calls require an external interface, if the routing action 'extern' is used\nwithout specific interface given.\n"
1370         "Calls forwarded by extension's 'settings' also require an external interface."},
1371
1372         {"tones", &inter_tones, "yes | no",
1373         "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1374
1375         {"earlyb", &inter_earlyb, "yes | no",
1376         "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1377
1378         {"hunt", &inter_hunt, "linear | roundrobin",
1379         "Select the algorithm for selecting port with free channel."},
1380
1381         {"port", &inter_port, "<number>",
1382         ""},
1383         {"portnum", &inter_portnum, "<number>",
1384         "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1385         {"portname", &inter_portname, "<name>",
1386         "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1387
1388         {"block", &inter_block, "",
1389         "If keyword is given, calls on this interface are blocked.\n"
1390         "This parameter must follow a 'port' parameter."},
1391
1392         {"ptp", &inter_ptp, "",
1393         "The given port above is opened as point-to-point.\n"
1394         "This is required on NT-mode ports that are multipoint by default.\n"
1395         "This parameter must follow a 'port' parameter."},
1396
1397 #if 0
1398         {"ptmp", &inter_ptmp, "",
1399         "The given port above is opened as point-to-multipoint.\n"
1400         "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1401         "This parameter must follow a 'port' parameter."},
1402 #endif
1403
1404         {"nt", &inter_nt, "",
1405         "The given port above is opened in NT-mode.\n"
1406         "This is required on interfaces that support both NT-mode and TE-mode.\n"
1407         "This parameter must follow a 'port' parameter."},
1408
1409         {"te-special", &inter_tespecial, "",
1410         "The given port uses a modified TE-mode.\n"
1411         "All information elements that are allowed Network->User will then be\n"
1412         "transmitted User->Network also. This is usefull to pass all informations\n"
1413         "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1414         "Note that this is not compliant with ISDN protocol.\n"
1415         "This parameter must follow a 'port' parameter."},
1416
1417         {"layer1hold", &inter_l1hold, "yes | no",
1418         "The given port will not release layer 1 after layer 2 is down.\n"
1419         "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1420         "This parameter must follow a 'port' parameter."},
1421
1422         {"layer2hold", &inter_l2hold, "yes | no",
1423         "The given port will continuously try to establish layer 2 link and hold it.\n"
1424         "It is required for PTP links in most cases, therefore it is default.\n"
1425         "This parameter must follow a 'port' parameter."},
1426
1427         {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1428         "Channel selection list for all outgoing calls to the interface.\n"
1429         "A free channels is searched in order of appearance.\n"
1430         "This parameter must follow a 'port' parameter.\n"
1431         " force - Forces the selected port with no acceptable alternative (see Q.931).\n"
1432         "  -> this will be automatically set for multipoint (ptmp) NT-mode ports\n"
1433         " <number>[,...] - List of channels to search.\n"
1434         " free - Select any free channel\n"
1435         " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1436         " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1437
1438         {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1439         "Channel selection list for all incoming calls from the interface.\n"
1440         "A free channels is accepted if in the list.\n"
1441         "If any channel was requested, the first free channel found is selected.\n"
1442         "This parameter must follow a 'port' parameter.\n"
1443         " <number>[,...] - List of channels to accept.\n"
1444         " free - Accept any free channel"},
1445
1446         {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1447         "Timeout values for call states. They are both for incoming and outgoing states.\n"
1448         "The default is 120 seconds for all states. Use 0 to disable.\n"
1449         "This parameter must follow a 'port' parameter.\n"},
1450
1451         {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1452         "Incoming caller ID is checked against given MSN numbers.\n"
1453         "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1454
1455         {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1456         "Adds an entry for incoming calls to the caller ID screen list.\n"
1457         "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1458         "If '%' is given after old caller ID, it matches even if caller ID has\n"
1459         "additional digits.\n"
1460         "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1461         "are added.\n"
1462         "Options can be:\n"
1463         " unknown | subsciber | national | international - Change caller ID type.\n"
1464         " present | restrict - Change presentation of caller ID."},
1465                 
1466         {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1467         "Adds an entry for outgoing calls to the caller ID screen list.\n"
1468         "See 'screen-in' for help."},
1469
1470         {"nodtmf", &inter_nodtmf, "",
1471         "Disables DTMF detection for this interface.\n"
1472         "This parameter must follow a 'port' parameter."},
1473
1474         {"dtmf-threshold", &inter_dtmf_threshold, "",
1475         "Set threshold value for minimum DTMF tone level.\n"
1476         "This parameter must follow a 'port' parameter."},
1477
1478         {"filter", &inter_filter, "<filter> <parameters>",
1479         "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1480         "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1481         "pipeline <string> - Sets echo cancelation pipeline.\n"
1482         "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1483
1484         {"dialmax", &inter_dialmax, "<digits>",
1485         "Limits the number of digits in setup/information message."},
1486
1487         {"tones_dir", &inter_tones_dir, "<path>",
1488         "Overrides the given tone_dir in options.conf.\n"
1489         "To used kernel tones in mISDN_dsp.ko, say 'american', 'german', or 'oldgerman'."},
1490
1491         {"gsm", &inter_gsm, "",
1492         ""},
1493         {"gsm-bs", &inter_gsm_bs, "[<socket name>]",
1494         "Sets up GSM base station interface for using OpenBSC.\n"
1495         "The socket is /tmp/bsc_mncc by default. If socket name is given, the socket will be\n"
1496         "extended to /tmp/bsc_mncc_<socket name>."},
1497         {"hr", &inter_gsm_bs_hr, "",
1498         "Enable and prefer half rate for mobile terminating calls."},
1499         {"gsm-ms", &inter_gsm_ms, "<socket name>",
1500         "Sets up GSM mobile station interface for using Osmocom-BB.\n"
1501         "The socket will be /tmp/ms_mncc_<socket name>."},
1502         {"sip", &inter_sip, "<local IP/host> <remote IP/host>",
1503         "Sets up SIP interface that represents one SIP endpoint."},
1504         {"register", &inter_register, "<user> <host>",
1505         "Registers to given SIP registrar."},
1506         {"authenticate", &inter_authenticate, "<user> <password>",
1507         "Defines SIP user and password for authentication."},
1508         {"options-timer", &options_timer, "<timer> | 0",
1509         "Defines SIP timer to send OPTIONS messages to keepalive SIP sessions."},
1510         {"stun", &options_stun, "<server> <interval>",
1511         "Defines STUN server to resolv real local IP.\n"
1512         "The interval is used to check if IP has changed. (use 300)"},
1513         {"rtp-ports", &inter_rtp_ports, "<port from> <port to>",
1514         "Defines the range of ports to be used for RTP. This overrides the default."},
1515         {"rtp-bridge", &inter_rtp_bridge, "",
1516         "Enables RTP bridging directly from this interface.\n"
1517         "This only works if both bridged interfaces use RTP, e.g. between gsm-bs and sip.\n"
1518         "This parameter must follow a 'bridge' parameter.\n"},
1519 #if 0
1520         not needed, since ms defines what is supports and remote (sip) tells what is selected
1521         {"rtp-payload", &inter_rtp_payload, "<codec>",
1522         "Define RTP payload to use. Only valid in conjuntion with gsm-bs!\n"
1523         "If multiple payloads are defined, the first has highest priority.\n"
1524         "If none are defined, GSM fullrate V1 (type 3) is assumed.\n"},
1525 #endif
1526         {"nonotify", &inter_nonotify, "",
1527         "Prevents sending notify messages to this interface. A call placed on hold will\n"
1528         "Not affect the remote end (phone or telcom switch).\n"
1529         "This parameter must follow a 'port' parameter."},
1530         {"bridge", &inter_bridge, "<destination interface>",
1531         "Define bridge application for this interface. All calls received on this\n"
1532         "interface will be directly bridged to the given destination interface.\n"
1533         "There will be no PBX application, nor routing."},
1534
1535 #ifdef WITH_SS5
1536         {"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
1537         "Interface uses CCITT No. 5 inband signalling rather than D-channel.\n"
1538         "This feature causes CPU load to rise and has no practical intend.\n"
1539         "If you don't know what it is, you don't need it.\n"
1540         "Features apply to protocol behaviour and blueboxing specials, they are:\n"
1541         " connect - Connect incomming call to throughconnect audio, if required.\n"
1542         " nodisconnect - Don't disconnect if incomming exchange disconnects.\n"
1543         " releaseguardtimer - Tries to prevent Blueboxing by a longer release-guard.\n"
1544         " bell - Allow releasing and pulse-dialing via 2600 Hz like old Bell systems.\n"
1545         " pulsedialing - Use pulse dialing on outgoing exchange. (takes long!)\n"
1546         " delay - Use on incomming exchange, to make you feel a delay when blueboxing.\n"
1547         " release - Pulse dialing a star (11 pulses per digit) clears current call.\n"
1548         " mutes-rx - Mute received 2600 and 2400 Hz tones when detected. (more realistic)\n"
1549         " mutes-tx - Mute received 2600 and 2400 Hz tones while transmitting reply tone. (more hackable)"},
1550 #endif
1551
1552         {"remote", &inter_remote, "<application>",
1553         "Sets up an interface that communicates with the remote application.\n"
1554         "Use \"asterisk\" to use chan_lcr as remote application."},
1555         {"context", &inter_context, "<context>",
1556         "Give context for calls to application."},
1557
1558         {"pots-flash", &inter_pots_flash, "",
1559         "Allow flash button to hold an active call and setup a new call.\n"
1560         "Ihis parameter only appies to POTS type of interfaces\n"
1561         "This parameter must follow a 'port' parameter.\n"},
1562         {"pots-ring-after-hangup", &inter_pots_ring, "",
1563         "Allow ringing of last hold call after hangup. Other calls on hold will not be\n"
1564         "released.\n"
1565         "Ihis parameter only appies to POTS type of interfaces\n"
1566         "This parameter must follow a 'port' parameter.\n"},
1567         {"pots-transfer-after-hangup", &inter_pots_transfer, "",
1568         "If two calls on hold, both are connected after hangup.\n"
1569         "If one call is on hold and another one alerting, call on hold is tranfered.\n"
1570         "Ihis parameter only appies to POTS type of interfaces\n"
1571         "This parameter must follow a 'port' parameter.\n"},
1572
1573         {"shutdown", &inter_shutdown, "",
1574         "Interface will not be loaded when processing interface.conf"},
1575
1576         {NULL, NULL, NULL, NULL}
1577 };
1578
1579 /* read interfaces
1580  *
1581  * read settings from interface.conf
1582  */
1583 char interface_error[256];
1584 struct interface *read_interfaces(void)
1585 {
1586         FILE                    *fp = NULL;
1587         char                    filename[128];
1588         char                    *p;
1589         unsigned int            line, i;
1590         char                    buffer[256];
1591         struct interface        *interface = NULL, /* in case no interface */
1592                                 **interfacep = &interface_newlist;
1593         char                    parameter[128];
1594         char                    value[256];
1595         int                     expecting = 1; /* expecting new interface */
1596         struct interface_param  *ifparam;
1597
1598         if (interface_newlist != NULL)
1599                 FATAL("list is not empty.\n");
1600         interface_error[0] = '\0';
1601         SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1602
1603         if (!(fp = fopen(filename,"r"))) {
1604                 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1605                 goto error;
1606         }
1607
1608         line=0;
1609         while((GETLINE(buffer, fp))) {
1610                 p=buffer;
1611                 line++;
1612
1613                 while(*p <= 32) { /* skip spaces */
1614                         if (*p == 0)
1615                                 break;
1616                         p++;
1617                 }
1618                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1619                         continue;
1620
1621                 parameter[0]=0;
1622                 value[0]=0;
1623                 i=0; /* read parameter */
1624                 while(*p > 32) {
1625                         if (i+1 >= sizeof(parameter)) {
1626                                 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1627                                 goto error;
1628                         }
1629                         parameter[i+1] = '\0';
1630                         parameter[i++] = *p++;
1631                 }
1632
1633                 while(*p <= 32) { /* skip spaces */
1634                         if (*p == 0)
1635                                 break;
1636                         p++;
1637                 }
1638
1639                 if (*p!=0 && *p!='#') { /* missing name */
1640                         i=0; /* read until end */
1641                         while(*p!=0 && *p!='#') {
1642                                 if (i+1 >= sizeof(value)) {
1643                                         SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1644                                         goto error;
1645                                 }
1646                                 value[i+1] = '\0';
1647                                 value[i++] = *p++;
1648                         }
1649
1650                         /* remove trailing spaces from value */
1651                         while(i) {
1652                                 if (value[i-1]==0 || value[i-1]>32)
1653                                         break;
1654                                 value[i-1] = '\0';
1655                                 i--;
1656                         }
1657                 }
1658
1659                 /* check for interface name as first statement */
1660                 if (expecting && parameter[0]!='[') {
1661                         SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1662                         goto error;
1663                 }
1664                 expecting = 0;
1665
1666                 /* check for new interface */
1667                 if (parameter[0] == '[') {
1668                         if (parameter[strlen(parameter)-1] != ']') {
1669                                 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1670                                 goto error;
1671                         }
1672                         parameter[strlen(parameter)-1] = '\0';
1673
1674                         /* check if interface name already exists */
1675                         interface = interface_newlist;
1676                         while(interface) {
1677                                 if (!strcasecmp(interface->name, parameter+1)) {
1678                                         SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1679                                         goto error;
1680                                 }
1681                                 interface = interface->next;
1682                         }
1683
1684                         /* append interface to new list */
1685                         interface = (struct interface *)MALLOC(sizeof(struct interface));
1686                         memuse++;
1687
1688                         /* name interface */
1689                         SCPY(interface->name, parameter+1);
1690
1691                         /* attach */
1692                         *interfacep = interface;
1693                         interfacep = &interface->next;
1694
1695                         continue;
1696                 }
1697
1698                 ifparam = interface_param;
1699                 while(ifparam->name) {
1700                         if (!strcasecmp(parameter, ifparam->name)) {
1701                                 if (ifparam->func(interface, filename, line, parameter, value))
1702                                         goto error;
1703                                 break;
1704                         }
1705                         ifparam++;
1706                 }
1707                 if (ifparam->name)
1708                         continue;
1709
1710                 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1711                 goto error;
1712         }
1713
1714         if (fp) fclose(fp);
1715         return(interface_newlist);
1716 error:
1717         PERROR_RUNTIME("%s", interface_error);
1718         if (fp) fclose(fp);
1719         free_interfaces(interface_newlist);
1720         interface_newlist = NULL;
1721         return(NULL);
1722 }
1723
1724
1725 /*
1726  * freeing chain of interfaces
1727  */
1728 void free_interfaces(struct interface *interface)
1729 {
1730         void *temp;
1731         struct interface_port *ifport;
1732         struct select_channel *selchannel;
1733         struct interface_msn *ifmsn;
1734         struct interface_screen *ifscreen;
1735
1736         while(interface) {
1737                 ifport = interface->ifport;
1738                 while(ifport) {
1739                         selchannel = ifport->in_channel;
1740                         while(selchannel) {
1741                                 temp = selchannel;
1742                                 selchannel = selchannel->next;
1743                                 FREE(temp, sizeof(struct select_channel));
1744                                 memuse--;
1745                         }
1746                         selchannel = ifport->out_channel;
1747                         while(selchannel) {
1748                                 temp = selchannel;
1749                                 selchannel = selchannel->next;
1750                                 FREE(temp, sizeof(struct select_channel));
1751                                 memuse--;
1752                         }
1753                         temp = ifport;
1754                         ifport = ifport->next;
1755                         FREE(temp, sizeof(struct interface_port));
1756                         memuse--;
1757                 }
1758                 ifmsn = interface->ifmsn;
1759                 while(ifmsn) {
1760                         temp = ifmsn;
1761                         ifmsn = ifmsn->next;
1762                         FREE(temp, sizeof(struct interface_msn));
1763                         memuse--;
1764                 }
1765                 ifscreen = interface->ifscreen_in;
1766                 while(ifscreen) {
1767                         temp = ifscreen;
1768                         ifscreen = ifscreen->next;
1769                         FREE(temp, sizeof(struct interface_screen));
1770                         memuse--;
1771                 }
1772                 ifscreen = interface->ifscreen_out;
1773                 while(ifscreen) {
1774                         temp = ifscreen;
1775                         ifscreen = ifscreen->next;
1776                         FREE(temp, sizeof(struct interface_screen));
1777                         memuse--;
1778                 }
1779                 temp = interface;
1780                 interface = interface->next;
1781                 FREE(temp, sizeof(struct interface));
1782                 memuse--;
1783         }
1784 }
1785
1786 #ifdef WITH_MISDN
1787 /*
1788  * defaults of ports if not specified by config
1789  */
1790 static void set_mISDN_defaults(struct interface_port *ifport)
1791 {
1792         /* default channel selection list */
1793         if (!ifport->out_channel)
1794                 default_out_channel(ifport);
1795         if (!ifport->in_channel)
1796                 default_in_channel(ifport);
1797         /* must force the channel on PTMP/NT ports */
1798         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
1799                 ifport->channel_force = 1;
1800         /* default is_tones */
1801         if (ifport->interface->is_tones)
1802                 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1803         else
1804                 ifport->mISDNport->tones = (ifport->mISDNport->ntmode || ifport->mISDNport->ss5)?1:0;
1805         /* default is_earlyb */
1806         if (ifport->interface->is_earlyb)
1807                 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1808         else
1809                 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode && !ifport->mISDNport->ss5)?0:1;
1810         /* set locally flag */
1811         if (ifport->interface->extension)
1812                 ifport->mISDNport->locally = 1;
1813         else
1814                 ifport->mISDNport->locally = 0;
1815 }
1816 #endif
1817
1818
1819 /*
1820  * all links between mISDNport and interface are made
1821  * unused mISDNports are closed, new mISDNports are opened
1822  * also set default select_channel lists
1823  */
1824 void relink_interfaces(void)
1825 {
1826 #ifdef WITH_MISDN
1827         struct mISDNport *mISDNport;
1828         struct interface_port *ifport;
1829 #endif
1830         struct interface *interface, *temp, *found;
1831
1832         interface = interface_first;
1833         while(interface) {
1834                 found = NULL;
1835                 temp = interface_newlist;
1836                 while(temp) {
1837                         if (!strcmp(temp->name, interface->name))
1838                                 found = temp;
1839                         temp = temp->next;
1840                 }
1841                 if (!found) {
1842 #ifdef WITH_GSM_MS
1843                         if (interface->gsm_ms)
1844                                 gsm_ms_delete(interface->gsm_ms_name);
1845 #endif
1846 #ifdef WITH_GSM_BS
1847                         if (interface->gsm_bs)
1848                                 gsm_bs_delete(interface->gsm_bs_name);
1849 #endif
1850 #ifdef WITH_SIP
1851                         if (interface->sip)
1852                                 sip_exit_inst(interface);
1853 #endif
1854                 } else {
1855 #ifdef WITH_SIP
1856                         if (interface->sip) {
1857                                 /* move sip instance, if we keep interface */
1858                                 found->sip_inst = interface->sip_inst;
1859                                 interface->sip_inst = NULL;
1860                         }
1861 #endif
1862                         ;
1863                 }
1864                 interface = interface->next;
1865         }
1866
1867         interface = interface_newlist;
1868         while(interface) {
1869                 found = NULL;
1870                 temp = interface_first;
1871                 while(temp) {
1872                         if (!strcmp(temp->name, interface->name))
1873                                 found = temp;
1874                         temp = temp->next;
1875                 }
1876                 if (!found) {
1877 #ifdef WITH_GSM_MS
1878                         if (interface->gsm_ms)
1879                                 gsm_ms_new(interface);
1880 #endif
1881 #ifdef WITH_GSM_BS
1882                         if (interface->gsm_bs)
1883                                 gsm_bs_new(interface);
1884 #endif
1885 #ifdef WITH_SIP
1886                         if (interface->sip)
1887                                 sip_init_inst(interface);
1888 #endif
1889                 }
1890                 interface = interface->next;
1891         }
1892
1893 #ifdef WITH_MISDN
1894         /* unlink all mISDNports */
1895         mISDNport = mISDNport_first;
1896         while(mISDNport) {
1897                 mISDNport->ifport = NULL;
1898                 mISDNport = mISDNport->next;
1899         }
1900
1901         /* relink existing mISDNports */
1902         interface = interface_newlist;
1903         while(interface) {
1904                 ifport = interface->ifport;
1905                 while(ifport) {
1906                         mISDNport = mISDNport_first;
1907                         while(mISDNport) {
1908                                 if (!strcmp(mISDNport->name, ifport->portname))
1909                                         ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1910                                 if (mISDNport->portnum == ifport->portnum) {
1911                                         PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", ifport->portnum, ifport->portname);
1912                                         ifport->mISDNport = mISDNport;
1913                                         mISDNport->ifport = ifport;
1914                                         set_mISDN_defaults(ifport);
1915                                 }
1916                                 mISDNport = mISDNport->next;
1917                         }
1918                         ifport = ifport->next;
1919                 }
1920                 interface = interface->next;
1921         }
1922
1923         /* close unused mISDNports */
1924         closeagain:
1925         mISDNport = mISDNport_first;
1926         while(mISDNport) {
1927                 if (mISDNport->ifport == NULL) {
1928                         PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1929                         /* destroy port */
1930                         mISDNport_close(mISDNport);
1931                         goto closeagain;
1932                 }
1933                 mISDNport = mISDNport->next;
1934         }
1935
1936         /* open and link new mISDNports */
1937         interface = interface_newlist;
1938         while(interface) {
1939                 ifport = interface->ifport;
1940                 while(ifport) {
1941                         if (!ifport->mISDNport) {
1942                                 if (!interface->shutdown) {
1943                                         load_mISDN_port(ifport);
1944                                 } else {
1945                                         ifport->block = 2;
1946                                 }
1947                         }
1948                         ifport = ifport->next;
1949                 }
1950                 interface = interface->next;
1951         }
1952 #endif
1953 }
1954
1955
1956 #ifdef WITH_MISDN
1957 /*
1958  * load port
1959  */
1960 void load_mISDN_port(struct interface_port *ifport)
1961 {
1962         struct mISDNport *mISDNport;
1963
1964         /* open new port */
1965         mISDNport = mISDNport_open(ifport);
1966         if (mISDNport) {
1967                 /* link port */
1968                 ifport->mISDNport = mISDNport;
1969                 mISDNport->ifport = ifport;
1970                 /* set number and name */
1971                 ifport->portnum = mISDNport->portnum;
1972                 SCPY(ifport->portname, mISDNport->name);
1973                 /* set defaults */
1974                 set_mISDN_defaults(ifport);
1975                 /* load static port instances */
1976                 mISDNport_static(mISDNport);
1977         } else {
1978                 ifport->block = 2; /* not available */
1979         }
1980 }
1981 #endif
1982
1983 /*
1984  * give summary of interface syntax
1985  */
1986 void doc_interface(void)
1987 {
1988         struct interface_param *ifparam;
1989         
1990         printf("Syntax overview\n");
1991         printf("---------------\n\n");
1992
1993         printf("[<name>]\n");
1994         ifparam = interface_param;
1995         while(ifparam->name) {
1996                 if (ifparam->name[0])
1997                         printf("%s %s\n", ifparam->name, ifparam->usage);
1998                 ifparam++;
1999         }
2000
2001         ifparam = interface_param;
2002         while(ifparam->name) {
2003                 if (ifparam->name[0]) {
2004                         printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
2005                         printf("%s\n", ifparam->help);
2006                 }
2007                 ifparam++;
2008         }
2009 }
2010
2011
2012 /* screen caller id
2013  * out==0: incoming caller id, out==1: outgoing caller id
2014  */
2015 void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
2016 {
2017         char                    *msn1;
2018         struct interface_msn    *ifmsn;
2019         struct interface_screen *ifscreen;
2020         char suffix[64];
2021         struct interface *interface = interface_first;
2022
2023         interface = getinterfacebyname(interface_name);
2024         if (!interface)
2025                 return;
2026
2027         /* screen incoming caller id */
2028         if (!out) {
2029                 /* check for MSN numbers, use first MSN if no match */
2030                 msn1 = NULL;
2031                 ifmsn = interface->ifmsn;
2032                 while(ifmsn) {
2033                         if (!msn1)
2034                                 msn1 = ifmsn->msn;
2035                         if (!strcmp(ifmsn->msn, id)) {
2036                                 break;
2037                         }
2038                         ifmsn = ifmsn->next;
2039                 }
2040                 if (ifmsn) {
2041                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
2042                         add_trace("msn", NULL, "%s", id);
2043                         end_trace();
2044                 }
2045                 if (!ifmsn && msn1) { // not in list, first msn given
2046                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
2047                         add_trace("msn", "given", "%s", id);
2048                         add_trace("msn", "used", "%s", msn1);
2049                         end_trace();
2050                         UNCPY(id, msn1, idsize);
2051                         id[idsize-1] = '\0';
2052                 }
2053         }
2054
2055         /* check screen list */
2056         if (out)
2057                 ifscreen = interface->ifscreen_out;
2058         else
2059                 ifscreen = interface->ifscreen_in;
2060         while (ifscreen) {
2061                 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
2062                 if (ifscreen->match_present==-1 || ifscreen->match_present==*present) {
2063                         if (strchr(ifscreen->match,'%')) {
2064                                 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
2065                                         break;
2066                         } else {
2067                                 if (!strcmp(ifscreen->match, id))
2068                                         break;
2069                         }
2070                 }
2071                 ifscreen = ifscreen->next;
2072         }
2073         if (ifscreen) { // match
2074                 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)");
2075                 switch(*type) {
2076                         case INFO_NTYPE_UNKNOWN:
2077                         add_trace("given", "type", "unknown");
2078                         break;
2079                         case INFO_NTYPE_SUBSCRIBER:
2080                         add_trace("given", "type", "subscriber");
2081                         break;
2082                         case INFO_NTYPE_NATIONAL:
2083                         add_trace("given", "type", "national");
2084                         break;
2085                         case INFO_NTYPE_INTERNATIONAL:
2086                         add_trace("given", "type", "international");
2087                         break;
2088                 }
2089                 switch(*present) {
2090                         case INFO_PRESENT_ALLOWED:
2091                         add_trace("given", "present", "allowed");
2092                         break;
2093                         case INFO_PRESENT_RESTRICTED:
2094                         add_trace("given", "present", "restricted");
2095                         break;
2096                         case INFO_PRESENT_NOTAVAIL:
2097                         add_trace("given", "present", "not available");
2098                         break;
2099                 }
2100                 add_trace("given", "id", "%s", id[0]?id:"<empty>");
2101                 if (ifscreen->result_type != -1) {
2102                         *type = ifscreen->result_type;
2103                         switch(*type) {
2104                                 case INFO_NTYPE_UNKNOWN:
2105                                 add_trace("used", "type", "unknown");
2106                                 break;
2107                                 case INFO_NTYPE_SUBSCRIBER:
2108                                 add_trace("used", "type", "subscriber");
2109                                 break;
2110                                 case INFO_NTYPE_NATIONAL:
2111                                 add_trace("used", "type", "national");
2112                                 break;
2113                                 case INFO_NTYPE_INTERNATIONAL:
2114                                 add_trace("used", "type", "international");
2115                                 break;
2116                         }
2117                 }
2118                 if (ifscreen->result_present != -1) {
2119                         *present = ifscreen->result_present;
2120                         switch(*present) {
2121                                 case INFO_PRESENT_ALLOWED:
2122                                 add_trace("used", "present", "allowed");
2123                                 break;
2124                                 case INFO_PRESENT_RESTRICTED:
2125                                 add_trace("used", "present", "restricted");
2126                                 break;
2127                                 case INFO_PRESENT_NOTAVAIL:
2128                                 add_trace("used", "present", "not available");
2129                                 break;
2130                         }
2131                 }
2132                 if (strchr(ifscreen->match,'%')) {
2133                         SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
2134                         UNCPY(id, ifscreen->result, idsize);
2135                         id[idsize-1] = '\0';
2136                         if (strchr(id,'%')) {
2137                                 *strchr(id,'%') = '\0';
2138                                 UNCAT(id, suffix, idsize);
2139                                 id[idsize-1] = '\0';
2140                         }
2141                 } else {
2142                         UNCPY(id, ifscreen->result, idsize);
2143                         id[idsize-1] = '\0';
2144                 }
2145                 add_trace("used", "id", "%s", id[0]?id:"<empty>");
2146                 end_trace();
2147         }
2148 }
2149
2150 struct interface *getinterfacebyname(const char *name)
2151 {
2152         struct interface *interface = interface_first;
2153
2154         while (interface) {
2155                 if (!strcmp(interface->name, name))
2156                         return interface;
2157                 interface = interface->next;
2158         }
2159
2160         return NULL;
2161 }
2162