testing
[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 <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include "main.h"
16
17 struct interface *interface_first = NULL; /* first interface is current list */
18 struct interface *interface_newlist = NULL; /* first interface in new list */
19
20
21 /* set default out_channel */
22 void default_out_channel(struct interface_port *ifport)
23 {
24         struct select_channel *selchannel, **selchannelp;
25
26         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
27         memuse++;
28         
29         if (ifport->mISDNport->ntmode)
30                 selchannel->channel = CHANNEL_FREE;
31         else
32                 selchannel->channel = CHANNEL_ANY;
33         
34         ifport->out_channel = selchannel;
35
36         /* additional channel selection for multipoint NT ports */
37         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
38         {
39                 selchannelp = &(selchannel->next);
40                 selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
41                 memuse++;
42                 selchannel->channel = CHANNEL_NO; // call waiting
43                 *selchannelp = selchannel;
44         }
45 }
46
47
48 /* set default in_channel */
49 void default_in_channel(struct interface_port *ifport)
50 {
51         struct select_channel *selchannel;
52
53         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
54         memuse++;
55         
56         selchannel->channel = CHANNEL_FREE;
57         
58         ifport->in_channel = selchannel;
59 }
60
61
62 /* parse string for a positive number */
63 static int get_number(char *value)
64 {
65         int val = 0;
66         char text[10];
67
68         val = atoi(value);
69         
70         SPRINT(text, "%d", val);
71
72         if (!strcmp(value, text))
73                 return(val);
74
75         return(-1);
76 }
77
78
79 /* remove element from buffer
80  * and return pointer to next element in buffer */
81 static char *get_seperated(char *buffer)
82 {
83         while(*buffer)
84         {
85                 if (*buffer==',' || *buffer<=32) /* seperate */
86                 {
87                         *buffer++ = '\0';
88                         while((*buffer>'\0' && *buffer<=32) || *buffer==',')
89                                 buffer++;
90                         return(buffer);
91                 }
92                 buffer++;
93         }
94         return(buffer);
95 }
96
97 /*
98  * parameter processing
99  */
100 static int inter_block(struct interface *interface, char *filename, int line, char *parameter, char *value)
101 {
102         struct interface_port *ifport;
103
104         /* port in chain ? */
105         if (!interface->ifport)
106         {
107                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
108                 return(-1);
109         }
110         /* goto end of chain */
111         ifport = interface->ifport;
112         while(ifport->next)
113                 ifport = ifport->next;
114         /* add value */
115         if (value[0])
116         {
117                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
118                 return(-1);
119         }
120         ifport->block = 1;
121         return(0);
122 }
123 static int inter_extension(struct interface *interface, char *filename, int line, char *parameter, char *value)
124 {
125         if (value[0])
126         {
127                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
128                 return(-1);
129         }
130         interface->extension = 1;
131         return(0);
132 }
133 static int inter_ptp(struct interface *interface, char *filename, int line, char *parameter, char *value)
134 {
135         struct interface_port *ifport;
136
137         /* port in chain ? */
138         if (!interface->ifport)
139         {
140                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
141                 return(-1);
142         }
143         if (interface->ifport->ptmp)
144         {
145                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptmp was given.\n", filename, line, parameter);
146                 return(-1);
147         }
148         /* goto end of chain */
149         ifport = interface->ifport;
150         while(ifport->next)
151                 ifport = ifport->next;
152         /* add value */
153         if (value[0])
154         {
155                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
156                 return(-1);
157         }
158         ifport->ptp = 1;
159         return(0);
160 }
161 static int inter_ptmp(struct interface *interface, char *filename, int line, char *parameter, char *value)
162 {
163         struct interface_port *ifport;
164
165         /* port in chain ? */
166         if (!interface->ifport)
167         {
168                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
169                 return(-1);
170         }
171         if (interface->ifport->ptp)
172         {
173                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' previously ptp was given.\n", filename, line, parameter);
174                 return(-1);
175         }
176         /* goto end of chain */
177         ifport = interface->ifport;
178         while(ifport->next)
179                 ifport = ifport->next;
180         /* add value */
181         if (value[0])
182         {
183                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
184                 return(-1);
185         }
186         ifport->ptmp = 1;
187         return(0);
188 }
189 static int inter_nt(struct interface *interface, char *filename, int line, char *parameter, char *value)
190 {
191 #ifdef SOCKET_MISDN
192         struct interface_port *ifport;
193
194         /* port in chain ? */
195         if (!interface->ifport)
196         {
197                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
198                 return(-1);
199         }
200         /* goto end of chain */
201         ifport = interface->ifport;
202         while(ifport->next)
203                 ifport = ifport->next;
204         /* add value */
205         if (value[0])
206         {
207                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects no value.\n", filename, line, parameter);
208                 return(-1);
209         }
210         ifport->nt = 1;
211 #endif
212         return(0);
213 }
214 static int inter_tones(struct interface *interface, char *filename, int line, char *parameter, char *value)
215 {
216         if (!strcasecmp(value, "yes"))
217         {
218                 interface->is_tones = IS_YES;
219         } else
220         if (!strcasecmp(value, "no"))
221         {
222                 interface->is_tones = IS_NO;
223         } else
224         {
225                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
226                 return(-1);
227         }
228         return(0);
229 }
230 static int inter_earlyb(struct interface *interface, char *filename, int line, char *parameter, char *value)
231 {
232         if (!strcasecmp(value, "yes"))
233         {
234                 interface->is_earlyb = IS_YES;
235         } else
236         if (!strcasecmp(value, "no"))
237         {
238                 interface->is_earlyb = IS_NO;
239         } else
240         {
241                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'yes' or 'no'.\n", filename, line, parameter);
242                 return(-1);
243         }
244         return(0);
245 }
246 static int inter_hunt(struct interface *interface, char *filename, int line, char *parameter, char *value)
247 {
248         if (!strcasecmp(value, "linear"))
249         {
250                 interface->hunt = HUNT_LINEAR;
251         } else
252         if (!strcasecmp(value, "roundrobin"))
253         {
254                 interface->hunt = HUNT_ROUNDROBIN;
255         } else
256         {
257                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects value 'linear' or 'roundrobin'.\n", filename, line, parameter);
258                 return(-1);
259         }
260         return(0);
261 }
262 static int inter_port(struct interface *interface, char *filename, int line, char *parameter, char *value)
263 {
264         struct interface_port *ifport, **ifportp;
265         struct interface *searchif;
266         int val;
267
268         val = get_number(value);
269         if (val == -1)
270         {
271                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one numeric value.\n", filename, line, parameter);
272                 return(-1);
273         }
274         /* check for port already assigned */
275         searchif = interface_newlist;
276         while(searchif)
277         {
278                 ifport = searchif->ifport;
279                 while(ifport)
280                 {
281                         if (ifport->portnum == val)
282                         {
283                                 SPRINT(interface_error, "Error in %s (line %d): port '%d' already used above.\n", filename, line, val);
284                                 return(-1);
285                         }
286                         ifport = ifport->next;
287                 }
288                 searchif = searchif->next;
289         }
290         /* alloc port substructure */
291         ifport = (struct interface_port *)MALLOC(sizeof(struct interface_port));
292         memuse++;
293         ifport->interface = interface;
294         /* set value */
295         ifport->portnum = val;
296         /* tail port */
297         ifportp = &interface->ifport;
298         while(*ifportp)
299                 ifportp = &((*ifportp)->next);
300         *ifportp = ifport;
301         return(0);
302 }
303 static int inter_channel_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
304 {
305         struct interface_port *ifport;
306         struct select_channel *selchannel, **selchannelp;
307         int val;
308         char *p, *el;
309
310         /* port in chain ? */
311         if (!interface->ifport)
312         {
313                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
314                 return(-1);
315         }
316         /* goto end of chain */
317         ifport = interface->ifport;
318         while(ifport->next)
319                 ifport = ifport->next;
320         p = value;
321         while(*p)
322         {
323                 el = p;
324                 p = get_seperated(p);
325                 if (!strcasecmp(el, "force"))
326                 {
327                         ifport->channel_force = 1;
328                         if (ifport->out_channel)
329                         {
330                                 SPRINT(interface_error, "Error in %s (line %d): value 'force' may only appear as first element in list.\n", filename, line);
331                                 return(-1);
332                         }
333                 } else
334                 if (!strcasecmp(el, "any"))
335                 {
336                         val = CHANNEL_ANY;
337                         goto selchannel;
338                 } else
339                 if (!strcasecmp(el, "free"))
340                 {
341                         val = CHANNEL_FREE;
342                         goto selchannel;
343                 } else
344                 if (!strcasecmp(el, "no"))
345                 {
346                         val = CHANNEL_NO;
347                         goto selchannel;
348                 } else
349                 {
350                         val = get_number(el);
351                         if (val == -1)
352                         {
353                                 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);
354                                 return(-1);
355                         }
356
357                         if (val<1 || val==16 || val>126)
358                         {
359                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
360                                 return(-1);
361                         }
362                         selchannel:
363                         /* add to select-channel list */
364                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
365                         memuse++;
366                         /* set value */
367                         selchannel->channel = val;
368                         /* tail port */
369                         selchannelp = &ifport->out_channel;
370                         while(*selchannelp)
371                                 selchannelp = &((*selchannelp)->next);
372                         *selchannelp = selchannel;
373                 }
374         }
375         return(0);
376 }
377 static int inter_channel_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
378 {
379         struct interface_port *ifport;
380         struct select_channel *selchannel, **selchannelp;
381         int val;
382         char *p, *el;
383
384         /* port in chain ? */
385         if (!interface->ifport)
386         {
387                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
388                 return(-1);
389         }
390         /* goto end of chain */
391         ifport = interface->ifport;
392         while(ifport->next)
393                 ifport = ifport->next;
394         p = value;
395         while(*p)
396         {
397                 el = p;
398                 p = get_seperated(p);
399                 if (ifport->in_channel) if (ifport->in_channel->channel == CHANNEL_FREE)
400                 {
401                         SPRINT(interface_error, "Error in %s (line %d): parameter '%s' has values behind 'free' keyword. They has no effect.\n", filename, line, parameter);
402                                 return(-1);
403                 }
404                 if (!strcasecmp(el, "free"))
405                 {
406                         val = CHANNEL_FREE;
407                         goto selchannel;
408                 } else
409                 {
410                         val = get_number(el);
411                         if (val == -1)
412                         {
413                                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects a comma seperated list of channel numbers and 'free'.\n", filename, line, parameter);
414                                 return(-1);
415                         }
416
417                         if (val<1 || val==16 || val>126)
418                         {
419                                 SPRINT(interface_error, "Error in %s (line %d): channel '%d' out of range.\n", filename, line, val);
420                                 return(-1);
421                         }
422                         selchannel:
423                         /* add to select-channel list */
424                         selchannel = (struct select_channel *)MALLOC(sizeof(struct select_channel));
425                         memuse++;
426                         /* set value */
427                         selchannel->channel = val;
428                         /* tail port */
429                         selchannelp = &ifport->in_channel;
430                         while(*selchannelp)
431                                 selchannelp = &((*selchannelp)->next);
432                         *selchannelp = selchannel;
433                 }
434         }
435         return(0);
436 }
437 static int inter_msn(struct interface *interface, char *filename, int line, char *parameter, char *value)
438 {
439         struct interface_msn *ifmsn, **ifmsnp;
440         char *p, *el;
441
442         if (!value[0])
443         {
444                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects one MSN number or a list.\n", filename, line, parameter);
445                 return(-1);
446         }
447         if (interface->ifscreen_in)
448         {
449                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'screen_in' parameter.\n", filename, line, parameter);
450                 return(-1);
451         }
452
453         /* process list */
454         p = value;
455         while(*p)
456         {
457                 el = p;
458                 p = get_seperated(p);
459                 /* add MSN to list */
460                 ifmsn = (struct interface_msn *)MALLOC(sizeof(struct interface_msn));
461                 memuse++;
462                 /* set value */
463                 SCPY(ifmsn->msn, el);
464                 /* tail port */
465                 ifmsnp = &interface->ifmsn;
466                 while(*ifmsnp)
467                         ifmsnp = &((*ifmsnp)->next);
468                 *ifmsnp = ifmsn;
469         }
470         return(0);
471 }
472 static int inter_screen(struct interface_screen **ifscreenp, struct interface *interface, char *filename, int line, char *parameter, char *value)
473 {
474         struct interface_screen *ifscreen;
475         char *p, *el;
476
477         if (!value[0])
478         {
479                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID and new caller ID.\n", filename, line, parameter);
480                 return(-1);
481         }
482         p = value;
483         el = p;
484         p = get_seperated(p);
485         /* add screen entry to list*/
486         ifscreen = (struct interface_screen *)MALLOC(sizeof(struct interface_screen));
487         memuse++;
488         ifscreen->match_type = -1; /* unchecked */
489         ifscreen->match_present = -1; /* unchecked */
490         ifscreen->result_type = -1; /* unchanged */
491         ifscreen->result_present = -1; /* unchanged */
492         /* tail port */
493         while(*ifscreenp)
494                 ifscreenp = &((*ifscreenp)->next);
495         *ifscreenp = ifscreen;
496         /* get match */
497         while(*p)
498         {
499                 el = p;
500                 p = get_seperated(p);
501                 if (!strcasecmp(el, "unknown"))
502                 {
503                         if (ifscreen->match_type != -1)
504                         {
505                                 typeerror:
506                                 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
507                                 return(-1);
508                         }
509                         ifscreen->match_type = INFO_NTYPE_UNKNOWN;
510                 } else
511                 if (!strcasecmp(el, "subscriber"))
512                 {
513                         if (ifscreen->match_type != -1)
514                                 goto typeerror;
515                         ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
516                 } else
517                 if (!strcasecmp(el, "national"))
518                 {
519                         if (ifscreen->match_type != -1)
520                                 goto typeerror;
521                         ifscreen->match_type = INFO_NTYPE_NATIONAL;
522                 } else
523                 if (!strcasecmp(el, "international"))
524                 {
525                         if (ifscreen->match_type != -1)
526                                 goto typeerror;
527                         ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
528                 } else
529                 if (!strcasecmp(el, "allowed"))
530                 {
531                         if (ifscreen->match_present != -1)
532                         {
533                                 presenterror:
534                                 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
535                                 return(-1);
536                         }
537                         ifscreen->match_present = INFO_PRESENT_ALLOWED;
538                 } else
539                 if (!strcasecmp(el, "restricted"))
540                 {
541                         if (ifscreen->match_present != -1)
542                                 goto presenterror;
543                         ifscreen->match_present = INFO_PRESENT_RESTRICTED;
544                 } else {
545                         SCPY(ifscreen->match, el);
546                         /* check for % at the end */
547                         if (strchr(el, '%'))
548                         {
549                                 if (strchr(el, '%') != el+strlen(el)-1)
550                                 {
551                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
552                                         return(-1);
553                                 }
554                         }
555                         break;
556                 }
557         }
558         if (ifscreen->match[0] == '\0')
559         {
560                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
561                 return(-1);
562         }
563         /* get result */
564         while(*p)
565         {
566                 el = p;
567                 p = get_seperated(p);
568                 if (!strcasecmp(el, "unknown"))
569                 {
570                         if (ifscreen->result_type != -1)
571                                 goto typeerror;
572                         ifscreen->result_type = INFO_NTYPE_UNKNOWN;
573                 } else
574                 if (!strcasecmp(el, "subscriber"))
575                 {
576                         if (ifscreen->result_type != -1)
577                                 goto typeerror;
578                         ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
579                 } else
580                 if (!strcasecmp(el, "national"))
581                 {
582                         if (ifscreen->result_type != -1)
583                                 goto typeerror;
584                         ifscreen->result_type = INFO_NTYPE_NATIONAL;
585                 } else
586                 if (!strcasecmp(el, "international"))
587                 {
588                         if (ifscreen->result_type != -1)
589                                 goto typeerror;
590                         ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
591                 } else
592                 if (!strcasecmp(el, "allowed"))
593                 {
594                         if (ifscreen->result_present != -1)
595                                 goto presenterror;
596                         ifscreen->result_present = INFO_PRESENT_ALLOWED;
597                 } else
598                 if (!strcasecmp(el, "restricted"))
599                 {
600                         if (ifscreen->result_present != -1)
601                                 goto presenterror;
602                         ifscreen->result_present = INFO_PRESENT_RESTRICTED;
603                 } else {
604                         SCPY(ifscreen->result, el);
605                         /* check for % at the end */
606                         if (strchr(el, '%'))
607                         {
608                                 if (strchr(el, '%') != el+strlen(el)-1)
609                                 {
610                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
611                                         return(-1);
612                                 }
613                         }
614                         break;
615                 }
616         }
617         if (ifscreen->result[0] == '\0')
618         {
619                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
620                 return(-1);
621         }
622         return(0);
623 }
624 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
625 {
626         if (interface->ifmsn)
627         {
628                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
629                 return(-1);
630         }
631
632         return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
633 }
634 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
635 {
636         return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
637 }
638 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
639 {
640         struct interface_port *ifport;
641
642         /* port in chain ? */
643         if (!interface->ifport)
644         {
645                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
646                 return(-1);
647         }
648         /* goto end of chain */
649         ifport = interface->ifport;
650         while(ifport->next)
651                 ifport = ifport->next;
652         ifport->nodtmf = 1;
653         return(0);
654 }
655 #warning filter to be done
656 #if 0
657 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
658 {
659         return(0);
660 }
661 #endif
662
663
664 /*
665  * structure of parameters
666  */
667 struct interface_param interface_param[] = {
668         { "extension", &inter_extension, "",
669         "If keyword is given, calls to interface are handled as internal extensions."},
670         {"tones", &inter_tones, "yes | no",
671         "Interface generates tones during call setup and release, or not.\nBy default only NT-mode ports generate tones."},
672
673         {"earlyb", &inter_earlyb, "yes | no",
674         "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode ports receive tones."},
675
676         {"hunt", &inter_hunt, "linear | roundrobin",
677         "Select the algorithm for selecting port with free channel."},
678
679         {"port", &inter_port, "<number>",
680         "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
681
682         {"block", &inter_block, "",
683         "If keyword is given, calls on this interface are blocked.\n"
684         "This parameter must follow a 'port' parameter."},
685
686         {"ptp", &inter_ptp, "",
687         "The given port above is opened as point-to-point.\n"
688         "This is required on NT-mode ports that are multipoint by default.\n"
689         "This parameter must follow a 'port' parameter."},
690
691         {"ptmp", &inter_ptmp, "",
692         "The given port above is opened as point-to-multipoint.\n"
693         "This is required on PRI NT-mode ports that are point-to-point by default.\n"
694         "This parameter must follow a 'port' parameter."},
695         {"nt", &inter_nt, "",
696         "The given port above is opened in NT-mode.\n"
697 #ifdef SOCKET_MISDN
698         "This is required on interfaces that support both NT-mode and TE-mode.\n"
699 #else
700         "This parameter is only required for socket based mISDN driver.\n"
701 #endif
702         "This parameter must follow a 'port' parameter."},
703
704         {"channel-out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
705         "Channel selection list for all outgoing calls to the interface.\n"
706         "A free channels is searched in order of appearance.\n"
707         "This parameter must follow a 'port' parameter.\n"
708         " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
709         " <number>[,...] - List of channels to search.\n"
710         " free - Select any free channel\n"
711         " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
712         " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
713
714         {"channel-in", &inter_channel_in, "[<number>][,...][,free]",
715         "Channel selection list for all incomming calls from the interface.\n"
716         "A free channels is accepted if in the list.\n"
717         "If any channel was requested, the first free channel found is selected.\n"
718         "This parameter must follow a 'port' parameter.\n"
719         " <number>[,...] - List of channels to accept.\n"
720         " free - Accept any free channel"},
721
722         {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
723         "Incomming caller ID is checked against given MSN numbers.\n"
724         "If the caller ID is not found in this list, it is overwritten by the first MSN"},
725
726         {"screen-in", &inter_screen_in, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
727         "Adds an entry for incomming calls to the caller ID screen list.\n"
728         "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
729         "If '%' is given after old caller ID, it matches even if caller ID has\n"
730         "additional digits.\n"
731         "If '%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
732         "are added.\n"
733         "Options can be:\n"
734         " unknown | subsciber | national | international - Change caller ID type.\n"
735         " present | restrict - Change presentation of caller ID."},
736                 
737         {"screen-out", &inter_screen_out, "[options] <old caller ID>[%] [options] <new caller ID>[%]",
738         "Adds an entry for outgoing calls to the caller ID screen list.\n"
739         "See 'screen-in' for help."},
740
741         {"nodtmf", &inter_nodtmf, "",
742         "Disables DTMF detection for this interface.\n"
743         "This parameter must follow a 'port' parameter."},
744
745 #if 0
746         {"layer2keep", &inter_layer2keep, "yes | no",
747         "By default, layer 2 is establised and kept up on PTP interfaces.\n"
748         ".\n"
749         "This parameter must follow a 'port' parameter."},
750 #endif
751
752 #if 0
753 #warning todo: filter, also in the PmISDN object
754         {"filter", &inter_filter, "<filter> [parameters]",
755         "Adds/appends a filter. Filters are ordered in transmit direction.\n"
756         "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
757         "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
758 #endif
759
760         {NULL, NULL, NULL, NULL}
761 };
762
763 /* read interfaces
764  *
765  * read settings from interface.conf
766  */
767 char interface_error[256];
768 struct interface *read_interfaces(void)
769 {
770         FILE                    *fp = NULL;
771         char                    filename[128];
772         char                    *p;
773         unsigned int            line, i;
774         char                    buffer[256];
775         struct interface        *interface = NULL, /* in case no interface */
776                                 **interfacep = &interface_newlist;
777         char                    parameter[128];
778         char                    value[256];
779         int                     expecting = 1; /* expecting new interface */
780         struct interface_param  *ifparam;
781
782         if (interface_newlist != NULL)
783                 FATAL("list is not empty.\n");
784         interface_error[0] = '\0';
785         SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
786
787         if (!(fp = fopen(filename,"r")))
788         {
789                 SPRINT(interface_error, "Cannot open '%s'\n", filename);
790                 goto error;
791         }
792
793         line=0;
794         while((fgets(buffer,sizeof(buffer),fp)))
795         {
796                 buffer[sizeof(buffer)-1]=0;
797                 if (buffer[0]) buffer[strlen(buffer)-1]=0;
798                 p=buffer;
799                 line++;
800
801                 while(*p <= 32) /* skip spaces */
802                 {
803                         if (*p == 0)
804                                 break;
805                         p++;
806                 }
807                 if (*p==0 || *p=='#') /* ignore comments and empty line */
808                         continue;
809
810                 parameter[0]=0;
811                 value[0]=0;
812                 i=0; /* read parameter */
813                 while(*p > 32)
814                 {
815                         if (i+1 >= sizeof(parameter))
816                         {
817                                 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
818                                 goto error;
819                         }
820                         parameter[i+1] = '\0';
821                         parameter[i++] = *p++;
822                 }
823
824                 while(*p <= 32) /* skip spaces */
825                 {
826                         if (*p == 0)
827                                 break;
828                         p++;
829                 }
830
831                 if (*p!=0 && *p!='#') /* missing name */
832                 {
833                         i=0; /* read until end */
834                         while(*p!=0 && *p!='#')
835                         {
836                                 if (i+1 >= sizeof(value))
837                                 {
838                                         SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
839                                         goto error;
840                                 }
841                                 value[i+1] = '\0';
842                                 value[i++] = *p++;
843                         }
844
845                         /* remove trailing spaces from value */
846                         while(i)
847                         {
848                                 if (value[i-1]==0 || value[i-1]>32)
849                                         break;
850                                 value[i-1] = '\0';
851                                 i--;
852                         }
853                 }
854
855                 /* check for interface name as first statement */
856                 if (expecting && parameter[0]!='[')
857                 {
858                         SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
859                         goto error;
860                 }
861                 expecting = 0;
862
863                 /* check for new interface */
864                 if (parameter[0] == '[')
865                 {
866                         if (parameter[strlen(parameter)-1] != ']')
867                         {
868                                 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
869                                 goto error;
870                         }
871                         parameter[strlen(parameter)-1] = '\0';
872
873                         /* check if interface name already exists */
874                         interface = interface_newlist;
875                         while(interface)
876                         {
877                                 if (!strcasecmp(interface->name, parameter+1))
878                                 {
879                                         SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
880                                         goto error;
881                                 }
882                                 interface = interface->next;
883                         }
884
885                         /* append interface to new list */
886                         interface = (struct interface *)MALLOC(sizeof(struct interface));
887                         memuse++;
888
889                         /* name interface */
890                         SCPY(interface->name, parameter+1);
891
892                         /* attach */
893                         *interfacep = interface;
894                         interfacep = &interface->next;
895
896                         continue;
897                 }
898
899                 ifparam = interface_param;
900                 while(ifparam->name)
901                 {
902                         if (!strcasecmp(parameter, ifparam->name))
903                         {
904                                 if (ifparam->func(interface, filename, line, parameter, value))
905                                         goto error;
906                                 break;
907                         }
908                         ifparam++;
909                 }
910                 if (ifparam->name)
911                         continue;
912
913                 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
914                 goto error;
915         }
916
917         if (fp) fclose(fp);
918         return(interface_newlist);
919 error:
920         PERROR_RUNTIME("%s", interface_error);
921         if (fp) fclose(fp);
922         free_interfaces(interface_newlist);
923         interface_newlist = NULL;
924         return(NULL);
925 }
926
927
928 /*
929  * freeing chain of interfaces
930  */
931 void free_interfaces(struct interface *interface)
932 {
933         void *temp;
934         struct interface_port *ifport;
935         struct select_channel *selchannel;
936         struct interface_msn *ifmsn;
937         struct interface_screen *ifscreen;
938         struct interface_filter *iffilter;
939
940         while(interface)
941         {
942                 ifport = interface->ifport;
943                 while(ifport)
944                 {
945                         selchannel = ifport->in_channel;
946                         while(selchannel)
947                         {
948                                 temp = selchannel;
949                                 selchannel = selchannel->next;
950                                 FREE(temp, sizeof(struct select_channel));
951                                 memuse--;
952                         }
953                         selchannel = ifport->out_channel;
954                         while(selchannel)
955                         {
956                                 temp = selchannel;
957                                 selchannel = selchannel->next;
958                                 FREE(temp, sizeof(struct select_channel));
959                                 memuse--;
960                         }
961                         temp = ifport;
962                         ifport = ifport->next;
963                         FREE(temp, sizeof(struct interface_port));
964                         memuse--;
965                 }
966                 ifmsn = interface->ifmsn;
967                 while(ifmsn)
968                 {
969                         temp = ifmsn;
970                         ifmsn = ifmsn->next;
971                         FREE(temp, sizeof(struct interface_msn));
972                         memuse--;
973                 }
974                 ifscreen = interface->ifscreen_in;
975                 while(ifscreen)
976                 {
977                         temp = ifscreen;
978                         ifscreen = ifscreen->next;
979                         FREE(temp, sizeof(struct interface_screen));
980                         memuse--;
981                 }
982                 ifscreen = interface->ifscreen_out;
983                 while(ifscreen)
984                 {
985                         temp = ifscreen;
986                         ifscreen = ifscreen->next;
987                         FREE(temp, sizeof(struct interface_screen));
988                         memuse--;
989                 }
990                 iffilter = interface->iffilter;
991                 while(iffilter)
992                 {
993                         temp = iffilter;
994                         iffilter = iffilter->next;
995                         FREE(temp, sizeof(struct interface_filter));
996                         memuse--;
997                 }
998                 temp = interface;
999                 interface = interface->next;
1000                 FREE(temp, sizeof(struct interface));
1001                 memuse--;
1002         }
1003 }
1004
1005 /*
1006  * defaults of ports if not specified by config
1007  */
1008 static void set_defaults(struct interface_port *ifport)
1009 {
1010         /* default channel selection list */
1011         if (!ifport->out_channel)
1012                 default_out_channel(ifport);
1013         if (!ifport->in_channel)
1014                 default_in_channel(ifport);
1015         /* default is_tones */
1016         if (ifport->interface->is_tones)
1017                 ifport->mISDNport->tones = (ifport->interface->is_tones==IS_YES);
1018         else
1019                 ifport->mISDNport->tones = (ifport->mISDNport->ntmode)?1:0;
1020         /* default is_earlyb */
1021         if (ifport->interface->is_earlyb)
1022                 ifport->mISDNport->earlyb = (ifport->interface->is_earlyb==IS_YES);
1023         else
1024                 ifport->mISDNport->earlyb = (ifport->mISDNport->ntmode)?0:1;
1025         /* set locally flag */
1026         if (ifport->interface->extension)
1027                 ifport->mISDNport->locally = 1;
1028         else
1029                 ifport->mISDNport->locally = 0;
1030 }
1031
1032
1033 /*
1034  * all links between mISDNport and interface are made
1035  * unused mISDNports are closed, new mISDNports are opened
1036  * also set default select_channel lists
1037  */
1038 void relink_interfaces(void)
1039 {
1040         struct mISDNport *mISDNport;
1041         struct interface *interface;
1042         struct interface_port *ifport;
1043
1044         /* unlink all mISDNports */
1045         mISDNport = mISDNport_first;
1046         while(mISDNport)
1047         {
1048                 mISDNport->ifport = NULL;
1049                 mISDNport = mISDNport->next;
1050         }
1051
1052         /* relink existing mISDNports */
1053         interface = interface_newlist;
1054         while(interface)
1055         {
1056                 ifport = interface->ifport;
1057                 while(ifport)
1058                 {
1059                         mISDNport = mISDNport_first;
1060                         while(mISDNport)
1061                         {
1062                                 if (mISDNport->portnum == ifport->portnum)
1063                                 {
1064                                         ifport->mISDNport = mISDNport;
1065                                         mISDNport->ifport = ifport;
1066                                         set_defaults(ifport);
1067                                 }
1068                                 mISDNport = mISDNport->next;
1069                         }
1070                         ifport = ifport->next;
1071                 }
1072                 interface = interface->next;
1073         }
1074
1075         /* close unused mISDNports */
1076         closeagain:
1077         mISDNport = mISDNport_first;
1078         while(mISDNport)
1079         {
1080                 if (mISDNport->ifport == NULL)
1081                 {
1082                         PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1083                         /* remove all port objects and destroy port */
1084                         mISDNport_close(mISDNport);
1085                         goto closeagain;
1086                 }
1087                 mISDNport = mISDNport->next;
1088         }
1089
1090         /* open and link new mISDNports */
1091         interface = interface_newlist;
1092         while(interface)
1093         {
1094                 ifport = interface->ifport;
1095                 while(ifport)
1096                 {
1097                         if (!ifport->mISDNport)
1098                         {
1099                                 load_port(ifport);
1100                         }
1101                         ifport = ifport->next;
1102                 }
1103                 interface = interface->next;
1104         }
1105
1106 }
1107
1108
1109 /*
1110  * load port
1111  */
1112 void load_port(struct interface_port *ifport)
1113 {
1114         struct mISDNport *mISDNport;
1115
1116         /* open new port */
1117         mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp, ifport->nt, ifport->interface);
1118         if (mISDNport)
1119         {
1120                 /* link port */
1121                 ifport->mISDNport = mISDNport;
1122                 mISDNport->ifport = ifport;
1123                 set_defaults(ifport);
1124         } else
1125         {
1126                 ifport->block = 2; /* not available */
1127         }
1128 }
1129
1130 /*
1131  * give summary of interface syntax
1132  */
1133 void doc_interface(void)
1134 {
1135         struct interface_param *ifparam;
1136         
1137         printf("Syntax overview\n");
1138         printf("---------------\n\n");
1139
1140         printf("[<name>]\n");
1141         ifparam = interface_param;
1142         while(ifparam->name)
1143         {
1144                 printf("%s %s\n", ifparam->name, ifparam->usage);
1145                 ifparam++;
1146         }
1147
1148         ifparam = interface_param;
1149         while(ifparam->name)
1150         {
1151                 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1152                 printf("%s\n", ifparam->help);
1153                 ifparam++;
1154         }
1155 }
1156