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