backup
[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         if (!selchannel)
28         {
29                 PERROR("No memory!");
30                 return;
31         }
32         memuse++;
33         memset(selchannel, 0, sizeof(struct select_channel));
34         
35         if (ifport->mISDNport->ntmode)
36                 selchannel->channel = CHANNEL_FREE;
37         else
38                 selchannel->channel = CHANNEL_ANY;
39         
40         ifport->out_channel = selchannel;
41
42         /* additional channel selection for multipoint NT ports */
43         if (!ifport->mISDNport->ptp && ifport->mISDNport->ntmode)
44         {
45                 selchannelp = &(selchannel->next);
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(selchannel, 0, sizeof(struct select_channel));
54                 selchannel->channel = CHANNEL_NO; // call waiting
55                 *selchannelp = selchannel;
56         }
57 }
58
59
60 /* set default in_channel */
61 void default_in_channel(struct interface_port *ifport)
62 {
63         struct select_channel *selchannel;
64
65         selchannel = (struct select_channel *)malloc(sizeof(struct select_channel));
66         if (!selchannel)
67         {
68                 PERROR("No memory!");
69                 return;
70         }
71         memuse++;
72         memset(selchannel, 0, sizeof(struct select_channel));
73         
74         selchannel->channel = CHANNEL_FREE;
75         
76         ifport->in_channel = selchannel;
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->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                         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->out_channel;
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_channel) if (ifport->in_channel->channel == 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 = 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_channel;
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         ifscreen->match_type = -1; /* unchecked */
513         ifscreen->match_present = -1; /* unchecked */
514         ifscreen->result_type = -1; /* unchanged */
515         ifscreen->result_present = -1; /* unchanged */
516         /* tail port */
517         while(*ifscreenp)
518                 ifscreenp = &((*ifscreenp)->next);
519         *ifscreenp = ifscreen;
520         /* get match */
521         while(*p)
522         {
523                 el = p;
524                 p = get_seperated(p);
525                 if (!strcasecmp(el, "unknown"))
526                 {
527                         if (ifscreen->match_type != -1)
528                         {
529                                 typeerror:
530                                 SPRINT(interface_error, "Error in %s (line %d): number type already set earlier.\n", filename, line, parameter);
531                                 return(-1);
532                         }
533                         ifscreen->match_type = INFO_NTYPE_UNKNOWN;
534                 } else
535                 if (!strcasecmp(el, "subscriber"))
536                 {
537                         if (ifscreen->match_type != -1)
538                                 goto typeerror;
539                         ifscreen->match_type = INFO_NTYPE_SUBSCRIBER;
540                 } else
541                 if (!strcasecmp(el, "national"))
542                 {
543                         if (ifscreen->match_type != -1)
544                                 goto typeerror;
545                         ifscreen->match_type = INFO_NTYPE_NATIONAL;
546                 } else
547                 if (!strcasecmp(el, "international"))
548                 {
549                         if (ifscreen->match_type != -1)
550                                 goto typeerror;
551                         ifscreen->match_type = INFO_NTYPE_INTERNATIONAL;
552                 } else
553                 if (!strcasecmp(el, "allowed"))
554                 {
555                         if (ifscreen->match_present != -1)
556                         {
557                                 presenterror:
558                                 SPRINT(interface_error, "Error in %s (line %d): presentation type already set earlier.\n", filename, line);
559                                 return(-1);
560                         }
561                         ifscreen->match_present = INFO_PRESENT_ALLOWED;
562                 } else
563                 if (!strcasecmp(el, "restricted"))
564                 {
565                         if (ifscreen->match_present != -1)
566                                 goto presenterror;
567                         ifscreen->match_present = INFO_PRESENT_RESTRICTED;
568                 } else {
569                         SCPY(ifscreen->match, el);
570                         /* check for % at the end */
571                         if (strchr(el, '%'))
572                         {
573                                 if (strchr(el, '%') != el+strlen(el)-1)
574                                 {
575                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
576                                         return(-1);
577                                 }
578                         }
579                         break;
580                 }
581         }
582         if (ifscreen->match[0] == '\0')
583         {
584                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects old caller ID.\n", filename, line, parameter);
585                 return(-1);
586         }
587         /* get result */
588         while(*p)
589         {
590                 el = p;
591                 p = get_seperated(p);
592                 if (!strcasecmp(el, "unknown"))
593                 {
594                         if (ifscreen->result_type != -1)
595                                 goto typeerror;
596                         ifscreen->result_type = INFO_NTYPE_UNKNOWN;
597                 } else
598                 if (!strcasecmp(el, "subscriber"))
599                 {
600                         if (ifscreen->result_type != -1)
601                                 goto typeerror;
602                         ifscreen->result_type = INFO_NTYPE_SUBSCRIBER;
603                 } else
604                 if (!strcasecmp(el, "national"))
605                 {
606                         if (ifscreen->result_type != -1)
607                                 goto typeerror;
608                         ifscreen->result_type = INFO_NTYPE_NATIONAL;
609                 } else
610                 if (!strcasecmp(el, "international"))
611                 {
612                         if (ifscreen->result_type != -1)
613                                 goto typeerror;
614                         ifscreen->result_type = INFO_NTYPE_INTERNATIONAL;
615                 } else
616                 if (!strcasecmp(el, "allowed"))
617                 {
618                         if (ifscreen->result_present != -1)
619                                 goto presenterror;
620                         ifscreen->result_present = INFO_PRESENT_ALLOWED;
621                 } else
622                 if (!strcasecmp(el, "restricted"))
623                 {
624                         if (ifscreen->result_present != -1)
625                                 goto presenterror;
626                         ifscreen->result_present = INFO_PRESENT_RESTRICTED;
627                 } else {
628                         SCPY(ifscreen->result, el);
629                         /* check for % at the end */
630                         if (strchr(el, '%'))
631                         {
632                                 if (strchr(el, '%') != el+strlen(el)-1)
633                                 {
634                                         SPRINT(interface_error, "Error in %s (line %d): %% joker found, but must at the end.\n", filename, line, parameter);
635                                         return(-1);
636                                 }
637                         }
638                         break;
639                 }
640         }
641         if (ifscreen->result[0] == '\0')
642         {
643                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects new caller ID.\n", filename, line, parameter);
644                 return(-1);
645         }
646         return(0);
647 }
648 static int inter_screen_in(struct interface *interface, char *filename, int line, char *parameter, char *value)
649 {
650         if (interface->ifmsn)
651         {
652                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' not allowed with 'msn' parameter.\n", filename, line, parameter);
653                 return(-1);
654         }
655
656         return(inter_screen(&interface->ifscreen_in, interface, filename, line, parameter, value));
657 }
658 static int inter_screen_out(struct interface *interface, char *filename, int line, char *parameter, char *value)
659 {
660         return(inter_screen(&interface->ifscreen_out, interface, filename, line, parameter, value));
661 }
662 static int inter_nodtmf(struct interface *interface, char *filename, int line, char *parameter, char *value)
663 {
664         struct interface_port *ifport;
665
666         /* port in chain ? */
667         if (!interface->ifport)
668         {
669                 SPRINT(interface_error, "Error in %s (line %d): parameter '%s' expects previous 'port' definition.\n", filename, line, parameter);
670                 return(-1);
671         }
672         /* goto end of chain */
673         ifport = interface->ifport;
674         while(ifport->next)
675                 ifport = ifport->next;
676         ifport->nodtmf = 1;
677         return(0);
678 }
679 #warning filter to be done
680 #if 0
681 static int inter_filter(struct interface *interface, char *filename, int line, char *parameter, char *value)
682 {
683         return(0);
684 }
685 #endif
686
687
688 /*
689  * structure of parameters
690  */
691 struct interface_param interface_param[] = {
692         { "extension", &inter_extension, "",
693         "If keyword is given, calls to interface are handled as internal extensions."},
694         {"tones", &inter_tones, "yes | no",
695         "Interface generates tones during call setup and release, or not.\nBy default only NT-mode interfaces generate tones."},
696
697         {"earlyb", &inter_earlyb, "yes | no",
698         "Interface receives and bridges tones during call setup and release, or not.\nBy default only TE-mode interfaces receive tones."},
699
700         {"hunt", &inter_hunt, "linear | roundrobin",
701         "Select the algorithm for selecting port with free channel."},
702
703         {"port", &inter_port, "<number>",
704         "Give exactly one port for this interface.\nTo give multiple ports, add more lines with port parameters."},
705
706         {"block", &inter_block, "",
707         "If keyword is given, calls on this interface are blocked.\n"
708         "This parameter must follow a 'port' parameter."},
709
710         {"ptp", &inter_ptp, "",
711         "The given port above is opened as point-to-point.\n"
712         "This is required on NT-mode ports that are multipoint by default.\n"
713         "This parameter must follow a 'port' parameter."},
714
715         {"ptmp", &inter_ptmp, "",
716         "The given port above is opened as point-to-multipoint.\n"
717         "This is required on PRI NT-mode ports that are point-to-point by default.\n"
718         "This parameter must follow a 'port' parameter."},
719
720         {"channel_out", &inter_channel_out, "[force,][<number>][,...][,free][,any][,no]",
721         "Channel selection list for all outgoing calls to the interface.\n"
722         "A free channels is searched in order of appearance.\n"
723         "This parameter must follow a 'port' parameter.\n"
724         " force - Forces the selected port with no acceptable alternative (see DSS1).\n"
725         " <number>[,...] - List of channels to search.\n"
726         " free - Select any free channel\n"
727         " any - On outgoing calls, signal 'any channel acceptable'. (see DSS1)\n"
728         " no - Signal 'no channel available' aka 'call waiting'. (see DSS1)"},
729
730         {"channel_in", &inter_channel_in, "[force,][<number>][,...][,free][,any][,no]",
731         "Channel selection list for all incomming calls from the interface.\n"
732         "A free channels is accepted if in the list.\n"
733         "If no channel was requested, the first free channel found is selected.\n"
734         "This parameter must follow a 'port' parameter.\n"
735         " <number>[,...] - List of channels to accept.\n"
736         " free - Accept any free channel"},
737
738         {"msn", &inter_msn, "<default MSN>,[<additional MSN>[,...]]",
739         "Incomming caller ID is checked against given MSN numbers.\n"
740         "If the caller ID is not found in this list, it is overwritten by the first MSN"},
741
742         {"screen-in", &inter_screen_in, "[options] <old caller ID>[%%] [options] <new caller ID>[%%]",
743         "Adds an entry for incomming calls to the caller ID screen list.\n"
744         "If the given 'old caller ID' matches, it is replaced by the 'new caller ID'\n"
745         "If '%%' is given after old caller ID, it matches even if caller ID has\n"
746         "additional digits.\n"
747         "If '%%' is given after mew caller ID, additinal digits of the 'old caller ID'\n"
748         "are added.\n"
749         "Options can be:\n"
750         " unknown | subsciber | national | international - Change caller ID type.\n"
751         " present | restrict - Change presentation of caller ID."},
752                 
753         {"screen-out", &inter_screen_out, "<old caller ID> <new caller ID> [options]",
754         "Adds an entry for outgoing calls to the caller ID screen list.\n"
755         "See 'screen-in' for help."},
756
757         {"nodtmf", &inter_nodtmf, "",
758         "Disables DTMF detection for this interface.\n"
759         "This parameter must follow a 'port' parameter."},
760
761 #if 0
762 #warning todo: filter, also in the PmISDN object
763         {"filter", &inter_filter, "<filter> [parameters]",
764         "Adds/appends a filter. Filters are ordered in transmit direction.\n"
765         "gain <tx-volume> <rx-volume> - Changes volume (-8 .. 8)\n"
766         "blowfish <key> - Adds encryption. Key must be 4-56 bytes (8-112 hex characters."},
767 #endif
768
769         {NULL, NULL, NULL, NULL}
770 };
771
772 /* read interfaces
773  *
774  * read settings from interface.conf
775  */
776 char interface_error[256];
777 struct interface *read_interfaces(void)
778 {
779         FILE                    *fp = NULL;
780         char                    filename[128];
781         char                    *p;
782         unsigned int            line, i;
783         char                    buffer[256];
784         struct interface        *interface = NULL, /* in case no interface */
785                                 **interfacep = &interface_newlist;
786         char                    parameter[128];
787         char                    value[256];
788         int                     expecting = 1; /* expecting new interface */
789         struct interface_param  *ifparam;
790
791         if (interface_newlist != NULL)
792         {
793                 PERROR("software error, list is not empty.\n");
794                 exit(-1);
795         }
796         interface_error[0] = '\0';
797         SPRINT(filename, "%s/interface.conf", INSTALL_DATA);
798
799         if (!(fp = fopen(filename,"r")))
800         {
801                 SPRINT(interface_error, "Cannot open '%s'\n", filename);
802                 goto error;
803         }
804
805         line=0;
806         while((fgets(buffer,sizeof(buffer),fp)))
807         {
808                 buffer[sizeof(buffer)-1]=0;
809                 if (buffer[0]) buffer[strlen(buffer)-1]=0;
810                 p=buffer;
811                 line++;
812
813                 while(*p <= 32) /* skip spaces */
814                 {
815                         if (*p == 0)
816                                 break;
817                         p++;
818                 }
819                 if (*p==0 || *p=='#') /* ignore comments and empty line */
820                         continue;
821
822                 parameter[0]=0;
823                 value[0]=0;
824                 i=0; /* read parameter */
825                 while(*p > 32)
826                 {
827                         if (i+1 >= sizeof(parameter))
828                         {
829                                 SPRINT(interface_error, "Error in %s (line %d): parameter name too long.\n",filename,line);
830                                 goto error;
831                         }
832                         parameter[i+1] = '\0';
833                         parameter[i++] = *p++;
834                 }
835
836                 while(*p <= 32) /* skip spaces */
837                 {
838                         if (*p == 0)
839                                 break;
840                         p++;
841                 }
842
843                 if (*p!=0 && *p!='#') /* missing name */
844                 {
845                         i=0; /* read until end */
846                         while(*p!=0 && *p!='#')
847                         {
848                                 if (i+1 >= sizeof(value))
849                                 {
850                                         SPRINT(interface_error, "Error in %s (line %d): value too long.\n", filename, line);
851                                         goto error;
852                                 }
853                                 value[i+1] = '\0';
854                                 value[i++] = *p++;
855                         }
856
857                         /* remove trailing spaces from value */
858                         while(i)
859                         {
860                                 if (value[i-1]==0 || value[i-1]>32)
861                                         break;
862                                 value[i-1] = '\0';
863                                 i--;
864                         }
865                 }
866
867                 /* check for interface name as first statement */
868                 if (expecting && parameter[0]!='[')
869                 {
870                         SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
871                         goto error;
872                 }
873                 expecting = 0;
874
875                 /* check for new interface */
876                 if (parameter[0] == '[')
877                 {
878                         if (parameter[strlen(parameter)-1] != ']')
879                         {
880                                 SPRINT(interface_error, "Error in %s (line %d): expecting interface name inside [ and ], but got: '%s'.\n", filename, line, parameter);
881                                 goto error;
882                         }
883                         parameter[strlen(parameter)-1] = '\0';
884
885                         /* check if interface name already exists */
886                         interface = interface_first;
887                         while(interface)
888                         {
889                                 if (!strcasecmp(interface->name, parameter+1))
890                                 {
891                                         SPRINT(interface_error, "Error in %s (line %d): interface name '%s' already defined above.\n", filename, line, parameter+1);
892                                         goto error;
893                                 }
894                                 interface = interface->next;
895                         }
896
897                         /* append interface to new list */
898                         interface = (struct interface *)malloc(sizeof(struct interface));
899                         if (!interface)
900                         {
901                                 SPRINT(interface_error, "No memory!");
902                                 goto error;
903                         }
904                         memuse++;
905                         memset(interface, 0, sizeof(struct interface));
906
907                         /* name interface */
908                         SCPY(interface->name, parameter+1);
909
910                         /* attach */
911                         *interfacep = interface;
912                         interfacep = &interface->next;
913
914                         continue;
915                 }
916
917                 ifparam = interface_param;
918                 while(ifparam->name)
919                 {
920                         if (!strcasecmp(parameter, ifparam->name))
921                         {
922                                 if (ifparam->func(interface, filename, line, parameter, value))
923                                         goto error;
924                                 continue;
925                         }
926                         ifparam++;
927                 }
928
929                 SPRINT(interface_error, "Error in %s (line %d): unknown parameter: '%s'.\n", filename, line, parameter);
930                 goto error;
931         }
932
933         if (fp) fclose(fp);
934         return(interface_newlist);
935 error:
936         PERROR_RUNTIME("%s", interface_error);
937         if (fp) fclose(fp);
938         free_interfaces(interface_newlist);
939         interface_newlist = NULL;
940         return(NULL);
941 }
942
943
944 /*
945  * freeing chain of interfaces
946  */
947 void free_interfaces(struct interface *interface)
948 {
949         void *temp;
950         struct interface_port *ifport;
951         struct select_channel *selchannel;
952         struct interface_msn *ifmsn;
953         struct interface_screen *ifscreen;
954         struct interface_filter *iffilter;
955
956         while(interface)
957         {
958                 ifport = interface->ifport;
959                 while(ifport)
960                 {
961                         selchannel = ifport->in_channel;
962                         while(selchannel)
963                         {
964                                 temp = selchannel;
965                                 selchannel = selchannel->next;
966                                 memset(temp, 0, sizeof(struct select_channel));
967                                 free(temp);
968                                 memuse--;
969                         }
970                         selchannel = ifport->out_channel;
971                         while(selchannel)
972                         {
973                                 temp = selchannel;
974                                 selchannel = selchannel->next;
975                                 memset(temp, 0, sizeof(struct select_channel));
976                                 free(temp);
977                                 memuse--;
978                         }
979                         temp = ifport;
980                         ifport = ifport->next;
981                         memset(temp, 0, sizeof(struct interface_port));
982                         free(temp);
983                         memuse--;
984                 }
985                 ifmsn = interface->ifmsn;
986                 while(ifmsn)
987                 {
988                         temp = ifmsn;
989                         ifmsn = ifmsn->next;
990                         memset(temp, 0, sizeof(struct interface_msn));
991                         free(temp);
992                         memuse--;
993                 }
994                 ifscreen = interface->ifscreen_in;
995                 while(ifscreen)
996                 {
997                         temp = ifscreen;
998                         ifscreen = ifscreen->next;
999                         memset(temp, 0, sizeof(struct interface_screen));
1000                         free(temp);
1001                         memuse--;
1002                 }
1003                 ifscreen = interface->ifscreen_out;
1004                 while(ifscreen)
1005                 {
1006                         temp = ifscreen;
1007                         ifscreen = ifscreen->next;
1008                         memset(temp, 0, sizeof(struct interface_screen));
1009                         free(temp);
1010                         memuse--;
1011                 }
1012                 iffilter = interface->iffilter;
1013                 while(iffilter)
1014                 {
1015                         temp = iffilter;
1016                         iffilter = iffilter->next;
1017                         memset(temp, 0, sizeof(struct interface_filter));
1018                         free(temp);
1019                         memuse--;
1020                 }
1021                 temp = interface;
1022                 interface = interface->next;
1023                 memset(temp, 0, sizeof(struct interface));
1024                 free(temp);
1025                 memuse--;
1026         }
1027 }
1028
1029
1030 /*
1031  * all links between mISDNport and interface are made
1032  * unused mISDNports are closed, new mISDNports are opened
1033  * also set default select_channel lists
1034  */
1035 void relink_interfaces(void)
1036 {
1037         struct mISDNport *mISDNport;
1038         struct interface *interface;
1039         struct interface_port *ifport;
1040
1041         /* unlink all mISDNports */
1042         mISDNport = mISDNport_first;
1043         while(mISDNport)
1044         {
1045                 mISDNport->ifport = NULL;
1046                 mISDNport = mISDNport->next;
1047         }
1048
1049         /* relink existing mISDNports */
1050         interface = interface_newlist;
1051         while(interface)
1052         {
1053                 ifport = interface->ifport;
1054                 while(ifport)
1055                 {
1056                         mISDNport = mISDNport_first;
1057                         while(mISDNport)
1058                         {
1059                                 if (mISDNport->portnum == ifport->portnum)
1060                                 {
1061                                         ifport->mISDNport = mISDNport;
1062                                         mISDNport->ifport = ifport;
1063                                 }
1064                                 mISDNport = mISDNport->next;
1065                         }
1066                         ifport = ifport->next;
1067                 }
1068                 interface = interface->next;
1069         }
1070
1071         /* close unused mISDNports */
1072         closeagain:
1073         mISDNport = mISDNport_first;
1074         while(mISDNport)
1075         {
1076                 if (mISDNport->ifport == NULL)
1077                 {
1078                         PDEBUG(DEBUG_ISDN, "Port %d is not used anymore and will be closed\n", mISDNport->portnum);
1079                         /* remove all port objects and destroy port */
1080                         mISDNport_close(mISDNport);
1081                         goto closeagain;
1082                 }
1083                 mISDNport = mISDNport->next;
1084         }
1085
1086         /* open and link new mISDNports */
1087         interface = interface_newlist;
1088         while(interface)
1089         {
1090                 ifport = interface->ifport;
1091                 while(ifport)
1092                 {
1093                         if (!ifport->mISDNport)
1094                         {
1095                                 /* open new port */
1096                                 mISDNport = mISDNport_open(ifport->portnum, ifport->ptp, ifport->ptmp);
1097                                 if (mISDNport)
1098                                 {
1099                                         ifport->mISDNport = mISDNport;
1100                                         mISDNport->ifport = ifport;
1101                                 }
1102                         }
1103                         if (ifport->mISDNport)
1104                         {
1105                                 /* default channel selection list */
1106                                 if (!ifport->out_channel)
1107                                         default_out_channel(ifport);
1108                                 if (!ifport->in_channel)
1109                                         default_in_channel(ifport);
1110                                 /* default is_tones */
1111                                 if (ifport->interface->is_tones)
1112                                         ifport->mISDNport->is_tones = (ifport->interface->is_tones==IS_YES);
1113                                 else
1114                                         ifport->mISDNport->is_tones = (ifport->mISDNport->ntmode)?1:0;
1115                                 /* default is_earlyb */
1116                                 if (ifport->interface->is_earlyb)
1117                                         ifport->mISDNport->is_earlyb = (ifport->interface->is_earlyb==IS_YES);
1118                                 else
1119                                         ifport->mISDNport->is_earlyb = (ifport->mISDNport->ntmode)?0:1;
1120                         }
1121                 }
1122                 interface = interface->next;
1123         }
1124
1125 }
1126
1127 /*
1128  * give summary of interface syntax
1129  */
1130 void doc_interface(void)
1131 {
1132         struct interface_param *ifparam;
1133         
1134         printf("Syntax overview\n");
1135         printf("---------------\n\n");
1136
1137         printf("[<name>]\n");
1138         ifparam = interface_param;
1139         while(ifparam->name)
1140         {
1141                 printf("%s %s\n", ifparam->name, ifparam->usage);
1142                 ifparam++;
1143         }
1144
1145         ifparam = interface_param;
1146         while(ifparam->name)
1147         {
1148                 printf("\nParameter: %s %s\n", ifparam->name, ifparam->usage);
1149                 printf("%s\n", ifparam->help);
1150                 ifparam++;
1151         }
1152 }
1153
1154