Allow one shot timer to be switched on a running system between i8254 and
[dragonfly.git] / usr.sbin / i4b / isdnd / rc_config.c
blob90432958ae3031db4e50d4f8cf94e42cb259dd1e
1 /*
2 * Copyright (c) 1997, 2001 Hellmuth Michaelis. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
25 *---------------------------------------------------------------------------
27 * i4b daemon - config file processing
28 * -----------------------------------
30 * $FreeBSD: src/usr.sbin/i4b/isdnd/rc_config.c,v 1.6.2.3 2002/04/24 18:50:07 joerg Exp $
31 * $DragonFly: src/usr.sbin/i4b/isdnd/rc_config.c,v 1.5 2008/04/20 13:44:26 swildner Exp $
33 * last edit-date: [Fri Jul 20 19:16:27 2001]
35 *---------------------------------------------------------------------------*/
37 #include <sys/types.h>
38 #include <sys/socket.h>
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
42 #include <sys/ioctl.h>
44 #include <net/if.h>
46 #include "isdnd.h"
47 #include "y.tab.h"
49 #include "monitor.h"
51 extern int entrycount;
52 extern int controllercount;
53 extern int lineno;
54 extern char *yytext;
56 extern FILE *yyin;
57 extern int yyparse();
59 static void set_config_defaults(void);
60 static void check_config(void);
61 static void print_config(void);
62 static void parse_valid(int entrycount, char *dt);
64 static int nregexpr = 0;
65 static int nregprog = 0;
67 /*---------------------------------------------------------------------------*
68 * called from main to read and process config file
69 *---------------------------------------------------------------------------*/
70 void
71 configure(char *filename, int reread)
73 extern void reset_scanner(FILE *inputfile);
75 set_config_defaults();
77 yyin = fopen(filename, "r");
79 if(reread)
81 reset_scanner(yyin);
84 if (yyin == NULL)
86 dolog(LL_ERR, "cannot fopen file [%s]", filename);
87 exit(1);
90 yyparse();
92 monitor_fixup_rights();
94 check_config(); /* validation and consistency check */
96 fclose(yyin);
98 if(do_print)
100 if(config_error_flag)
102 dolog(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag);
103 exit(1);
105 print_config();
106 do_exit(0);
110 /*---------------------------------------------------------------------------*
111 * yacc error routine
112 *---------------------------------------------------------------------------*/
113 void
114 yyerror(const char *msg)
116 dolog(LL_ERR, "configuration error: %s at line %d, token \"%s\"", msg, lineno+1, yytext);
117 config_error_flag++;
120 /*---------------------------------------------------------------------------*
121 * fill all config entries with default values
122 *---------------------------------------------------------------------------*/
123 static void
124 set_config_defaults(void)
126 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
127 int i;
129 /* system section cleanup */
131 nregprog = nregexpr = 0;
133 rt_prio = RTPRIO_NOTUSED;
135 mailer[0] = '\0';
136 mailto[0] = '\0';
138 /* clean regular expression table */
140 for(i=0; i < MAX_RE; i++)
142 if(rarr[i].re_expr)
143 free(rarr[i].re_expr);
144 rarr[i].re_expr = NULL;
146 if(rarr[i].re_prog)
147 free(rarr[i].re_prog);
148 rarr[i].re_prog = NULL;
150 rarr[i].re_flg = 0;
153 strcpy(rotatesuffix, "");
156 * controller table cleanup, beware: has already
157 * been setup in main, init_controller() !
160 for(i=0; i < ncontroller; i++)
162 isdn_ctrl_tab[i].protocol = PROTOCOL_DSS1;
163 isdn_ctrl_tab[i].firmware = NULL;
166 /* entry section cleanup */
168 for(i=0; i < CFG_ENTRY_MAX; i++, cep++)
170 bzero(cep, sizeof(cfg_entry_t));
172 /* ====== filled in at startup configuration, then static */
174 sprintf(cep->name, "ENTRY%d", i);
176 cep->isdncontroller = INVALID;
177 cep->isdnchannel = CHAN_ANY;
179 cep->usrdevicename = INVALID;
180 cep->usrdeviceunit = INVALID;
182 cep->remote_numbers_handling = RNH_LAST;
184 cep->dialin_reaction = REACT_IGNORE;
186 cep->b1protocol = BPROT_NONE;
188 cep->unitlength = UNITLENGTH_DEFAULT;
190 cep->earlyhangup = EARLYHANGUP_DEFAULT;
192 cep->ratetype = INVALID_RATE;
194 cep->unitlengthsrc = ULSRC_NONE;
196 cep->answerprog = ANSWERPROG_DEF;
198 cep->callbackwait = CALLBACKWAIT_MIN;
200 cep->calledbackwait = CALLEDBACKWAIT_MIN;
202 cep->dialretries = DIALRETRIES_DEF;
204 cep->recoverytime = RECOVERYTIME_MIN;
206 cep->dialouttype = DIALOUT_NORMAL;
208 cep->inout = DIR_INOUT;
210 cep->ppp_expect_auth = AUTH_UNDEF;
212 cep->ppp_send_auth = AUTH_UNDEF;
214 cep->ppp_auth_flags = AUTH_RECHALLENGE | AUTH_REQUIRED;
216 /* ======== filled in after start, then dynamic */
218 cep->cdid = CDID_UNUSED;
220 cep->state = ST_IDLE;
222 cep->aoc_valid = AOC_INVALID;
226 /*---------------------------------------------------------------------------*
227 * internaly set values for ommitted controler sectin
228 *---------------------------------------------------------------------------*/
229 void
230 cfg_set_controller_default(void)
232 controllercount = 0;
233 DBGL(DL_RCCF, (dolog(LL_DBG, "[defaults, no controller section] controller %d: protocol = dss1", controllercount)));
234 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_DSS1;
237 #define PPP_PAP 0xc023
238 #define PPP_CHAP 0xc223
240 static void
241 set_isppp_auth(int entry)
243 cfg_entry_t *cep = &cfg_entry_tab[entry]; /* ptr to config entry */
245 struct ifreq ifr;
246 struct spppreq spr;
247 int s;
248 int doioctl = 0;
250 if(cep->usrdevicename != BDRV_ISPPP)
251 return;
253 if(cep->ppp_expect_auth == AUTH_UNDEF
254 && cep->ppp_send_auth == AUTH_UNDEF)
255 return;
257 if(cep->ppp_expect_auth == AUTH_NONE
258 || cep->ppp_send_auth == AUTH_NONE)
259 doioctl = 1;
261 if ((cep->ppp_expect_auth == AUTH_CHAP
262 || cep->ppp_expect_auth == AUTH_PAP)
263 && cep->ppp_expect_name[0] != 0
264 && cep->ppp_expect_password[0] != 0)
265 doioctl = 1;
267 if ((cep->ppp_send_auth == AUTH_CHAP || cep->ppp_send_auth == AUTH_PAP)
268 && cep->ppp_send_name[0] != 0
269 && cep->ppp_send_password[0] != 0)
270 doioctl = 1;
272 if(!doioctl)
273 return;
275 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "isp%d", cep->usrdeviceunit);
277 /* use a random AF to create the socket */
278 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
279 dolog(LL_ERR, "ERROR opening control socket at line %d!", lineno);
280 config_error_flag++;
281 return;
283 spr.cmd = (int)SPPPIOGDEFS;
284 ifr.ifr_data = (caddr_t)&spr;
286 if (ioctl(s, SIOCGIFGENERIC, &ifr) == -1) {
287 dolog(LL_ERR, "ERROR fetching active PPP authentication info for %s at line %d!", ifr.ifr_name, lineno);
288 close(s);
289 config_error_flag++;
290 return;
292 if (cep->ppp_expect_auth != AUTH_UNDEF)
294 if(cep->ppp_expect_auth == AUTH_NONE)
296 spr.defs.hisauth.proto = 0;
298 else if ((cep->ppp_expect_auth == AUTH_CHAP
299 || cep->ppp_expect_auth == AUTH_PAP)
300 && cep->ppp_expect_name[0] != 0
301 && cep->ppp_expect_password[0] != 0)
303 spr.defs.hisauth.proto = cep->ppp_expect_auth == AUTH_PAP ? PPP_PAP : PPP_CHAP;
304 strncpy(spr.defs.hisauth.name, cep->ppp_expect_name, AUTHNAMELEN);
305 strncpy(spr.defs.hisauth.secret, cep->ppp_expect_password, AUTHKEYLEN);
308 if (cep->ppp_send_auth != AUTH_UNDEF)
310 if(cep->ppp_send_auth == AUTH_NONE)
312 spr.defs.myauth.proto = 0;
314 else if ((cep->ppp_send_auth == AUTH_CHAP
315 || cep->ppp_send_auth == AUTH_PAP)
316 && cep->ppp_send_name[0] != 0
317 && cep->ppp_send_password[0] != 0)
319 spr.defs.myauth.proto = cep->ppp_send_auth == AUTH_PAP ? PPP_PAP : PPP_CHAP;
320 strncpy(spr.defs.myauth.name, cep->ppp_send_name, AUTHNAMELEN);
321 strncpy(spr.defs.myauth.secret, cep->ppp_send_password, AUTHKEYLEN);
323 if(cep->ppp_auth_flags & AUTH_REQUIRED)
324 spr.defs.hisauth.flags &= ~AUTHFLAG_NOCALLOUT;
325 else
326 spr.defs.hisauth.flags |= AUTHFLAG_NOCALLOUT;
328 if(cep->ppp_auth_flags & AUTH_RECHALLENGE)
329 spr.defs.hisauth.flags &= ~AUTHFLAG_NORECHALLENGE;
330 else
331 spr.defs.hisauth.flags |= AUTHFLAG_NORECHALLENGE;
335 spr.cmd = (int)SPPPIOSDEFS;
337 if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1) {
338 dolog(LL_ERR, "ERROR setting new PPP authentication parameters for %s at line %d!", ifr.ifr_name, lineno);
339 config_error_flag++;
341 close(s);
344 /*---------------------------------------------------------------------------*
345 * extract values from config and fill table
346 *---------------------------------------------------------------------------*/
347 void
348 cfg_setval(int keyword)
350 int i;
352 switch(keyword)
354 case ACCTALL:
355 acct_all = yylval.booln;
356 DBGL(DL_RCCF, (dolog(LL_DBG, "system: acctall = %d", yylval.booln)));
357 break;
359 case ACCTFILE:
360 strcpy(acctfile, yylval.str);
361 DBGL(DL_RCCF, (dolog(LL_DBG, "system: acctfile = %s", yylval.str)));
362 break;
364 case ALERT:
365 if(yylval.num < MINALERT)
367 yylval.num = MINALERT;
368 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: alert < %d, min = %d", entrycount, MINALERT, yylval.num)));
370 else if(yylval.num > MAXALERT)
372 yylval.num = MAXALERT;
373 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: alert > %d, min = %d", entrycount, MAXALERT, yylval.num)));
376 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: alert = %d", entrycount, yylval.num)));
377 cfg_entry_tab[entrycount].alert = yylval.num;
378 break;
380 case ALIASING:
381 DBGL(DL_RCCF, (dolog(LL_DBG, "system: aliasing = %d", yylval.booln)));
382 aliasing = yylval.booln;
383 break;
385 case ALIASFNAME:
386 strcpy(aliasfile, yylval.str);
387 DBGL(DL_RCCF, (dolog(LL_DBG, "system: aliasfile = %s", yylval.str)));
388 break;
390 case ANSWERPROG:
391 if((cfg_entry_tab[entrycount].answerprog = malloc(strlen(yylval.str)+1)) == NULL)
393 dolog(LL_ERR, "entry %d: answerstring, malloc failed!", entrycount);
394 do_exit(1);
396 strcpy(cfg_entry_tab[entrycount].answerprog, yylval.str);
397 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: answerprog = %s", entrycount, yylval.str)));
398 break;
400 case B1PROTOCOL:
401 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: b1protocol = %s", entrycount, yylval.str)));
402 if(!(strcmp(yylval.str, "raw")))
403 cfg_entry_tab[entrycount].b1protocol = BPROT_NONE;
404 else if(!(strcmp(yylval.str, "hdlc")))
405 cfg_entry_tab[entrycount].b1protocol = BPROT_RHDLC;
406 else
408 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"b1protocol\" at line %d!", lineno);
409 config_error_flag++;
411 break;
413 case BEEPCONNECT:
414 do_bell = yylval.booln;
415 DBGL(DL_RCCF, (dolog(LL_DBG, "system: beepconnect = %d", yylval.booln)));
416 break;
418 case BUDGETCALLBACKPERIOD:
419 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-callbackperiod = %d", entrycount, yylval.num)));
420 cfg_entry_tab[entrycount].budget_callbackperiod = yylval.num;
421 break;
423 case BUDGETCALLBACKNCALLS:
424 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-callbackncalls = %d", entrycount, yylval.num)));
425 cfg_entry_tab[entrycount].budget_callbackncalls = yylval.num;
426 break;
428 case BUDGETCALLOUTPERIOD:
429 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-calloutperiod = %d", entrycount, yylval.num)));
430 cfg_entry_tab[entrycount].budget_calloutperiod = yylval.num;
431 break;
433 case BUDGETCALLOUTNCALLS:
434 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-calloutncalls = %d", entrycount, yylval.num)));
435 cfg_entry_tab[entrycount].budget_calloutncalls = yylval.num;
436 break;
438 case BUDGETCALLBACKSFILEROTATE:
439 cfg_entry_tab[entrycount].budget_callbacksfile_rotate = yylval.booln;
440 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-callbacksfile-rotate = %d", entrycount, yylval.booln)));
441 break;
443 case BUDGETCALLBACKSFILE:
445 FILE *fp;
446 int s, l;
447 int n;
448 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-callbacksfile = %s", entrycount, yylval.str)));
449 fp = fopen(yylval.str, "r");
450 if(fp != NULL)
452 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
454 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: initializing budget-callbacksfile %s", entrycount, yylval.str)));
455 fclose(fp);
456 fp = fopen(yylval.str, "w");
457 if(fp != NULL)
458 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
459 fclose(fp);
462 else
464 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: creating budget-callbacksfile %s", entrycount, yylval.str)));
465 fp = fopen(yylval.str, "w");
466 if(fp != NULL)
467 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
468 fclose(fp);
471 fp = fopen(yylval.str, "r");
472 if(fp != NULL)
474 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
476 if((cfg_entry_tab[entrycount].budget_callbacks_file = malloc(strlen(yylval.str)+1)) == NULL)
478 dolog(LL_ERR, "entry %d: budget-callbacksfile, malloc failed!", entrycount);
479 do_exit(1);
481 strcpy(cfg_entry_tab[entrycount].budget_callbacks_file, yylval.str);
482 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: using callbacksfile %s", entrycount, yylval.str)));
484 fclose(fp);
487 break;
489 case BUDGETCALLOUTSFILEROTATE:
490 cfg_entry_tab[entrycount].budget_calloutsfile_rotate = yylval.booln;
491 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-calloutsfile-rotate = %d", entrycount, yylval.booln)));
492 break;
494 case BUDGETCALLOUTSFILE:
496 FILE *fp;
497 int s, l;
498 int n;
499 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: budget-calloutsfile = %s", entrycount, yylval.str)));
500 fp = fopen(yylval.str, "r");
501 if(fp != NULL)
503 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
505 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: initializing budget-calloutsfile %s", entrycount, yylval.str)));
506 fclose(fp);
507 fp = fopen(yylval.str, "w");
508 if(fp != NULL)
509 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
510 fclose(fp);
513 else
515 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: creating budget-calloutsfile %s", entrycount, yylval.str)));
516 fp = fopen(yylval.str, "w");
517 if(fp != NULL)
518 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
519 fclose(fp);
522 fp = fopen(yylval.str, "r");
523 if(fp != NULL)
525 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
527 if((cfg_entry_tab[entrycount].budget_callouts_file = malloc(strlen(yylval.str)+1)) == NULL)
529 dolog(LL_ERR, "entry %d: budget-calloutsfile, malloc failed!", entrycount);
530 do_exit(1);
532 strcpy(cfg_entry_tab[entrycount].budget_callouts_file, yylval.str);
533 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: using calloutsfile %s", entrycount, yylval.str)));
535 fclose(fp);
538 break;
540 case CALLBACKWAIT:
541 if(yylval.num < CALLBACKWAIT_MIN)
543 yylval.num = CALLBACKWAIT_MIN;
544 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: callbackwait < %d, min = %d", entrycount, CALLBACKWAIT_MIN, yylval.num)));
547 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: callbackwait = %d", entrycount, yylval.num)));
548 cfg_entry_tab[entrycount].callbackwait = yylval.num;
549 break;
551 case CALLEDBACKWAIT:
552 if(yylval.num < CALLEDBACKWAIT_MIN)
554 yylval.num = CALLEDBACKWAIT_MIN;
555 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: calledbackwait < %d, min = %d", entrycount, CALLEDBACKWAIT_MIN, yylval.num)));
558 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: calledbackwait = %d", entrycount, yylval.num)));
559 cfg_entry_tab[entrycount].calledbackwait = yylval.num;
560 break;
562 case CLONE:
564 * clone = <entryname>
565 * Loads the entry from the named, existing one.
566 * Fields such as name and usrdeviceunit should
567 * always be specified after clone as they must be
568 * unique.
570 * NOTE: all malloc()'d fields must be dup()'d here,
571 * we can't have multiple references to same storage.
573 for (i = 0; i < entrycount; i++)
574 if (!strcmp(cfg_entry_tab[i].name, yylval.str))
575 break;
576 if (i == entrycount) {
577 dolog(LL_ERR, "entry %d: clone, unknown entry %s!", entrycount, yylval.str);
578 do_exit(1);
581 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: clone = %s", entrycount, yylval.str)));
583 memcpy(&cfg_entry_tab[entrycount], &cfg_entry_tab[i],
584 sizeof(cfg_entry_tab[0]));
586 if (cfg_entry_tab[entrycount].answerprog)
587 cfg_entry_tab[entrycount].answerprog = strdup(cfg_entry_tab[entrycount].answerprog);
588 if (cfg_entry_tab[entrycount].budget_callbacks_file)
589 cfg_entry_tab[entrycount].budget_callbacks_file = strdup(cfg_entry_tab[entrycount].budget_callbacks_file);
590 if (cfg_entry_tab[entrycount].budget_callouts_file)
591 cfg_entry_tab[entrycount].budget_callouts_file = strdup(cfg_entry_tab[entrycount].budget_callouts_file);
592 if (cfg_entry_tab[entrycount].connectprog)
593 cfg_entry_tab[entrycount].connectprog = strdup(cfg_entry_tab[entrycount].connectprog);
594 if (cfg_entry_tab[entrycount].disconnectprog)
595 cfg_entry_tab[entrycount].disconnectprog = strdup(cfg_entry_tab[entrycount].disconnectprog);
596 break;
598 case CONNECTPROG:
599 if((cfg_entry_tab[entrycount].connectprog = malloc(strlen(yylval.str)+1)) == NULL)
601 dolog(LL_ERR, "entry %d: connectprog, malloc failed!", entrycount);
602 do_exit(1);
604 strcpy(cfg_entry_tab[entrycount].connectprog, yylval.str);
605 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: connectprog = %s", entrycount, yylval.str)));
606 break;
608 case DIALOUTTYPE:
609 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: dialouttype = %s", entrycount, yylval.str)));
610 if(!(strcmp(yylval.str, "normal")))
611 cfg_entry_tab[entrycount].dialouttype = DIALOUT_NORMAL;
612 else if(!(strcmp(yylval.str, "calledback")))
613 cfg_entry_tab[entrycount].dialouttype = DIALOUT_CALLEDBACK;
614 else
616 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialout-type\" at line %d!", lineno);
617 config_error_flag++;
619 break;
621 case DIALRETRIES:
622 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: dialretries = %d", entrycount, yylval.num)));
623 cfg_entry_tab[entrycount].dialretries = yylval.num;
624 break;
626 case DIALRANDINCR:
627 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: dialrandincr = %d", entrycount, yylval.booln)));
628 cfg_entry_tab[entrycount].dialrandincr = yylval.booln;
629 break;
631 case DIRECTION:
632 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: direction = %s", entrycount, yylval.str)));
634 if(!(strcmp(yylval.str, "inout")))
635 cfg_entry_tab[entrycount].inout = DIR_INOUT;
636 else if(!(strcmp(yylval.str, "in")))
637 cfg_entry_tab[entrycount].inout = DIR_INONLY;
638 else if(!(strcmp(yylval.str, "out")))
639 cfg_entry_tab[entrycount].inout = DIR_OUTONLY;
640 else
642 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"direction\" at line %d!", lineno);
643 config_error_flag++;
645 break;
647 case DISCONNECTPROG:
648 if((cfg_entry_tab[entrycount].disconnectprog = malloc(strlen(yylval.str)+1)) == NULL)
650 dolog(LL_ERR, "entry %d: disconnectprog, malloc failed!", entrycount);
651 do_exit(1);
653 strcpy(cfg_entry_tab[entrycount].disconnectprog, yylval.str);
654 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: disconnectprog = %s", entrycount, yylval.str)));
655 break;
657 case DOWNTRIES:
658 if(yylval.num > DOWN_TRIES_MAX)
659 yylval.num = DOWN_TRIES_MAX;
660 else if(yylval.num < DOWN_TRIES_MIN)
661 yylval.num = DOWN_TRIES_MIN;
663 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: downtries = %d", entrycount, yylval.num)));
664 cfg_entry_tab[entrycount].downtries = yylval.num;
665 break;
667 case DOWNTIME:
668 if(yylval.num > DOWN_TIME_MAX)
669 yylval.num = DOWN_TIME_MAX;
670 else if(yylval.num < DOWN_TIME_MIN)
671 yylval.num = DOWN_TIME_MIN;
673 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: downtime = %d", entrycount, yylval.num)));
674 cfg_entry_tab[entrycount].downtime = yylval.num;
675 break;
677 case EARLYHANGUP:
678 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: earlyhangup = %d", entrycount, yylval.num)));
679 cfg_entry_tab[entrycount].earlyhangup = yylval.num;
680 break;
682 case EXTCALLATTR:
683 DBGL(DL_RCCF, (dolog(LL_DBG, "system: extcallattr = %d", yylval.booln)));
684 extcallattr = yylval.booln;
685 break;
687 case FIRMWARE:
688 DBGL(DL_RCCF, (dolog(LL_DBG, "controller %d: firmware = %s", controllercount, yylval.str)));
689 isdn_ctrl_tab[controllercount].firmware = strdup(yylval.str);
690 break;
692 case HOLIDAYFILE:
693 strcpy(holidayfile, yylval.str);
694 DBGL(DL_RCCF, (dolog(LL_DBG, "system: holidayfile = %s", yylval.str)));
695 break;
697 case IDLE_ALG_OUT:
698 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: idle-algorithm-outgoing = %s", entrycount, yylval.str)));
700 if(!(strcmp(yylval.str, "fix-unit-size")))
702 cfg_entry_tab[entrycount].shorthold_algorithm = SHA_FIXU;
704 else if(!(strcmp(yylval.str, "var-unit-size")))
706 cfg_entry_tab[entrycount].shorthold_algorithm = SHA_VARU;
708 else
710 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"idle-algorithm-outgoing\" at line %d!", lineno);
711 config_error_flag++;
713 break;
715 case IDLETIME_IN:
716 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: idle_time_in = %d", entrycount, yylval.num)));
717 cfg_entry_tab[entrycount].idle_time_in = yylval.num;
718 break;
720 case IDLETIME_OUT:
721 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: idle_time_out = %d", entrycount, yylval.num)));
722 cfg_entry_tab[entrycount].idle_time_out = yylval.num;
723 break;
725 case ISDNCONTROLLER:
726 cfg_entry_tab[entrycount].isdncontroller = yylval.num;
727 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: isdncontroller = %d", entrycount, yylval.num)));
728 break;
730 case ISDNCHANNEL:
731 if (yylval.num == 0 || yylval.num == -1)
733 cfg_entry_tab[entrycount].isdnchannel = CHAN_ANY;
734 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: isdnchannel = any", entrycount)));
736 else if (yylval.num > MAX_BCHAN)
738 dolog(LL_DBG, "entry %d: isdnchannel value out of range", entrycount);
739 config_error_flag++;
741 else
743 cfg_entry_tab[entrycount].isdnchannel = yylval.num-1;
744 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: isdnchannel = B%d", entrycount, yylval.num)));
746 break;
748 case ISDNTIME:
749 DBGL(DL_RCCF, (dolog(LL_DBG, "system: isdntime = %d", yylval.booln)));
750 isdntime = yylval.booln;
751 break;
753 case ISDNTXDELIN:
754 cfg_entry_tab[entrycount].isdntxdelin = yylval.num;
755 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: isdntxdel-incoming = %d", entrycount, yylval.num)));
756 break;
758 case ISDNTXDELOUT:
759 cfg_entry_tab[entrycount].isdntxdelout = yylval.num;
760 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: isdntxdel-outgoing = %d", entrycount, yylval.num)));
761 break;
763 case LOCAL_PHONE_DIALOUT:
764 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: local_phone_dialout = %s", entrycount, yylval.str)));
765 strcpy(cfg_entry_tab[entrycount].local_phone_dialout, yylval.str);
766 break;
768 case LOCAL_PHONE_INCOMING:
769 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: local_phone_incoming = %s", entrycount, yylval.str)));
770 strcpy(cfg_entry_tab[entrycount].local_phone_incoming, yylval.str);
771 break;
773 case MAILER:
774 strcpy(mailer, yylval.str);
775 DBGL(DL_RCCF, (dolog(LL_DBG, "system: mailer = %s", yylval.str)));
776 break;
778 case MAILTO:
779 strcpy(mailto, yylval.str);
780 DBGL(DL_RCCF, (dolog(LL_DBG, "system: mailto = %s", yylval.str)));
781 break;
783 case MAXCONNECTTIME:
784 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: maxconnecttime = %d", entrycount, yylval.num)));
785 cfg_entry_tab[entrycount].maxconnecttime = yylval.num;
786 break;
788 case MONITORPORT:
789 monitorport = yylval.num;
790 DBGL(DL_RCCF, (dolog(LL_DBG, "system: monitorport = %d", yylval.num)));
791 break;
793 case MONITORSW:
794 if (yylval.booln && inhibit_monitor)
796 do_monitor = 0;
797 DBGL(DL_RCCF, (dolog(LL_DBG, "system: monitor-enable overridden by command line flag")));
799 else
801 do_monitor = yylval.booln;
802 DBGL(DL_RCCF, (dolog(LL_DBG, "system: monitor-enable = %d", yylval.booln)));
804 break;
806 case NAME:
807 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: name = %s", entrycount, yylval.str)));
808 strcpy(cfg_entry_tab[entrycount].name, yylval.str);
809 break;
811 case PPP_AUTH_RECHALLENGE:
812 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-auth-rechallenge = %d", entrycount, yylval.booln)));
813 if(yylval.booln)
814 cfg_entry_tab[entrycount].ppp_auth_flags |= AUTH_RECHALLENGE;
815 else
816 cfg_entry_tab[entrycount].ppp_auth_flags &= ~AUTH_RECHALLENGE;
817 set_isppp_auth(entrycount);
818 break;
820 case PPP_AUTH_PARANOID:
821 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-auth-paranoid = %d", entrycount, yylval.booln)));
822 if(yylval.booln)
823 cfg_entry_tab[entrycount].ppp_auth_flags |= AUTH_REQUIRED;
824 else
825 cfg_entry_tab[entrycount].ppp_auth_flags &= ~AUTH_REQUIRED;
826 set_isppp_auth(entrycount);
827 break;
829 case PPP_EXPECT_AUTH:
830 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-expect-auth = %s", entrycount, yylval.str)));
831 if(!(strcmp(yylval.str, "none")))
832 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_NONE;
833 else if(!(strcmp(yylval.str, "pap")))
834 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_PAP;
835 else if(!(strcmp(yylval.str, "chap")))
836 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_CHAP;
837 else
839 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-expect-auth\" at line %d!", lineno);
840 config_error_flag++;
841 break;
843 set_isppp_auth(entrycount);
844 break;
846 case PPP_EXPECT_NAME:
847 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-expect-name = %s", entrycount, yylval.str)));
848 strncpy(cfg_entry_tab[entrycount].ppp_expect_name, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_expect_name) -1);
849 set_isppp_auth(entrycount);
850 break;
852 case PPP_EXPECT_PASSWORD:
853 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-expect-password = %s", entrycount, yylval.str)));
854 strncpy(cfg_entry_tab[entrycount].ppp_expect_password, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_expect_password) -1);
855 set_isppp_auth(entrycount);
856 break;
858 case PPP_SEND_AUTH:
859 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-send-auth = %s", entrycount, yylval.str)));
860 if(!(strcmp(yylval.str, "none")))
861 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_NONE;
862 else if(!(strcmp(yylval.str, "pap")))
863 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_PAP;
864 else if(!(strcmp(yylval.str, "chap")))
865 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_CHAP;
866 else
868 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-send-auth\" at line %d!", lineno);
869 config_error_flag++;
870 break;
872 set_isppp_auth(entrycount);
873 break;
875 case PPP_SEND_NAME:
876 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-send-name = %s", entrycount, yylval.str)));
877 strncpy(cfg_entry_tab[entrycount].ppp_send_name, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_send_name) -1);
878 set_isppp_auth(entrycount);
879 break;
881 case PPP_SEND_PASSWORD:
882 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ppp-send-password = %s", entrycount, yylval.str)));
883 strncpy(cfg_entry_tab[entrycount].ppp_send_password, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_send_password) -1);
884 set_isppp_auth(entrycount);
885 break;
887 case PROTOCOL:
888 DBGL(DL_RCCF, (dolog(LL_DBG, "controller %d: protocol = %s", controllercount, yylval.str)));
889 if(!(strcmp(yylval.str, "dss1")))
890 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_DSS1;
891 else if(!(strcmp(yylval.str, "d64s")))
892 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_D64S;
893 else
895 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"protocol\" at line %d!", lineno);
896 config_error_flag++;
898 break;
900 case REACTION:
901 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: dialin_reaction = %s", entrycount, yylval.str)));
902 if(!(strcmp(yylval.str, "accept")))
903 cfg_entry_tab[entrycount].dialin_reaction = REACT_ACCEPT;
904 else if(!(strcmp(yylval.str, "reject")))
905 cfg_entry_tab[entrycount].dialin_reaction = REACT_REJECT;
906 else if(!(strcmp(yylval.str, "ignore")))
907 cfg_entry_tab[entrycount].dialin_reaction = REACT_IGNORE;
908 else if(!(strcmp(yylval.str, "answer")))
909 cfg_entry_tab[entrycount].dialin_reaction = REACT_ANSWER;
910 else if(!(strcmp(yylval.str, "callback")))
911 cfg_entry_tab[entrycount].dialin_reaction = REACT_CALLBACK;
912 else
914 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialin_reaction\" at line %d!", lineno);
915 config_error_flag++;
917 break;
919 case REMOTE_PHONE_DIALOUT:
920 if(cfg_entry_tab[entrycount].remote_numbers_count >= MAXRNUMBERS)
922 dolog(LL_ERR, "ERROR parsing config file: too many remote numbers at line %d!", lineno);
923 config_error_flag++;
924 break;
927 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: remote_phone_dialout #%d = %s",
928 entrycount, cfg_entry_tab[entrycount].remote_numbers_count, yylval.str)));
930 strcpy(cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].number, yylval.str);
931 cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].flag = 0;
933 cfg_entry_tab[entrycount].remote_numbers_count++;
935 break;
937 case REMOTE_NUMBERS_HANDLING:
938 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: remdial_handling = %s", entrycount, yylval.str)));
939 if(!(strcmp(yylval.str, "next")))
940 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_NEXT;
941 else if(!(strcmp(yylval.str, "last")))
942 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_LAST;
943 else if(!(strcmp(yylval.str, "first")))
944 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_FIRST;
945 else
947 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"remdial_handling\" at line %d!", lineno);
948 config_error_flag++;
950 break;
952 case REMOTE_PHONE_INCOMING:
954 int n;
955 n = cfg_entry_tab[entrycount].incoming_numbers_count;
956 if (n >= MAX_INCOMING)
958 dolog(LL_ERR, "ERROR parsing config file: too many \"remote_phone_incoming\" entries at line %d!", lineno);
959 config_error_flag++;
960 break;
962 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: remote_phone_incoming #%d = %s", entrycount, n, yylval.str)));
963 strcpy(cfg_entry_tab[entrycount].remote_phone_incoming[n].number, yylval.str);
964 cfg_entry_tab[entrycount].incoming_numbers_count++;
966 break;
968 case RATESFILE:
969 strcpy(ratesfile, yylval.str);
970 DBGL(DL_RCCF, (dolog(LL_DBG, "system: ratesfile = %s", yylval.str)));
971 break;
973 case RATETYPE:
974 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: ratetype = %d", entrycount, yylval.num)));
975 cfg_entry_tab[entrycount].ratetype = yylval.num;
976 break;
978 case RECOVERYTIME:
979 if(yylval.num < RECOVERYTIME_MIN)
981 yylval.num = RECOVERYTIME_MIN;
982 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: recoverytime < %d, min = %d", entrycount, RECOVERYTIME_MIN, yylval.num)));
985 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: recoverytime = %d", entrycount, yylval.num)));
986 cfg_entry_tab[entrycount].recoverytime = yylval.num;
987 break;
989 case REGEXPR:
990 if(nregexpr >= MAX_RE)
992 dolog(LL_ERR, "system: regexpr #%d >= MAX_RE", nregexpr);
993 config_error_flag++;
994 break;
997 if((i = regcomp(&(rarr[nregexpr].re), yylval.str, REG_EXTENDED|REG_NOSUB)) != 0)
999 char buf[256];
1000 regerror(i, &(rarr[nregexpr].re), buf, sizeof(buf));
1001 dolog(LL_ERR, "system: regcomp error for %s: [%s]", yylval.str, buf);
1002 config_error_flag++;
1003 break;
1005 else
1007 if((rarr[nregexpr].re_expr = malloc(strlen(yylval.str)+1)) == NULL)
1009 dolog(LL_ERR, "system: regexpr malloc error error for %s", yylval.str);
1010 config_error_flag++;
1011 break;
1013 strcpy(rarr[nregexpr].re_expr, yylval.str);
1015 DBGL(DL_RCCF, (dolog(LL_DBG, "system: regexpr %s stored into slot %d", yylval.str, nregexpr)));
1017 if(rarr[nregexpr].re_prog != NULL)
1018 rarr[nregexpr].re_flg = 1;
1020 nregexpr++;
1023 break;
1025 case REGPROG:
1026 if(nregprog >= MAX_RE)
1028 dolog(LL_ERR, "system: regprog #%d >= MAX_RE", nregprog);
1029 config_error_flag++;
1030 break;
1032 if((rarr[nregprog].re_prog = malloc(strlen(yylval.str)+1)) == NULL)
1034 dolog(LL_ERR, "system: regprog malloc error error for %s", yylval.str);
1035 config_error_flag++;
1036 break;
1038 strcpy(rarr[nregprog].re_prog, yylval.str);
1040 DBGL(DL_RCCF, (dolog(LL_DBG, "system: regprog %s stored into slot %d", yylval.str, nregprog)));
1042 if(rarr[nregprog].re_expr != NULL)
1043 rarr[nregprog].re_flg = 1;
1045 nregprog++;
1046 break;
1048 case ROTATESUFFIX:
1049 strcpy(rotatesuffix, yylval.str);
1050 DBGL(DL_RCCF, (dolog(LL_DBG, "system: rotatesuffix = %s", yylval.str)));
1051 break;
1053 case RTPRIO:
1054 #ifdef USE_RTPRIO
1055 rt_prio = yylval.num;
1056 if(rt_prio < RTP_PRIO_MIN || rt_prio > RTP_PRIO_MAX)
1058 config_error_flag++;
1059 dolog(LL_ERR, "system: error, rtprio (%d) out of range!", yylval.num);
1061 else
1063 DBGL(DL_RCCF, (dolog(LL_DBG, "system: rtprio = %d", yylval.num)));
1065 #else
1066 rt_prio = RTPRIO_NOTUSED;
1067 #endif
1068 break;
1070 case TINAINITPROG:
1071 strcpy(tinainitprog, yylval.str);
1072 DBGL(DL_RCCF, (dolog(LL_DBG, "system: tinainitprog = %s", yylval.str)));
1073 break;
1075 case UNITLENGTH:
1076 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: unitlength = %d", entrycount, yylval.num)));
1077 cfg_entry_tab[entrycount].unitlength = yylval.num;
1078 break;
1080 case UNITLENGTHSRC:
1081 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: unitlengthsrc = %s", entrycount, yylval.str)));
1082 if(!(strcmp(yylval.str, "none")))
1083 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_NONE;
1084 else if(!(strcmp(yylval.str, "cmdl")))
1085 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CMDL;
1086 else if(!(strcmp(yylval.str, "conf")))
1087 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CONF;
1088 else if(!(strcmp(yylval.str, "rate")))
1089 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_RATE;
1090 else if(!(strcmp(yylval.str, "aocd")))
1091 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_DYN;
1092 else
1094 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"unitlengthsrc\" at line %d!", lineno);
1095 config_error_flag++;
1097 break;
1099 case USRDEVICENAME:
1100 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: usrdevicename = %s", entrycount, yylval.str)));
1101 if(!strcmp(yylval.str, "rbch"))
1102 cfg_entry_tab[entrycount].usrdevicename = BDRV_RBCH;
1103 else if(!strcmp(yylval.str, "tel"))
1104 cfg_entry_tab[entrycount].usrdevicename = BDRV_TEL;
1105 else if(!strcmp(yylval.str, "ipr"))
1106 cfg_entry_tab[entrycount].usrdevicename = BDRV_IPR;
1107 else if(!strcmp(yylval.str, "isp"))
1108 cfg_entry_tab[entrycount].usrdevicename = BDRV_ISPPP;
1109 #ifdef __bsdi__
1110 else if(!strcmp(yylval.str, "ibc"))
1111 cfg_entry_tab[entrycount].usrdevicename = BDRV_IBC;
1112 #endif
1113 else if(!strcmp(yylval.str, "ing"))
1114 cfg_entry_tab[entrycount].usrdevicename = BDRV_ING;
1115 else
1117 dolog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"usrdevicename\" at line %d!", lineno);
1118 config_error_flag++;
1120 break;
1122 case USRDEVICEUNIT:
1123 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: usrdeviceunit = %d", entrycount, yylval.num)));
1124 cfg_entry_tab[entrycount].usrdeviceunit = yylval.num;
1125 break;
1127 case USEACCTFILE:
1128 useacctfile = yylval.booln;
1129 DBGL(DL_RCCF, (dolog(LL_DBG, "system: useacctfile = %d", yylval.booln)));
1130 break;
1132 case USEDOWN:
1133 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: usedown = %d", entrycount, yylval.booln)));
1134 cfg_entry_tab[entrycount].usedown = yylval.booln;
1135 break;
1137 case VALID:
1138 DBGL(DL_RCCF, (dolog(LL_DBG, "entry %d: valid = %s", entrycount, yylval.str)));
1139 parse_valid(entrycount, yylval.str);
1140 break;
1142 default:
1143 dolog(LL_ERR, "ERROR parsing config file: unknown keyword at line %d!", lineno);
1144 config_error_flag++;
1145 break;
1149 /*---------------------------------------------------------------------------*
1150 * parse a date/time range
1151 *---------------------------------------------------------------------------*/
1152 static void
1153 parse_valid(int entrycount, char *dt)
1155 /* a valid string consists of some days of week separated by
1156 * commas, where 0=sunday, 1=monday .. 6=saturday and a special
1157 * value of 7 which is a holiday from the holiday file.
1158 * after the days comes an optional (!) time range in the form
1159 * aa:bb-cc:dd, this format is fixed to be parsable by sscanf.
1160 * Valid specifications looks like this:
1161 * 1,2,3,4,5,09:00-18:00 Monday-Friday 9-18h
1162 * 1,2,3,4,5,18:00-09:00 Monday-Friday 18-9h
1163 * 6 Saturday (whole day)
1164 * 0,7 Sunday and Holidays
1167 int day = 0;
1168 int fromhr = 0;
1169 int frommin = 0;
1170 int tohr = 0;
1171 int tomin = 0;
1172 int ret;
1174 for(;;)
1176 if( ( ((*dt >= '0') && (*dt <= '9')) && (*(dt+1) == ':') ) ||
1177 ( ((*dt >= '0') && (*dt <= '2')) && ((*(dt+1) >= '0') && (*(dt+1) <= '9')) && (*(dt+2) == ':') ) )
1179 /* dt points to time spec */
1180 ret = sscanf(dt, "%d:%d-%d:%d", &fromhr, &frommin, &tohr, &tomin);
1181 if(ret !=4)
1183 dolog(LL_ERR, "ERROR parsing config file: timespec [%s] error at line %d!", *dt, lineno);
1184 config_error_flag++;
1185 return;
1188 if(fromhr < 0 || fromhr > 24 || tohr < 0 || tohr > 24 ||
1189 frommin < 0 || frommin > 59 || tomin < 0 || tomin > 59)
1191 dolog(LL_ERR, "ERROR parsing config file: invalid time [%s] at line %d!", *dt, lineno);
1192 config_error_flag++;
1193 return;
1195 break;
1197 else if ((*dt >= '0') && (*dt <= '7'))
1199 /* dt points to day spec */
1200 day |= 1 << (*dt - '0');
1201 dt++;
1202 continue;
1204 else if (*dt == ',')
1206 /* dt points to delimiter */
1207 dt++;
1208 continue;
1210 else if (*dt == '\0')
1212 /* dt points to end of string */
1213 break;
1215 else
1217 /* dt points to illegal character */
1218 dolog(LL_ERR, "ERROR parsing config file: illegal character [%c=0x%x] in date/time spec at line %d!", *dt, *dt, lineno);
1219 config_error_flag++;
1220 return;
1223 cfg_entry_tab[entrycount].day = day;
1224 cfg_entry_tab[entrycount].fromhr = fromhr;
1225 cfg_entry_tab[entrycount].frommin = frommin;
1226 cfg_entry_tab[entrycount].tohr = tohr;
1227 cfg_entry_tab[entrycount].tomin = tomin;
1230 /*---------------------------------------------------------------------------*
1231 * configuration validation and consistency check
1232 *---------------------------------------------------------------------------*/
1233 static void
1234 check_config(void)
1236 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
1237 int i;
1238 int error = 0;
1240 /* regular expression table */
1242 for(i=0; i < MAX_RE; i++)
1244 if((rarr[i].re_expr != NULL) && (rarr[i].re_prog == NULL))
1246 dolog(LL_ERR, "check_config: regular expression %d without program!", i);
1247 error++;
1249 if((rarr[i].re_prog != NULL) && (rarr[i].re_expr == NULL))
1251 dolog(LL_ERR, "check_config: regular expression program %d without expression!", i);
1252 error++;
1256 /* entry sections */
1258 for(i=0; i <= entrycount; i++, cep++)
1260 /* isdn controller number */
1262 if((cep->isdncontroller < -1) || (cep->isdncontroller > (ncontroller-1)))
1264 dolog(LL_ERR, "check_config: WARNING, isdncontroller out of range in entry %d!", i);
1267 /* numbers used for dialout */
1269 if((cep->inout != DIR_INONLY) && (cep->dialin_reaction != REACT_ANSWER))
1271 if(cep->remote_numbers_count == 0)
1273 dolog(LL_ERR, "check_config: remote-phone-dialout not set in entry %d!", i);
1274 error++;
1276 if(strlen(cep->local_phone_dialout) == 0)
1278 dolog(LL_ERR, "check_config: local-phone-dialout not set in entry %d!", i);
1279 error++;
1283 /* numbers used for incoming calls */
1285 if(cep->inout != DIR_OUTONLY)
1287 if(strlen(cep->local_phone_incoming) == 0)
1289 dolog(LL_ERR, "check_config: local-phone-incoming not set in entry %d!", i);
1290 error++;
1292 if(cep->incoming_numbers_count == 0)
1294 dolog(LL_ERR, "check_config: remote-phone-incoming not set in entry %d!", i);
1295 error++;
1299 if((cep->dialin_reaction == REACT_ANSWER) && (cep->b1protocol != BPROT_NONE))
1301 dolog(LL_ERR, "check_config: b1protocol not raw for telephony in entry %d!", i);
1302 error++;
1305 if((cep->ppp_send_auth == AUTH_PAP) || (cep->ppp_send_auth == AUTH_CHAP))
1307 if(cep->ppp_send_name[0] == 0)
1309 dolog(LL_ERR, "check_config: no remote authentification name in entry %d!", i);
1310 error++;
1312 if(cep->ppp_send_password[0] == 0)
1314 dolog(LL_ERR, "check_config: no remote authentification password in entry %d!", i);
1315 error++;
1318 if((cep->ppp_expect_auth == AUTH_PAP) || (cep->ppp_expect_auth == AUTH_CHAP))
1320 if(cep->ppp_expect_name[0] == 0)
1322 dolog(LL_ERR, "check_config: no local authentification name in entry %d!", i);
1323 error++;
1325 if(cep->ppp_expect_password[0] == 0)
1327 dolog(LL_ERR, "check_config: no local authentification secret in entry %d!", i);
1328 error++;
1332 if(error)
1334 dolog(LL_ERR, "check_config: %d error(s) in configuration file, exit!", error);
1335 do_exit(1);
1339 /*---------------------------------------------------------------------------*
1340 * print the configuration
1341 *---------------------------------------------------------------------------*/
1342 static void
1343 print_config(void)
1345 #define PFILE stdout
1347 #ifdef I4B_EXTERNAL_MONITOR
1348 extern struct monitor_rights * monitor_next_rights(const struct monitor_rights *r);
1349 struct monitor_rights *m_rights;
1350 #endif
1351 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
1352 int i, j;
1353 time_t clock;
1354 char mytime[64];
1356 time(&clock);
1357 strcpy(mytime, ctime(&clock));
1358 mytime[strlen(mytime)-1] = '\0';
1360 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1361 fprintf(PFILE, "# system section (generated %s)\n", mytime);
1362 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1363 fprintf(PFILE, "system\n");
1364 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");
1365 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");
1366 fprintf(PFILE, "acctfile = %s\t\t# accounting information file\n", acctfile);
1367 fprintf(PFILE, "ratesfile = %s\t\t# charging rates database file\n", ratesfile);
1369 #ifdef USE_RTPRIO
1370 if(rt_prio == RTPRIO_NOTUSED)
1371 fprintf(PFILE, "# rtprio is unused\n");
1372 else
1373 fprintf(PFILE, "rtprio = %d\t\t\t\t# isdnd runs at realtime priority\n", rt_prio);
1374 #endif
1376 /* regular expression table */
1378 for(i=0; i < MAX_RE; i++)
1380 if(rarr[i].re_expr != NULL)
1382 fprintf(PFILE, "regexpr = \"%s\"\t\t# scan logfile for this expression\n", rarr[i].re_expr);
1384 if(rarr[i].re_prog != NULL)
1386 fprintf(PFILE, "regprog = %s\t\t# program to run when expression is matched\n", rarr[i].re_prog);
1390 #ifdef I4B_EXTERNAL_MONITOR
1392 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");
1393 fprintf(PFILE, "monitor-port = %d\t\t\t\t# TCP/IP port number used for remote monitoring\n", monitorport);
1395 m_rights = monitor_next_rights(NULL);
1396 if(m_rights != NULL)
1398 char *s = "error\n";
1399 char b[512];
1401 for ( ; m_rights != NULL; m_rights = monitor_next_rights(m_rights))
1403 if(m_rights->local)
1405 fprintf(PFILE, "monitor = \"%s\"\t\t# local socket name for monitoring\n", m_rights->name);
1407 else
1409 struct in_addr ia;
1410 ia.s_addr = ntohl(m_rights->net);
1412 switch(m_rights->mask)
1414 case 0xffffffff:
1415 s = "32";
1416 break;
1417 case 0xfffffffe:
1418 s = "31";
1419 break;
1420 case 0xfffffffc:
1421 s = "30";
1422 break;
1423 case 0xfffffff8:
1424 s = "29";
1425 break;
1426 case 0xfffffff0:
1427 s = "28";
1428 break;
1429 case 0xffffffe0:
1430 s = "27";
1431 break;
1432 case 0xffffffc0:
1433 s = "26";
1434 break;
1435 case 0xffffff80:
1436 s = "25";
1437 break;
1438 case 0xffffff00:
1439 s = "24";
1440 break;
1441 case 0xfffffe00:
1442 s = "23";
1443 break;
1444 case 0xfffffc00:
1445 s = "22";
1446 break;
1447 case 0xfffff800:
1448 s = "21";
1449 break;
1450 case 0xfffff000:
1451 s = "20";
1452 break;
1453 case 0xffffe000:
1454 s = "19";
1455 break;
1456 case 0xffffc000:
1457 s = "18";
1458 break;
1459 case 0xffff8000:
1460 s = "17";
1461 break;
1462 case 0xffff0000:
1463 s = "16";
1464 break;
1465 case 0xfffe0000:
1466 s = "15";
1467 break;
1468 case 0xfffc0000:
1469 s = "14";
1470 break;
1471 case 0xfff80000:
1472 s = "13";
1473 break;
1474 case 0xfff00000:
1475 s = "12";
1476 break;
1477 case 0xffe00000:
1478 s = "11";
1479 break;
1480 case 0xffc00000:
1481 s = "10";
1482 break;
1483 case 0xff800000:
1484 s = "9";
1485 break;
1486 case 0xff000000:
1487 s = "8";
1488 break;
1489 case 0xfe000000:
1490 s = "7";
1491 break;
1492 case 0xfc000000:
1493 s = "6";
1494 break;
1495 case 0xf8000000:
1496 s = "5";
1497 break;
1498 case 0xf0000000:
1499 s = "4";
1500 break;
1501 case 0xe0000000:
1502 s = "3";
1503 break;
1504 case 0xc0000000:
1505 s = "2";
1506 break;
1507 case 0x80000000:
1508 s = "1";
1509 break;
1510 case 0x00000000:
1511 s = "0";
1512 break;
1514 fprintf(PFILE, "monitor = \"%s/%s\"\t\t# host (net/mask) allowed to connect for monitoring\n", inet_ntoa(ia), s);
1516 b[0] = '\0';
1518 if((m_rights->rights) & I4B_CA_COMMAND_FULL)
1519 strcat(b, "fullcmd,");
1520 if((m_rights->rights) & I4B_CA_COMMAND_RESTRICTED)
1521 strcat(b, "restrictedcmd,");
1522 if((m_rights->rights) & I4B_CA_EVNT_CHANSTATE)
1523 strcat(b, "channelstate,");
1524 if((m_rights->rights) & I4B_CA_EVNT_CALLIN)
1525 strcat(b, "callin,");
1526 if((m_rights->rights) & I4B_CA_EVNT_CALLOUT)
1527 strcat(b, "callout,");
1528 if((m_rights->rights) & I4B_CA_EVNT_I4B)
1529 strcat(b, "logevents,");
1531 if(b[strlen(b)-1] == ',')
1532 b[strlen(b)-1] = '\0';
1534 fprintf(PFILE, "monitor-access = %s\t\t# monitor access rights\n", b);
1538 #endif
1539 /* entry sections */
1541 for(i=0; i <= entrycount; i++, cep++)
1543 fprintf(PFILE, "\n");
1544 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1545 fprintf(PFILE, "# entry section %d\n", i);
1546 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1547 fprintf(PFILE, "entry\n");
1549 fprintf(PFILE, "name = %s\t\t# name for this entry section\n", cep->name);
1551 fprintf(PFILE, "isdncontroller = %d\t\t# ISDN card number used for this entry\n", cep->isdncontroller);
1552 fprintf(PFILE, "isdnchannel = ");
1553 switch(cep->isdnchannel)
1555 case CHAN_ANY:
1556 fprintf(PFILE, "-1\t\t# any ISDN B-channel may be used\n");
1557 break;
1558 default:
1559 fprintf(PFILE, "%d\t\t# only ISDN B-channel %d may be used\n", cep->isdnchannel+1, cep->isdnchannel+1);
1560 break;
1563 fprintf(PFILE, "usrdevicename = %s\t\t# name of userland ISDN B-channel device\n", bdrivername(cep->usrdevicename));
1564 fprintf(PFILE, "usrdeviceunit = %d\t\t# unit number of userland ISDN B-channel device\n", cep->usrdeviceunit);
1566 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");
1568 if(!(cep->usrdevicename == BDRV_TEL))
1570 fprintf(PFILE, "direction = ");
1571 switch(cep->inout)
1573 case DIR_INONLY:
1574 fprintf(PFILE, "in\t\t# only incoming connections allowed\n");
1575 break;
1576 case DIR_OUTONLY:
1577 fprintf(PFILE, "out\t\t# only outgoing connections allowed\n");
1578 break;
1579 case DIR_INOUT:
1580 fprintf(PFILE, "inout\t\t# incoming and outgoing connections allowed\n");
1581 break;
1585 if(!((cep->usrdevicename == BDRV_TEL) || (cep->inout == DIR_INONLY)))
1587 if(cep->remote_numbers_count > 1)
1589 for(j=0; j<cep->remote_numbers_count; j++)
1590 fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number %d for dialing out to remote\n", cep->remote_numbers[j].number, j+1);
1592 fprintf(PFILE, "remdial-handling = ");
1594 switch(cep->remote_numbers_handling)
1596 case RNH_NEXT:
1597 fprintf(PFILE, "next\t\t# use next number after last successful for new dial\n");
1598 break;
1599 case RNH_LAST:
1600 fprintf(PFILE, "last\t\t# use last successful number for new dial\n");
1601 break;
1602 case RNH_FIRST:
1603 fprintf(PFILE, "first\t\t# always start with first number for new dial\n");
1604 break;
1607 else
1609 fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number for dialing out to remote\n", cep->remote_numbers[0].number);
1612 fprintf(PFILE, "local-phone-dialout = %s\t\t# show this number to remote when dialling out\n", cep->local_phone_dialout);
1613 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");
1616 if(!(cep->inout == DIR_OUTONLY))
1618 int n;
1620 fprintf(PFILE, "local-phone-incoming = %s\t\t# incoming calls must match this (mine) telephone number\n", cep->local_phone_incoming);
1621 for (n = 0; n < cep->incoming_numbers_count; n++)
1622 fprintf(PFILE, "remote-phone-incoming = %s\t\t# this is a valid remote number to call me\n",
1623 cep->remote_phone_incoming[n].number);
1625 fprintf(PFILE, "dialin-reaction = ");
1626 switch(cep->dialin_reaction)
1628 case REACT_ACCEPT:
1629 fprintf(PFILE, "accept\t\t# i accept a call from remote and connect\n");
1630 break;
1631 case REACT_REJECT:
1632 fprintf(PFILE, "reject\t\t# i reject the call from remote\n");
1633 break;
1634 case REACT_IGNORE:
1635 fprintf(PFILE, "ignore\t\t# i ignore the call from remote\n");
1636 break;
1637 case REACT_ANSWER:
1638 fprintf(PFILE, "answer\t\t# i will start telephone answering when remote calls in\n");
1639 break;
1640 case REACT_CALLBACK:
1641 fprintf(PFILE, "callback\t\t# when remote calls in, i will hangup and call back\n");
1642 break;
1646 if(cep->usrdevicename == BDRV_ISPPP)
1648 char *s;
1649 switch(cep->ppp_expect_auth)
1651 case AUTH_NONE:
1652 s = "none";
1653 break;
1654 case AUTH_PAP:
1655 s = "pap";
1656 break;
1657 case AUTH_CHAP:
1658 s = "chap";
1659 break;
1660 default:
1661 s = NULL;
1662 break;
1664 if(s != NULL)
1666 fprintf(PFILE, "ppp-expect-auth = %s\t\t# the auth protocol we expect to receive on dial-in (none,pap,chap)\n", s);
1667 if(cep->ppp_expect_auth != AUTH_NONE)
1669 fprintf(PFILE, "ppp-expect-name = %s\t\t# the user name allowed in\n", cep->ppp_expect_name);
1670 fprintf(PFILE, "ppp-expect-password = %s\t\t# the key expected from the other side\n", cep->ppp_expect_password);
1671 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");
1674 switch(cep->ppp_send_auth)
1676 case AUTH_NONE:
1677 s = "none";
1678 break;
1679 case AUTH_PAP:
1680 s = "pap";
1681 break;
1682 case AUTH_CHAP:
1683 s = "chap";
1684 break;
1685 default:
1686 s = NULL;
1687 break;
1689 if(s != NULL)
1691 fprintf(PFILE, "ppp-send-auth = %s\t\t# the auth protocol we use when dialing out (none,pap,chap)\n", s);
1692 if(cep->ppp_send_auth != AUTH_NONE)
1694 fprintf(PFILE, "ppp-send-name = %s\t\t# our PPP account used for dial-out\n", cep->ppp_send_name);
1695 fprintf(PFILE, "ppp-send-password = %s\t\t# the key sent to the other side\n", cep->ppp_send_password);
1698 if(cep->ppp_send_auth == AUTH_CHAP ||
1699 cep->ppp_expect_auth == AUTH_CHAP) {
1700 fprintf(PFILE, "ppp-auth-rechallenge = %s\t\t# rechallenge CHAP connections once in a while\n", cep->ppp_auth_flags & AUTH_RECHALLENGE ? "yes" : "no");
1704 if(!((cep->inout == DIR_INONLY) || (cep->usrdevicename == BDRV_TEL)))
1706 char *s;
1707 fprintf(PFILE, "idletime-outgoing = %d\t\t# outgoing call idle timeout\n", cep->idle_time_out);
1709 switch( cep->shorthold_algorithm )
1711 case SHA_FIXU:
1712 s = "fix-unit-size";
1713 break;
1714 case SHA_VARU:
1715 s = "var-unit-size";
1716 break;
1717 default:
1718 s = "error!!!";
1719 break;
1722 fprintf(PFILE, "idle-algorithm-outgoing = %s\t\t# outgoing call idle algorithm\n", s);
1725 if(!(cep->inout == DIR_OUTONLY))
1726 fprintf(PFILE, "idletime-incoming = %d\t\t# incoming call idle timeout\n", cep->idle_time_in);
1728 if(!(cep->usrdevicename == BDRV_TEL))
1730 fprintf(PFILE, "unitlengthsrc = ");
1731 switch(cep->unitlengthsrc)
1733 case ULSRC_NONE:
1734 fprintf(PFILE, "none\t\t# no unit length specified, using default\n");
1735 break;
1736 case ULSRC_CMDL:
1737 fprintf(PFILE, "cmdl\t\t# using unit length specified on commandline\n");
1738 break;
1739 case ULSRC_CONF:
1740 fprintf(PFILE, "conf\t\t# using unitlength specified by unitlength-keyword\n");
1741 fprintf(PFILE, "unitlength = %d\t\t# fixed unitlength\n", cep->unitlength);
1742 break;
1743 case ULSRC_RATE:
1744 fprintf(PFILE, "rate\t\t# using unitlength specified in rate database\n");
1745 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1746 break;
1747 case ULSRC_DYN:
1748 fprintf(PFILE, "aocd\t\t# using dynamically calculated unitlength based on AOCD subscription\n");
1749 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1750 break;
1753 fprintf(PFILE, "earlyhangup = %d\t\t# early hangup safety time\n", cep->earlyhangup);
1757 if(cep->usrdevicename == BDRV_TEL)
1759 fprintf(PFILE, "answerprog = %s\t\t# program used to answer incoming telephone calls\n", cep->answerprog);
1760 fprintf(PFILE, "alert = %d\t\t# number of seconds to wait before accepting a call\n", cep->alert);
1763 if(!(cep->usrdevicename == BDRV_TEL))
1765 if(cep->dialin_reaction == REACT_CALLBACK)
1766 fprintf(PFILE, "callbackwait = %d\t\t# i am waiting this time before calling back remote\n", cep->callbackwait);
1768 if(cep->dialouttype == DIALOUT_CALLEDBACK)
1769 fprintf(PFILE, "calledbackwait = %d\t\t# i am waiting this time for a call back from remote\n", cep->calledbackwait);
1771 if(!(cep->inout == DIR_INONLY))
1773 fprintf(PFILE, "dialretries = %d\t\t# number of dialing retries\n", cep->dialretries);
1774 fprintf(PFILE, "recoverytime = %d\t\t# time to wait between dialling retries\n", cep->recoverytime);
1775 fprintf(PFILE, "dialrandincr = %s\t\t# use random dialing time addon\n", cep->dialrandincr ? "on" : "off");
1777 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");
1778 if(cep->usedown)
1780 fprintf(PFILE, "downtries = %d\t\t# number of dialretries failures before switching off\n", cep->downtries);
1781 fprintf(PFILE, "downtime = %d\t\t# time device is switched off\n", cep->downtime);
1786 fprintf(PFILE, "\n");
1789 /* EOF */