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