static void createkey (const char *keyname, const dki_t *list, const zconf_t *conf) { const char *dir = ""; dki_t *dkp; if ( keyname == NULL || *keyname == '\0' ) fatal ("Create key: no keyname!"); dbg_val2 ("createkey: keyname %s, pathflag = %d\n", keyname, pathflag); /* search for already existent key to get the directory name */ if ( pathflag && (dkp = (dki_t *)zkt_search (list, 0, keyname)) != NULL ) { char path[MAX_PATHSIZE+1]; zconf_t localconf; dir = dkp->dname; pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL); if ( fileexist (path) ) /* load local config file */ { dbg_val ("Load local config file \"%s\"\n", path); memcpy (&localconf, conf, sizeof (zconf_t)); conf = loadconfig (path, &localconf); } } if ( zskflag ) dkp = dki_new (dir, keyname, DKI_ZSK, conf->k_algo, conf->z_bits, conf->z_random, conf->z_life / DAYSEC); else dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC); if ( dkp == NULL ) fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ()); /* create a new key always in state published, which means "standby" for ksk */ dki_setstatus (dkp, DKI_PUB); }
static int parsedirectory (const char *dir, dki_t ** listp) { dki_t *dkp; DIR *dirp; struct dirent *dentp; char path[MAX_PATHSIZE + 1]; if (dirflag) return 0; dbg_val ("directory: opendir(%s)\n", dir); if ((dirp = opendir (dir)) == NULL) return 0; while ((dentp = readdir (dirp)) != NULL) { if (is_dotfilename (dentp->d_name)) continue; dbg_val ("directory: check %s\n", dentp->d_name); pathname (path, sizeof (path), dir, dentp->d_name, NULL); if (is_directory (path) && recflag) { dbg_val ("directory: recursive %s\n", path); parsedirectory (path, listp); } else if (is_keyfilename (dentp->d_name)) if ((dkp = dki_read (dir, dentp->d_name))) { // fprintf (stderr, "parsedir: tssearch (%d %s)\n", dkp, dkp->name); #if defined (USE_TREE) && USE_TREE dki_tadd (listp, dkp, 1); #else dki_add (listp, dkp); #endif } } closedir (dirp); return 1; }
static int searchkw (const char *keyword) { int i; dbg_val ("keyparse: searchkw (%s)\n", keyword); i = 0; while ( kw[i].name && strcmp (kw[i].name, keyword) != 0 ) i++; return kw[i].tok; }
/***************************************************************** ** ** parse_keyconf (const char *filename, dir, dirsize, int (*func) ()) ** ** Very dumb named.conf parser. ** - For every key definition "func (keyname, algo, secret)" will be called ** *****************************************************************/ static int parse_keyconf (const char *filename, char *dir, size_t dirsize, tsigkey_t *k, const char *lookup) { FILE *fp; int ret; int tok; char path[511+1]; char strval[4095+1]; char key[255+1]; char alg[31+1]; char secret[255+1]; dbg_val ("parse_keyconf: parsing file \"%s\" \n", filename); assert (filename != NULL); assert (dir != NULL && dirsize != 0); assert ( k != NULL); if ( (fp = fopen (filename, "r")) == NULL ) return -1; ret = 0; while ( (tok = gettok (fp, strval, sizeof strval)) != EOF ) { if ( tok > 0 && tok < 256 ) { fprintf (stderr, "parse_keyconf: token found with value %-10d: %c\n", tok, tok); } else if ( tok == TOK_DIR ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { dbg_val2 ("parse_namedconf: directory found \"%s\" (dir is %s)\n", strval, dir); if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); snprintf (dir, dirsize, "%s", path); dbg_val ("parse_namedconf: new dir \"%s\" \n", dir); } } else if ( tok == TOK_INCLUDE ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); if ( (ret = parse_keyconf (path, dir, dirsize, k, lookup)) != 0 ) return ret; } else { fprintf (stderr, "parse_keyconf: need a filename after \"include\"!\n"); } } else if ( tok == TOK_KEY ) { int nrtok; dbg_val0 ("parse_keyconf: new key found \n"); if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) continue; snprintf (key, sizeof key, "%s", strval); /* store the name of the key */ dbg_val ("parse_keyconf: keyname \"%s\" \n", key); nrtok = 0; while ( nrtok < 2 && (tok = gettok (fp, strval, sizeof (strval))) ) { if ( tok == TOK_ALG ) { switch ( gettok (fp, strval, sizeof (strval)) ) { case TOK_HMAC_MD5: case TOK_HMAC_SHA1: case TOK_HMAC_SHA224: case TOK_HMAC_SHA256: case TOK_HMAC_SHA384: case TOK_HMAC_SHA512: snprintf (alg, sizeof alg, "%s", strval); /* this is the algorithm */ break; default: *alg = '\0'; continue; } } else if ( tok == TOK_SECRET ) { if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) break; snprintf (secret, sizeof secret, "%s", strval); /* this is the secret */ } nrtok++; } dbg_val5 ("dir %s key %s alg %s secret %s lookup \"%s\"\n", dir, key, alg, secret, lookup ? lookup: "NULL"); if ( lookup == NULL || lookup[0] == '\0' || strcmp (key, lookup) == 0 ) { snprintf (k->name, sizeof (k->name), "%s", key); snprintf (k->algo, sizeof (k->algo), "%s", alg); snprintf (k->secret, sizeof (k->secret), "%s", secret); ret = 1; break; } } else dbg_val3 ("%-10s(%d): %s\n", tok2str(tok), tok, strval); } fclose (fp); dbg_val2 ("parse_keyconf: leaving file \"%s\" ret = %d \n", filename, ret); return ret; }
int main (int argc, char *argv[]) { int c; int opt_index; int action; int major; int minor; const char *file; const char *defconfname = NULL; const char *confname = NULL; char *p; char str[254+1]; zconf_t *refconfig = NULL; zconf_t *config; progname = *argv; if ( (p = strrchr (progname, '/')) ) progname = ++p; view = getnameappendix (progname, "zkt-conf"); defconfname = getdefconfname (view); dbg_val0 ("Load built in config \"%s\"\n"); config = loadconfig ("", (zconf_t *)NULL); /* load built in config */ if ( fileexist (defconfname) ) /* load default config file */ { dbg_val ("Load site wide config file \"%s\"\n", defconfname); config = loadconfig (defconfname, config); } if ( config == NULL ) fatal ("Out of memory\n"); confname = defconfname; opterr = 0; opt_index = 0; action = 0; setconfigversion (100); #if defined(HAVE_GETOPT_LONG) && HAVE_GETOPT_LONG while ( (c = getopt_long (argc, argv, short_options, long_options, &opt_index)) != -1 ) #else while ( (c = getopt (argc, argv, short_options)) != -1 ) #endif { switch ( c ) { case 'V': /* view name */ view = optarg; defconfname = getdefconfname (view); if ( fileexist (defconfname) ) /* load default config file */ config = loadconfig (defconfname, config); if ( config == NULL ) fatal ("Out of memory\n"); confname = defconfname; break; case 'O': /* read option from commandline */ config = loadconfig_fromstr (optarg, config); break; case 'C': switch ( sscanf (optarg, "%d.%d", &major, &minor) ) { case 2: major = major * 100 + minor; case 1: break; default: usage ("illegal release number"); } setconfigversion (major); break; case 'c': if ( *optarg == '\0' ) usage ("empty config file name"); config = loadconfig (optarg, config); if ( *optarg == '-' || strcmp (optarg, "stdin") == 0 ) confname = "stdout"; else confname = optarg; break; case 'd': /* built-in default config */ config = loadconfig ("", config); /* load built-in config */ confname = defconfname; break; case 's': /* side wide config */ /* this is the default **/ break; case 'a': /* set all flag */ allflag = 1; break; case 'l': /* local config file */ refconfig = dupconfig (config); /* duplicate current config */ confname = LOCALCONF_FILE; if ( fileexist (LOCALCONF_FILE) ) /* try to load local config file */ { dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE); config = loadconfig (LOCALCONF_FILE, config); } else if ( !writeflag ) usage ("error: no local config file found"); break; case 't': /* test config */ testflag = 1; break; case 'v': /* version */ fprintf (stderr, "%s version %s compiled for BIND version %d\n", progname, ZKT_VERSION, BIND_VERSION); fprintf (stderr, "ZKT %s\n", ZKT_COPYRIGHT); return 0; break; case 'w': /* write back conf file */ writeflag = 1; break; case 'h': /* print help */ usage (""); break; case ':': snprintf (str, sizeof(str), "option \"-%c\" requires an argument.", optopt); usage (str); break; case '?': if ( isprint (optopt) ) snprintf (str, sizeof(str), "Unknown option \"-%c\".", optopt); else snprintf (str, sizeof (str), "Unknown option char \\x%x.", optopt); usage (str); break; default: abort(); } } c = optind; if ( c >= argc ) /* no arguments given on commandline */ { if ( testflag ) { if ( checkconfig (config) ) fprintf (stderr, "All config file parameter seems to be ok\n"); } else { if ( !writeflag ) /* print to stdout */ confname = "stdout"; if ( refconfig ) /* have we seen a local config file ? */ if ( allflag ) printconfig (confname, config); else printconfigdiff (confname, refconfig, config); else printconfig (confname, config); } } else /* command line argument found: use it as name of zone file */ { long minttl; long maxttl; int keydbfound; char *dnskeydb; file = argv[c++]; dnskeydb = config->keyfile; minttl = 0x7FFFFFFF; maxttl = 0; keydbfound = parsezonefile (file, &minttl, &maxttl, dnskeydb); if ( keydbfound < 0 ) error ("can't parse zone file %s\n", file); if ( dnskeydb && !keydbfound ) { if ( writeflag ) { addkeydb (file, dnskeydb); printf ("\"$INCLUDE %s\" directive added to \"%s\"\n", dnskeydb, file); } else printf ("\"$INCLUDE %s\" should be added to \"%s\" (run with option -w)\n", dnskeydb, file); } if ( minttl < (10 * MINSEC) ) fprintf (stderr, "Min_TTL of %s (%ld seconds) is too low to use it in a signed zone (see RFC4641)\n", timeint2str (minttl), minttl); else fprintf (stderr, "Min_TTL:\t%s\t# (%ld seconds)\n", timeint2str (minttl), minttl); fprintf (stdout, "Max_TTL:\t%s\t# (%ld seconds)\n", timeint2str (maxttl), maxttl); if ( writeflag ) { refconfig = dupconfig (config); /* duplicate current config */ confname = LOCALCONF_FILE; if ( fileexist (LOCALCONF_FILE) ) /* try to load local config file */ { dbg_val ("Load local config file \"%s\"\n", LOCALCONF_FILE); config = loadconfig (LOCALCONF_FILE, config); } setconfigpar (config, "Max_TTL", &maxttl); printconfigdiff (confname, refconfig, config); } } return 0; }
/***************************************************************** ** parsezonefile () ** parse the BIND zone file 'file' and store the minimum and ** maximum ttl value in the corresponding parameter. ** if keydbfile is set, check if this file is already include. ** if inclfiles is not NULL store a list of included files names ** in it. ** return 0 if keydbfile is not included ** return 1 if keydbfile is included ** return -1 on error *****************************************************************/ int parsezonefile (const char *file, long *pminttl, long *pmaxttl, const char *keydbfile, char *inclfiles, size_t *plen) { FILE *infp; int len; int lnr; long ttl; int multi_line_rr; int keydbfilefound; char buf[1024]; const char *p; assert (file != NULL); assert (pminttl != NULL); assert (pmaxttl != NULL); dbg_val4 ("parsezonefile (\"%s\", %ld, %ld, \"%s\")\n", file, *pminttl, *pmaxttl, keydbfile); if ( (infp = fopen (file, "r")) == NULL ) { error ("parsezonefile: couldn't open file \"%s\" for input\n", file); return -1; } lnr = 0; keydbfilefound = 0; multi_line_rr = 0; while ( fgets (buf, sizeof buf, infp) != NULL ) { len = strlen (buf); if ( buf[len-1] != '\n' ) /* line too long ? */ fprintf (stderr, "line too long\n"); lnr++; p = buf; if ( multi_line_rr ) /* skip line if it's part of a multiline rr */ { is_multiline_rr (&multi_line_rr, p); continue; } if ( *p == '$' ) /* special directive ? */ { if ( strncmp (p+1, "TTL", 3) == 0 ) /* $TTL ? */ { ttl = get_ttl (p+4); dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl); setminmax (pminttl, ttl, pmaxttl); } else if ( strncmp (p+1, "INCLUDE", 7) == 0 ) /* $INCLUDE ? */ { char fname[30+1]; sscanf (p+9, "%30s", fname); dbg_val ("$INCLUDE directive for file \"%s\" found\n", fname); if ( strcmp (fname, keydbfile) == 0 ) keydbfilefound = 1; else { if ( inclfiles && plen ) { len = snprintf (inclfiles, *plen, ",%s", fname); if ( *plen <= len ) /* no space left in include file string */ return keydbfilefound; inclfiles += len; *plen -= len; } int ret = parsezonefile (fname, pminttl, pmaxttl, keydbfile, inclfiles, plen); if ( ret ) /* keydb found or read error ? */ keydbfilefound = ret; } } } else if ( !isspace (*p) ) /* label ? */ p = skiplabel (p); p = skipws (p); if ( *p == ';' ) /* skip line if it's a comment line */ continue; /* skip class (hesiod is not supported now) */ if ( (toupper (*p) == 'I' && toupper (p[1]) == 'N') || (toupper (*p) == 'C' && toupper (p[1]) == 'H') ) p += 2; p = skipws (p); if ( isdigit (*p) ) /* ttl ? */ { ttl = get_ttl (p); dbg_val3 ("%s:%d:ttl %ld\n", file, lnr, ttl); setminmax (pminttl, ttl, pmaxttl); } /* check the rest of the line if it's the beginning of a multi_line_rr */ is_multiline_rr (&multi_line_rr, p); } if ( file ) fclose (infp); dbg_val5 ("parsezonefile (\"%s\", %ld, %ld, \"%s\") ==> %d\n", file, *pminttl, *pmaxttl, keydbfile, keydbfilefound); return keydbfilefound; }
static void ksk_roll (const char *keyname, int phase, const dki_t *list, const zconf_t *conf) { char path[MAX_PATHSIZE+1]; zconf_t localconf; const char *dir; dki_t *keylist; dki_t *dkp; dki_t *standby; int parent_exist; int parent_age; int parent_phase; int parent_propagation; int key_ttl; int ksk; if ( phase == 9 ) /* usage */ { fprintf (stderr, "A KSK rollover requires three consecutive steps:\n"); fprintf (stderr, "\n"); fprintf (stderr, "-1%s", loptstr ("|--ksk-roll-phase1 (--ksk-newkey)\n", "")); fprintf (stderr, "\t Create a new KSK.\n"); fprintf (stderr, "\t This step also creates a parent-<domain> file which contains only\n"); fprintf (stderr, "\t the _old_ key. This file will be copied in hierarchical mode\n"); fprintf (stderr, "\t by dnssec-signer to the parent directory as keyset-<domain> file.\n"); fprintf (stderr, "\t Wait until the new keyset is propagated, before going to the next step.\n"); fprintf (stderr, "\n"); fprintf (stderr, "-2%s", loptstr ("|--ksk-roll-phase2 (--ksk-publish)\n", "")); fprintf (stderr, "\t This step creates a parent-<domain> file with the _new_ key only.\n"); fprintf (stderr, "\t Please send this file immediately to the parent (In hierarchical\n"); fprintf (stderr, "\t mode this will be done automatically by the dnssec-signer command).\n"); fprintf (stderr, "\t Then wait until the new DS is generated by the parent and propagated\n"); fprintf (stderr, "\t to all the parent name server, plus the old DS TTL before going to step three.\n"); fprintf (stderr, "\n"); fprintf (stderr, "-3%s", loptstr ("|--ksk-roll-phase3 (--ksk-delkey)\n", "")); fprintf (stderr, "\t Remove (rename) the old KSK and the parent-<domain> file.\n"); fprintf (stderr, "\t You have to manually delete the old KSK (look at file names beginning\n"); fprintf (stderr, "\t with an lower 'k').\n"); fprintf (stderr, "\n"); fprintf (stderr, "-0%s", loptstr ("|--ksk-roll-stat (--ksk-status)\n", "")); fprintf (stderr, "\t Show the current KSK rollover state of a domain.\n"); fprintf (stderr, "\n"); return; } if ( keyname == NULL || *keyname == '\0' ) fatal ("ksk rollover: no domain!"); dbg_val2 ("ksk_roll: keyname %s, phase = %d\n", keyname, phase); /* search for already existent key to get the directory name */ if ( (keylist = (dki_t *)zkt_search (list, 0, keyname)) == NULL ) fatal ("ksk rollover: domain %s not found!\n", keyname); dkp = keylist; /* try to read local config file */ dir = dkp->dname; pathname (path, sizeof (path), dir, LOCALCONF_FILE, NULL); if ( fileexist (path) ) /* load local config file */ { dbg_val ("Load local config file \"%s\"\n", path); memcpy (&localconf, conf, sizeof (zconf_t)); conf = loadconfig (path, &localconf); } key_ttl = conf->key_ttl; /* check if parent-file already exist */ pathname (path, sizeof (path), dir, "parent-", keyname); parent_phase = parent_age = 0; if ( (parent_exist = fileexist (path)) != 0 ) { parent_phase = get_parent_phase (path); parent_age = file_age (path); } // parent_propagation = 2 * DAYSEC; parent_propagation = 5 * MINSEC; ksk = 0; /* count active(!) key signing keys */ standby = NULL; /* find standby key if available */ for ( dkp = keylist; dkp; dkp = dkp->next ) if ( dki_isksk (dkp) ) { if ( dki_status (dkp) == DKI_ACT ) ksk++; else if ( dki_status (dkp) == DKI_PUB ) standby = dkp; } switch ( phase ) { case 0: /* print status (debug) */ fprintf (stdout, "ksk_rollover:\n"); fprintf (stdout, "\t domain = %s\n", keyname); fprintf (stdout, "\t phase = %d\n", parent_phase); fprintf (stdout, "\t parent_file %s %s\n", path, parent_exist ? "exist": "not exist"); if ( parent_exist ) fprintf (stdout, "\t age of parent_file %d %s\n", parent_age, str_delspace (age2str (parent_age))); fprintf (stdout, "\t # of active key signing keys %d\n", ksk); fprintf (stdout, "\t parent_propagation %d %s\n", parent_propagation, str_delspace (age2str (parent_propagation))); fprintf (stdout, "\t keys ttl %d %s\n", key_ttl, age2str (key_ttl)); for ( dkp = keylist; dkp; dkp = dkp->next ) { /* TODO: Nur zum testen */ dki_prt_dnskey (dkp, stdout); } break; case 1: if ( parent_exist || ksk > 1 ) fatal ("Can\'t create new ksk because there is already an ksk rollover in progress\n"); fprintf (stdout, "create new ksk \n"); dkp = dki_new (dir, keyname, DKI_KSK, conf->k_algo, conf->k_bits, conf->k_random, conf->k_life / DAYSEC); if ( dkp == NULL ) fatal ("Can't create key %s: %s!\n", keyname, dki_geterrstr ()); if ( standby ) { dki_setstatus (standby, DKI_ACT); /* activate standby key */ dki_setstatus (dkp, DKI_PUB); /* new key will be the new standby */ } // dkp = keylist; /* use old key to create the parent file */ if ( (dkp = (dki_t *)dki_findalgo (keylist, 1, conf->k_algo, 'a', 1)) == NULL ) /* find the oldest active ksk to create the parent file */ fatal ("ksk_rollover phase1: Couldn't find the old active key\n"); if ( !create_parent_file (path, phase, key_ttl, dkp) ) fatal ("Couldn't create parentfile %s\n", path); break; case 2: if ( ksk < 2 ) fatal ("Can\'t publish new key because no one exist\n"); if ( !parent_exist ) fatal ("More than one KSK but no parent file found!\n"); if ( parent_phase != 1 ) fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase); if ( parent_age < conf->proptime + key_ttl ) fatal ("ksk_rollover (phase2): you have to wait for the propagation of the new KSK (at least %dsec or %s)\n", conf->proptime + key_ttl - parent_age, str_delspace (age2str (conf->proptime + key_ttl - parent_age))); fprintf (stdout, "save new ksk in parent file\n"); dkp = keylist->next; /* set dkp to new ksk */ if ( !create_parent_file (path, phase, key_ttl, dkp) ) fatal ("Couldn't create parentfile %s\n", path); break; case 3: if ( !parent_exist || ksk < 2 ) fatal ("ksk-delkey only allowed after ksk-publish\n"); if ( parent_phase != 2 ) fatal ("Parent file exists but is in wrong state (phase = %d)\n", parent_phase); if ( parent_age < parent_propagation + key_ttl ) fatal ("ksk_rollover (phase3): you have to wait for DS propagation (at least %dsec or %s)\n", parent_propagation + key_ttl - parent_age, str_delspace (age2str (parent_propagation + key_ttl - parent_age))); /* remove the parentfile */ fprintf (stdout, "remove parentfile \n"); unlink (path); /* remove or rename the old key */ fprintf (stdout, "old ksk renamed \n"); dkp = keylist; /* set dkp to old ksk */ dki_remove (dkp); break; default: assert (phase == 1 || phase == 2 || phase == 3); } }
/***************************************************************** ** ** parse_namedconf (const char *filename, chroot_dir, dir, dirsize, int (*func) ()) ** ** Very dumb named.conf parser. ** - In a zone declaration the _first_ keyword MUST be "type" ** - For every master zone "func (directory, zone, filename)" will be called ** *****************************************************************/ int parse_namedconf (const char *filename, const char *chroot_dir, char *dir, size_t dirsize, int (*func) ()) { FILE *fp; int tok; char path[511+1]; #if 1 /* this is potentialy too small for key data, but we don't need the keys... */ char strval[255+1]; #else char strval[4095+1]; #endif char view[255+1]; char zone[255+1]; char zonefile[255+1]; dbg_val ("parse_namedconf: parsing file \"%s\" \n", filename); assert (filename != NULL); assert (dir != NULL && dirsize != 0); assert (func != NULL); view[0] = '\0'; if ( (fp = fopen (filename, "r")) == NULL ) return 0; while ( (tok = gettok (fp, strval, sizeof strval)) != EOF ) { if ( tok > 0 && tok < 256 ) { error ("parse_namedconf: token found with value %-10d: %c\n", tok, tok); lg_mesg (LG_ERROR, "parse_namedconf: token found with value %-10d: %c", tok, tok); } else if ( tok == TOK_DIR ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { dbg_val2 ("parse_namedconf: directory found \"%s\" (dir is %s)\n", strval, dir); if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); /* prepend chroot directory (do it only once) */ if ( chroot_dir && *chroot_dir ) { snprintf (dir, dirsize, "%s%s%s", chroot_dir, *path == '/' ? "": "/", path); chroot_dir = NULL; } else snprintf (dir, dirsize, "%s", path); dbg_val ("parse_namedconf: new dir \"%s\" \n", dir); } } else if ( tok == TOK_INCLUDE ) { if ( gettok (fp, strval, sizeof (strval)) == TOK_STRING ) { if ( *strval != '/' && *dir ) snprintf (path, sizeof (path), "%s/%s", dir, strval); else snprintf (path, sizeof (path), "%s", strval); if ( !parse_namedconf (path, chroot_dir, dir, dirsize, func) ) return 0; } else { error ("parse_namedconf: need a filename after \"include\"!\n"); lg_mesg (LG_ERROR, "parse_namedconf: need a filename after \"include\"!"); } } else if ( tok == TOK_VIEW ) { if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) continue; snprintf (view, sizeof view, "%s", strval); /* store the name of the view */ } else if ( tok == TOK_ZONE ) { if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) continue; snprintf (zone, sizeof zone, "%s", strval); /* store the name of the zone */ if ( gettok (fp, strval, sizeof (strval)) != TOK_MASTER ) continue; if ( gettok (fp, strval, sizeof (strval)) != TOK_FILE ) continue; if ( gettok (fp, strval, sizeof (strval)) != TOK_STRING ) continue; snprintf (zonefile, sizeof zonefile, "%s", strval); /* this is the filename */ dbg_val4 ("dir %s view %s zone %s file %s\n", dir, view, zone, zonefile); (*func) (dir, view, zone, zonefile); } else dbg_val3 ("%-10s(%d): %s\n", tok2str(tok), tok, strval); } fclose (fp); return 1; }