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