Added GSM network 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 /* set default out_channel */
19 void default_out_channel(struct interface_port *ifport)
20 {
21         struct select_channel *selchannel, **selchannelp;
22
23         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
24         memuse++;
25         
26         if (ifport->mISDNport->ntmode)
27                 selchannel->channel = CHANNEL_FREE;
28         else
29                 selchannel->channel = CHANNEL_ANY;
30         
31         ifport->out_channel = selchannel;
32
33         /* additional channel selection for multipoint NT ports */
34         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
35         {
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
58
59 /* parse string for a positive number */
60 static int get_number(char *value)
61 {
62         int val = 0;
63         char text[10];
64
65         val = atoi(value);
66         
67         SPRINT(text, "%d", val);
68
69         if (!strcmp(value, text))
70                 return(val);
71
72         return(-1);
73 }
74
75
76 /* remove element from buffer
77  * and return pointer to next element in buffer */
78 static char *get_seperated(char *buffer)
79 {
80         while(*buffer)
81         {
82                 if (*buffer==',' || *buffer<=32) /* seperate */
83                 {
84                         *buffer++ = '\0';
85                         while((*buffer>'\0' && *buffer<=32) || *buffer==',')
86                                 buffer++;
87                         return(buffer);
88                 }
89                 buffer++;
90         }
91         return(buffer);
92 }
93
94 /*
95  * parameter processing
96  */
97 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
98 {
99         struct interface_port *ifport;
100
101         /* port in chain ? */
102         if (!interface->ifport)
103         {
104                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
105                 return(-1);
106         }
107         /* goto end of chain */
108         ifport = interface->ifport;
109         while(ifport->next)
110                 ifport = ifport->next;
111         /* add value */
112         if (value[0])
113         {
114                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
115                 return(-1);
116         }
117         ifport->block = 1;
118         return(0);
119 }
120 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
121 {
122         if (value[0])
123         {
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_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
131 {
132         struct interface_port *ifport;
133
134         /* port in chain ? */
135         if (!interface->ifport)
136         {
137                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
138                 return(-1);
139         }
140         if (interface->ifport->ptmp)
141         {
142                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
143                 return(-1);
144         }
145         /* goto end of chain */
146         ifport = interface->ifport;
147         while(ifport->next)
148                 ifport = ifport->next;
149         /* add value */
150         if (value[0])
151         {
152                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
153                 return(-1);
154         }
155         ifport->ptp = 1;
156         return(0);
157 }
158 #if 0
159 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
160 {
161         struct interface_port *ifport;
162
163         /* port in chain ? */
164         if (!interface->ifport)
165         {
166                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
167                 return(-1);
168         }
169         if (interface->ifport->ptp)
170         {
171                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
172                 return(-1);
173         }
174         /* goto end of chain */
175         ifport = interface->ifport;
176         while(ifport->next)
177                 ifport = ifport->next;
178         /* add value */
179         if (value[0])
180         {
181                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
182                 return(-1);
183         }
184         ifport->ptmp = 1;
185         return(0);
186 }
187 #endif
188 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
189 {
190         struct interface_port *ifport;
191
192         /* port in chain ? */
193         if (!interface->ifport)
194         {
195                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
196                 return(-1);
197         }
198         /* goto end of chain */
199         ifport = interface->ifport;
200         while(ifport->next)
201                 ifport = ifport->next;
202         /* add value */
203         if (value[0])
204         {
205                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
206                 return(-1);
207         }
208         ifport->nt = 1;
209         return(0);
210 }
211 static int inter_tespecial(struct interface *interface, char *filename, int line, char *parameter, char *value)
212 {
213         struct interface_port *ifport;
214
215         /* port in chain ? */
216         if (!interface->ifport)
217         {
218                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
219                 return(-1);
220         }
221         /* goto end of chain */
222         ifport = interface->ifport;
223         while(ifport->next)
224                 ifport = ifport->next;
225         /* add value */
226         if (value[0])
227         {
228                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
229                 return(-1);
230         }
231         ifport->tespecial = 1;
232         return(0);
233 }
234 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
235 {
236         if (!strcasecmp(value, "yes"))
237         {
238                 interface->is_tones = IS_YES;
239         } else
240         if (!strcasecmp(value, "no"))
241         {
242                 interface->is_tones = IS_NO;
243         } else
244         {
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         {
254                 interface->is_earlyb = IS_YES;
255         } else
256         if (!strcasecmp(value, "no"))
257         {
258                 interface->is_earlyb = IS_NO;
259         } else
260         {
261                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
262                 return(-1);
263         }
264         return(0);
265 }
266 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
267 {
268         if (!strcasecmp(value, "linear"))
269         {
270                 interface->hunt = HUNT_LINEAR;
271         } else
272         if (!strcasecmp(value, "roundrobin"))
273         {
274                 interface->hunt = HUNT_ROUNDROBIN;
275         } else
276         {
277                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
278                 return(-1);
279         }
280         return(0);
281 }
282 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
283 {
284         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);
285         return(-1);
286 }
287 static int inter_portnum(struct interface *interface, char *filename, int line, char *parameter, char *value)
288 {
289         struct interface_port *ifport, **ifportp;
290         struct interface *searchif;
291         int val;
292
293         val = get_number(value);
294         if (val == -1)
295         {
296                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
297                 return(-1);
298         }
299         /* check for port already assigned */
300         searchif = interface_newlist;
301         while(searchif)
302         {
303                 ifport = searchif->ifport;
304                 while(ifport)
305                 {
306                         if (ifport->portnum == val)
307                         {
308                                 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
309                                 return(-1);
310                         }
311                         ifport = ifport->next;
312                 }
313                 searchif = searchif->next;
314         }
315         /* alloc port substructure */
316         ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
317         memuse++;
318         ifport->interface = interface;
319         /* set value */
320         ifport->portnum = val;
321         /* tail port */
322         ifportp = &interface->ifport;
323         while(*ifportp)
324                 ifportp = &((*ifportp)->next);
325         *ifportp = ifport;
326         return(0);
327 }
328 static int inter_portname(struct interface *interface, char *filename, int line, char *parameter, char *value)
329 {
330         struct interface_port *ifport, **ifportp;
331         struct interface *searchif;
332
333         /* check for port already assigned */
334         searchif = interface_newlist;
335         while(searchif)
336         {
337                 ifport = searchif->ifport;
338                 while(ifport)
339                 {
340                         if (!strcasecmp(ifport->portname, value))
341                         {
342                                 SPRINT(interface_error, "Error in %s (line %d): port '%s' already used above.\n", filename, line, value);
343                                 return(-1);
344                         }
345                         /* check for use as GSM */
346                         if (ifport->gsm)
347                         {
348                                 SPRINT(interface_error, "Error in %s (line %d): Interface already used for GSM.\n", filename, line);
349                                 return(-1);
350                         }
351                         ifport = ifport->next;
352                 }
353                 searchif = searchif->next;
354         }
355         /* alloc port substructure */
356         ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
357         memuse++;
358         ifport->interface = interface;
359         /* set value */
360         ifport->portnum = -1; // disable until resolved
361         SCPY(ifport->portname, value);
362         /* tail port */
363         ifportp = &interface->ifport;
364         while(*ifportp)
365                 ifportp = &((*ifportp)->next);
366         *ifportp = ifport;
367         return(0);
368 }
369 static int inter_l1hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
370 {
371         struct interface_port *ifport;
372
373         /* port in chain ? */
374         if (!interface->ifport)
375         {
376                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
377                 return(-1);
378         }
379         /* goto end of chain */
380         ifport = interface->ifport;
381         while(ifport->next)
382                 ifport = ifport->next;
383         if (!strcmp(value, "yes"))
384         {
385                 ifport->l1hold = 1;
386         } else
387         if (!strcmp(value, "no"))
388         {
389                 ifport->l1hold = 0;
390         } else
391         {
392                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
393                 return(-1);
394         }
395         return(0);
396 }
397 static int inter_l2hold(struct interface *interface, char *filename, int line, char *parameter, char *value)
398 {
399         struct interface_port *ifport;
400
401         /* port in chain ? */
402         if (!interface->ifport)
403         {
404                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
405                 return(-1);
406         }
407         /* goto end of chain */
408         ifport = interface->ifport;
409         while(ifport->next)
410                 ifport = ifport->next;
411         if (!strcmp(value, "yes"))
412         {
413                 ifport->l2hold = 1;
414         } else
415         if (!strcmp(value, "no"))
416         {
417                 ifport->l2hold = -1;
418         } else
419         {
420                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expecting parameter 'yes' or 'no'.\n", filename, line, parameter);
421                 return(-1);
422         }
423         return(0);
424 }
425 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
426 {
427         struct interface_port *ifport;
428         struct select_channel *selchannel, **selchannelp;
429         int val;
430         char *p, *el;
431
432         /* port in chain ? */
433         if (!interface->ifport)
434         {
435                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
436                 return(-1);
437         }
438         /* goto end of chain */
439         ifport = interface->ifport;
440         while(ifport->next)
441                 ifport = ifport->next;
442         p = value;
443         while(*p)
444         {
445                 el = p;
446                 p = get_seperated(p);
447                 if (!strcasecmp(el, "force"))
448                 {
449                         ifport->channel_force = 1;
450                         if (ifport->out_channel)
451                         {
452                                 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
453                                 return(-1);
454                         }
455                 } else
456                 if (!strcasecmp(el, "any"))
457                 {
458                         val = CHANNEL_ANY;
459                         goto selchannel;
460                 } else
461                 if (!strcasecmp(el, "free"))
462                 {
463                         val = CHANNEL_FREE;
464                         goto selchannel;
465                 } else
466                 if (!strcasecmp(el, "no"))
467                 {
468                         val = CHANNEL_NO;
469                         goto selchannel;
470                 } else
471                 {
472                         val = get_number(el);
473                         if (val == -1)
474                         {
475                                 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);
476                                 return(-1);
477                         }
478
479                         if (val<1 || val==16 || val>126)
480                         {
481                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
482                                 return(-1);
483                         }
484                         selchannel:
485                         /* add to select-channel list */
486                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
487                         memuse++;
488                         /* set value */
489                         selchannel->channel = val;
490                         /* tail port */
491                         selchannelp = &ifport->out_channel;
492                         while(*selchannelp)
493                                 selchannelp = &((*selchannelp)->next);
494                         *selchannelp = selchannel;
495                 }
496         }
497         return(0);
498 }
499 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
500 {
501         struct interface_port *ifport;
502         struct select_channel *selchannel, **selchannelp;
503         int val;
504         char *p, *el;
505
506         /* port in chain ? */
507         if (!interface->ifport)
508         {
509                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
510                 return(-1);
511         }
512         /* goto end of chain */
513         ifport = interface->ifport;
514         while(ifport->next)
515                 ifport = ifport->next;
516         p = value;
517         while(*p)
518         {
519                 el = p;
520                 p = get_seperated(p);
521                 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
522                 {
523                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
524                                 return(-1);
525                 }
526                 if (!strcasecmp(el, "free"))
527                 {
528                         val = CHANNEL_FREE;
529                         goto selchannel;
530                 } else
531                 {
532                         val = get_number(el);
533                         if (val == -1)
534                         {
535                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
536                                 return(-1);
537                         }
538
539                         if (val<1 || val==16 || val>126)
540                         {
541                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
542                                 return(-1);
543                         }
544                         selchannel:
545                         /* add to select-channel list */
546                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
547                         memuse++;
548                         /* set value */
549                         selchannel->channel = val;
550                         /* tail port */
551                         selchannelp = &ifport->in_channel;
552                         while(*selchannelp)
553                                 selchannelp = &((*selchannelp)->next);
554                         *selchannelp = selchannel;
555                 }
556         }
557         return(0);
558 }
559 static int inter_timeouts(struct interface *interface, char *filename, int line, char *parameter, char *value)
560 {
561         struct interface_port *ifport;
562 //      struct select_channel *selchannel, **selchannelp;
563 //      int val;
564         char *p, *el;
565
566         /* port in chain ? */
567         if (!interface->ifport)
568         {
569                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
570                 return(-1);
571         }
572         /* goto end of chain */
573         ifport = interface->ifport;
574         while(ifport->next)
575                 ifport = ifport->next;
576         p = value;
577         if (!*p)
578         {
579                 nofive:
580                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects five timeout values.\n", filename, line, parameter);
581                 return(-1);
582         }
583         el = p;
584         p = get_seperated(p);
585         ifport->tout_setup = atoi(el);
586         if (!*p)
587                 goto nofive;
588         el = p;
589         p = get_seperated(p);
590         ifport->tout_dialing = atoi(el);
591         if (!*p)
592                 goto nofive;
593         el = p;
594         p = get_seperated(p);
595         ifport->tout_proceeding = atoi(el);
596         if (!*p)
597                 goto nofive;
598         el = p;
599         p = get_seperated(p);
600         ifport->tout_alerting = atoi(el);
601         if (!*p)
602                 goto nofive;
603         el = p;
604         p = get_seperated(p);
605         ifport->tout_disconnect = atoi(el);
606         return(0);
607 }
608 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
609 {
610         struct interface_msn *ifmsn, **ifmsnp;
611         char *p, *el;
612
613         if (!value[0])
614         {
615                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
616                 return(-1);
617         }
618         if (interface->ifscreen_in)
619         {
620                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
621                 return(-1);
622         }
623
624         /* process list */
625         p = value;
626         while(*p)
627         {
628                 el = p;
629                 p = get_seperated(p);
630                 /* add MSN to list */
631                 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
632                 memuse++;
633                 /* set value */
634                 SCPY(ifmsn->msn, el);
635                 /* tail port */
636                 ifmsnp = &interface->ifmsn;
637                 while(*ifmsnp)
638                         ifmsnp = &((*ifmsnp)->next);
639                 *ifmsnp = ifmsn;
640         }
641         return(0);
642 }
643 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
644 {
645         struct interface_screen *ifscreen;
646         char *p, *el;
647
648         if (!value[0])
649         {
650                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
651                 return(-1);
652         }
653         /* add screen entry to list*/
654         ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
655         memuse++;
656         ifscreen->match_type = -1; /* unchecked */
657         ifscreen->match_present = -1; /* unchecked */
658         ifscreen->result_type = -1; /* unchanged */
659         ifscreen->result_present = -1; /* unchanged */
660         /* tail port */
661         while(*ifscreenp)
662                 ifscreenp = &((*ifscreenp)->next);
663         *ifscreenp = ifscreen;
664 //      printf("interface=%s\n", interface->name);
665         /* get match */
666         p = value;
667         while(*p)
668         {
669                 el = p;
670                 p = get_seperated(p);
671                 if (!strcasecmp(el, "unknown"))
672                 {
673                         if (ifscreen->match_type != -1)
674                         {
675                                 typeerror:
676                                 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
677                                 return(-1);
678                         }
679                         ifscreen->match_type = INFO_NTYPE_UNKNOWN;
680                 } else
681                 if (!strcasecmp(el, "subscriber"))
682                 {
683                         if (ifscreen->match_type != -1)
684                                 goto typeerror;
685                         ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
686                 } else
687                 if (!strcasecmp(el, "national"))
688                 {
689                         if (ifscreen->match_type != -1)
690                                 goto typeerror;
691                         ifscreen->match_type = INFO_NTYPE_NATIONAL;
692                 } else
693                 if (!strcasecmp(el, "international"))
694                 {
695                         if (ifscreen->match_type != -1)
696                                 goto typeerror;
697                         ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
698                 } else
699                 if (!strcasecmp(el, "allowed"))
700                 {
701                         if (ifscreen->match_present != -1)
702                         {
703                                 presenterror:
704                                 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
705                                 return(-1);
706                         }
707                         ifscreen->match_present = INFO_PRESENT_ALLOWED;
708                 } else
709                 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted"))
710                 {
711                         if (ifscreen->match_present != -1)
712                                 goto presenterror;
713                         ifscreen->match_present = INFO_PRESENT_RESTRICTED;
714                 } else {
715                         SCPY(ifscreen->match, el);
716                         /* check for % at the end */
717                         if (strchr(el, '%'))
718                         {
719                                 if (strchr(el, '%') != el+strlen(el)-1)
720                                 {
721                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
722                                         return(-1);
723                                 }
724                         }
725                         break;
726                 }
727         }
728         if (ifscreen->match[0] == '\0')
729         {
730                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
731                 return(-1);
732         }
733         /* get result */
734         while(*p)
735         {
736                 el = p;
737                 p = get_seperated(p);
738                 if (!strcasecmp(el, "unknown"))
739                 {
740                         if (ifscreen->result_type != -1)
741                                 goto typeerror;
742                         ifscreen->result_type = INFO_NTYPE_UNKNOWN;
743                 } else
744                 if (!strcasecmp(el, "subscriber"))
745                 {
746                         if (ifscreen->result_type != -1)
747                                 goto typeerror;
748                         ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
749                 } else
750                 if (!strcasecmp(el, "national"))
751                 {
752                         if (ifscreen->result_type != -1)
753                                 goto typeerror;
754                         ifscreen->result_type = INFO_NTYPE_NATIONAL;
755                 } else
756                 if (!strcasecmp(el, "international"))
757                 {
758                         if (ifscreen->result_type != -1)
759                                 goto typeerror;
760                         ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
761                 } else
762                 if (!strcasecmp(el, "present") || !strcasecmp(el, "presented") || !strcasecmp(el, "allowed") || !strcasecmp(el, "allow"))
763                 {
764                         if (ifscreen->result_present != -1)
765                                 goto presenterror;
766                         ifscreen->result_present = INFO_PRESENT_ALLOWED;
767                 } else
768                 if (!strcasecmp(el, "restrict") || !strcasecmp(el, "restricted") || !strcasecmp(el, "deny") || !strcasecmp(el, "denied"))
769                 {
770                         if (ifscreen->result_present != -1)
771                                 goto presenterror;
772                         ifscreen->result_present = INFO_PRESENT_RESTRICTED;
773                 } else {
774                         SCPY(ifscreen->result, el);
775                         /* check for % at the end */
776                         if (strchr(el, '%'))
777                         {
778                                 if (strchr(el, '%') != el+strlen(el)-1)
779                                 {
780                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
781                                         return(-1);
782                                 }
783                         }
784                         break;
785                 }
786         }
787         if (ifscreen->result[0] == '\0')
788         {
789                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
790                 return(-1);
791         }
792         return(0);
793 }
794 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
795 {
796         if (interface->ifmsn)
797         {
798                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
799                 return(-1);
800         }
801
802         return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
803 }
804 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
805 {
806         return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
807 }
808 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
809 {
810         struct interface_port *ifport;
811
812         /* port in chain ? */
813         if (!interface->ifport)
814         {
815                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
816                 return(-1);
817         }
818         /* goto end of chain */
819         ifport = interface->ifport;
820         while(ifport->next)
821                 ifport = ifport->next;
822         ifport->nodtmf = 1;
823         return(0);
824 }
825 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
826 {
827         char *p, *q;
828
829         /* seperate parameter from filter */
830         p = value;
831         while(*p > 32)
832                 p++;
833         if (*p)
834         {
835                 *p++ = 0;
836                 while(*p > 0 && *p <= 32)
837                         p++;
838         }
839
840         if (!strcasecmp(value, "gain"))
841         {
842                 q = p;
843                 while(*q > 32)
844                         q++;
845                 if (*q)
846                 {
847                         *q++ = 0;
848                         while(*q > 0 && *q <= 32)
849                                 q++;
850                 }
851                 if (*p == 0 || *q == 0)
852                 {
853                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects two gain values.\n", filename, line, parameter, value);
854                         return(-1);
855                 }
856                 if (atoi(p)<-8 || atoi(p)>8 || atoi(q)<-8 || atoi(q)>8)
857                 {
858                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' gain values not in range. (-8...8)\n", filename, line, parameter, value);
859                         return(-1);
860                 }
861                 interface->tx_gain = atoi(p);
862                 interface->rx_gain = atoi(q);
863         } else
864         if (!strcasecmp(value, "pipeline"))
865         {
866                 if (*p == 0)
867                 {
868                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects pipeline string.\n", filename, line, parameter, value);
869                         return(-1);
870                 }
871                 SCPY(interface->pipeline, p);
872         } else
873         if (!strcasecmp(value, "blowfish"))
874         {
875                 unsigned char key[56];
876                 int l;
877                 
878                 if (!!strncmp(p, "0x", 2))
879                 {
880                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' expects blowfish key starting with '0x'.\n", filename, line, parameter, value);
881                         return(-1);
882                 }
883                 p += 2;
884                 l = 0; 
885                 while(*p)
886                 {
887                         if (l == 56)
888                         {
889                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s %s' key too long.\n", filename, line, parameter, value);
890                                 return(-1);
891                         }
892                         if (*p >= '0' && *p <= '9')
893                                 key[l] = (*p-'0')<<4;
894                         else if (*p >= 'a' && *p <= 'f')
895                                 key[l] = (*p-'a'+10)<<4;
896                         else if (*p >= 'A' && *p <= 'F')
897                                 key[l] = (*p-'A'+10)<<4;
898                         else
899                         {
900                                 digout:
901                                 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);
902                                 return(-1);
903                         }
904                         p++;
905                         if (*p == 0)
906                         {
907                                 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);
908                                 return(-1);
909                         }
910                         if (*p >= '0' && *p <= '9')
911                                 key[l] = (*p-'0')<<4;
912                         else if (*p >= 'a' && *p <= 'f')
913                                 key[l] = (*p-'a'+10)<<4;
914                         else if (*p >= 'A' && *p <= 'F')
915                                 key[l] = (*p-'A'+10)<<4;
916                         else
917                                 goto digout;
918                         p++;
919                         l++;
920                 }
921                 if (l < 4)
922                 {
923                         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);
924                         return(-1);
925                 }
926                 memcpy(interface->bf_key, key, l);
927                 interface->bf_len = l;
928         } else
929         {
930                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has unknown filter '%s'.\n", filename, line, parameter, value);
931                 return(-1);
932         }
933         return(0);
934 }
935 static int inter_dialmax(struct interface *interface, char *filename, int line, char *parameter, char *value)
936 {
937         struct interface_port *ifport;
938
939         /* port in chain ? */
940         if (!interface->ifport)
941         {
942                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
943                 return(-1);
944         }
945         /* goto end of chain */
946         ifport = interface->ifport;
947         while(ifport->next)
948                 ifport = ifport->next;
949         ifport->dialmax = atoi(value);
950         return(0);
951 }
952 static int inter_gsm(struct interface *interface, char *filename, int line, char *parameter, char *value)
953 {
954 #ifndef WITH_GSM
955         SPRINT(interface_error, "Error in %s (line %d): GSM not compiled in.\n", filename, line);
956         return(-1);
957 #else
958         struct interface_port *ifport;
959         struct interface *searchif;
960
961         /* check gsm */
962         if (!gsm)
963         {
964                 SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
965                 return(-1);
966         }
967         searchif = interface_newlist;
968         while(searchif)
969         {
970                 ifport = searchif->ifport;
971                 while(ifport)
972                 {
973                         if (ifport->gsm)
974                         {
975                                 SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm\n", filename, line, value);
976                                 return(-1);
977                         }
978                         ifport = ifport->next;
979                 }
980                 searchif = searchif->next;
981         }
982
983         /* set portname */
984         if (inter_portname(interface, filename, line, "portname", gsm->conf.interface_lcr))
985                 return(-1);
986         /* goto end of chain again to set gsmflag*/
987         ifport = interface->ifport;
988         while(ifport->next)
989                 ifport = ifport->next;
990         ifport->gsm = 1;
991         return(0);
992 #endif
993 }
994
995
996 /*
997  * structure of parameters
998  */
999 struct interface_param interface_param[] = {
1000         { "extension", &inter_extension, "",
1001         "If keyword is given, calls to interface are handled as internal extensions."},
1002         {"tones", &inter_tones, "yes | no",
1003         "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
1004
1005         {"earlyb", &inter_earlyb, "yes | no",
1006         "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
1007
1008         {"hunt", &inter_hunt, "linear | roundrobin",
1009         "Select the algorithm for selecting port with free channel."},
1010
1011         {"port", &inter_port, "<number>",
1012         ""},
1013         {"portnum", &inter_portnum, "<number>",
1014         "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
1015         {"portname", &inter_portname, "<name>",
1016         "Same as 'portnum', but the name is given instead.\nUse 'isdninfo' to list all available ports and names."},
1017
1018         {"block", &inter_block, "",
1019         "If keyword is given, calls on this interface are blocked.\n"
1020         "This parameter must follow a 'port' parameter."},
1021
1022         {"ptp", &inter_ptp, "",
1023         "The given port above is opened as point-to-point.\n"
1024         "This is required on NT-mode ports that are multipoint by default.\n"
1025         "This parameter must follow a 'port' parameter."},
1026
1027 #if 0
1028         {"ptmp", &inter_ptmp, "",
1029         "The given port above is opened as point-to-multipoint.\n"
1030         "This is required on PRI NT-mode ports that are point-to-point by default.\n"
1031         "This parameter must follow a 'port' parameter."},
1032 #endif
1033
1034         {"nt", &inter_nt, "",
1035         "The given port above is opened in NT-mode.\n"
1036         "This is required on interfaces that support both NT-mode and TE-mode.\n"
1037         "This parameter must follow a 'port' parameter."},
1038
1039         {"te-special", &inter_tespecial, "",
1040         "The given port uses a modified TE-mode.\n"
1041         "All information elements that are allowed Network->User will then be\n"
1042         "transmitted User->Network also. This is usefull to pass all informations\n"
1043         "between two interconnected LCRs, like 'redirected number' or 'display'.\n"
1044         "Note that this is not compliant with ISDN protocol.\n"
1045         "This parameter must follow a 'port' parameter."},
1046
1047         {"layer1hold", &inter_l1hold, "yes | no",
1048         "The given port will not release layer 1 after layer 2 is down.\n"
1049         "It is required to keep layer 1 of telephones up, to solve activation problems.\n"
1050         "This parameter must follow a 'port' parameter."},
1051
1052         {"layer2hold", &inter_l2hold, "yes | no",
1053         "The given port will continuously try to establish layer 2 link and hold it.\n"
1054         "It is required for PTP links in most cases, therefore it is default.\n"
1055         "This parameter must follow a 'port' parameter."},
1056
1057         {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
1058         "Channel selection list for all outgoing calls to the interface.\n"
1059         "A free channels is searched in order of appearance.\n"
1060         "This parameter must follow a 'port' parameter.\n"
1061         " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
1062         " <number>[,...] - List of channels to search.\n"
1063         " free - Select any free channel\n"
1064         " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
1065         " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
1066
1067         {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
1068         "Channel selection list for all incoming calls from the interface.\n"
1069         "A free channels is accepted if in the list.\n"
1070         "If any channel was requested, the first free channel found is selected.\n"
1071         "This parameter must follow a 'port' parameter.\n"
1072         " <number>[,...] - List of channels to accept.\n"
1073         " free - Accept any free channel"},
1074
1075         {"timeouts", &inter_timeouts, "<setup> <dialing> <proceeding> <alerting> <disconnect>",
1076         "Timeout values for call states. They are both for incoming and outgoing states.\n"
1077         "The default is 120 seconds for all states. Use 0 to disable.\n"
1078         "This parameter must follow a 'port' parameter.\n"},
1079
1080         {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
1081         "Incoming caller ID is checked against given MSN numbers.\n"
1082         "If the caller ID is not found in this list, it is overwritten by the first MSN"},
1083
1084         {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1085         "Adds an entry for incoming calls to the caller ID screen list.\n"
1086         "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
1087         "If '%' is given after old caller ID, it matches even if caller ID has\n"
1088         "additional digits.\n"
1089         "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
1090         "are added.\n"
1091         "Options can be:\n"
1092         " unknown | subsciber | national | international - Change caller ID type.\n"
1093         " present | restrict - Change presentation of caller ID."},
1094                 
1095         {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
1096         "Adds an entry for outgoing calls to the caller ID screen list.\n"
1097         "See 'screen-in' for help."},
1098
1099         {"nodtmf", &inter_nodtmf, "",
1100         "Disables DTMF detection for this interface.\n"
1101         "This parameter must follow a 'port' parameter."},
1102
1103         {"filter", &inter_filter, "<filter> <parameters>",
1104         "Adds/appends a filter. Filters are ordered in transmit direction.\n"
1105         "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
1106         "pipeline <string> - Sets echo cancelation pipeline.\n"
1107         "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
1108
1109         {"dialmax", &inter_dialmax, "<digits>",
1110         "Limits the number of digits in setup/information message."},
1111
1112         {"gsm", &inter_gsm, "",
1113         "Sets up GSM interface for using OpenBSC.\n"
1114         "This interface must be a loopback interface. The second loopback interface\n"
1115         "must be assigned to OpenBSC"},
1116
1117         {NULL, NULL, NULL, NULL}
1118 };
1119
1120 /* read interfaces
1121  *
1122  * read settings from interface.conf
1123  */
1124 char interface_error[256];
1125 struct interface *read_interfaces(void)
1126 {
1127         FILE                    *fp = NULL;
1128         char                    filename[128];
1129         char                    *p;
1130         unsigned int            line, i;
1131         char                    buffer[256];
1132         struct interface        *interface = NULL, /* in case no interface */
1133                                 **interfacep = &interface_newlist;
1134         char                    parameter[128];
1135         char                    value[256];
1136         int                     expecting = 1; /* expecting new interface */
1137         struct interface_param  *ifparam;
1138
1139         if (interface_newlist != NULL)
1140                 FATAL("list is not empty.\n");
1141         interface_error[0] = '\0';
1142         SPRINT(filename, "%s/interface.conf", CONFIG_DATA);
1143
1144         if (!(fp = fopen(filename,"r")))
1145         {
1146                 SPRINT(interface_error, "Cannot open '%s'\n", filename);
1147                 goto error;
1148         }
1149
1150         line=0;
1151         while((fgets(buffer,sizeof(buffer),fp)))
1152         {
1153                 buffer[sizeof(buffer)-1]=0;
1154                 if (buffer[0]) buffer[strlen(buffer)-1]=0;
1155                 p=buffer;
1156                 line++;
1157
1158                 while(*p <= 32) /* skip spaces */
1159                 {
1160                         if (*p == 0)
1161                                 break;
1162                         p++;
1163                 }
1164                 if (*p==0 || *p=='#') /* ignore comments and empty line */
1165                         continue;
1166
1167                 parameter[0]=0;
1168                 value[0]=0;
1169                 i=0; /* read parameter */
1170                 while(*p > 32)
1171                 {
1172                         if (i+1 >= sizeof(parameter))
1173                         {
1174                                 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
1175                                 goto error;
1176                         }
1177                         parameter[i+1] = '\0';
1178                         parameter[i++] = *p++;
1179                 }
1180
1181                 while(*p <= 32) /* skip spaces */
1182                 {
1183                         if (*p == 0)
1184                                 break;
1185                         p++;
1186                 }
1187
1188                 if (*p!=0 && *p!='#') /* missing name */
1189                 {
1190                         i=0; /* read until end */
1191                         while(*p!=0 && *p!='#')
1192                         {
1193                                 if (i+1 >= sizeof(value))
1194                                 {
1195                                         SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
1196                                         goto error;
1197                                 }
1198                                 value[i+1] = '\0';
1199                                 value[i++] = *p++;
1200                         }
1201
1202                         /* remove trailing spaces from value */
1203                         while(i)
1204                         {
1205                                 if (value[i-1]==0 || value[i-1]>32)
1206                                         break;
1207                                 value[i-1] = '\0';
1208                                 i--;
1209                         }
1210                 }
1211
1212                 /* check for interface name as first statement */
1213                 if (expecting && parameter[0]!='[')
1214                 {
1215                         SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1216                         goto error;
1217                 }
1218                 expecting = 0;
1219
1220                 /* check for new interface */
1221                 if (parameter[0] == '[')
1222                 {
1223                         if (parameter[strlen(parameter)-1] != ']')
1224                         {
1225                                 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
1226                                 goto error;
1227                         }
1228                         parameter[strlen(parameter)-1] = '\0';
1229
1230                         /* check if interface name already exists */
1231                         interface = interface_newlist;
1232                         while(interface)
1233                         {
1234                                 if (!strcasecmp(interface->name, parameter+1))
1235                                 {
1236                                         SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
1237                                         goto error;
1238                                 }
1239                                 interface = interface->next;
1240                         }
1241
1242                         /* append interface to new list */
1243                         interface = (struct interface *)MALLOC(sizeof(struct interface));
1244                         memuse++;
1245
1246                         /* name interface */
1247                         SCPY(interface->name, parameter+1);
1248
1249                         /* attach */
1250                         *interfacep = interface;
1251                         interfacep = &interface->next;
1252
1253                         continue;
1254                 }
1255
1256                 ifparam = interface_param;
1257                 while(ifparam->name)
1258                 {
1259                         if (!strcasecmp(parameter, ifparam->name))
1260                         {
1261                                 if (ifparam->func(interface, filename, line, parameter, value))
1262                                         goto error;
1263                                 break;
1264                         }
1265                         ifparam++;
1266                 }
1267                 if (ifparam->name)
1268                         continue;
1269
1270                 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
1271                 goto error;
1272         }
1273
1274         if (fp) fclose(fp);
1275         return(interface_newlist);
1276 error:
1277         PERROR_RUNTIME("%s", interface_error);
1278         if (fp) fclose(fp);
1279         free_interfaces(interface_newlist);
1280         interface_newlist = NULL;
1281         return(NULL);
1282 }
1283
1284
1285 /*
1286  * freeing chain of interfaces
1287  */
1288 void free_interfaces(struct interface *interface)
1289 {
1290         void *temp;
1291         struct interface_port *ifport;
1292         struct select_channel *selchannel;
1293         struct interface_msn *ifmsn;
1294         struct interface_screen *ifscreen;
1295
1296         while(interface)
1297         {
1298                 ifport = interface->ifport;
1299                 while(ifport)
1300                 {
1301                         selchannel = ifport->in_channel;
1302                         while(selchannel)
1303                         {
1304                                 temp = selchannel;
1305                                 selchannel = selchannel->next;
1306                                 FREE(temp, sizeof(struct select_channel));
1307                                 memuse--;
1308                         }
1309                         selchannel = ifport->out_channel;
1310                         while(selchannel)
1311                         {
1312                                 temp = selchannel;
1313                                 selchannel = selchannel->next;
1314                                 FREE(temp, sizeof(struct select_channel));
1315                                 memuse--;
1316                         }
1317                         temp = ifport;
1318                         ifport = ifport->next;
1319                         FREE(temp, sizeof(struct interface_port));
1320                         memuse--;
1321                 }
1322                 ifmsn = interface->ifmsn;
1323                 while(ifmsn)
1324                 {
1325                         temp = ifmsn;
1326                         ifmsn = ifmsn->next;
1327                         FREE(temp, sizeof(struct interface_msn));
1328                         memuse--;
1329                 }
1330                 ifscreen = interface->ifscreen_in;
1331                 while(ifscreen)
1332                 {
1333                         temp = ifscreen;
1334                         ifscreen = ifscreen->next;
1335                         FREE(temp, sizeof(struct interface_screen));
1336                         memuse--;
1337                 }
1338                 ifscreen = interface->ifscreen_out;
1339                 while(ifscreen)
1340                 {
1341                         temp = ifscreen;
1342                         ifscreen = ifscreen->next;
1343                         FREE(temp, sizeof(struct interface_screen));
1344                         memuse--;
1345                 }
1346                 temp = interface;
1347                 interface = interface->next;
1348                 FREE(temp, sizeof(struct interface));
1349                 memuse--;
1350         }
1351 }
1352
1353 /*
1354  * defaults of ports if not specified by config
1355  */
1356 static void set_defaults(struct interface_port *ifport)
1357 {
1358         /* default channel selection list */
1359         if (!ifport->out_channel)
1360                 default_out_channel(ifport);
1361         if (!ifport->in_channel)
1362                 default_in_channel(ifport);
1363         /* default is_tones */
1364         if (ifport->interface->is_tones)
1365                 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1366         else
1367                 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1368         /* default is_earlyb */
1369         if (ifport->interface->is_earlyb)
1370                 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1371         else
1372                 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1373         /* set locally flag */
1374         if (ifport->interface->extension)
1375                 ifport->mISDNport->locally = 1;
1376         else
1377                 ifport->mISDNport->locally = 0;
1378 }
1379
1380
1381 /*
1382  * all links between mISDNport and interface are made
1383  * unused mISDNports are closed, new mISDNports are opened
1384  * also set default select_channel lists
1385  */
1386 void relink_interfaces(void)
1387 {
1388         struct mISDNport *mISDNport;
1389         struct interface *interface;
1390         struct interface_port *ifport;
1391
1392         /* unlink all mISDNports */
1393         mISDNport = mISDNport_first;
1394         while(mISDNport)
1395         {
1396                 mISDNport->ifport = NULL;
1397                 mISDNport = mISDNport->next;
1398         }
1399
1400         /* relink existing mISDNports */
1401         interface = interface_newlist;
1402         while(interface)
1403         {
1404                 ifport = interface->ifport;
1405                 while(ifport)
1406                 {
1407                         mISDNport = mISDNport_first;
1408                         while(mISDNport)
1409                         {
1410                                 if (!strcmp(mISDNport->name, ifport->portname))
1411                                         ifport->portnum = mISDNport->portnum; /* same name, so we use same number */
1412                                 if (mISDNport->portnum == ifport->portnum)
1413                                 {
1414                                         PDEBUG(DEBUG_ISDN, "Port %d:%s relinking!\n", mISDNport->portnum);
1415                                         ifport->mISDNport = mISDNport;
1416                                         mISDNport->ifport = ifport;
1417                                         set_defaults(ifport);
1418                                 }
1419                                 mISDNport = mISDNport->next;
1420                         }
1421                         ifport = ifport->next;
1422                 }
1423                 interface = interface->next;
1424         }
1425
1426         /* close unused mISDNports */
1427         closeagain:
1428         mISDNport = mISDNport_first;
1429         while(mISDNport)
1430         {
1431                 if (mISDNport->ifport == NULL)
1432                 {
1433                         PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1434                         /* remove all port objects and destroy port */
1435                         mISDNport_close(mISDNport);
1436                         goto closeagain;
1437                 }
1438                 mISDNport = mISDNport->next;
1439         }
1440
1441         /* open and link new mISDNports */
1442         interface = interface_newlist;
1443         while(interface)
1444         {
1445                 ifport = interface->ifport;
1446                 while(ifport)
1447                 {
1448                         if (!ifport->mISDNport)
1449                         {
1450                                 load_port(ifport);
1451                         }
1452                         ifport = ifport->next;
1453                 }
1454                 interface = interface->next;
1455         }
1456
1457 }
1458
1459
1460 /*
1461  * load port
1462  */
1463 void load_port(struct interface_port *ifport)
1464 {
1465         struct mISDNport *mISDNport;
1466
1467         /* open new port */
1468         mISDNport = mISDNport_open(ifport->portnum, ifport->portname, ifport->ptp, ifport->nt, ifport->tespecial, ifport->l1hold, ifport->l2hold, ifport->interface, ifport->gsm);
1469         if (mISDNport)
1470         {
1471                 /* link port */
1472                 ifport->mISDNport = mISDNport;
1473                 mISDNport->ifport = ifport;
1474                 /* set number and name */
1475                 ifport->portnum = mISDNport->portnum;
1476                 SCPY(ifport->portname, mISDNport->name);
1477                 /* set defaults */
1478                 set_defaults(ifport);
1479         } else
1480         {
1481                 ifport->block = 2; /* not available */
1482         }
1483 }
1484
1485 /*
1486  * give summary of interface syntax
1487  */
1488 void doc_interface(void)
1489 {
1490         struct interface_param *ifparam;
1491         
1492         printf("Syntax overview\n");
1493         printf("---------------\n\n");
1494
1495         printf("[<name>]\n");
1496         ifparam = interface_param;
1497         while(ifparam->name)
1498         {
1499                 if (ifparam->name[0])
1500                         printf("%s %s\n", ifparam->name, ifparam->usage);
1501                 ifparam++;
1502         }
1503
1504         ifparam = interface_param;
1505         while(ifparam->name)
1506         {
1507                 if (ifparam->name[0])
1508                 {
1509                         printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1510                         printf("%s\n", ifparam->help);
1511                 }
1512                 ifparam++;
1513         }
1514 }
1515
1516
1517 /* screen caller id
1518  * out==0: incoming caller id, out==1: outgoing caller id
1519  */
1520 void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
1521 {
1522         char                    *msn1;
1523         struct interface_msn    *ifmsn;
1524         struct interface_screen *ifscreen;
1525         char suffix[64];
1526
1527         /* screen incoming caller id */
1528         if (!out)
1529         {
1530                 /* check for MSN numbers, use first MSN if no match */
1531                 msn1 = NULL;
1532                 ifmsn = interface->ifmsn;
1533                 while(ifmsn)
1534                 {
1535                         if (!msn1)
1536                                 msn1 = ifmsn->msn;
1537                         if (!strcmp(ifmsn->msn, id))
1538                         {
1539                                 break;
1540                         }
1541                         ifmsn = ifmsn->next;
1542                 }
1543                 if (ifmsn)
1544                 {
1545                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (found in MSN list)");
1546                         add_trace("msn", NULL, "%s", id);
1547                         end_trace();
1548                 }
1549                 if (!ifmsn && msn1) // not in list, first msn given
1550                 {
1551                         start_trace(-1, interface, numberrize_callerinfo(id, *type, options.national, options.international), NULL, DIRECTION_IN, 0, 0, "SCREEN (not found in MSN list)");
1552                         add_trace("msn", "given", "%s", id);
1553                         add_trace("msn", "used", "%s", msn1);
1554                         end_trace();
1555                         UNCPY(id, msn1, idsize);
1556                         id[idsize-1] = '\0';
1557                 }
1558         }
1559
1560         /* check screen list */
1561         if (out)
1562                 ifscreen = interface->ifscreen_out;
1563         else
1564                 ifscreen = interface->ifscreen_in;
1565         while (ifscreen)
1566         {
1567                 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
1568                 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
1569                 {
1570                         if (strchr(ifscreen->match,'%'))
1571                         {
1572                                 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
1573                                         break;
1574                         } else
1575                         {
1576                                 if (!strcmp(ifscreen->match, id))
1577                                         break;
1578                         }
1579                 }
1580                 ifscreen = ifscreen->next;
1581         }
1582         if (ifscreen) // match
1583         {
1584                 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)");
1585                 switch(*type)
1586                 {
1587                         case INFO_NTYPE_UNKNOWN:
1588                         add_trace("given", "type", "unknown");
1589                         break;
1590                         case INFO_NTYPE_SUBSCRIBER:
1591                         add_trace("given", "type", "subscriber");
1592                         break;
1593                         case INFO_NTYPE_NATIONAL:
1594                         add_trace("given", "type", "national");
1595                         break;
1596                         case INFO_NTYPE_INTERNATIONAL:
1597                         add_trace("given", "type", "international");
1598                         break;
1599                 }
1600                 switch(*present)
1601                 {
1602                         case INFO_PRESENT_ALLOWED:
1603                         add_trace("given", "present", "allowed");
1604                         break;
1605                         case INFO_PRESENT_RESTRICTED:
1606                         add_trace("given", "present", "restricted");
1607                         break;
1608                         case INFO_PRESENT_NOTAVAIL:
1609                         add_trace("given", "present", "not available");
1610                         break;
1611                 }
1612                 add_trace("given", "id", "%s", id[0]?id:"<empty>");
1613                 if (ifscreen->result_type != -1)
1614                 {
1615                         *type = ifscreen->result_type;
1616                         switch(*type)
1617                         {
1618                                 case INFO_NTYPE_UNKNOWN:
1619                                 add_trace("used", "type", "unknown");
1620                                 break;
1621                                 case INFO_NTYPE_SUBSCRIBER:
1622                                 add_trace("used", "type", "subscriber");
1623                                 break;
1624                                 case INFO_NTYPE_NATIONAL:
1625                                 add_trace("used", "type", "national");
1626                                 break;
1627                                 case INFO_NTYPE_INTERNATIONAL:
1628                                 add_trace("used", "type", "international");
1629                                 break;
1630                         }
1631                 }
1632                 if (ifscreen->result_present != -1)
1633                 {
1634                         *present = ifscreen->result_present;
1635                         switch(*present)
1636                         {
1637                                 case INFO_PRESENT_ALLOWED:
1638                                 add_trace("used", "present", "allowed");
1639                                 break;
1640                                 case INFO_PRESENT_RESTRICTED:
1641                                 add_trace("used", "present", "restricted");
1642                                 break;
1643                                 case INFO_PRESENT_NOTAVAIL:
1644                                 add_trace("used", "present", "not available");
1645                                 break;
1646                         }
1647                 }
1648                 if (strchr(ifscreen->match,'%'))
1649                 {
1650                         SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
1651                         UNCPY(id, ifscreen->result, idsize);
1652                         id[idsize-1] = '\0';
1653                         if (strchr(id,'%'))
1654                         {
1655                                 *strchr(id,'%') = '\0';
1656                                 UNCAT(id, suffix, idsize);
1657                                 id[idsize-1] = '\0';
1658                         }
1659                 } else
1660                 {
1661                         UNCPY(id, ifscreen->result, idsize);
1662                         id[idsize-1] = '\0';
1663                 }
1664                 add_trace("used", "id", "%s", id[0]?id:"<empty>");
1665                 end_trace();
1666         }
1667 }
1668