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