1 /* $MirOS: src/usr.sbin/isdn/isdnd/rc_config.c,v 1.2 2005/03/13 19:17:03 tg Exp $ */
2
3 /*
4 * Copyright (c) 1997, 2000 Hellmuth Michaelis. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *---------------------------------------------------------------------------
28 *
29 * i4b daemon - config file processing
30 * -----------------------------------
31 *
32 * $Id: rc_config.c,v 1.22 2004/05/06 21:13:28 martin Exp $
33 *
34 * $FreeBSD$
35 *
36 * last edit-date: [Sat Jan 6 12:57:36 2001]
37 *
38 *---------------------------------------------------------------------------*/
39
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <netinet/in.h>
43 #include <arpa/inet.h>
44
45 #ifdef __OpenBSD__
46 #include <sys/timeout.h>
47 #else
48 #include <sys/callout.h>
49 #endif
50 #include <sys/ioctl.h>
51 #include <ifaddrs.h>
52
53 #include "isdnd.h"
54 #include "rc_parse.h"
55
56 #include "monitor.h"
57
58 __RCSID("$MirOS: src/usr.sbin/isdn/isdnd/rc_config.c,v 1.2 2005/03/13 19:17:03 tg Exp $");
59
60 extern int lineno;
61 extern char *yytext;
62
63 extern FILE *yyin;
64 extern int yyparse(void);
65
66 static void set_config_defaults(void);
67 static void check_config(void);
68 static void print_config(void);
69 static void parse_valid(char *dt);
70 static int lookup_l4_driver(const char *name);
71 void init_currrent_cfg_state(void);
72 #ifdef SPPPGETAUTHCFG
73 static void set_isppp_auth(struct cfg_entry*);
74 #endif
75 static void set_autoupdown(struct cfg_entry*);
76 void flush_config(void);
77
78 static int nregexpr = 0;
79 static int nregprog = 0;
80 static struct cfg_entry * current_cfe = NULL;
81 struct isdn_ctrl_state * cur_ctrl = NULL;
82
83 /*---------------------------------------------------------------------------*
84 * called from main to read and process config file
85 *---------------------------------------------------------------------------*/
86 void
configure(char * filename,int reread)87 configure(char *filename, int reread)
88 {
89 extern void reset_scanner(FILE *inputfile);
90
91 set_config_defaults();
92
93 yyin = fopen(filename, "r");
94
95 if (reread)
96 {
97 reset_scanner(yyin);
98 current_cfe = NULL;
99 }
100
101 if (yyin == NULL)
102 {
103 logit(LL_ERR, "cannot fopen file [%s]", filename);
104 exit(1);
105 }
106
107 yyparse();
108
109 monitor_fixup_rights();
110
111 check_config(); /* validation and consistency check */
112
113 fclose(yyin);
114
115 if (do_print)
116 {
117 if (config_error_flag)
118 {
119 logit(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag);
120 exit(1);
121 }
122 print_config();
123 do_exit(0);
124 }
125 }
126
127 /*---------------------------------------------------------------------------*
128 * yacc error routine
129 *---------------------------------------------------------------------------*/
130 void
yyerror(const char * msg)131 yyerror(const char *msg)
132 {
133 logit(LL_ERR, "configuration error: %s at line %d, token \"%s\"", msg, lineno+1, yytext);
134 config_error_flag++;
135 }
136
137 /*
138 * Prepare a new default entry
139 */
140 void
init_currrent_cfg_state()141 init_currrent_cfg_state()
142 {
143 if (current_cfe != NULL) {
144 add_cfg_entry(current_cfe);
145 }
146 current_cfe = malloc(sizeof(struct cfg_entry));
147 memset(current_cfe, 0, sizeof(struct cfg_entry));
148
149 current_cfe->isdncontroller = INVALID;
150 current_cfe->isdnchannel = CHAN_ANY;
151 current_cfe->usrdevice = INVALID;
152 current_cfe->usrdeviceunit = INVALID;
153 current_cfe->remote_numbers_handling = RNH_LAST;
154 current_cfe->dialin_reaction = REACT_IGNORE;
155 current_cfe->b1protocol = BPROT_NONE;
156 current_cfe->unitlength = UNITLENGTH_DEFAULT;
157 current_cfe->earlyhangup = EARLYHANGUP_DEFAULT;
158 current_cfe->ratetype = INVALID_RATE;
159 current_cfe->unitlengthsrc = ULSRC_NONE;
160 current_cfe->answerprog = ANSWERPROG_DEF;
161 current_cfe->callbackwait = CALLBACKWAIT_MIN;
162 current_cfe->calledbackwait = CALLEDBACKWAIT_MIN;
163 current_cfe->dialretries = DIALRETRIES_DEF;
164 current_cfe->recoverytime = RECOVERYTIME_MIN;
165 current_cfe->dialouttype = DIALOUT_NORMAL;
166 current_cfe->inout = DIR_INOUT;
167 current_cfe->ppp_expect_auth = AUTH_UNDEF;
168 current_cfe->ppp_send_auth = AUTH_UNDEF;
169 current_cfe->ppp_auth_flags = AUTH_RECHALLENGE | AUTH_REQUIRED;
170 current_cfe->cdid = CDID_UNUSED;
171 current_cfe->state = ST_IDLE;
172 current_cfe->aoc_valid = AOC_INVALID;
173 current_cfe->autoupdown = AUTOUPDOWN_YES;
174 }
175
176 /*---------------------------------------------------------------------------*
177 * fill all config entries with default values
178 *---------------------------------------------------------------------------*/
179 static void
set_config_defaults(void)180 set_config_defaults(void)
181 {
182 int i;
183
184 /* system section cleanup */
185
186 nregprog = nregexpr = 0;
187
188 rt_prio = RTPRIO_NOTUSED;
189
190 mailer[0] = '\0';
191 mailto[0] = '\0';
192
193 /* clean regular expression table */
194
195 for (i=0; i < MAX_RE; i++)
196 {
197 if (rarr[i].re_expr)
198 free(rarr[i].re_expr);
199 rarr[i].re_expr = NULL;
200
201 if (rarr[i].re_prog)
202 free(rarr[i].re_prog);
203 rarr[i].re_prog = NULL;
204
205 rarr[i].re_flg = 0;
206 }
207
208 strlcpy(rotatesuffix, "", sizeof(rotatesuffix));
209 }
210
211 static void
set_autoupdown(struct cfg_entry * cep)212 set_autoupdown(struct cfg_entry *cep)
213 {
214 struct ifaddrs *res = NULL, *p;
215 struct ifreq ifr;
216 int r, s, cnt, in6;
217
218 s = socket(AF_INET, SOCK_DGRAM, 0);
219 memset(&ifr, 0, sizeof ifr);
220 snprintf(ifr.ifr_name, sizeof ifr.ifr_name, "%s%d", cep->usrdevicename, cep->usrdeviceunit);
221 r = ioctl(s, SIOCGIFFLAGS, &ifr);
222
223 /*
224 * See if this interface has got any valid addresses - if not,
225 * leave it alone.
226 */
227 if (r >= 0 && !(ifr.ifr_flags & IFF_UP)) {
228 cnt = in6 = 0;
229 if (getifaddrs(&res) == 0) {
230 for (p = res; p; p = p->ifa_next) {
231 if (p->ifa_addr == NULL)
232 continue;
233 if (p->ifa_addr->sa_family == AF_LINK)
234 continue;
235 if (strcmp(p->ifa_name, ifr.ifr_name) != 0)
236 continue;
237 if (p->ifa_addr->sa_family == AF_INET6)
238 in6 = 1;
239 cnt++;
240 }
241 freeifaddrs(res);
242 }
243
244 if (in6)
245 cnt--; /* XXX - heuristic to adjust for INET6 local scope */
246
247 /* Ok, we have some addres - so UP the interface */
248 if (cnt > 0) {
249 ifr.ifr_flags |= IFF_UP;
250 r = ioctl(s, SIOCSIFFLAGS, &ifr);
251 if (r >= 0)
252 cep->autoupdown |= AUTOUPDOWN_DONE;
253 }
254 }
255
256 close(s);
257 }
258
259 #ifdef SPPPGETAUTHCFG
260 static void
set_isppp_auth(struct cfg_entry * cep)261 set_isppp_auth(struct cfg_entry *cep)
262 {
263 struct spppauthcfg spcfg;
264 int s;
265 int doioctl = 0;
266
267 if (cep->ppp_expect_auth == AUTH_UNDEF
268 && cep->ppp_send_auth == AUTH_UNDEF)
269 return;
270
271 if (cep->ppp_expect_auth == AUTH_NONE
272 || cep->ppp_send_auth == AUTH_NONE)
273 doioctl = 1;
274
275 if ((cep->ppp_expect_auth == AUTH_CHAP
276 || cep->ppp_expect_auth == AUTH_PAP)
277 && cep->ppp_expect_name != NULL
278 && cep->ppp_expect_password != NULL)
279 doioctl = 1;
280
281 if ((cep->ppp_send_auth == AUTH_CHAP || cep->ppp_send_auth == AUTH_PAP)
282 && cep->ppp_send_name != NULL
283 && cep->ppp_send_password != NULL)
284 doioctl = 1;
285
286 if (!doioctl)
287 return;
288
289 memset(&spcfg, 0, sizeof spcfg);
290 snprintf(spcfg.ifname, sizeof(spcfg.ifname), "%s%d",
291 cep->usrdevicename, cep->usrdeviceunit);
292
293 /* use a random AF to create the socket */
294 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
295 logit(LL_ERR, "ERROR opening control socket at line %d!", lineno);
296 config_error_flag++;
297 return;
298 }
299
300 if (ioctl(s, SPPPGETAUTHCFG, &spcfg) == -1) {
301 logit(LL_ERR, "ERROR fetching active PPP authentication info for %s at line %d!", spcfg.ifname, lineno);
302 close(s);
303 config_error_flag++;
304 return;
305 }
306 if (cep->ppp_expect_auth != AUTH_UNDEF)
307 {
308 if (cep->ppp_expect_auth == AUTH_NONE)
309 {
310 spcfg.hisauth = SPPP_AUTHPROTO_NONE;
311 }
312 else if ((cep->ppp_expect_auth == AUTH_CHAP
313 || cep->ppp_expect_auth == AUTH_PAP)
314 && cep->ppp_expect_name != NULL
315 && cep->ppp_expect_password != NULL)
316 {
317 spcfg.hisauth = cep->ppp_expect_auth == AUTH_PAP ? SPPP_AUTHPROTO_PAP : SPPP_AUTHPROTO_CHAP;
318 spcfg.hisname = cep->ppp_expect_name;
319 spcfg.hisname_length = strlen(cep->ppp_expect_name)+1;
320 spcfg.hissecret = cep->ppp_expect_password;
321 spcfg.hissecret_length = strlen(cep->ppp_expect_password)+1;
322 }
323 }
324 if (cep->ppp_send_auth != AUTH_UNDEF)
325 {
326 if (cep->ppp_send_auth == AUTH_NONE)
327 {
328 spcfg.myauth = SPPP_AUTHPROTO_NONE;
329 }
330 else if ((cep->ppp_send_auth == AUTH_CHAP
331 || cep->ppp_send_auth == AUTH_PAP)
332 && cep->ppp_send_name != NULL
333 && cep->ppp_send_password != NULL)
334 {
335 spcfg.myauth = cep->ppp_send_auth == AUTH_PAP ? SPPP_AUTHPROTO_PAP : SPPP_AUTHPROTO_CHAP;
336 spcfg.myname = cep->ppp_send_name;
337 spcfg.myname_length = strlen(cep->ppp_send_name)+1;
338 spcfg.mysecret = cep->ppp_send_password;
339 spcfg.mysecret_length = strlen(cep->ppp_send_password)+1;
340
341 if (cep->ppp_auth_flags & AUTH_REQUIRED)
342 spcfg.hisauthflags &= ~SPPP_AUTHFLAG_NOCALLOUT;
343 else
344 spcfg.hisauthflags |= SPPP_AUTHFLAG_NOCALLOUT;
345
346 if (cep->ppp_auth_flags & AUTH_RECHALLENGE)
347 spcfg.hisauthflags &= ~SPPP_AUTHFLAG_NORECHALLENGE;
348 else
349 spcfg.hisauthflags |= SPPP_AUTHFLAG_NORECHALLENGE;
350 }
351 }
352
353 if (ioctl(s, SPPPSETAUTHCFG, &spcfg) == -1) {
354 logit(LL_ERR, "ERROR setting new PPP authentication parameters for %s at line %d!", spcfg.ifname, lineno);
355 config_error_flag++;
356 }
357 close(s);
358 }
359 #endif
360
361 /*---------------------------------------------------------------------------*
362 * extract values from config and fill table
363 *---------------------------------------------------------------------------*/
364 void
cfg_setval(int keyword)365 cfg_setval(int keyword)
366 {
367 int i;
368
369 switch (keyword)
370 {
371 case ACCTALL:
372 acct_all = yylval.booln;
373 DBGL(DL_RCCF, (logit(LL_DBG, "system: acctall = %d", yylval.booln)));
374 break;
375
376 case ACCTFILE:
377 strlcpy(acctfile, yylval.str, sizeof(acctfile));
378 DBGL(DL_RCCF, (logit(LL_DBG, "system: acctfile = %s", yylval.str)));
379 break;
380
381 case ALERT:
382 if (yylval.num < MINALERT)
383 {
384 yylval.num = MINALERT;
385 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: alert < %d, min = %d", current_cfe->name, MINALERT, yylval.num)));
386 }
387 else if (yylval.num > MAXALERT)
388 {
389 yylval.num = MAXALERT;
390 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: alert > %d, min = %d", current_cfe->name, MAXALERT, yylval.num)));
391 }
392
393 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: alert = %d", current_cfe->name, yylval.num)));
394 current_cfe->alert = yylval.num;
395 break;
396
397 case ALIASING:
398 DBGL(DL_RCCF, (logit(LL_DBG, "system: aliasing = %d", yylval.booln)));
399 aliasing = yylval.booln;
400 break;
401
402 case ALIASFNAME:
403 strlcpy(aliasfile, yylval.str, sizeof(aliasfile));
404 DBGL(DL_RCCF, (logit(LL_DBG, "system: aliasfile = %s", yylval.str)));
405 break;
406
407 case ANSWERPROG:
408 if ((current_cfe->answerprog = strdup(yylval.str)) == NULL)
409 {
410 logit(LL_ERR, "entry %s: answerstring, malloc failed!", current_cfe->name);
411 do_exit(1);
412 }
413 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: answerprog = %s", current_cfe->name, yylval.str)));
414 break;
415
416 case B1PROTOCOL:
417 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: b1protocol = %s", current_cfe->name, yylval.str)));
418 if (!(strcmp(yylval.str, "raw")))
419 current_cfe->b1protocol = BPROT_NONE;
420 else if (!(strcmp(yylval.str, "hdlc")))
421 current_cfe->b1protocol = BPROT_RHDLC;
422 else
423 {
424 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"b1protocol\" at line %d!", lineno);
425 config_error_flag++;
426 }
427 break;
428
429 case BEEPCONNECT:
430 do_bell = yylval.booln;
431 DBGL(DL_RCCF, (logit(LL_DBG, "system: beepconnect = %d", yylval.booln)));
432 break;
433
434 case BUDGETCALLBACKPERIOD:
435 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-callbackperiod = %d", current_cfe->name, yylval.num)));
436 current_cfe->budget_callbackperiod = yylval.num;
437 break;
438
439 case BUDGETCALLBACKNCALLS:
440 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-callbackncalls = %d", current_cfe->name, yylval.num)));
441 current_cfe->budget_callbackncalls = yylval.num;
442 break;
443
444 case BUDGETCALLOUTPERIOD:
445 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-calloutperiod = %d", current_cfe->name, yylval.num)));
446 current_cfe->budget_calloutperiod = yylval.num;
447 break;
448
449 case BUDGETCALLOUTNCALLS:
450 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-calloutncalls = %d", current_cfe->name, yylval.num)));
451 current_cfe->budget_calloutncalls = yylval.num;
452 break;
453
454 case AUTOUPDOWN:
455 current_cfe->autoupdown = yylval.booln;
456 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: autoupdown = %d", current_cfe->name, yylval.booln)));
457 break;
458
459 case BUDGETCALLBACKSFILEROTATE:
460 current_cfe->budget_callbacksfile_rotate = yylval.booln;
461 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-callbacksfile-rotate = %d", current_cfe->name, yylval.booln)));
462 break;
463
464 case BUDGETCALLBACKSFILE:
465 {
466 FILE *fp;
467 int s, l;
468 int n;
469 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-callbacksfile = %s", yylval.str)));
470 fp = fopen(yylval.str, "r");
471 if (fp != NULL)
472 {
473 if ((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
474 {
475 DBGL(DL_RCCF, (logit(LL_DBG, "entry %d: initializing budget-callbacksfile %s", current_cfe->name, yylval.str)));
476 fclose(fp);
477 fp = fopen(yylval.str, "w");
478 if (fp != NULL)
479 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
480 fclose(fp);
481 }
482 }
483 else
484 {
485 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: creating budget-callbacksfile %s", current_cfe->name, yylval.str)));
486 fp = fopen(yylval.str, "w");
487 if (fp != NULL)
488 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
489 fclose(fp);
490 }
491
492 fp = fopen(yylval.str, "r");
493 if (fp != NULL)
494 {
495 if ((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
496 {
497 if ((current_cfe->budget_callbacks_file = strdup(yylval.str)) == NULL)
498 {
499 logit(LL_ERR, "entry %s: budget-callbacksfile, malloc failed!", current_cfe->name);
500 do_exit(1);
501 }
502 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: using callbacksfile %s", current_cfe->name, yylval.str)));
503 }
504 fclose(fp);
505 }
506 }
507 break;
508
509 case BUDGETCALLOUTSFILEROTATE:
510 current_cfe->budget_calloutsfile_rotate = yylval.booln;
511 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-calloutsfile-rotate = %d", current_cfe->name, yylval.booln)));
512 break;
513
514 case BUDGETCALLOUTSFILE:
515 {
516 FILE *fp;
517 int s, l;
518 int n;
519 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: budget-calloutsfile = %s", current_cfe->name, yylval.str)));
520 fp = fopen(yylval.str, "r");
521 if (fp != NULL)
522 {
523 if ((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
524 {
525 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: initializing budget-calloutsfile %s", current_cfe->name, yylval.str)));
526 fclose(fp);
527 fp = fopen(yylval.str, "w");
528 if (fp != NULL)
529 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
530 fclose(fp);
531 }
532 }
533 else
534 {
535 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: creating budget-calloutsfile %s", current_cfe->name, yylval.str)));
536 fp = fopen(yylval.str, "w");
537 if (fp != NULL)
538 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
539 fclose(fp);
540 }
541
542 fp = fopen(yylval.str, "r");
543 if (fp != NULL)
544 {
545 if ((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
546 {
547 if ((current_cfe->budget_callouts_file = strdup(yylval.str)) == NULL)
548 {
549 logit(LL_ERR, "entry %s: budget-calloutsfile, malloc failed!", current_cfe->name);
550 do_exit(1);
551 }
552 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: using calloutsfile %s", current_cfe->name, yylval.str)));
553 }
554 fclose(fp);
555 }
556 }
557 break;
558
559 case CALLBACKWAIT:
560 if (yylval.num < CALLBACKWAIT_MIN)
561 {
562 yylval.num = CALLBACKWAIT_MIN;
563 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: callbackwait < %d, min = %d", current_cfe->name, CALLBACKWAIT_MIN, yylval.num)));
564 }
565
566 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: callbackwait = %d", current_cfe->name, yylval.num)));
567 current_cfe->callbackwait = yylval.num;
568 break;
569
570 case CALLEDBACKWAIT:
571 if (yylval.num < CALLEDBACKWAIT_MIN)
572 {
573 yylval.num = CALLEDBACKWAIT_MIN;
574 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: calledbackwait < %d, min = %d", current_cfe->name, CALLEDBACKWAIT_MIN, yylval.num)));
575 }
576
577 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: calledbackwait = %d", current_cfe->name, yylval.num)));
578 current_cfe->calledbackwait = yylval.num;
579 break;
580
581 case CONNECTPROG:
582 if ((current_cfe->connectprog = strdup(yylval.str)) == NULL)
583 {
584 logit(LL_ERR, "entry %s: connectprog, malloc failed!", current_cfe->name);
585 do_exit(1);
586 }
587 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: connectprog = %s", current_cfe->name, yylval.str)));
588 break;
589
590 case DIALOUTTYPE:
591 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: dialouttype = %s", current_cfe->name, yylval.str)));
592 if (!(strcmp(yylval.str, "normal")))
593 current_cfe->dialouttype = DIALOUT_NORMAL;
594 else if (!(strcmp(yylval.str, "calledback")))
595 current_cfe->dialouttype = DIALOUT_CALLEDBACK;
596 else
597 {
598 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialout-type\" at line %d!", lineno);
599 config_error_flag++;
600 }
601 break;
602
603 case DIALRETRIES:
604 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: dialretries = %d", current_cfe->name, yylval.num)));
605 current_cfe->dialretries = yylval.num;
606 break;
607
608 case DIALRANDINCR:
609 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: dialrandincr = %d", current_cfe->name, yylval.booln)));
610 current_cfe->dialrandincr = yylval.booln;
611 break;
612
613 case DIRECTION:
614 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: direction = %s", current_cfe->name, yylval.str)));
615
616 if (!(strcmp(yylval.str, "inout")))
617 current_cfe->inout = DIR_INOUT;
618 else if (!(strcmp(yylval.str, "in")))
619 current_cfe->inout = DIR_INONLY;
620 else if (!(strcmp(yylval.str, "out")))
621 current_cfe->inout = DIR_OUTONLY;
622 else
623 {
624 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"direction\" at line %d!", lineno);
625 config_error_flag++;
626 }
627 break;
628
629 case DISCONNECTPROG:
630 if ((current_cfe->disconnectprog = strdup(yylval.str)) == NULL)
631 {
632 logit(LL_ERR, "entry %s: disconnectprog, malloc failed!", current_cfe->name);
633 do_exit(1);
634 }
635 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: disconnectprog = %s", current_cfe->name, yylval.str)));
636 break;
637
638 case DOWNTRIES:
639 if (yylval.num > DOWN_TRIES_MAX)
640 yylval.num = DOWN_TRIES_MAX;
641 else if (yylval.num < DOWN_TRIES_MIN)
642 yylval.num = DOWN_TRIES_MIN;
643
644 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: downtries = %d", current_cfe->name, yylval.num)));
645 current_cfe->downtries = yylval.num;
646 break;
647
648 case DOWNTIME:
649 if (yylval.num > DOWN_TIME_MAX)
650 yylval.num = DOWN_TIME_MAX;
651 else if (yylval.num < DOWN_TIME_MIN)
652 yylval.num = DOWN_TIME_MIN;
653
654 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: downtime = %d", current_cfe->name, yylval.num)));
655 current_cfe->downtime = yylval.num;
656 break;
657
658 case EARLYHANGUP:
659 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: earlyhangup = %d", current_cfe->name, yylval.num)));
660 current_cfe->earlyhangup = yylval.num;
661 break;
662
663 case EXTCALLATTR:
664 DBGL(DL_RCCF, (logit(LL_DBG, "system: extcallattr = %d", yylval.booln)));
665 extcallattr = yylval.booln;
666 break;
667
668 case FIRMWARE:
669 DBGL(DL_RCCF, (logit(LL_DBG, "controller %d: firmware = %s", cur_ctrl->isdnif, yylval.str)));
670 cur_ctrl->firmware = strdup(yylval.str);
671 break;
672
673 case HOLIDAYFILE:
674 strlcpy(holidayfile, yylval.str, sizeof(holidayfile));
675 DBGL(DL_RCCF, (logit(LL_DBG, "system: holidayfile = %s", yylval.str)));
676 break;
677
678 case IDLE_ALG_OUT:
679 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: idle-algorithm-outgoing = %s", current_cfe->name, yylval.str)));
680
681 if (!(strcmp(yylval.str, "fix-unit-size")))
682 {
683 current_cfe->shorthold_algorithm = SHA_FIXU;
684 }
685 else if (!(strcmp(yylval.str, "var-unit-size")))
686 {
687 current_cfe->shorthold_algorithm = SHA_VARU;
688 }
689 else
690 {
691 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"idle-algorithm-outgoing\" at line %d!", lineno);
692 config_error_flag++;
693 }
694 break;
695
696 case IDLETIME_IN:
697 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: idle_time_in = %d", current_cfe->name, yylval.num)));
698 current_cfe->idle_time_in = yylval.num;
699 break;
700
701 case IDLETIME_OUT:
702 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: idle_time_out = %d", current_cfe->name, yylval.num)));
703 current_cfe->idle_time_out = yylval.num;
704 break;
705
706 case ISDNCONTROLLER:
707 current_cfe->isdncontroller = yylval.num;
708 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: isdncontroller = %d", current_cfe->name, yylval.num)));
709 break;
710
711 case ISDNCHANNEL:
712 if (yylval.num == 0 || yylval.num == -1) {
713 current_cfe->isdnchannel = CHAN_ANY;
714 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: isdnchannel = any", current_cfe->name)));
715 } else if (yylval.num > MAX_BCHAN) {
716 logit(LL_DBG, "entry %s: isdnchannel value out of range", current_cfe->name);
717 config_error_flag++;
718 } else {
719 current_cfe->isdnchannel = yylval.num - 1;
720 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: isdnchannel = %d", current_cfe->name, yylval.num)));
721 }
722 break;
723
724 case ISDNTIME:
725 DBGL(DL_RCCF, (logit(LL_DBG, "system: isdntime = %d", yylval.booln)));
726 isdntime = yylval.booln;
727 break;
728
729 case ISDNTXDELIN:
730 current_cfe->isdntxdelin = yylval.num;
731 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: isdntxdel-incoming = %d", current_cfe->name, yylval.num)));
732 break;
733
734 case ISDNTXDELOUT:
735 current_cfe->isdntxdelout = yylval.num;
736 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: isdntxdel-outgoing = %d", current_cfe->name, yylval.num)));
737 break;
738
739 case LOCAL_PHONE_DIALOUT:
740 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: local_phone_dialout = %s", current_cfe->name, yylval.str)));
741 strlcpy(current_cfe->local_phone_dialout, yylval.str,
742 sizeof(current_cfe->local_phone_dialout));
743 break;
744
745 case LOCAL_PHONE_INCOMING:
746 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: local_phone_incoming = %s", current_cfe->name, yylval.str)));
747 strlcpy(current_cfe->local_phone_incoming, yylval.str,
748 sizeof(current_cfe->local_phone_incoming));
749 break;
750
751 case MAILER:
752 strlcpy(mailer, yylval.str, sizeof(mailer));
753 DBGL(DL_RCCF, (logit(LL_DBG, "system: mailer = %s", yylval.str)));
754 break;
755
756 case MAILTO:
757 strlcpy(mailto, yylval.str, sizeof(mailto));
758 DBGL(DL_RCCF, (logit(LL_DBG, "system: mailto = %s", yylval.str)));
759 break;
760
761 case MONITORPORT:
762 monitorport = yylval.num;
763 DBGL(DL_RCCF, (logit(LL_DBG, "system: monitorport = %d", yylval.num)));
764 break;
765
766 case MONITORSW:
767 if (yylval.booln && inhibit_monitor)
768 {
769 do_monitor = 0;
770 DBGL(DL_RCCF, (logit(LL_DBG, "system: monitor-enable overriden by command line flag")));
771 }
772 else
773 {
774 do_monitor = yylval.booln;
775 DBGL(DL_RCCF, (logit(LL_DBG, "system: monitor-enable = %d", yylval.booln)));
776 }
777 break;
778
779 case NAME:
780 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: name = %s", current_cfe->name, yylval.str)));
781 strlcpy(current_cfe->name, yylval.str,
782 sizeof(current_cfe->name));
783 break;
784
785 case PPP_AUTH_RECHALLENGE:
786 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-auth-rechallenge = %d", current_cfe->name, yylval.booln)));
787 if (yylval.booln)
788 current_cfe->ppp_auth_flags |= AUTH_RECHALLENGE;
789 else
790 current_cfe->ppp_auth_flags &= ~AUTH_RECHALLENGE;
791 break;
792
793 case PPP_AUTH_PARANOID:
794 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-auth-paranoid = %d", current_cfe->name, yylval.booln)));
795 if (yylval.booln)
796 current_cfe->ppp_auth_flags |= AUTH_REQUIRED;
797 else
798 current_cfe->ppp_auth_flags &= ~AUTH_REQUIRED;
799 break;
800
801 case PPP_EXPECT_AUTH:
802 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-expect-auth = %s", current_cfe->name, yylval.str)));
803 if (!(strcmp(yylval.str, "none")))
804 current_cfe->ppp_expect_auth = AUTH_NONE;
805 else if (!(strcmp(yylval.str, "pap")))
806 current_cfe->ppp_expect_auth = AUTH_PAP;
807 else if (!(strcmp(yylval.str, "chap")))
808 current_cfe->ppp_expect_auth = AUTH_CHAP;
809 else
810 {
811 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-expect-auth\" at line %d!", lineno);
812 config_error_flag++;
813 break;
814 }
815 break;
816
817 case PPP_EXPECT_NAME:
818 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-expect-name = %s", current_cfe->name, yylval.str)));
819 if (current_cfe->ppp_expect_name)
820 free(current_cfe->ppp_expect_name);
821 current_cfe->ppp_expect_name = strdup(yylval.str);
822 break;
823
824 case PPP_EXPECT_PASSWORD:
825 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-expect-password = %s", current_cfe->name, yylval.str)));
826 if (current_cfe->ppp_expect_password)
827 free(current_cfe->ppp_expect_password);
828 current_cfe->ppp_expect_password = strdup(yylval.str);
829 break;
830
831 case PPP_SEND_AUTH:
832 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-send-auth = %s", current_cfe->name, yylval.str)));
833 if (!(strcmp(yylval.str, "none")))
834 current_cfe->ppp_send_auth = AUTH_NONE;
835 else if (!(strcmp(yylval.str, "pap")))
836 current_cfe->ppp_send_auth = AUTH_PAP;
837 else if (!(strcmp(yylval.str, "chap")))
838 current_cfe->ppp_send_auth = AUTH_CHAP;
839 else
840 {
841 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-send-auth\" at line %d!", lineno);
842 config_error_flag++;
843 break;
844 }
845 break;
846
847 case PPP_SEND_NAME:
848 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-send-name = %s", current_cfe->name, yylval.str)));
849 if (current_cfe->ppp_send_name)
850 free(current_cfe->ppp_send_name);
851 current_cfe->ppp_send_name = strdup(yylval.str);
852 break;
853
854 case PPP_SEND_PASSWORD:
855 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ppp-send-password = %s", current_cfe->name, yylval.str)));
856 if (current_cfe->ppp_send_password)
857 free(current_cfe->ppp_send_password);
858 current_cfe->ppp_send_password = strdup(yylval.str);
859 break;
860
861 case PROTOCOL:
862 DBGL(DL_RCCF, (logit(LL_DBG, "controller %d: protocol = %s", cur_ctrl->isdnif, yylval.str)));
863 if (!(strcmp(yylval.str, "dss1")))
864 cur_ctrl->protocol = PROTOCOL_DSS1;
865 else if (!(strcmp(yylval.str, "d64s")))
866 cur_ctrl->protocol = PROTOCOL_D64S;
867 else
868 {
869 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"protocol\" at line %d!", lineno);
870 config_error_flag++;
871 }
872 break;
873
874 case REACTION:
875 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: dialin_reaction = %s", current_cfe->name, yylval.str)));
876 if (!(strcmp(yylval.str, "accept")))
877 current_cfe->dialin_reaction = REACT_ACCEPT;
878 else if (!(strcmp(yylval.str, "reject")))
879 current_cfe->dialin_reaction = REACT_REJECT;
880 else if (!(strcmp(yylval.str, "ignore")))
881 current_cfe->dialin_reaction = REACT_IGNORE;
882 else if (!(strcmp(yylval.str, "answer")))
883 current_cfe->dialin_reaction = REACT_ANSWER;
884 else if (!(strcmp(yylval.str, "callback")))
885 current_cfe->dialin_reaction = REACT_CALLBACK;
886 else
887 {
888 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialin_reaction\" at line %d!", lineno);
889 config_error_flag++;
890 }
891 break;
892
893 case REMOTE_PHONE_DIALOUT:
894 if (current_cfe->remote_numbers_count >= MAXRNUMBERS)
895 {
896 logit(LL_ERR, "ERROR parsing config file: too many remote numbers at line %d!", lineno);
897 config_error_flag++;
898 break;
899 }
900
901 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: remote_phone_dialout #%d = %s",
902 current_cfe->name, current_cfe->remote_numbers_count, yylval.str)));
903
904 strlcpy(current_cfe->remote_numbers[current_cfe->remote_numbers_count].number,
905 yylval.str,
906 sizeof(current_cfe->remote_numbers[current_cfe->remote_numbers_count].number));
907 current_cfe->remote_numbers[current_cfe->remote_numbers_count].flag = 0;
908
909 current_cfe->remote_numbers_count++;
910
911 break;
912
913 case REMOTE_NUMBERS_HANDLING:
914 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: remdial_handling = %s", current_cfe->name, yylval.str)));
915 if (!(strcmp(yylval.str, "next")))
916 current_cfe->remote_numbers_handling = RNH_NEXT;
917 else if (!(strcmp(yylval.str, "last")))
918 current_cfe->remote_numbers_handling = RNH_LAST;
919 else if (!(strcmp(yylval.str, "first")))
920 current_cfe->remote_numbers_handling = RNH_FIRST;
921 else
922 {
923 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"remdial_handling\" at line %d!", lineno);
924 config_error_flag++;
925 }
926 break;
927
928 case REMOTE_PHONE_INCOMING:
929 {
930 int n;
931 n = current_cfe->incoming_numbers_count;
932 if (n >= MAX_INCOMING)
933 {
934 logit(LL_ERR, "ERROR parsing config file: too many \"remote_phone_incoming\" entries at line %d!", lineno);
935 config_error_flag++;
936 break;
937 }
938 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: remote_phone_incoming #%d = %s", current_cfe->name, n, yylval.str)));
939 strlcpy(current_cfe->remote_phone_incoming[n].number,
940 yylval.str,
941 sizeof(current_cfe->remote_phone_incoming[n].number));
942 current_cfe->incoming_numbers_count++;
943 }
944 break;
945
946 case RATESFILE:
947 strlcpy(ratesfile, yylval.str, sizeof(ratesfile));
948 DBGL(DL_RCCF, (logit(LL_DBG, "system: ratesfile = %s", yylval.str)));
949 break;
950
951 case RATETYPE:
952 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: ratetype = %d", current_cfe->name, yylval.num)));
953 current_cfe->ratetype = yylval.num;
954 break;
955
956 case RECOVERYTIME:
957 if (yylval.num < RECOVERYTIME_MIN)
958 {
959 yylval.num = RECOVERYTIME_MIN;
960 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: recoverytime < %d, min = %d", current_cfe->name, RECOVERYTIME_MIN, yylval.num)));
961 }
962
963 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: recoverytime = %d", current_cfe->name, yylval.num)));
964 current_cfe->recoverytime = yylval.num;
965 break;
966
967 case REGEXPR:
968 if (nregexpr >= MAX_RE)
969 {
970 logit(LL_ERR, "system: regexpr #%d >= MAX_RE", nregexpr);
971 config_error_flag++;
972 break;
973 }
974
975 if ((i = regcomp(&(rarr[nregexpr].re), yylval.str, REG_EXTENDED|REG_NOSUB)) != 0)
976 {
977 char buf[256];
978 regerror(i, &(rarr[nregexpr].re), buf, sizeof(buf));
979 logit(LL_ERR, "system: regcomp error for %s: [%s]", yylval.str, buf);
980 config_error_flag++;
981 break;
982 }
983 else
984 {
985 if ((rarr[nregexpr].re_expr = strdup(yylval.str)) == NULL)
986 {
987 logit(LL_ERR, "system: regexpr malloc error error for %s", yylval.str);
988 config_error_flag++;
989 break;
990 }
991
992 DBGL(DL_RCCF, (logit(LL_DBG, "system: regexpr %s stored into slot %d", yylval.str, nregexpr)));
993
994 if (rarr[nregexpr].re_prog != NULL)
995 rarr[nregexpr].re_flg = 1;
996
997 nregexpr++;
998
999 }
1000 break;
1001
1002 case REGPROG:
1003 if (nregprog >= MAX_RE)
1004 {
1005 logit(LL_ERR, "system: regprog #%d >= MAX_RE", nregprog);
1006 config_error_flag++;
1007 break;
1008 }
1009 if ((rarr[nregprog].re_prog = strdup(yylval.str)) == NULL)
1010 {
1011 logit(LL_ERR, "system: regprog malloc error error for %s", yylval.str);
1012 config_error_flag++;
1013 break;
1014 }
1015
1016 DBGL(DL_RCCF, (logit(LL_DBG, "system: regprog %s stored into slot %d", yylval.str, nregprog)));
1017
1018 if (rarr[nregprog].re_expr != NULL)
1019 rarr[nregprog].re_flg = 1;
1020
1021 nregprog++;
1022 break;
1023
1024 case ROTATESUFFIX:
1025 strlcpy(rotatesuffix, yylval.str, sizeof(rotatesuffix));
1026 DBGL(DL_RCCF, (logit(LL_DBG, "system: rotatesuffix = %s", yylval.str)));
1027 break;
1028
1029 case RTPRIO:
1030 #ifdef USE_RTPRIO
1031 rt_prio = yylval.num;
1032 if (rt_prio < RTP_PRIO_MIN || rt_prio > RTP_PRIO_MAX)
1033 {
1034 config_error_flag++;
1035 logit(LL_ERR, "system: error, rtprio (%d) out of range!", yylval.num);
1036 }
1037 else
1038 {
1039 DBGL(DL_RCCF, (logit(LL_DBG, "system: rtprio = %d", yylval.num)));
1040 }
1041 #else
1042 rt_prio = RTPRIO_NOTUSED;
1043 #endif
1044 break;
1045
1046 case TINAINITPROG:
1047 strlcpy(tinainitprog, yylval.str, sizeof(tinainitprog));
1048 DBGL(DL_RCCF, (logit(LL_DBG, "system: tinainitprog = %s", yylval.str)));
1049 break;
1050
1051 case UNITLENGTH:
1052 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: unitlength = %d", current_cfe->name, yylval.num)));
1053 current_cfe->unitlength = yylval.num;
1054 break;
1055
1056 case UNITLENGTHSRC:
1057 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: unitlengthsrc = %s", current_cfe->name, yylval.str)));
1058 if (!(strcmp(yylval.str, "none")))
1059 current_cfe->unitlengthsrc = ULSRC_NONE;
1060 else if (!(strcmp(yylval.str, "cmdl")))
1061 current_cfe->unitlengthsrc = ULSRC_CMDL;
1062 else if (!(strcmp(yylval.str, "conf")))
1063 current_cfe->unitlengthsrc = ULSRC_CONF;
1064 else if (!(strcmp(yylval.str, "rate")))
1065 current_cfe->unitlengthsrc = ULSRC_RATE;
1066 else if (!(strcmp(yylval.str, "aocd")))
1067 current_cfe->unitlengthsrc = ULSRC_DYN;
1068 else
1069 {
1070 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"unitlengthsrc\" at line %d!", lineno);
1071 config_error_flag++;
1072 }
1073 break;
1074
1075 case USRDEVICENAME:
1076 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: usrdevicename = %s", current_cfe->name, yylval.str)));
1077 strncpy(current_cfe->usrdevicename, yylval.str, sizeof(current_cfe->usrdevicename));
1078 current_cfe->usrdevice = lookup_l4_driver(yylval.str);
1079 if (current_cfe->usrdevice < 0)
1080 {
1081 logit(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"usrdevicename\" at line %d!", lineno);
1082 config_error_flag++;
1083 }
1084 break;
1085
1086 case USRDEVICEUNIT:
1087 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: usrdeviceunit = %d", current_cfe->name, yylval.num)));
1088 current_cfe->usrdeviceunit = yylval.num;
1089 break;
1090
1091 case USEACCTFILE:
1092 useacctfile = yylval.booln;
1093 DBGL(DL_RCCF, (logit(LL_DBG, "system: useacctfile = %d", yylval.booln)));
1094 break;
1095
1096 case USEDOWN:
1097 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: usedown = %d", current_cfe->name, yylval.booln)));
1098 current_cfe->usedown = yylval.booln;
1099 break;
1100
1101 case VALID:
1102 DBGL(DL_RCCF, (logit(LL_DBG, "entry %s: valid = %s", current_cfe->name, yylval.str)));
1103 parse_valid(yylval.str);
1104 break;
1105
1106 default:
1107 logit(LL_ERR, "ERROR parsing config file: unknown keyword at line %d!", lineno);
1108 config_error_flag++;
1109 break;
1110 }
1111 }
1112
1113 /*---------------------------------------------------------------------------*
1114 * parse a date/time range
1115 *---------------------------------------------------------------------------*/
1116 static void
parse_valid(char * dt)1117 parse_valid(char *dt)
1118 {
1119 /* a valid string consists of some days of week separated by
1120 * commas, where 0=sunday, 1=monday .. 6=saturday and a special
1121 * value of 7 which is a holiday from the holiday file.
1122 * after the days comes an optional (!) time range in the form
1123 * aa:bb-cc:dd, this format is fixed to be parsable by sscanf.
1124 * Valid specifications looks like this:
1125 * 1,2,3,4,5,09:00-18:00 Monday-Friday 9-18h
1126 * 1,2,3,4,5,18:00-09:00 Monday-Friday 18-9h
1127 * 6 Saturday (whole day)
1128 * 0,7 Sunday and Holidays
1129 */
1130
1131 int day = 0;
1132 int fromhr = 0;
1133 int frommin = 0;
1134 int tohr = 0;
1135 int tomin = 0;
1136 int ret;
1137
1138 for (;;)
1139 {
1140 if ( ( ((*dt >= '0') && (*dt <= '9')) && (*(dt+1) == ':') ) ||
1141 ( ((*dt >= '0') && (*dt <= '2')) && ((*(dt+1) >= '0') && (*(dt+1) <= '9')) && (*(dt+2) == ':') ) )
1142 {
1143 /* dt points to time spec */
1144 ret = sscanf(dt, "%d:%d-%d:%d", &fromhr, &frommin, &tohr, &tomin);
1145 if (ret !=4)
1146 {
1147 logit(LL_ERR, "ERROR parsing config file: timespec [%s] error at line %d!", *dt, lineno);
1148 config_error_flag++;
1149 return;
1150 }
1151
1152 if (fromhr < 0 || fromhr > 24 || tohr < 0 || tohr > 24 ||
1153 frommin < 0 || frommin > 59 || tomin < 0 || tomin > 59)
1154 {
1155 logit(LL_ERR, "ERROR parsing config file: invalid time [%s] at line %d!", *dt, lineno);
1156 config_error_flag++;
1157 return;
1158 }
1159 break;
1160 }
1161 else if ((*dt >= '0') && (*dt <= '7'))
1162 {
1163 /* dt points to day spec */
1164 day |= 1 << (*dt - '0');
1165 dt++;
1166 continue;
1167 }
1168 else if (*dt == ',')
1169 {
1170 /* dt points to delimiter */
1171 dt++;
1172 continue;
1173 }
1174 else if (*dt == '\0')
1175 {
1176 /* dt points to end of string */
1177 break;
1178 }
1179 else
1180 {
1181 /* dt points to illegal character */
1182 logit(LL_ERR, "ERROR parsing config file: illegal character [%c=0x%x] in date/time spec at line %d!", *dt, *dt, lineno);
1183 config_error_flag++;
1184 return;
1185 }
1186 }
1187 current_cfe->day = day;
1188 current_cfe->fromhr = fromhr;
1189 current_cfe->frommin = frommin;
1190 current_cfe->tohr = tohr;
1191 current_cfe->tomin = tomin;
1192 }
1193
1194 void
flush_config()1195 flush_config()
1196 {
1197 if (current_cfe != NULL) {
1198 add_cfg_entry(current_cfe);
1199 }
1200 }
1201
1202 /*---------------------------------------------------------------------------*
1203 * configuration validation and consistency check
1204 *---------------------------------------------------------------------------*/
1205 static void
check_config(void)1206 check_config(void)
1207 {
1208 struct cfg_entry *cep = NULL;
1209 int i;
1210 int error = 0;
1211
1212 /* regular expression table */
1213
1214 for (i=0; i < MAX_RE; i++)
1215 {
1216 if ((rarr[i].re_expr != NULL) && (rarr[i].re_prog == NULL))
1217 {
1218 logit(LL_ERR, "check_config: regular expression %d without program!", i);
1219 error++;
1220 }
1221 if ((rarr[i].re_prog != NULL) && (rarr[i].re_expr == NULL))
1222 {
1223 logit(LL_ERR, "check_config: regular expression program %d without expression!", i);
1224 error++;
1225 }
1226 }
1227
1228 /* entry sections */
1229
1230 for (cep = get_first_cfg_entry(); cep; cep = NEXT_CFE(cep)) {
1231
1232 /* does this entry have a bchannel driver configured? */
1233 if (cep->usrdevice < 0) {
1234 logit(LL_ERR, "check_config: usrdevicename not set in entry \"%s\"!",
1235 cep->name);
1236 error++;
1237 }
1238 if (cep->usrdeviceunit < 0) {
1239 logit(LL_ERR, "check_config: usrdeviceunit not set in entry \"%s\"!",
1240 cep->name);
1241 error++;
1242 }
1243
1244 /* numbers used for dialout */
1245
1246 if ((cep->inout != DIR_INONLY) && (cep->dialin_reaction != REACT_ANSWER))
1247 {
1248 if (cep->remote_numbers_count == 0)
1249 {
1250 logit(LL_ERR, "check_config: remote-phone-dialout not set in entry \"%s\"!",
1251 cep->name);
1252 error++;
1253 }
1254 }
1255
1256 /* numbers used for incoming calls */
1257
1258 if (cep->inout != DIR_OUTONLY)
1259 {
1260 if (strlen(cep->local_phone_incoming) == 0)
1261 {
1262 logit(LL_ERR, "check_config: local-phone-incoming not set in entry \"%s\"!",
1263 cep->name);
1264 error++;
1265 }
1266 if (cep->incoming_numbers_count == 0)
1267 {
1268 logit(LL_ERR, "check_config: remote-phone-incoming not set in entry \"%s\"!",
1269 cep->name);
1270 error++;
1271 }
1272 }
1273
1274 if ((cep->dialin_reaction == REACT_ANSWER) && (cep->b1protocol != BPROT_NONE))
1275 {
1276 logit(LL_ERR, "check_config: b1protocol not raw for telephony in entry \"%s\"!",
1277 cep->name);
1278 error++;
1279 }
1280
1281 if ((cep->ppp_send_auth == AUTH_PAP) || (cep->ppp_send_auth == AUTH_CHAP))
1282 {
1283 if (cep->ppp_send_name == NULL)
1284 {
1285 logit(LL_ERR, "check_config: no remote authentification name in entry \"%s\"!",
1286 cep->name);
1287 error++;
1288 }
1289 if (cep->ppp_send_password == NULL)
1290 {
1291 logit(LL_ERR, "check_config: no remote authentification password in entry \"%s\"!",
1292 cep->name);
1293 error++;
1294 }
1295 }
1296 if ((cep->ppp_expect_auth == AUTH_PAP) || (cep->ppp_expect_auth == AUTH_CHAP))
1297 {
1298 if (cep->ppp_expect_name == NULL)
1299 {
1300 logit(LL_ERR, "check_config: no local authentification name in entry \"%s\"!",
1301 cep->name);
1302 error++;
1303 }
1304 if (cep->ppp_expect_password == NULL)
1305 {
1306 logit(LL_ERR, "check_config: no local authentification secret in entry \"%s\"!",
1307 cep->name);
1308 error++;
1309 }
1310 }
1311
1312 #ifdef SPPPGETAUTHCFG
1313 if (cep->ppp_expect_auth != AUTH_UNDEF
1314 || cep->ppp_send_auth != AUTH_UNDEF)
1315 set_isppp_auth(cep);
1316 #endif
1317
1318 /*
1319 * Only if AUTOUPDOWN_YES is the only bit set, otherwise
1320 * we already have handled this interface.
1321 */
1322 if (cep->autoupdown == AUTOUPDOWN_YES)
1323 set_autoupdown(cep);
1324 }
1325 if (error) {
1326 logit(LL_ERR, "check_config: %d error(s) in configuration file, exiting!",
1327 error);
1328 do_exit(1);
1329 }
1330 }
1331
1332 /*---------------------------------------------------------------------------*
1333 * print the configuration
1334 *---------------------------------------------------------------------------*/
1335 static void
print_config(void)1336 print_config(void)
1337 {
1338 #define PFILE stdout
1339
1340 #ifdef I4B_EXTERNAL_MONITOR
1341 extern struct monitor_rights * monitor_next_rights(const struct monitor_rights *r);
1342 struct monitor_rights *m_rights;
1343 #endif
1344 struct cfg_entry *cep = NULL;
1345 int i, j;
1346 time_t clock;
1347 char mytime[64];
1348
1349 time(&clock);
1350 strlcpy(mytime, ctime(&clock), sizeof(mytime));
1351 mytime[strlen(mytime)-1] = '\0';
1352
1353 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1354 fprintf(PFILE, "# system section (generated %s)\n", mytime);
1355 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1356 fprintf(PFILE, "system\n");
1357 fprintf(PFILE, "useacctfile = %s\n", useacctfile ? "on\t\t\t\t# update accounting information file" : "off\t\t\t\t# don't update accounting information file");
1358 fprintf(PFILE, "acctall = %s\n", acct_all ? "on\t\t\t\t# put all events into accounting file" : "off\t\t\t\t# put only charged events into accounting file");
1359 fprintf(PFILE, "acctfile = %s\t\t# accounting information file\n", acctfile);
1360 fprintf(PFILE, "ratesfile = %s\t\t# charging rates database file\n", ratesfile);
1361
1362 #ifdef USE_RTPRIO
1363 if (rt_prio == RTPRIO_NOTUSED)
1364 fprintf(PFILE, "# rtprio is unused\n");
1365 else
1366 fprintf(PFILE, "rtprio = %d\t\t\t\t# isdnd runs at realtime priority\n", rt_prio);
1367 #endif
1368
1369 /* regular expression table */
1370
1371 for (i=0; i < MAX_RE; i++)
1372 {
1373 if (rarr[i].re_expr != NULL)
1374 {
1375 fprintf(PFILE, "regexpr = \"%s\"\t\t# scan logfile for this expression\n", rarr[i].re_expr);
1376 }
1377 if (rarr[i].re_prog != NULL)
1378 {
1379 fprintf(PFILE, "regprog = %s\t\t# program to run when expression is matched\n", rarr[i].re_prog);
1380 }
1381 }
1382
1383 #ifdef I4B_EXTERNAL_MONITOR
1384
1385 fprintf(PFILE, "monitor-allowed = %s\n", do_monitor ? "on\t\t\t\t# remote isdnd monitoring allowed" : "off\t\t\t\t# remote isdnd monitoring disabled");
1386 fprintf(PFILE, "monitor-port = %d\t\t\t\t# TCP/IP port number used for remote monitoring\n", monitorport);
1387
1388 m_rights = monitor_next_rights(NULL);
1389 if (m_rights != NULL)
1390 {
1391 char *s = "error\n";
1392 char b[512];
1393
1394 for ( ; m_rights != NULL; m_rights = monitor_next_rights(m_rights))
1395 {
1396 if (m_rights->local)
1397 {
1398 fprintf(PFILE, "monitor = \"%s\"\t\t# local socket name for monitoring\n", m_rights->name);
1399 }
1400 else
1401 {
1402 struct in_addr ia;
1403 ia.s_addr = ntohl(m_rights->net);
1404
1405 switch (m_rights->mask)
1406 {
1407 case 0xffffffff:
1408 s = "32";
1409 break;
1410 case 0xfffffffe:
1411 s = "31";
1412 break;
1413 case 0xfffffffc:
1414 s = "30";
1415 break;
1416 case 0xfffffff8:
1417 s = "29";
1418 break;
1419 case 0xfffffff0:
1420 s = "28";
1421 break;
1422 case 0xffffffe0:
1423 s = "27";
1424 break;
1425 case 0xffffffc0:
1426 s = "26";
1427 break;
1428 case 0xffffff80:
1429 s = "25";
1430 break;
1431 case 0xffffff00:
1432 s = "24";
1433 break;
1434 case 0xfffffe00:
1435 s = "23";
1436 break;
1437 case 0xfffffc00:
1438 s = "22";
1439 break;
1440 case 0xfffff800:
1441 s = "21";
1442 break;
1443 case 0xfffff000:
1444 s = "20";
1445 break;
1446 case 0xffffe000:
1447 s = "19";
1448 break;
1449 case 0xffffc000:
1450 s = "18";
1451 break;
1452 case 0xffff8000:
1453 s = "17";
1454 break;
1455 case 0xffff0000:
1456 s = "16";
1457 break;
1458 case 0xfffe0000:
1459 s = "15";
1460 break;
1461 case 0xfffc0000:
1462 s = "14";
1463 break;
1464 case 0xfff80000:
1465 s = "13";
1466 break;
1467 case 0xfff00000:
1468 s = "12";
1469 break;
1470 case 0xffe00000:
1471 s = "11";
1472 break;
1473 case 0xffc00000:
1474 s = "10";
1475 break;
1476 case 0xff800000:
1477 s = "9";
1478 break;
1479 case 0xff000000:
1480 s = "8";
1481 break;
1482 case 0xfe000000:
1483 s = "7";
1484 break;
1485 case 0xfc000000:
1486 s = "6";
1487 break;
1488 case 0xf8000000:
1489 s = "5";
1490 break;
1491 case 0xf0000000:
1492 s = "4";
1493 break;
1494 case 0xe0000000:
1495 s = "3";
1496 break;
1497 case 0xc0000000:
1498 s = "2";
1499 break;
1500 case 0x80000000:
1501 s = "1";
1502 break;
1503 case 0x00000000:
1504 s = "0";
1505 break;
1506 }
1507 fprintf(PFILE, "monitor = \"%s/%s\"\t\t# host (net/mask) allowed to connect for monitoring\n", inet_ntoa(ia), s);
1508 }
1509 b[0] = '\0';
1510
1511 if ((m_rights->rights) & I4B_CA_COMMAND_FULL)
1512 strlcat(b, "fullcmd,", sizeof(b));
1513 if ((m_rights->rights) & I4B_CA_COMMAND_RESTRICTED)
1514 strlcat(b, "restrictedcmd,", sizeof(b));
1515 if ((m_rights->rights) & I4B_CA_EVNT_CHANSTATE)
1516 strlcat(b, "channelstate,", sizeof(b));
1517 if ((m_rights->rights) & I4B_CA_EVNT_CALLIN)
1518 strlcat(b, "callin,", sizeof(b));
1519 if ((m_rights->rights) & I4B_CA_EVNT_CALLOUT)
1520 strlcat(b, "callout,", sizeof(b));
1521 if ((m_rights->rights) & I4B_CA_EVNT_I4B)
1522 strlcat(b, "logevents,", sizeof(b));
1523
1524 if (strlen(b) > 0 && b[strlen(b)-1] == ',')
1525 b[strlen(b)-1] = '\0';
1526
1527 fprintf(PFILE, "monitor-access = %s\t\t# monitor access rights\n", b);
1528 }
1529 }
1530
1531 #endif
1532 /* entry sections */
1533
1534 for (cep = get_first_cfg_entry(); cep; cep = NEXT_CFE(cep)) {
1535 fprintf(PFILE, "\n");
1536 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1537 fprintf(PFILE, "# entry section %d\n", i);
1538 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1539 fprintf(PFILE, "entry\n");
1540
1541 fprintf(PFILE, "name = %s\t\t# name for this entry section\n", cep->name);
1542
1543 fprintf(PFILE, "isdncontroller = %d\t\t# ISDN card number used for this entry\n", cep->isdncontroller);
1544 fprintf(PFILE, "isdnchannel = ");
1545 switch (cep->isdnchannel)
1546 {
1547 case CHAN_ANY:
1548 fprintf(PFILE, "-1\t\t# any ISDN B-channel may be used\n");
1549 break;
1550 default:
1551 fprintf(PFILE, "1\t\t# only ISDN B-channel %d may be used\n", cep->isdnchannel);
1552 break;
1553 }
1554
1555 fprintf(PFILE, "usrdevicename = %s\t\t# name of userland ISDN B-channel device\n", cep->usrdevicename);
1556 fprintf(PFILE, "usrdeviceunit = %d\t\t# unit number of userland ISDN B-channel device\n", cep->usrdeviceunit);
1557
1558 fprintf(PFILE, "b1protocol = %s\n", cep->b1protocol ? "hdlc\t\t# B-channel layer 1 protocol is HDLC" : "raw\t\t# No B-channel layer 1 protocol used");
1559
1560 fprintf(PFILE, "direction = ");
1561 switch (cep->inout)
1562 {
1563 case DIR_INONLY:
1564 fprintf(PFILE, "in\t\t# only incoming connections allowed\n");
1565 break;
1566 case DIR_OUTONLY:
1567 fprintf(PFILE, "out\t\t# only outgoing connections allowed\n");
1568 break;
1569 case DIR_INOUT:
1570 fprintf(PFILE, "inout\t\t# incoming and outgoing connections allowed\n");
1571 break;
1572 }
1573
1574 if (cep->remote_numbers_count > 1)
1575 {
1576 for (j = 0; j < cep->remote_numbers_count; j++)
1577 fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number %d for dialing out to remote\n", cep->remote_numbers[j].number, j+1);
1578
1579 fprintf(PFILE, "remdial-handling = ");
1580
1581 switch (cep->remote_numbers_handling)
1582 {
1583 case RNH_NEXT:
1584 fprintf(PFILE, "next\t\t# use next number after last successful for new dial\n");
1585 break;
1586 case RNH_LAST:
1587 fprintf(PFILE, "last\t\t# use last successful number for new dial\n");
1588 break;
1589 case RNH_FIRST:
1590 fprintf(PFILE, "first\t\t# always start with first number for new dial\n");
1591 break;
1592 }
1593 }
1594
1595 if (cep->local_phone_dialout[0])
1596 fprintf(PFILE, "local-phone-dialout = %s\t\t# show this number to remote when dialling out\n",
1597 cep->local_phone_dialout);
1598 fprintf(PFILE, "dialout-type = %s\n", cep->dialouttype ? "calledback\t\t# i am called back by remote" : "normal\t\t# i am not called back by remote");
1599 }
1600
1601 if (!(cep->inout == DIR_OUTONLY))
1602 {
1603 int n;
1604
1605 fprintf(PFILE, "local-phone-incoming = %s\t\t# incoming calls must match this (mine) telephone number\n", cep->local_phone_incoming);
1606 for (n = 0; n < cep->incoming_numbers_count; n++)
1607 fprintf(PFILE, "remote-phone-incoming = %s\t\t# this is a valid remote number to call me\n",
1608 cep->remote_phone_incoming[n].number);
1609
1610 fprintf(PFILE, "dialin-reaction = ");
1611 switch (cep->dialin_reaction)
1612 {
1613 case REACT_ACCEPT:
1614 fprintf(PFILE, "accept\t\t# i accept a call from remote and connect\n");
1615 break;
1616 case REACT_REJECT:
1617 fprintf(PFILE, "reject\t\t# i reject the call from remote\n");
1618 break;
1619 case REACT_IGNORE:
1620 fprintf(PFILE, "ignore\t\t# i ignore the call from remote\n");
1621 break;
1622 case REACT_ANSWER:
1623 fprintf(PFILE, "answer\t\t# i will start telephone answering when remote calls in\n");
1624 break;
1625 case REACT_CALLBACK:
1626 fprintf(PFILE, "callback\t\t# when remote calls in, i will hangup and call back\n");
1627 break;
1628 }
1629 }
1630
1631 {
1632 char *s;
1633 switch (cep->ppp_expect_auth)
1634 {
1635 case AUTH_NONE:
1636 s = "none";
1637 break;
1638 case AUTH_PAP:
1639 s = "pap";
1640 break;
1641 case AUTH_CHAP:
1642 s = "chap";
1643 break;
1644 default:
1645 s = NULL;
1646 break;
1647 }
1648 if (s != NULL)
1649 {
1650 fprintf(PFILE, "ppp-expect-auth = %s\t\t# the auth protocol we expect to receive on dial-in (none,pap,chap)\n", s);
1651 if (cep->ppp_expect_auth != AUTH_NONE)
1652 {
1653 fprintf(PFILE, "ppp-expect-name = %s\t\t# the user name allowed in\n", cep->ppp_expect_name);
1654 fprintf(PFILE, "ppp-expect-password = %s\t\t# the key expected from the other side\n", cep->ppp_expect_password);
1655 fprintf(PFILE, "ppp-auth-paranoid = %s\t\t# do we require remote to authenticate even if we dial out\n", cep->ppp_auth_flags & AUTH_REQUIRED ? "yes" : "no");
1656 }
1657 }
1658 switch (cep->ppp_send_auth)
1659 {
1660 case AUTH_NONE:
1661 s = "none";
1662 break;
1663 case AUTH_PAP:
1664 s = "pap";
1665 break;
1666 case AUTH_CHAP:
1667 s = "chap";
1668 break;
1669 default:
1670 s = NULL;
1671 break;
1672 }
1673 if (s != NULL)
1674 {
1675 fprintf(PFILE, "ppp-send-auth = %s\t\t# the auth protocol we use when dialing out (none,pap,chap)\n", s);
1676 if (cep->ppp_send_auth != AUTH_NONE)
1677 {
1678 fprintf(PFILE, "ppp-send-name = %s\t\t# our PPP account used for dial-out\n", cep->ppp_send_name);
1679 fprintf(PFILE, "ppp-send-password = %s\t\t# the key sent to the other side\n", cep->ppp_send_password);
1680 }
1681 }
1682 if (cep->ppp_send_auth == AUTH_CHAP ||
1683 cep->ppp_expect_auth == AUTH_CHAP) {
1684 fprintf(PFILE, "ppp-auth-rechallenge = %s\t\t# rechallenge CHAP connections once in a while\n", cep->ppp_auth_flags & AUTH_RECHALLENGE ? "yes" : "no");
1685 }
1686 }
1687
1688 if (cep->autoupdown == AUTOUPDOWN_NO)
1689 fprintf(PFILE, "autoupdown = no\n");
1690
1691 {
1692 char *s;
1693 fprintf(PFILE, "idletime-outgoing = %d\t\t# outgoing call idle timeout\n", cep->idle_time_out);
1694
1695 switch ( cep->shorthold_algorithm )
1696 {
1697 case SHA_FIXU:
1698 s = "fix-unit-size";
1699 break;
1700 case SHA_VARU:
1701 s = "var-unit-size";
1702 break;
1703 default:
1704 s = "error!!!";
1705 break;
1706 }
1707
1708 fprintf(PFILE, "idle-algorithm-outgoing = %s\t\t# outgoing call idle algorithm\n", s);
1709 }
1710
1711 if (!(cep->inout == DIR_OUTONLY))
1712 fprintf(PFILE, "idletime-incoming = %d\t\t# incoming call idle timeout\n", cep->idle_time_in);
1713
1714 {
1715 fprintf(PFILE, "unitlengthsrc = ");
1716 switch (cep->unitlengthsrc)
1717 {
1718 case ULSRC_NONE:
1719 fprintf(PFILE, "none\t\t# no unit length specified, using default\n");
1720 break;
1721 case ULSRC_CMDL:
1722 fprintf(PFILE, "cmdl\t\t# using unit length specified on commandline\n");
1723 break;
1724 case ULSRC_CONF:
1725 fprintf(PFILE, "conf\t\t# using unitlength specified by unitlength-keyword\n");
1726 fprintf(PFILE, "unitlength = %d\t\t# fixed unitlength\n", cep->unitlength);
1727 break;
1728 case ULSRC_RATE:
1729 fprintf(PFILE, "rate\t\t# using unitlength specified in rate database\n");
1730 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1731 break;
1732 case ULSRC_DYN:
1733 fprintf(PFILE, "aocd\t\t# using dynamically calculated unitlength based on AOCD subscription\n");
1734 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1735 break;
1736 }
1737
1738 fprintf(PFILE, "earlyhangup = %d\t\t# early hangup safety time\n", cep->earlyhangup);
1739
1740 }
1741
1742 {
1743 fprintf(PFILE, "answerprog = %s\t\t# program used to answer incoming telephone calls\n", cep->answerprog);
1744 fprintf(PFILE, "alert = %d\t\t# number of seconds to wait before accepting a call\n", cep->alert);
1745 }
1746
1747 {
1748 if (cep->dialin_reaction == REACT_CALLBACK)
1749 fprintf(PFILE, "callbackwait = %d\t\t# i am waiting this time before calling back remote\n", cep->callbackwait);
1750
1751 if (cep->dialouttype == DIALOUT_CALLEDBACK)
1752 fprintf(PFILE, "calledbackwait = %d\t\t# i am waiting this time for a call back from remote\n", cep->calledbackwait);
1753
1754 if (!(cep->inout == DIR_INONLY))
1755 {
1756 fprintf(PFILE, "dialretries = %d\t\t# number of dialing retries\n", cep->dialretries);
1757 fprintf(PFILE, "recoverytime = %d\t\t# time to wait between dialling retries\n", cep->recoverytime);
1758 fprintf(PFILE, "dialrandincr = %s\t\t# use random dialing time addon\n", cep->dialrandincr ? "on" : "off");
1759
1760 fprintf(PFILE, "usedown = %s\n", cep->usedown ? "on\t\t# ISDN device switched off on excessive dial failures" : "off\t\t# no device switchoff on excessive dial failures");
1761 if (cep->usedown)
1762 {
1763 fprintf(PFILE, "downtries = %d\t\t# number of dialretries failures before switching off\n", cep->downtries);
1764 fprintf(PFILE, "downtime = %d\t\t# time device is switched off\n", cep->downtime);
1765 }
1766 }
1767 }
1768 fprintf(PFILE, "\n");
1769 }
1770
1771 static int
lookup_l4_driver(const char * name)1772 lookup_l4_driver(const char *name)
1773 {
1774 msg_l4driver_lookup_t query;
1775 int e;
1776
1777 memset(&query, 0, sizeof query);
1778 strncpy(query.name, name, sizeof query.name);
1779 e = ioctl(isdnfd, I4B_L4DRIVER_LOOKUP, &query);
1780 if (e != 0) return -1;
1781 return query.driver_id;
1782 }
1783