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