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