2 * Copyright (c) 1997, 2002 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
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
25 *---------------------------------------------------------------------------
27 * i4b daemon - config file processing
28 * -----------------------------------
32 * last edit-date: [Sat May 13 13:11:48 2006]
34 *---------------------------------------------------------------------------*/
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
41 #include <sys/ioctl.h>
50 extern int entrycount;
51 extern int controllercount;
58 static void set_config_defaults(void);
59 static void check_config(void);
60 static void print_config(void);
61 static void parse_valid(int entrycount, char *dt);
63 static int nregexpr = 0;
64 static int nregprog = 0;
66 /*---------------------------------------------------------------------------*
67 * called from main to read and process config file
68 *---------------------------------------------------------------------------*/
70 configure(char *filename, int reread)
72 extern void reset_scanner(FILE *inputfile);
74 set_config_defaults();
76 yyin = fopen(filename, "r");
80 llog(LL_ERR, "cannot fopen file [%s]", filename);
91 monitor_fixup_rights();
93 check_config(); /* validation and consistency check */
101 llog(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag);
109 /*---------------------------------------------------------------------------*
111 *---------------------------------------------------------------------------*/
113 yyerror(const char *msg)
115 llog(LL_ERR, "configuration error: %s at line %d, token \"%s\"", msg, lineno+1, yytext);
119 /*---------------------------------------------------------------------------*
120 * fill all config entries with default values
121 *---------------------------------------------------------------------------*/
123 set_config_defaults(void)
125 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
128 /* system section cleanup */
130 nregprog = nregexpr = 0;
132 rt_prio = RTPRIO_NOTUSED;
137 /* clean regular expression table */
139 for(i=0; i < MAX_RE; i++)
142 free(rarr[i].re_expr);
143 rarr[i].re_expr = NULL;
146 free(rarr[i].re_prog);
147 rarr[i].re_prog = NULL;
152 strcpy(rotatesuffix, "");
155 * controller table cleanup, beware: has already
156 * been setup in main, init_controller() !
159 for(i=0; i < ncontroller; i++)
161 isdn_ctrl_tab[i].protocol = PROTOCOL_DSS1;
162 isdn_ctrl_tab[i].firmware = NULL;
165 /* entry section cleanup */
167 for(i=0; i < CFG_ENTRY_MAX; i++, cep++)
169 bzero(cep, sizeof(cfg_entry_t));
171 /* ====== filled in at startup configuration, then static */
173 sprintf(cep->name, "ENTRY%d", i);
175 cep->isdncontroller = INVALID;
176 cep->isdnchannel = CHAN_ANY;
178 cep->usrdevicename = INVALID;
179 cep->usrdeviceunit = INVALID;
181 cep->remote_numbers_handling = RNH_LAST;
183 cep->dialin_reaction = REACT_IGNORE;
185 cep->b1protocol = BPROT_NONE;
187 cep->unitlength = UNITLENGTH_DEFAULT;
189 cep->earlyhangup = EARLYHANGUP_DEFAULT;
191 cep->ratetype = INVALID_RATE;
193 cep->unitlengthsrc = ULSRC_NONE;
195 cep->answerprog = ANSWERPROG_DEF;
197 cep->callbackwait = CALLBACKWAIT_MIN;
199 cep->calledbackwait = CALLEDBACKWAIT_MIN;
201 cep->dialretries = DIALRETRIES_DEF;
203 cep->recoverytime = RECOVERYTIME_MIN;
205 cep->dialouttype = DIALOUT_NORMAL;
207 cep->inout = DIR_INOUT;
209 cep->ppp_expect_auth = AUTH_UNDEF;
211 cep->ppp_send_auth = AUTH_UNDEF;
213 cep->ppp_auth_flags = AUTH_RECHALLENGE | AUTH_REQUIRED;
215 /* ======== filled in after start, then dynamic */
217 cep->cdid = CDID_UNUSED;
219 cep->state = ST_IDLE;
221 cep->aoc_valid = AOC_INVALID;
227 /*---------------------------------------------------------------------------*
228 * internaly set values for ommitted controler sectin
229 *---------------------------------------------------------------------------*/
231 cfg_set_controller_default()
234 DBGL(DL_RCCF, (llog(LL_DBG, "[defaults, no controller section] controller %d: protocol = dss1", controllercount)));
235 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_DSS1;
238 #define PPP_PAP 0xc023
239 #define PPP_CHAP 0xc223
242 set_isppp_auth(int entry)
244 cfg_entry_t *cep = &cfg_entry_tab[entry]; /* ptr to config entry */
251 if(cep->usrdevicename != BDRV_ISPPP)
254 if(cep->ppp_expect_auth == AUTH_UNDEF
255 && cep->ppp_send_auth == AUTH_UNDEF)
258 if(cep->ppp_expect_auth == AUTH_NONE
259 || cep->ppp_send_auth == AUTH_NONE)
262 if ((cep->ppp_expect_auth == AUTH_CHAP
263 || cep->ppp_expect_auth == AUTH_PAP)
264 && cep->ppp_expect_name[0] != 0
265 && cep->ppp_expect_password[0] != 0)
268 if ((cep->ppp_send_auth == AUTH_CHAP || cep->ppp_send_auth == AUTH_PAP)
269 && cep->ppp_send_name[0] != 0
270 && cep->ppp_send_password[0] != 0)
276 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "isp%d", cep->usrdeviceunit);
278 /* use a random AF to create the socket */
279 if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
280 llog(LL_ERR, "ERROR opening control socket at line %d!", lineno);
284 spr.cmd = (int)SPPPIOGDEFS;
285 ifr.ifr_data = (caddr_t)&spr;
287 if (ioctl(s, SIOCGIFGENERIC, &ifr) == -1) {
288 llog(LL_ERR, "ERROR fetching active PPP authentication info for %s at line %d!", ifr.ifr_name, lineno);
293 if (cep->ppp_expect_auth != AUTH_UNDEF)
295 if(cep->ppp_expect_auth == AUTH_NONE)
297 spr.defs.hisauth.proto = 0;
299 else if ((cep->ppp_expect_auth == AUTH_CHAP
300 || cep->ppp_expect_auth == AUTH_PAP)
301 && cep->ppp_expect_name[0] != 0
302 && cep->ppp_expect_password[0] != 0)
304 spr.defs.hisauth.proto = cep->ppp_expect_auth == AUTH_PAP ? PPP_PAP : PPP_CHAP;
305 strncpy(spr.defs.hisauth.name, cep->ppp_expect_name, AUTHNAMELEN);
306 strncpy(spr.defs.hisauth.secret, cep->ppp_expect_password, AUTHKEYLEN);
309 if (cep->ppp_send_auth != AUTH_UNDEF)
311 if(cep->ppp_send_auth == AUTH_NONE)
313 spr.defs.myauth.proto = 0;
315 else if ((cep->ppp_send_auth == AUTH_CHAP
316 || cep->ppp_send_auth == AUTH_PAP)
317 && cep->ppp_send_name[0] != 0
318 && cep->ppp_send_password[0] != 0)
320 spr.defs.myauth.proto = cep->ppp_send_auth == AUTH_PAP ? PPP_PAP : PPP_CHAP;
321 strncpy(spr.defs.myauth.name, cep->ppp_send_name, AUTHNAMELEN);
322 strncpy(spr.defs.myauth.secret, cep->ppp_send_password, AUTHKEYLEN);
324 if(cep->ppp_auth_flags & AUTH_REQUIRED)
325 spr.defs.hisauth.flags &= ~AUTHFLAG_NOCALLOUT;
327 spr.defs.hisauth.flags |= AUTHFLAG_NOCALLOUT;
329 if(cep->ppp_auth_flags & AUTH_RECHALLENGE)
330 spr.defs.hisauth.flags &= ~AUTHFLAG_NORECHALLENGE;
332 spr.defs.hisauth.flags |= AUTHFLAG_NORECHALLENGE;
336 spr.cmd = (int)SPPPIOSDEFS;
338 if (ioctl(s, SIOCSIFGENERIC, &ifr) == -1) {
339 llog(LL_ERR, "ERROR setting new PPP authentication parameters for %s at line %d!", ifr.ifr_name, lineno);
345 /*---------------------------------------------------------------------------*
346 * extract values from config and fill table
347 *---------------------------------------------------------------------------*/
349 cfg_setval(int keyword)
356 acct_all = yylval.booln;
357 DBGL(DL_RCCF, (llog(LL_DBG, "system: acctall = %d", yylval.booln)));
361 strcpy(acctfile, yylval.str);
362 DBGL(DL_RCCF, (llog(LL_DBG, "system: acctfile = %s", yylval.str)));
366 addprefix = yylval.booln;
367 DBGL(DL_RCCF, (llog(LL_DBG, "system: add-prefix = %d", yylval.booln)));
371 if(yylval.num < MINALERT)
373 yylval.num = MINALERT;
374 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: alert < %d, min = %d", entrycount, MINALERT, yylval.num)));
376 else if(yylval.num > MAXALERT)
378 yylval.num = MAXALERT;
379 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: alert > %d, min = %d", entrycount, MAXALERT, yylval.num)));
382 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: alert = %d", entrycount, yylval.num)));
383 cfg_entry_tab[entrycount].alert = yylval.num;
387 DBGL(DL_RCCF, (llog(LL_DBG, "system: aliasing = %d", yylval.booln)));
388 aliasing = yylval.booln;
392 strcpy(aliasfile, yylval.str);
393 DBGL(DL_RCCF, (llog(LL_DBG, "system: aliasfile = %s", yylval.str)));
397 if((cfg_entry_tab[entrycount].answerprog = malloc(strlen(yylval.str)+1)) == NULL)
399 llog(LL_ERR, "entry %d: answerstring, malloc failed!", entrycount);
402 strcpy(cfg_entry_tab[entrycount].answerprog, yylval.str);
403 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: answerprog = %s", entrycount, yylval.str)));
407 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: b1protocol = %s", entrycount, yylval.str)));
408 if(!(strcmp(yylval.str, "raw")))
409 cfg_entry_tab[entrycount].b1protocol = BPROT_NONE;
410 else if(!(strcmp(yylval.str, "hdlc")))
411 cfg_entry_tab[entrycount].b1protocol = BPROT_RHDLC;
414 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"b1protocol\" at line %d!", lineno);
420 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: bcap = %s", entrycount, yylval.str)));
421 cfg_entry_tab[entrycount].bcap = BCAP_NONE;
422 if(!(strcmp(yylval.str, "dov")))
423 cfg_entry_tab[entrycount].bcap = BCAP_DOV;
427 do_bell = yylval.booln;
428 DBGL(DL_RCCF, (llog(LL_DBG, "system: beepconnect = %d", yylval.booln)));
431 case BUDGETCALLBACKPERIOD:
432 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-callbackperiod = %d", entrycount, yylval.num)));
433 cfg_entry_tab[entrycount].budget_callbackperiod = yylval.num;
436 case BUDGETCALLBACKNCALLS:
437 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-callbackncalls = %d", entrycount, yylval.num)));
438 cfg_entry_tab[entrycount].budget_callbackncalls = yylval.num;
441 case BUDGETCALLOUTPERIOD:
442 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-calloutperiod = %d", entrycount, yylval.num)));
443 cfg_entry_tab[entrycount].budget_calloutperiod = yylval.num;
446 case BUDGETCALLOUTNCALLS:
447 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-calloutncalls = %d", entrycount, yylval.num)));
448 cfg_entry_tab[entrycount].budget_calloutncalls = yylval.num;
451 case BUDGETCALLBACKSFILEROTATE:
452 cfg_entry_tab[entrycount].budget_callbacksfile_rotate = yylval.booln;
453 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-callbacksfile-rotate = %d", entrycount, yylval.booln)));
456 case BUDGETCALLBACKSFILE:
461 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-callbacksfile = %s", entrycount, yylval.str)));
462 fp = fopen(yylval.str, "r");
465 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
467 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: initializing budget-callbacksfile %s", entrycount, yylval.str)));
469 fp = fopen(yylval.str, "w");
472 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
479 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: creating budget-callbacksfile %s", entrycount, yylval.str)));
480 fp = fopen(yylval.str, "w");
483 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
488 fp = fopen(yylval.str, "r");
491 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
493 if((cfg_entry_tab[entrycount].budget_callbacks_file = malloc(strlen(yylval.str)+1)) == NULL)
495 llog(LL_ERR, "entry %d: budget-callbacksfile, malloc failed!", entrycount);
498 strcpy(cfg_entry_tab[entrycount].budget_callbacks_file, yylval.str);
499 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: using callbacksfile %s", entrycount, yylval.str)));
506 case BUDGETCALLOUTSFILEROTATE:
507 cfg_entry_tab[entrycount].budget_calloutsfile_rotate = yylval.booln;
508 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-calloutsfile-rotate = %d", entrycount, yylval.booln)));
511 case BUDGETCALLOUTSFILE:
516 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: budget-calloutsfile = %s", entrycount, yylval.str)));
517 fp = fopen(yylval.str, "r");
520 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) != 3)
522 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: initializing budget-calloutsfile %s", entrycount, yylval.str)));
524 fp = fopen(yylval.str, "w");
527 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
534 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: creating budget-calloutsfile %s", entrycount, yylval.str)));
535 fp = fopen(yylval.str, "w");
538 fprintf(fp, "%d %d %d", (int)time(NULL), (int)time(NULL), 0);
543 fp = fopen(yylval.str, "r");
546 if((fscanf(fp, "%d %d %d", (int *)&s, (int *)&l, &n)) == 3)
548 if((cfg_entry_tab[entrycount].budget_callouts_file = malloc(strlen(yylval.str)+1)) == NULL)
550 llog(LL_ERR, "entry %d: budget-calloutsfile, malloc failed!", entrycount);
553 strcpy(cfg_entry_tab[entrycount].budget_callouts_file, yylval.str);
554 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: using calloutsfile %s", entrycount, yylval.str)));
562 if(yylval.num < CALLBACKWAIT_MIN)
564 yylval.num = CALLBACKWAIT_MIN;
565 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: callbackwait < %d, min = %d", entrycount, CALLBACKWAIT_MIN, yylval.num)));
568 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: callbackwait = %d", entrycount, yylval.num)));
569 cfg_entry_tab[entrycount].callbackwait = yylval.num;
573 if(yylval.num < CALLEDBACKWAIT_MIN)
575 yylval.num = CALLEDBACKWAIT_MIN;
576 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: calledbackwait < %d, min = %d", entrycount, CALLEDBACKWAIT_MIN, yylval.num)));
579 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: calledbackwait = %d", entrycount, yylval.num)));
580 cfg_entry_tab[entrycount].calledbackwait = yylval.num;
585 * clone = <entryname>
586 * Loads the entry from the named, existing one.
587 * Fields such as name and usrdeviceunit should
588 * always be specified after clone as they must be
591 * NOTE: all malloc()'d fields must be dup()'d here,
592 * we can't have multiple references to same storage.
594 for (i = 0; i < entrycount; i++)
595 if (!strcmp(cfg_entry_tab[i].name, yylval.str))
597 if (i == entrycount) {
598 llog(LL_ERR, "entry %d: clone, unknown entry %s!", entrycount, yylval.str);
602 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: clone = %s", entrycount, yylval.str)));
604 memcpy(&cfg_entry_tab[entrycount], &cfg_entry_tab[i],
605 sizeof(cfg_entry_tab[0]));
607 if (cfg_entry_tab[entrycount].answerprog)
608 cfg_entry_tab[entrycount].answerprog = strdup(cfg_entry_tab[entrycount].answerprog);
609 if (cfg_entry_tab[entrycount].budget_callbacks_file)
610 cfg_entry_tab[entrycount].budget_callbacks_file = strdup(cfg_entry_tab[entrycount].budget_callbacks_file);
611 if (cfg_entry_tab[entrycount].budget_callouts_file)
612 cfg_entry_tab[entrycount].budget_callouts_file = strdup(cfg_entry_tab[entrycount].budget_callouts_file);
613 if (cfg_entry_tab[entrycount].connectprog)
614 cfg_entry_tab[entrycount].connectprog = strdup(cfg_entry_tab[entrycount].connectprog);
615 if (cfg_entry_tab[entrycount].disconnectprog)
616 cfg_entry_tab[entrycount].disconnectprog = strdup(cfg_entry_tab[entrycount].disconnectprog);
620 if((cfg_entry_tab[entrycount].connectprog = malloc(strlen(yylval.str)+1)) == NULL)
622 llog(LL_ERR, "entry %d: connectprog, malloc failed!", entrycount);
625 strcpy(cfg_entry_tab[entrycount].connectprog, yylval.str);
626 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: connectprog = %s", entrycount, yylval.str)));
630 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: dialouttype = %s", entrycount, yylval.str)));
631 if(!(strcmp(yylval.str, "normal")))
632 cfg_entry_tab[entrycount].dialouttype = DIALOUT_NORMAL;
633 else if(!(strcmp(yylval.str, "calledback")))
634 cfg_entry_tab[entrycount].dialouttype = DIALOUT_CALLEDBACK;
637 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialout-type\" at line %d!", lineno);
643 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: dialretries = %d", entrycount, yylval.num)));
644 cfg_entry_tab[entrycount].dialretries = yylval.num;
648 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: dialrandincr = %d", entrycount, yylval.booln)));
649 cfg_entry_tab[entrycount].dialrandincr = yylval.booln;
653 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: direction = %s", entrycount, yylval.str)));
655 if(!(strcmp(yylval.str, "inout")))
656 cfg_entry_tab[entrycount].inout = DIR_INOUT;
657 else if(!(strcmp(yylval.str, "in")))
658 cfg_entry_tab[entrycount].inout = DIR_INONLY;
659 else if(!(strcmp(yylval.str, "out")))
660 cfg_entry_tab[entrycount].inout = DIR_OUTONLY;
663 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"direction\" at line %d!", lineno);
669 if((cfg_entry_tab[entrycount].disconnectprog = malloc(strlen(yylval.str)+1)) == NULL)
671 llog(LL_ERR, "entry %d: disconnectprog, malloc failed!", entrycount);
674 strcpy(cfg_entry_tab[entrycount].disconnectprog, yylval.str);
675 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: disconnectprog = %s", entrycount, yylval.str)));
679 if(yylval.num > DOWN_TRIES_MAX)
680 yylval.num = DOWN_TRIES_MAX;
681 else if(yylval.num < DOWN_TRIES_MIN)
682 yylval.num = DOWN_TRIES_MIN;
684 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: downtries = %d", entrycount, yylval.num)));
685 cfg_entry_tab[entrycount].downtries = yylval.num;
689 if(yylval.num > DOWN_TIME_MAX)
690 yylval.num = DOWN_TIME_MAX;
691 else if(yylval.num < DOWN_TIME_MIN)
692 yylval.num = DOWN_TIME_MIN;
694 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: downtime = %d", entrycount, yylval.num)));
695 cfg_entry_tab[entrycount].downtime = yylval.num;
699 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: earlyhangup = %d", entrycount, yylval.num)));
700 cfg_entry_tab[entrycount].earlyhangup = yylval.num;
704 DBGL(DL_RCCF, (llog(LL_DBG, "system: extcallattr = %d", yylval.booln)));
705 extcallattr = yylval.booln;
709 DBGL(DL_RCCF, (llog(LL_DBG, "controller %d: firmware = %s", controllercount, yylval.str)));
710 isdn_ctrl_tab[controllercount].firmware = strdup(yylval.str);
714 strcpy(holidayfile, yylval.str);
715 DBGL(DL_RCCF, (llog(LL_DBG, "system: holidayfile = %s", yylval.str)));
719 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: idle-algorithm-outgoing = %s", entrycount, yylval.str)));
721 if(!(strcmp(yylval.str, "fix-unit-size")))
723 cfg_entry_tab[entrycount].shorthold_algorithm = SHA_FIXU;
725 else if(!(strcmp(yylval.str, "var-unit-size")))
727 cfg_entry_tab[entrycount].shorthold_algorithm = SHA_VARU;
731 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"idle-algorithm-outgoing\" at line %d!", lineno);
737 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: idle_time_in = %d", entrycount, yylval.num)));
738 cfg_entry_tab[entrycount].idle_time_in = yylval.num;
742 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: idle_time_out = %d", entrycount, yylval.num)));
743 cfg_entry_tab[entrycount].idle_time_out = yylval.num;
747 cfg_entry_tab[entrycount].isdncontroller = yylval.num;
748 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: isdncontroller = %d", entrycount, yylval.num)));
752 if (yylval.num == 0 || yylval.num == -1)
754 cfg_entry_tab[entrycount].isdnchannel = CHAN_ANY;
755 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: isdnchannel = any", entrycount)));
757 else if (yylval.num > MAX_BCHAN)
759 llog(LL_DBG, "entry %d: isdnchannel value out of range", entrycount);
764 cfg_entry_tab[entrycount].isdnchannel = yylval.num-1;
765 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: isdnchannel = B%d", entrycount, yylval.num)));
770 DBGL(DL_RCCF, (llog(LL_DBG, "system: isdntime = %d", yylval.booln)));
771 isdntime = yylval.booln;
775 cfg_entry_tab[entrycount].isdntxdelin = yylval.num;
776 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: isdntxdel-incoming = %d", entrycount, yylval.num)));
780 cfg_entry_tab[entrycount].isdntxdelout = yylval.num;
781 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: isdntxdel-outgoing = %d", entrycount, yylval.num)));
784 case LOCAL_PHONE_DIALOUT:
785 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: local_phone_dialout = %s", entrycount, yylval.str)));
786 strcpy(cfg_entry_tab[entrycount].local_phone_dialout.number, yylval.str);
789 case LOCAL_SUBADDR_DIALOUT:
790 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: local_subaddr_dialout = %s", entrycount, yylval.str)));
791 strcpy(cfg_entry_tab[entrycount].local_phone_dialout.subaddr, yylval.str);
794 case LOCAL_PHONE_INCOMING:
795 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: local_phone_incoming = %s", entrycount, yylval.str)));
796 strcpy(cfg_entry_tab[entrycount].local_phone_incoming.number, yylval.str);
799 case LOCAL_SUBADDR_INCOMING:
800 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: local_subaddr_incoming = %s", entrycount, yylval.str)));
801 strcpy(cfg_entry_tab[entrycount].local_phone_incoming.subaddr, yylval.str);
805 strcpy(mailer, yylval.str);
806 DBGL(DL_RCCF, (llog(LL_DBG, "system: mailer = %s", yylval.str)));
810 strcpy(mailto, yylval.str);
811 DBGL(DL_RCCF, (llog(LL_DBG, "system: mailto = %s", yylval.str)));
815 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: maxconnecttime = %d", entrycount, yylval.num)));
816 cfg_entry_tab[entrycount].maxconnecttime = yylval.num;
820 monitorport = yylval.num;
821 DBGL(DL_RCCF, (llog(LL_DBG, "system: monitorport = %d", yylval.num)));
825 if (yylval.booln && inhibit_monitor)
828 DBGL(DL_RCCF, (llog(LL_DBG, "system: monitor-enable overriden by command line flag")));
832 do_monitor = yylval.booln;
833 DBGL(DL_RCCF, (llog(LL_DBG, "system: monitor-enable = %d", yylval.booln)));
838 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: name = %s", entrycount, yylval.str)));
839 strcpy(cfg_entry_tab[entrycount].name, yylval.str);
842 case PPP_AUTH_RECHALLENGE:
843 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-auth-rechallenge = %d", entrycount, yylval.booln)));
845 cfg_entry_tab[entrycount].ppp_auth_flags |= AUTH_RECHALLENGE;
847 cfg_entry_tab[entrycount].ppp_auth_flags &= ~AUTH_RECHALLENGE;
848 set_isppp_auth(entrycount);
851 case PPP_AUTH_PARANOID:
852 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-auth-paranoid = %d", entrycount, yylval.booln)));
854 cfg_entry_tab[entrycount].ppp_auth_flags |= AUTH_REQUIRED;
856 cfg_entry_tab[entrycount].ppp_auth_flags &= ~AUTH_REQUIRED;
857 set_isppp_auth(entrycount);
860 case PPP_EXPECT_AUTH:
861 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-expect-auth = %s", entrycount, yylval.str)));
862 if(!(strcmp(yylval.str, "none")))
863 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_NONE;
864 else if(!(strcmp(yylval.str, "pap")))
865 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_PAP;
866 else if(!(strcmp(yylval.str, "chap")))
867 cfg_entry_tab[entrycount].ppp_expect_auth = AUTH_CHAP;
870 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-expect-auth\" at line %d!", lineno);
874 set_isppp_auth(entrycount);
877 case PPP_EXPECT_NAME:
878 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-expect-name = %s", entrycount, yylval.str)));
879 strncpy(cfg_entry_tab[entrycount].ppp_expect_name, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_expect_name) -1);
880 set_isppp_auth(entrycount);
883 case PPP_EXPECT_PASSWORD:
884 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-expect-password = %s", entrycount, yylval.str)));
885 strncpy(cfg_entry_tab[entrycount].ppp_expect_password, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_expect_password) -1);
886 set_isppp_auth(entrycount);
890 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-send-auth = %s", entrycount, yylval.str)));
891 if(!(strcmp(yylval.str, "none")))
892 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_NONE;
893 else if(!(strcmp(yylval.str, "pap")))
894 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_PAP;
895 else if(!(strcmp(yylval.str, "chap")))
896 cfg_entry_tab[entrycount].ppp_send_auth = AUTH_CHAP;
899 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"ppp-send-auth\" at line %d!", lineno);
903 set_isppp_auth(entrycount);
907 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-send-name = %s", entrycount, yylval.str)));
908 strncpy(cfg_entry_tab[entrycount].ppp_send_name, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_send_name) -1);
909 set_isppp_auth(entrycount);
912 case PPP_SEND_PASSWORD:
913 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ppp-send-password = %s", entrycount, yylval.str)));
914 strncpy(cfg_entry_tab[entrycount].ppp_send_password, yylval.str, sizeof(cfg_entry_tab[entrycount].ppp_send_password) -1);
915 set_isppp_auth(entrycount);
918 case PREFIXINTERNATIONAL:
919 strncpy(prefixinternational, yylval.str, sizeof(prefixinternational)-1);
920 DBGL(DL_RCCF, (llog(LL_DBG, "system: prefix-international = %s", prefixinternational)));
924 strncpy(prefixnational, yylval.str, sizeof(prefixnational)-1);
925 DBGL(DL_RCCF, (llog(LL_DBG, "system: prefix-national = %s", prefixnational)));
929 DBGL(DL_RCCF, (llog(LL_DBG, "controller %d: protocol = %s", controllercount, yylval.str)));
930 if(!(strcmp(yylval.str, "dss1")))
931 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_DSS1;
932 else if(!(strcmp(yylval.str, "d64s")))
933 isdn_ctrl_tab[controllercount].protocol = PROTOCOL_D64S;
936 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"protocol\" at line %d!", lineno);
942 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: dialin_reaction = %s", entrycount, yylval.str)));
943 if(!(strcmp(yylval.str, "accept")))
944 cfg_entry_tab[entrycount].dialin_reaction = REACT_ACCEPT;
945 else if(!(strcmp(yylval.str, "reject")))
946 cfg_entry_tab[entrycount].dialin_reaction = REACT_REJECT;
947 else if(!(strcmp(yylval.str, "ignore")))
948 cfg_entry_tab[entrycount].dialin_reaction = REACT_IGNORE;
949 else if(!(strcmp(yylval.str, "answer")))
950 cfg_entry_tab[entrycount].dialin_reaction = REACT_ANSWER;
951 else if(!(strcmp(yylval.str, "callback")))
952 cfg_entry_tab[entrycount].dialin_reaction = REACT_CALLBACK;
955 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialin_reaction\" at line %d!", lineno);
960 case REMOTE_PHONE_DIALOUT:
961 if(cfg_entry_tab[entrycount].remote_numbers_count >= MAXRNUMBERS)
963 llog(LL_ERR, "ERROR parsing config file: too many remote numbers at line %d!", lineno);
968 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: remote_phone_dialout #%d = %s",
969 entrycount, cfg_entry_tab[entrycount].remote_numbers_count, yylval.str)));
971 strcpy(cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].number, yylval.str);
972 cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].flag = 0;
974 cfg_entry_tab[entrycount].remote_numbers_count++;
978 case REMOTE_SUBADDR_DIALOUT:
979 if(cfg_entry_tab[entrycount].remote_subaddr_count >= MAXRNUMBERS)
981 llog(LL_ERR, "ERROR parsing config file: too many remote subaddresses at line %d!", lineno);
986 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: remote_subaddr_dialout #%d = %s",
987 entrycount, cfg_entry_tab[entrycount].remote_numbers_count, yylval.str)));
989 strcpy(cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].subaddr, yylval.str);
993 case REMOTE_NUMBERS_HANDLING:
994 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: remdial_handling = %s", entrycount, yylval.str)));
995 if(!(strcmp(yylval.str, "next")))
996 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_NEXT;
997 else if(!(strcmp(yylval.str, "last")))
998 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_LAST;
999 else if(!(strcmp(yylval.str, "first")))
1000 cfg_entry_tab[entrycount].remote_numbers_handling = RNH_FIRST;
1003 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"remdial_handling\" at line %d!", lineno);
1004 config_error_flag++;
1008 case REMOTE_PHONE_INCOMING:
1011 n = cfg_entry_tab[entrycount].incoming_numbers_count;
1012 if (n >= MAX_INCOMING)
1014 llog(LL_ERR, "ERROR parsing config file: too many \"remote_phone_incoming\" entries at line %d!", lineno);
1015 config_error_flag++;
1018 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: remote_phone_incoming #%d = %s", entrycount, n, yylval.str)));
1019 strcpy(cfg_entry_tab[entrycount].remote_phone_incoming[n].number, yylval.str);
1020 cfg_entry_tab[entrycount].incoming_numbers_count++;
1024 case REMOTE_SUBADDR_INCOMING:
1027 n = cfg_entry_tab[entrycount].incoming_numbers_count;
1028 if (n >= MAX_INCOMING)
1030 llog(LL_ERR, "ERROR parsing config file: too many \"remote_subaddr_incoming\" entries at line %d!", lineno);
1031 config_error_flag++;
1034 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: remote_subaddr_incoming #%d = %s", entrycount, n, yylval.str)));
1035 strcpy(cfg_entry_tab[entrycount].remote_phone_incoming[n].subaddr, yylval.str);
1040 strcpy(ratesfile, yylval.str);
1041 DBGL(DL_RCCF, (llog(LL_DBG, "system: ratesfile = %s", yylval.str)));
1045 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: ratetype = %d", entrycount, yylval.num)));
1046 cfg_entry_tab[entrycount].ratetype = yylval.num;
1050 if(yylval.num < RECOVERYTIME_MIN)
1052 yylval.num = RECOVERYTIME_MIN;
1053 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: recoverytime < %d, min = %d", entrycount, RECOVERYTIME_MIN, yylval.num)));
1056 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: recoverytime = %d", entrycount, yylval.num)));
1057 cfg_entry_tab[entrycount].recoverytime = yylval.num;
1061 if(nregexpr >= MAX_RE)
1063 llog(LL_ERR, "system: regexpr #%d >= MAX_RE", nregexpr);
1064 config_error_flag++;
1068 if((i = regcomp(&(rarr[nregexpr].re), yylval.str, REG_EXTENDED|REG_NOSUB)) != 0)
1071 regerror(i, &(rarr[nregexpr].re), buf, sizeof(buf));
1072 llog(LL_ERR, "system: regcomp error for %s: [%s]", yylval.str, buf);
1073 config_error_flag++;
1078 if((rarr[nregexpr].re_expr = malloc(strlen(yylval.str)+1)) == NULL)
1080 llog(LL_ERR, "system: regexpr malloc error error for %s", yylval.str);
1081 config_error_flag++;
1084 strcpy(rarr[nregexpr].re_expr, yylval.str);
1086 DBGL(DL_RCCF, (llog(LL_DBG, "system: regexpr %s stored into slot %d", yylval.str, nregexpr)));
1088 if(rarr[nregexpr].re_prog != NULL)
1089 rarr[nregexpr].re_flg = 1;
1097 if(nregprog >= MAX_RE)
1099 llog(LL_ERR, "system: regprog #%d >= MAX_RE", nregprog);
1100 config_error_flag++;
1103 if((rarr[nregprog].re_prog = malloc(strlen(yylval.str)+1)) == NULL)
1105 llog(LL_ERR, "system: regprog malloc error error for %s", yylval.str);
1106 config_error_flag++;
1109 strcpy(rarr[nregprog].re_prog, yylval.str);
1111 DBGL(DL_RCCF, (llog(LL_DBG, "system: regprog %s stored into slot %d", yylval.str, nregprog)));
1113 if(rarr[nregprog].re_expr != NULL)
1114 rarr[nregprog].re_flg = 1;
1120 strcpy(rotatesuffix, yylval.str);
1121 DBGL(DL_RCCF, (llog(LL_DBG, "system: rotatesuffix = %s", yylval.str)));
1126 rt_prio = yylval.num;
1127 if(rt_prio < RTP_PRIO_MIN || rt_prio > RTP_PRIO_MAX)
1129 config_error_flag++;
1130 llog(LL_ERR, "system: error, rtprio (%d) out of range!", yylval.num);
1134 DBGL(DL_RCCF, (llog(LL_DBG, "system: rtprio = %d", yylval.num)));
1137 rt_prio = RTPRIO_NOTUSED;
1142 strcpy(tinainitprog, yylval.str);
1143 DBGL(DL_RCCF, (llog(LL_DBG, "system: tinainitprog = %s", yylval.str)));
1147 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: unitlength = %d", entrycount, yylval.num)));
1148 cfg_entry_tab[entrycount].unitlength = yylval.num;
1152 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: unitlengthsrc = %s", entrycount, yylval.str)));
1153 if(!(strcmp(yylval.str, "none")))
1154 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_NONE;
1155 else if(!(strcmp(yylval.str, "cmdl")))
1156 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CMDL;
1157 else if(!(strcmp(yylval.str, "conf")))
1158 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CONF;
1159 else if(!(strcmp(yylval.str, "rate")))
1160 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_RATE;
1161 else if(!(strcmp(yylval.str, "aocd")))
1162 cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_DYN;
1165 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"unitlengthsrc\" at line %d!", lineno);
1166 config_error_flag++;
1171 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: usrdevicename = %s", entrycount, yylval.str)));
1172 if(!strcmp(yylval.str, "rbch"))
1173 cfg_entry_tab[entrycount].usrdevicename = BDRV_RBCH;
1174 else if(!strcmp(yylval.str, "tel"))
1175 cfg_entry_tab[entrycount].usrdevicename = BDRV_TEL;
1176 else if(!strcmp(yylval.str, "ipr"))
1177 cfg_entry_tab[entrycount].usrdevicename = BDRV_IPR;
1178 else if(!strcmp(yylval.str, "isp"))
1179 cfg_entry_tab[entrycount].usrdevicename = BDRV_ISPPP;
1181 else if(!strcmp(yylval.str, "ibc"))
1182 cfg_entry_tab[entrycount].usrdevicename = BDRV_IBC;
1184 else if(!strcmp(yylval.str, "ing"))
1185 cfg_entry_tab[entrycount].usrdevicename = BDRV_ING;
1188 llog(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"usrdevicename\" at line %d!", lineno);
1189 config_error_flag++;
1194 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: usrdeviceunit = %d", entrycount, yylval.num)));
1195 cfg_entry_tab[entrycount].usrdeviceunit = yylval.num;
1199 useacctfile = yylval.booln;
1200 DBGL(DL_RCCF, (llog(LL_DBG, "system: useacctfile = %d", yylval.booln)));
1204 cfg_entry_tab[entrycount].usesubaddr = yylval.booln;
1205 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: usesubaddr = %d", entrycount, yylval.booln)));
1209 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: usedown = %d", entrycount, yylval.booln)));
1210 cfg_entry_tab[entrycount].usedown = yylval.booln;
1214 DBGL(DL_RCCF, (llog(LL_DBG, "entry %d: valid = %s", entrycount, yylval.str)));
1215 parse_valid(entrycount, yylval.str);
1219 llog(LL_ERR, "ERROR parsing config file: unknown keyword at line %d!", lineno);
1220 config_error_flag++;
1225 /*---------------------------------------------------------------------------*
1226 * parse a date/time range
1227 *---------------------------------------------------------------------------*/
1229 parse_valid(int entrycount, char *dt)
1231 /* a valid string consists of some days of week separated by
1232 * commas, where 0=sunday, 1=monday .. 6=saturday and a special
1233 * value of 7 which is a holiday from the holiday file.
1234 * after the days comes an optional (!) time range in the form
1235 * aa:bb-cc:dd, this format is fixed to be parsable by sscanf.
1236 * Valid specifications looks like this:
1237 * 1,2,3,4,5,09:00-18:00 Monday-Friday 9-18h
1238 * 1,2,3,4,5,18:00-09:00 Monday-Friday 18-9h
1239 * 6 Saturday (whole day)
1240 * 0,7 Sunday and Holidays
1252 if( ( ((*dt >= '0') && (*dt <= '9')) && (*(dt+1) == ':') ) ||
1253 ( ((*dt >= '0') && (*dt <= '2')) && ((*(dt+1) >= '0') && (*(dt+1) <= '9')) && (*(dt+2) == ':') ) )
1255 /* dt points to time spec */
1256 ret = sscanf(dt, "%d:%d-%d:%d", &fromhr, &frommin, &tohr, &tomin);
1259 llog(LL_ERR, "ERROR parsing config file: timespec [%s] error at line %d!", *dt, lineno);
1260 config_error_flag++;
1264 if(fromhr < 0 || fromhr > 24 || tohr < 0 || tohr > 24 ||
1265 frommin < 0 || frommin > 59 || tomin < 0 || tomin > 59)
1267 llog(LL_ERR, "ERROR parsing config file: invalid time [%s] at line %d!", *dt, lineno);
1268 config_error_flag++;
1273 else if ((*dt >= '0') && (*dt <= '7'))
1275 /* dt points to day spec */
1276 day |= 1 << (*dt - '0');
1280 else if (*dt == ',')
1282 /* dt points to delimiter */
1286 else if (*dt == '\0')
1288 /* dt points to end of string */
1293 /* dt points to illegal character */
1294 llog(LL_ERR, "ERROR parsing config file: illegal character [%c=0x%x] in date/time spec at line %d!", *dt, *dt, lineno);
1295 config_error_flag++;
1299 cfg_entry_tab[entrycount].day = day;
1300 cfg_entry_tab[entrycount].fromhr = fromhr;
1301 cfg_entry_tab[entrycount].frommin = frommin;
1302 cfg_entry_tab[entrycount].tohr = tohr;
1303 cfg_entry_tab[entrycount].tomin = tomin;
1306 /*---------------------------------------------------------------------------*
1307 * configuration validation and consistency check
1308 *---------------------------------------------------------------------------*/
1312 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
1316 /* regular expression table */
1318 for(i=0; i < MAX_RE; i++)
1320 if((rarr[i].re_expr != NULL) && (rarr[i].re_prog == NULL))
1322 llog(LL_ERR, "check_config: regular expression %d without program!", i);
1325 if((rarr[i].re_prog != NULL) && (rarr[i].re_expr == NULL))
1327 llog(LL_ERR, "check_config: regular expression program %d without expression!", i);
1332 /* entry sections */
1334 for(i=0; i <= entrycount; i++, cep++)
1336 /* isdn controller number */
1338 if((cep->isdncontroller < -1) || (cep->isdncontroller > (ncontroller-1)))
1340 llog(LL_ERR, "check_config: WARNING, isdncontroller out of range in entry %d!", i);
1343 /* numbers used for dialout */
1345 if((cep->inout != DIR_INONLY) && (cep->dialin_reaction != REACT_ANSWER))
1347 if(cep->remote_numbers_count == 0)
1349 llog(LL_ERR, "check_config: remote-phone-dialout not set in entry %d!", i);
1352 if(strlen(cep->local_phone_dialout.number) == 0)
1354 llog(LL_ERR, "check_config: local-phone-dialout not set in entry %d!", i);
1359 /* numbers used for incoming calls */
1361 if(cep->inout != DIR_OUTONLY)
1363 if(strlen(cep->local_phone_incoming.number) == 0)
1365 llog(LL_ERR, "check_config: local-phone-incoming not set in entry %d!", i);
1368 if(cep->incoming_numbers_count == 0)
1370 llog(LL_ERR, "check_config: remote-phone-incoming not set in entry %d!", i);
1375 if((cep->dialin_reaction == REACT_ANSWER) && (cep->b1protocol != BPROT_NONE))
1377 llog(LL_ERR, "check_config: b1protocol not raw for telephony in entry %d!", i);
1381 if((cep->ppp_send_auth == AUTH_PAP) || (cep->ppp_send_auth == AUTH_CHAP))
1383 if(cep->ppp_send_name[0] == 0)
1385 llog(LL_ERR, "check_config: no remote authentification name in entry %d!", i);
1388 if(cep->ppp_send_password[0] == 0)
1390 llog(LL_ERR, "check_config: no remote authentification password in entry %d!", i);
1394 if((cep->ppp_expect_auth == AUTH_PAP) || (cep->ppp_expect_auth == AUTH_CHAP))
1396 if(cep->ppp_expect_name[0] == 0)
1398 llog(LL_ERR, "check_config: no local authentification name in entry %d!", i);
1401 if(cep->ppp_expect_password[0] == 0)
1403 llog(LL_ERR, "check_config: no local authentification secret in entry %d!", i);
1410 llog(LL_ERR, "check_config: %d error(s) in configuration file, exit!", error);
1415 /*---------------------------------------------------------------------------*
1416 * print the configuration
1417 *---------------------------------------------------------------------------*/
1421 #define PFILE stdout
1423 #ifdef I4B_EXTERNAL_MONITOR
1424 extern struct monitor_rights * monitor_next_rights(const struct monitor_rights *r);
1425 struct monitor_rights *m_rights;
1427 cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */
1433 strcpy(mytime, ctime(&clock));
1434 mytime[strlen(mytime)-1] = '\0';
1436 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1437 fprintf(PFILE, "# system section (generated %s)\n", mytime);
1438 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1439 fprintf(PFILE, "system\n");
1440 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");
1441 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");
1442 fprintf(PFILE, "acctfile = %s\t\t# accounting information file\n", acctfile);
1443 fprintf(PFILE, "ratesfile = %s\t\t# charging rates database file\n", ratesfile);
1446 if(rt_prio == RTPRIO_NOTUSED)
1447 fprintf(PFILE, "# rtprio is unused\n");
1449 fprintf(PFILE, "rtprio = %d\t\t\t\t# isdnd runs at realtime priority\n", rt_prio);
1452 /* regular expression table */
1454 for(i=0; i < MAX_RE; i++)
1456 if(rarr[i].re_expr != NULL)
1458 fprintf(PFILE, "regexpr = \"%s\"\t\t# scan logfile for this expression\n", rarr[i].re_expr);
1460 if(rarr[i].re_prog != NULL)
1462 fprintf(PFILE, "regprog = %s\t\t# program to run when expression is matched\n", rarr[i].re_prog);
1466 #ifdef I4B_EXTERNAL_MONITOR
1468 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");
1469 fprintf(PFILE, "monitor-port = %d\t\t\t\t# TCP/IP port number used for remote monitoring\n", monitorport);
1471 m_rights = monitor_next_rights(NULL);
1472 if(m_rights != NULL)
1474 char *s = "error\n";
1477 for ( ; m_rights != NULL; m_rights = monitor_next_rights(m_rights))
1481 fprintf(PFILE, "monitor = \"%s\"\t\t# local socket name for monitoring\n", m_rights->name);
1486 ia.s_addr = ntohl(m_rights->net);
1488 switch(m_rights->mask)
1590 fprintf(PFILE, "monitor = \"%s/%s\"\t\t# host (net/mask) allowed to connect for monitoring\n", inet_ntoa(ia), s);
1594 if((m_rights->rights) & I4B_CA_COMMAND_FULL)
1595 strcat(b, "fullcmd,");
1596 if((m_rights->rights) & I4B_CA_COMMAND_RESTRICTED)
1597 strcat(b, "restrictedcmd,");
1598 if((m_rights->rights) & I4B_CA_EVNT_CHANSTATE)
1599 strcat(b, "channelstate,");
1600 if((m_rights->rights) & I4B_CA_EVNT_CALLIN)
1601 strcat(b, "callin,");
1602 if((m_rights->rights) & I4B_CA_EVNT_CALLOUT)
1603 strcat(b, "callout,");
1604 if((m_rights->rights) & I4B_CA_EVNT_I4B)
1605 strcat(b, "logevents,");
1607 if(b[strlen(b)-1] == ',')
1608 b[strlen(b)-1] = '\0';
1610 fprintf(PFILE, "monitor-access = %s\t\t# monitor access rights\n", b);
1615 /* entry sections */
1617 for(i=0; i <= entrycount; i++, cep++)
1619 fprintf(PFILE, "\n");
1620 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1621 fprintf(PFILE, "# entry section %d\n", i);
1622 fprintf(PFILE, "#---------------------------------------------------------------------------\n");
1623 fprintf(PFILE, "entry\n");
1625 fprintf(PFILE, "name = %s\t\t# name for this entry section\n", cep->name);
1627 fprintf(PFILE, "isdncontroller = %d\t\t# ISDN card number used for this entry\n", cep->isdncontroller);
1628 fprintf(PFILE, "isdnchannel = ");
1629 switch(cep->isdnchannel)
1632 fprintf(PFILE, "-1\t\t# any ISDN B-channel may be used\n");
1635 fprintf(PFILE, "%d\t\t# only ISDN B-channel %d may be used\n", cep->isdnchannel+1, cep->isdnchannel+1);
1639 fprintf(PFILE, "usrdevicename = %s\t\t# name of userland ISDN B-channel device\n", bdrivername(cep->usrdevicename));
1640 fprintf(PFILE, "usrdeviceunit = %d\t\t# unit number of userland ISDN B-channel device\n", cep->usrdeviceunit);
1642 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");
1644 if(!(cep->usrdevicename == BDRV_TEL))
1646 fprintf(PFILE, "direction = ");
1650 fprintf(PFILE, "in\t\t# only incoming connections allowed\n");
1653 fprintf(PFILE, "out\t\t# only outgoing connections allowed\n");
1656 fprintf(PFILE, "inout\t\t# incoming and outgoing connections allowed\n");
1661 if(!((cep->usrdevicename == BDRV_TEL) || (cep->inout == DIR_INONLY)))
1663 if(cep->remote_numbers_count > 1)
1665 for(j=0; j<cep->remote_numbers_count; j++)
1666 fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number %d for dialing out to remote\n", cep->remote_numbers[j].number, j+1);
1668 fprintf(PFILE, "remdial-handling = ");
1670 switch(cep->remote_numbers_handling)
1673 fprintf(PFILE, "next\t\t# use next number after last successfull for new dial\n");
1676 fprintf(PFILE, "last\t\t# use last successfull number for new dial\n");
1679 fprintf(PFILE, "first\t\t# always start with first number for new dial\n");
1685 fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number for dialing out to remote\n", cep->remote_numbers[0].number);
1688 fprintf(PFILE, "local-phone-dialout = %s\t\t# show this number to remote when dialling out\n", cep->local_phone_dialout.number);
1689 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");
1692 if(!(cep->inout == DIR_OUTONLY))
1696 fprintf(PFILE, "local-phone-incoming = %s\t\t# incoming calls must match this (mine) telephone number\n", cep->local_phone_incoming.number);
1697 for (n = 0; n < cep->incoming_numbers_count; n++)
1698 fprintf(PFILE, "remote-phone-incoming = %s\t\t# this is a valid remote number to call me\n",
1699 cep->remote_phone_incoming[n].number);
1701 fprintf(PFILE, "dialin-reaction = ");
1702 switch(cep->dialin_reaction)
1705 fprintf(PFILE, "accept\t\t# i accept a call from remote and connect\n");
1708 fprintf(PFILE, "reject\t\t# i reject the call from remote\n");
1711 fprintf(PFILE, "ignore\t\t# i ignore the call from remote\n");
1714 fprintf(PFILE, "answer\t\t# i will start telephone answering when remote calls in\n");
1716 case REACT_CALLBACK:
1717 fprintf(PFILE, "callback\t\t# when remote calls in, i will hangup and call back\n");
1722 if(cep->usrdevicename == BDRV_ISPPP)
1725 switch(cep->ppp_expect_auth)
1742 fprintf(PFILE, "ppp-expect-auth = %s\t\t# the auth protocol we expect to receive on dial-in (none,pap,chap)\n", s);
1743 if(cep->ppp_expect_auth != AUTH_NONE)
1745 fprintf(PFILE, "ppp-expect-name = %s\t\t# the user name allowed in\n", cep->ppp_expect_name);
1746 fprintf(PFILE, "ppp-expect-password = %s\t\t# the key expected from the other side\n", cep->ppp_expect_password);
1747 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");
1750 switch(cep->ppp_send_auth)
1767 fprintf(PFILE, "ppp-send-auth = %s\t\t# the auth protocol we use when dialing out (none,pap,chap)\n", s);
1768 if(cep->ppp_send_auth != AUTH_NONE)
1770 fprintf(PFILE, "ppp-send-name = %s\t\t# our PPP account used for dial-out\n", cep->ppp_send_name);
1771 fprintf(PFILE, "ppp-send-password = %s\t\t# the key sent to the other side\n", cep->ppp_send_password);
1774 if(cep->ppp_send_auth == AUTH_CHAP ||
1775 cep->ppp_expect_auth == AUTH_CHAP) {
1776 fprintf(PFILE, "ppp-auth-rechallenge = %s\t\t# rechallenge CHAP connections once in a while\n", cep->ppp_auth_flags & AUTH_RECHALLENGE ? "yes" : "no");
1780 if(!((cep->inout == DIR_INONLY) || (cep->usrdevicename == BDRV_TEL)))
1783 fprintf(PFILE, "idletime-outgoing = %d\t\t# outgoing call idle timeout\n", cep->idle_time_out);
1785 switch( cep->shorthold_algorithm )
1788 s = "fix-unit-size";
1791 s = "var-unit-size";
1798 fprintf(PFILE, "idle-algorithm-outgoing = %s\t\t# outgoing call idle algorithm\n", s);
1801 if(!(cep->inout == DIR_OUTONLY))
1802 fprintf(PFILE, "idletime-incoming = %d\t\t# incoming call idle timeout\n", cep->idle_time_in);
1804 if(!(cep->usrdevicename == BDRV_TEL))
1806 fprintf(PFILE, "unitlengthsrc = ");
1807 switch(cep->unitlengthsrc)
1810 fprintf(PFILE, "none\t\t# no unit length specified, using default\n");
1813 fprintf(PFILE, "cmdl\t\t# using unit length specified on commandline\n");
1816 fprintf(PFILE, "conf\t\t# using unitlength specified by unitlength-keyword\n");
1817 fprintf(PFILE, "unitlength = %d\t\t# fixed unitlength\n", cep->unitlength);
1820 fprintf(PFILE, "rate\t\t# using unitlength specified in rate database\n");
1821 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1824 fprintf(PFILE, "aocd\t\t# using dynamically calculated unitlength based on AOCD subscription\n");
1825 fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype);
1829 fprintf(PFILE, "earlyhangup = %d\t\t# early hangup safety time\n", cep->earlyhangup);
1833 if(cep->usrdevicename == BDRV_TEL)
1835 fprintf(PFILE, "answerprog = %s\t\t# program used to answer incoming telephone calls\n", cep->answerprog);
1836 fprintf(PFILE, "alert = %d\t\t# number of seconds to wait before accepting a call\n", cep->alert);
1839 if(!(cep->usrdevicename == BDRV_TEL))
1841 if(cep->dialin_reaction == REACT_CALLBACK)
1842 fprintf(PFILE, "callbackwait = %d\t\t# i am waiting this time before calling back remote\n", cep->callbackwait);
1844 if(cep->dialouttype == DIALOUT_CALLEDBACK)
1845 fprintf(PFILE, "calledbackwait = %d\t\t# i am waiting this time for a call back from remote\n", cep->calledbackwait);
1847 if(!(cep->inout == DIR_INONLY))
1849 fprintf(PFILE, "dialretries = %d\t\t# number of dialing retries\n", cep->dialretries);
1850 fprintf(PFILE, "recoverytime = %d\t\t# time to wait between dialling retries\n", cep->recoverytime);
1851 fprintf(PFILE, "dialrandincr = %s\t\t# use random dialing time addon\n", cep->dialrandincr ? "on" : "off");
1853 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");
1856 fprintf(PFILE, "downtries = %d\t\t# number of dialretries failures before switching off\n", cep->downtries);
1857 fprintf(PFILE, "downtime = %d\t\t# time device is switched off\n", cep->downtime);
1862 fprintf(PFILE, "\n");