confndc.c 39.4 KB
Newer Older
1
/*
Bob Halley's avatar
Bob Halley committed
2
 * Copyright (C) 2000  Internet Software Consortium.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
 * 
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
 * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
 * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 * SOFTWARE.
 */

David Lawrence's avatar
David Lawrence committed
18
/* $Id: confndc.c,v 1.16 2000/06/01 18:25:43 tale Exp $ */
19 20 21

/*
**	options {
22
**	  [ default-server server_name; ]
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
**	  [ default-key key_name; ]
**	};
**	
**	server server_name {
**	  key key_name;
**	  [ host name_or_addr; ]
**	};
**	
**	key key_name {
**	  algorithm string;
**	  secret  string;
**	};
**	
*/


#include <config.h>

#include <ctype.h>
42
#include <stdlib.h>
43

44
#include <isc/string.h>
45
#include <isc/dir.h>
46 47
#include <isc/lex.h>
#include <isc/mem.h>
48
#include <isc/net.h>
49
#include <isc/print.h>
50
#include <isc/symtab.h>
Bob Halley's avatar
Bob Halley committed
51
#include <isc/util.h>
52 53 54 55 56 57 58 59 60 61 62

#include <dns/confndc.h>
#include <dns/log.h>
 
/* Type keys for symtab lookup */
#define KEYWORD_SYM_TYPE 0x1
#define CLASS_SYM_TYPE 0x2
#define ACL_SYM_TYPE 0x3

#define CONF_MAX_IDENT 1024

63
typedef struct  {
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
	isc_mem_t	       *themem;
	isc_lex_t	       *thelexer;
	isc_symtab_t	       *thekeywords;
	int			errors;
	int			warnings;
	isc_boolean_t		debug_lexer;

	dns_c_ndcctx_t	       *thecontext;

	isc_uint32_t		currtok;
	isc_uint32_t		prevtok;
	char			tokstr[CONF_MAX_IDENT];
	char			prevtokstr[CONF_MAX_IDENT];

	isc_uint32_t		intval;
	struct in_addr		ip4addr;
	struct in6_addr		ip6addr;
} ndcpcontext;

83
struct keywordtoken {
David Lawrence's avatar
David Lawrence committed
84 85
        const char *token;
        const int yaccval;
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
};


/* 
 * DATA
 */

#define L_ALGORITHM                                        1
#define L_DEFAULT_KEY                                      3
#define L_DEFAULT_SERVER                                   4
#define L_END_INCLUDE                                      5
#define L_END_INPUT                                        6
#define L_EOS                                              7
#define L_HOST                                             8
#define L_IP4ADDR                                          9
#define L_IP6ADDR                                          10
#define L_KEY                                              11
#define L_LBRACE                                           12
#define L_OPTIONS                                          13
#define L_QSTRING                                          14
#define L_QUOTE                                            15
#define L_RBRACE                                           16
#define L_SECRET                                           17
#define L_SERVER                                           18
#define L_STRING                                           20
#define L_INTEGER					   21

David Lawrence's avatar
David Lawrence committed
113
static struct keywordtoken keyword_tokens[] = {
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
        { "{",                          L_LBRACE },
        { "}",                          L_RBRACE },
        { ";",                          L_EOS },
	{ "default-server",		L_DEFAULT_SERVER },
	{ "default-key",		L_DEFAULT_KEY },
	{ "key",			L_KEY },
	{ "host",			L_HOST },
	{ "algorithm",			L_ALGORITHM },
	{ "secret",			L_SECRET },
	{ "options", 			L_OPTIONS },
	{ "server", 			L_SERVER },
        { NULL, 0 }
};


/* This table contains all the L_* values that are not stored in any other
 * keywordtoken table.
 */

static struct keywordtoken misc_tokens[] = {
	{ "<end-of-include>", L_END_INCLUDE },
	{ "<end-of-input>", L_END_INPUT },
	{ "<ip4 address>", L_IP4ADDR },
	{ "<ip6 address>", L_IP6ADDR },
	{ "<quoted string>", L_QSTRING },
	{ "<quote character>", L_QUOTE },
	{ "<string>", L_STRING },
};



David Lawrence's avatar
David Lawrence committed
145 146
static isc_result_t
parse_file(ndcpcontext *pctx, dns_c_ndcctx_t **context);
147

David Lawrence's avatar
David Lawrence committed
148 149 150 151 152 153 154 155
static isc_result_t
parse_statement(ndcpcontext *pctx);
static isc_result_t
parse_options(ndcpcontext *pctx, dns_c_ndcopts_t **opts);
static isc_result_t
parse_serverstmt(ndcpcontext *pctx, dns_c_ndcserver_t **server);
static isc_result_t
parse_keystmt(ndcpcontext *pctx, dns_c_kdeflist_t *keys);
156

David Lawrence's avatar
David Lawrence committed
157 158 159 160 161 162 163 164 165 166
static const char *
keyword2str(isc_int32_t val);
static isc_boolean_t
eat(ndcpcontext *pctx, isc_uint32_t token);
static isc_boolean_t
eat_eos(ndcpcontext *pctx);
static isc_boolean_t
eat_lbrace(ndcpcontext *pctx);
static isc_boolean_t
eat_rbrace(ndcpcontext *pctx);
167

David Lawrence's avatar
David Lawrence committed
168 169 170 171
static isc_boolean_t
looking_at(ndcpcontext *pctx, isc_uint32_t token);
static isc_boolean_t
looking_at_anystring(ndcpcontext *pctx);
172

David Lawrence's avatar
David Lawrence committed
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
static isc_result_t
parser_setup(ndcpcontext *pctx, isc_mem_t *mem, const char *filename);
static void
parser_complain(isc_boolean_t is_warning, isc_boolean_t print_last_token,
		ndcpcontext *pctx, const char *format, va_list args);
static void
parser_error(ndcpcontext *pctx, isc_boolean_t lasttoken, const char *fmt, ...);
static void
parser_warn(ndcpcontext *pctx, isc_boolean_t lasttoken, const char *fmt, ...);
static isc_boolean_t
is_ip6addr(const char *string, struct in6_addr *addr);
static isc_boolean_t
is_ip4addr(const char *string, struct in_addr *addr);
static isc_result_t
getnexttoken(ndcpcontext *pctx);
static void
syntax_error(ndcpcontext *pctx, isc_uint32_t keyword);
190 191 192 193 194 195 196


/* *********************************************************************** */
/*	              PUBLIC DATA STRUCTURE FUNCTIONS                      */
/* *********************************************************************** */

isc_result_t
197
dns_c_ndcctx_new(isc_mem_t *mem, dns_c_ndcctx_t **ctx) {
198 199 200 201 202 203
	dns_c_ndcctx_t *newctx;

	REQUIRE(ctx != NULL);
	REQUIRE(*ctx == NULL);

	newctx = isc_mem_get(mem, sizeof *newctx);
204
	if (newctx == NULL)
205 206 207 208 209 210 211 212 213 214 215 216 217
		return (ISC_R_NOMEMORY);
	
	newctx->mem = mem;
	newctx->magic = DNS_C_NDCCTX_MAGIC;
	newctx->opts = NULL;
	newctx->servers = NULL;
	newctx->keys = NULL;

	*ctx = newctx;
	return (ISC_R_SUCCESS);
}

isc_result_t
218
dns_c_ndcctx_destroy(dns_c_ndcctx_t **ndcctx) {
219 220 221 222 223 224 225 226 227 228 229 230
	dns_c_ndcctx_t *ctx;
	isc_mem_t *mem;
	
	REQUIRE(ndcctx != NULL);

	ctx = *ndcctx;
	
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));

	mem = ctx->mem;
	ctx->mem = NULL;

231
	if (ctx->opts != NULL)
232 233
		dns_c_ndcopts_destroy(&ctx->opts);

234
	if (ctx->servers != NULL)
235 236
		dns_c_ndcserverlist_destroy(&ctx->servers);

237
	if (ctx->keys != NULL)
238 239 240 241 242
		dns_c_kdeflist_delete(&ctx->keys);

	ctx->magic = 0;
	isc_mem_put(mem, ctx, sizeof *ctx);

243 244
	*ndcctx = NULL;

245 246 247 248 249
	return (ISC_R_SUCCESS);
}


void
250
dns_c_ndcctx_print(FILE *fp, dns_c_ndcctx_t *ctx) {
251 252 253
	REQUIRE(fp != NULL);
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));

254
	if (ctx->opts != NULL)
255 256
		dns_c_ndcopts_print(fp, ctx->opts);

257
	if (ctx->servers != NULL)
258 259
		dns_c_ndcserverlist_print(fp, ctx->servers);

260
	if (ctx->keys != NULL)
261 262 263 264 265
		dns_c_kdeflist_print(fp, 0, ctx->keys);
}


void
266
dns_c_ndcopts_print(FILE *fp, dns_c_ndcopts_t *opts) {
267 268 269 270
	REQUIRE(fp != NULL);
	REQUIRE(DNS_C_NDCOPTIONS_VALID(opts));

	fprintf(fp, "options {\n");
271
	if (opts->defserver != NULL)
272
		fprintf(fp, "\tdefault-server %s;\n", opts->defserver);
273 274

	if (opts->defkey != NULL)
275
		fprintf(fp, "\tdefault-key %s;\n", opts->defkey);
276

277 278 279 280 281
	fprintf(fp, "};\n\n\n");
}


void
282
dns_c_ndcserverlist_print(FILE *fp, dns_c_ndcserverlist_t *servers) {
283 284 285 286 287 288 289 290 291 292 293 294 295 296
	dns_c_ndcserver_t *server;
	
	REQUIRE(DNS_C_NDCSERVERLIST_VALID(servers));
	REQUIRE(fp != NULL);

	server = dns_c_ndcserverlist_first(servers);
	while (server != NULL) {
		dns_c_ndcserver_print(fp, server);
		server = dns_c_ndcserverlist_next(server);
	}
}


void
297
dns_c_ndcserver_print(FILE *fp, dns_c_ndcserver_t *server) {
298
	fprintf(fp, "server %s {\n", server->name);
299
	if (server->key != NULL)
300 301
		fprintf(fp, "\tkey %s;\n", server->key);

302
	if (server->host != NULL)
303 304 305 306 307 308 309
		fprintf(fp, "\thost %s;\n", server->host);

	fprintf(fp, "};\n\n\n");
}


isc_result_t
310
dns_c_ndcctx_setoptions(dns_c_ndcctx_t *ctx, dns_c_ndcopts_t *opts) {
311 312 313 314 315 316 317 318 319
	isc_boolean_t existed;
	
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(opts == NULL || DNS_C_NDCOPTIONS_VALID(opts));

	existed = ISC_TF(ctx->opts != NULL);
	
	ctx->opts = opts;

320 321 322 323
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
324 325 326
}

isc_result_t
327
dns_c_ndcctx_getoptions(dns_c_ndcctx_t *ctx, dns_c_ndcopts_t **opts) {
328 329 330 331 332 333
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(opts != NULL);
	REQUIRE(*opts == NULL);
	
	*opts = ctx->opts;

334 335 336 337
	if (ctx->opts == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
338 339 340
}

isc_result_t
341
dns_c_ndcctx_setservers(dns_c_ndcctx_t *ctx, dns_c_ndcserverlist_t *servers) {
342
	isc_boolean_t existed;
343

344 345 346 347 348 349 350
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(servers == NULL || DNS_C_NDCSERVERLIST_VALID(servers));

	existed = ISC_TF(ctx->servers != NULL);
	
	ctx->servers = servers;

351 352 353 354
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
355 356 357
}

isc_result_t
358
dns_c_ndcctx_getservers(dns_c_ndcctx_t *ctx, dns_c_ndcserverlist_t **servers) {
359 360 361 362 363 364
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(servers != NULL);
	REQUIRE(*servers == NULL);
	
	*servers = ctx->servers;

365 366 367 368
	if (ctx->servers == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
369 370 371
}

isc_result_t
372 373
dns_c_ndcctx_addserver(dns_c_ndcctx_t *ctx, dns_c_ndcserver_t **server) {
	isc_result_t result;
374 375 376 377 378 379
	
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(server != NULL);
	REQUIRE(DNS_C_NDCSERVER_VALID(*server));
	
	if (ctx->servers == NULL) {
380 381 382
		result = dns_c_ndcserverlist_new(ctx->mem, &ctx->servers);
		if (result != ISC_R_SUCCESS)
			return (result);
383
	}
384

385 386 387 388 389 390
	ISC_LIST_APPEND(ctx->servers->list, *server, next);
	*server = NULL;

	return (ISC_R_SUCCESS);
}

391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
isc_result_t
dns_c_ndcctx_getserver(dns_c_ndcctx_t *ctx, const char *name,
		       dns_c_ndcserver_t **server)
{
	dns_c_ndcserver_t *s;

	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(name != NULL);
	REQUIRE(server != NULL && *server == NULL);

	if (ctx->servers != NULL) {
		for (s = ISC_LIST_HEAD(ctx->servers->list); s != NULL;
		     s = ISC_LIST_NEXT(s, next)) {
			INSIST(s->name != NULL);
			if (strcasecmp(s->name, name) == 0) {
				*server = s;
				return (ISC_R_SUCCESS);
			}
		}
	}

	return (ISC_R_NOTFOUND);
}

415
isc_result_t
416
dns_c_ndcctx_getkeys(dns_c_ndcctx_t *ctx, dns_c_kdeflist_t **keys) {
417 418 419 420 421 422
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(keys != NULL);
	REQUIRE(*keys == NULL);

	*keys = ctx->keys;

423 424 425 426
	if (ctx->keys == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
427 428 429
}

isc_result_t
430
dns_c_ndcctx_setkeys(dns_c_ndcctx_t *ctx, dns_c_kdeflist_t *keys) {
431 432 433 434 435 436 437 438 439
	isc_boolean_t existed;
	
	REQUIRE(DNS_C_NDCCTX_VALID(ctx));
	REQUIRE(DNS_C_KDEFLIST_VALID(keys));

	existed = ISC_TF(ctx->keys != NULL);
	
	ctx->keys = keys;

440 441 442 443
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
444 445 446
}

isc_result_t
447
dns_c_ndcserverlist_new(isc_mem_t *mem, dns_c_ndcserverlist_t **servers) {
448 449 450 451 452 453
	dns_c_ndcserverlist_t *newlist;

	REQUIRE(servers != NULL);
	REQUIRE(*servers == NULL);
	
	newlist = isc_mem_get(mem, sizeof *newlist);
454
	if (newlist == NULL)
455 456 457 458 459 460 461 462 463 464 465 466
		return (ISC_R_NOMEMORY);

	newlist->mem = mem;
	newlist->magic = DNS_C_NDCSERVERLIST_MAGIC;
	ISC_LIST_INIT(newlist->list);

	*servers = newlist;
	
	return (ISC_R_SUCCESS);
}

isc_result_t
467
dns_c_ndcserverlist_destroy(dns_c_ndcserverlist_t **servers) {
468 469 470 471 472
	dns_c_ndcserverlist_t *slist;
	dns_c_ndcserver_t *server;
	dns_c_ndcserver_t *p;
	isc_mem_t *mem;

Bob Halley's avatar
Bob Halley committed
473
	REQUIRE(servers != NULL);
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495

	slist = *servers;

	REQUIRE(DNS_C_NDCSERVERLIST_VALID(slist));

	server = ISC_LIST_HEAD(slist->list);
	while (server != NULL) {
		p = ISC_LIST_NEXT(server, next);
		ISC_LIST_UNLINK(slist->list, server, next);
		dns_c_ndcserver_destroy(&server);
		server = p;
	}

	mem = slist->mem;
	slist->mem = NULL;
	slist->magic = 0;
	isc_mem_put(mem, slist, sizeof *slist);

	return (ISC_R_SUCCESS);
}

dns_c_ndcserver_t *
496
dns_c_ndcserverlist_first(dns_c_ndcserverlist_t *servers) {
497 498 499 500 501 502
	REQUIRE(DNS_C_NDCSERVERLIST_VALID(servers));
	
	return (ISC_LIST_HEAD(servers->list));
}

dns_c_ndcserver_t *
503
dns_c_ndcserverlist_next(dns_c_ndcserver_t *server) {
504
	REQUIRE(DNS_C_NDCSERVER_VALID(server));
505

506 507 508 509 510
	return (ISC_LIST_NEXT(server, next));
}


isc_result_t
511
dns_c_ndcopts_new(isc_mem_t *mem, dns_c_ndcopts_t **opts) {
512 513 514 515 516 517
	dns_c_ndcopts_t *newo;
	
	REQUIRE(opts != NULL);
	REQUIRE(*opts == NULL);

	newo = isc_mem_get(mem, sizeof *newo);
518
	if (newo == NULL)
519 520 521 522 523 524 525 526 527 528 529 530 531
		return (ISC_R_NOMEMORY);

	newo->magic = DNS_C_NDCOPTIONS_MAGIC;
	newo->mem = mem;
	newo->defserver = NULL;
	newo->defkey = NULL;

	*opts = newo;
	
	return (ISC_R_SUCCESS);
}

isc_result_t
532
dns_c_ndcopts_destroy(dns_c_ndcopts_t **opts) {
533 534 535 536 537 538 539 540 541
	dns_c_ndcopts_t *o;
	isc_mem_t *mem;
	
	REQUIRE(opts != NULL);

	o = *opts;
	
	REQUIRE(DNS_C_NDCOPTIONS_VALID(o));

542
	if (o->defserver != NULL)
543 544
		isc_mem_free(o->mem, o->defserver);

545
	if (o->defkey != NULL)
546 547 548 549 550 551 552 553 554 555 556 557 558
		isc_mem_free(o->mem, o->defkey);

	mem = o->mem;
	o->mem = NULL;
	o->magic = 0;

	isc_mem_put(mem, o, sizeof *o);

	return (ISC_R_SUCCESS);
}
	
		
isc_result_t
559
dns_c_ndcopts_getdefserver(dns_c_ndcopts_t *opts, const char **retval) {
560 561 562 563 564 565
	REQUIRE(DNS_C_NDCOPTIONS_VALID(opts));
	REQUIRE(retval != NULL);
	REQUIRE(*retval == NULL);

	*retval = opts->defserver;

566 567 568 569
	if (opts->defserver == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
570 571 572
}

isc_result_t
573
dns_c_ndcopts_getdefkey(dns_c_ndcopts_t *opts, const char **retval) {
574 575 576 577 578 579
	REQUIRE(DNS_C_NDCOPTIONS_VALID(opts));
	REQUIRE(retval != NULL);
	REQUIRE(*retval == NULL);

	*retval = opts->defkey;

580 581 582 583
	if (opts->defkey == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
584 585 586
}

isc_result_t
587
dns_c_ndcopts_setdefserver(dns_c_ndcopts_t *opts, const char *newval) {
588
	isc_boolean_t existed;
589

590 591 592 593
	REQUIRE(DNS_C_NDCOPTIONS_VALID(opts));
	REQUIRE(newval == NULL || *newval != '\0');

	existed = ISC_TF(opts->defserver != NULL);
594

595 596
	if (newval != NULL) {
		opts->defserver = isc_mem_strdup(opts->mem, newval);
597
		if (opts->defserver == NULL)
598
			return (ISC_R_NOMEMORY);
599 600

	} else
601 602
		opts->defserver = NULL;

603 604 605 606
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
607 608 609
}

isc_result_t
610
dns_c_ndcopts_setdefkey(dns_c_ndcopts_t *opts, const char *newval) {
611
	isc_boolean_t existed;
612

613 614 615 616 617 618 619
	REQUIRE(DNS_C_NDCOPTIONS_VALID(opts));
	REQUIRE(newval == NULL || *newval != '\0');

	existed = ISC_TF(opts->defkey != NULL);
	
	if (newval != NULL) {
		opts->defkey = isc_mem_strdup(opts->mem, newval);
620
		if (opts->defkey == NULL)
621
			return (ISC_R_NOMEMORY);
622 623

	} else
624 625
		opts->defkey = NULL;

626 627 628 629
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
630 631 632 633 634
}



isc_result_t
635
dns_c_ndcserver_new(isc_mem_t *mem, dns_c_ndcserver_t **server) {
636 637 638 639 640 641
	dns_c_ndcserver_t *serv = NULL;
	
	REQUIRE(server != NULL);
	REQUIRE(*server == NULL);

	serv = isc_mem_get(mem, sizeof *serv);
642
	if (serv == NULL)
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
		return (ISC_R_NOMEMORY);

	serv->magic = DNS_C_NDCSERVER_MAGIC;
	serv->mem = mem;
	serv->name = NULL;
	serv->key = NULL;
	serv->host = NULL;
	ISC_LINK_INIT(serv, next);

	*server = serv;

	return (ISC_R_SUCCESS);
}
	
isc_result_t
658
dns_c_ndcserver_destroy(dns_c_ndcserver_t **server) {
659 660 661 662 663 664 665 666
	dns_c_ndcserver_t *serv;
	isc_mem_t *mem;
	
	REQUIRE(server != NULL);

	serv = *server ;
	REQUIRE(DNS_C_NDCSERVER_VALID(serv));

667
	if (serv->name != NULL)
668 669
		isc_mem_free(serv->mem, serv->name);
	
670
	if (serv->key != NULL)
671 672
		isc_mem_free(serv->mem, serv->key);
	
673
	if (serv->host != NULL)
674 675 676 677 678 679 680 681 682 683 684 685 686
		isc_mem_free(serv->mem, serv->host);

	mem = serv->mem;
	serv->mem = NULL;
	serv->magic = 0;

	isc_mem_put(mem, serv, sizeof *serv);

	return (ISC_R_SUCCESS);
}

	
isc_result_t
687
dns_c_ndcserver_setkey(dns_c_ndcserver_t *server, const char *val) {
688 689 690 691 692 693 694 695
	isc_boolean_t existed;
	
	REQUIRE(DNS_C_NDCSERVER_VALID(server));

	existed = ISC_TF(server->key != NULL);

	if (val != NULL) {
		server->key = isc_mem_strdup(server->mem, val);
696
		if (server->key == NULL)
697
			return (ISC_R_NOMEMORY);
698 699

	} else
700 701
		server->key = NULL;

702 703 704 705
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
706 707 708
}

isc_result_t
709
dns_c_ndcserver_setname(dns_c_ndcserver_t *server, const char *val) {
710 711 712 713 714 715 716 717
	isc_boolean_t existed;
	
	REQUIRE(DNS_C_NDCSERVER_VALID(server));

	existed = ISC_TF(server->name != NULL);

	if (val != NULL) {
		server->name = isc_mem_strdup(server->mem, val);
718
		if (server->name == NULL)
719
			return (ISC_R_NOMEMORY);
720 721

	} else
722 723
		server->name = NULL;

724 725 726 727
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
728 729 730
}

isc_result_t
731
dns_c_ndcserver_sethost(dns_c_ndcserver_t *server, const char *val) {
732 733 734 735 736 737 738 739
	isc_boolean_t existed;
	
	REQUIRE(DNS_C_NDCSERVER_VALID(server));

	existed = ISC_TF(server->host != NULL);

	if (val != NULL) {
		server->host = isc_mem_strdup(server->mem, val);
740
		if (server->host == NULL)
741
			return (ISC_R_NOMEMORY);
742 743

	} else
744 745
		server->host = NULL;

746 747 748 749
	if (existed)
		return (ISC_R_EXISTS);
	else
		return (ISC_R_SUCCESS);
750 751 752
}
	
isc_result_t
753
dns_c_ndcserver_getkey(dns_c_ndcserver_t *server, const char **val) {
754 755 756 757 758 759
	REQUIRE(DNS_C_NDCSERVER_VALID(server));
	REQUIRE(val != NULL);
	REQUIRE (*val == NULL);

	*val = server->key;

760 761 762 763
	if (server->key == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
764 765 766
}

isc_result_t
767
dns_c_ndcserver_gethost(dns_c_ndcserver_t *server, const char **val) {
768 769 770 771 772 773
	REQUIRE(DNS_C_NDCSERVER_VALID(server));
	REQUIRE(val != NULL);
	REQUIRE (*val == NULL);

	*val = server->host;

774 775 776 777
	if (server->host == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
778 779 780
}


781 782
isc_result_t
dns_c_ndcserver_getname(dns_c_ndcserver_t *server, const char **val) {
783 784 785 786 787 788
	REQUIRE(DNS_C_NDCSERVER_VALID(server));
	REQUIRE(val != NULL);
	REQUIRE (*val == NULL);

	*val = server->name;

789 790 791 792
	if (server->name == NULL)
		return (ISC_R_NOTFOUND);
	else
		return (ISC_R_SUCCESS);
793 794 795 796 797 798 799 800 801 802 803
}

/* *********************************************************************** */
/*                       PUBLIC PARSING ROUTINE                            */
/* *********************************************************************** */

isc_result_t
dns_c_ndcparseconf(const char *filename, isc_mem_t *mem,
		   dns_c_ndcctx_t **ndcctx)
{
	ndcpcontext pctx;
804
	isc_result_t result;
805 806
	dns_c_ndcctx_t *aConfig;
	
807 808 809
	result = parser_setup(&pctx, mem, filename);
	if (result != ISC_R_SUCCESS)
		goto done;
810
	
811 812 813
	result = parse_file(&pctx, &aConfig);
	if (result != ISC_R_SUCCESS && aConfig != NULL)
		dns_c_ndcctx_destroy(&aConfig);
814 815 816 817 818 819 820 821 822 823

 done:
	if (pctx.thelexer != NULL)
		isc_lex_destroy(&pctx.thelexer);
	
	if (pctx.thekeywords != NULL)
		isc_symtab_destroy(&pctx.thekeywords);

	*ndcctx = aConfig;
	
824
	return (result);
825 826 827 828 829 830 831
}

/* *********************************************************************** */
/*                      PRIVATE PARSING ROUTINES                           */
/* *********************************************************************** */

static isc_result_t
832 833
parse_file(ndcpcontext *pctx, dns_c_ndcctx_t **context) {
	isc_result_t result;
834 835
	isc_boolean_t done = ISC_FALSE;

836 837 838
	result = dns_c_ndcctx_new(pctx->themem, context);
	if (result != ISC_R_SUCCESS)
		return (result);
839 840 841

	pctx->thecontext = *context;

842 843
	result = getnexttoken(pctx);
	done = ISC_TF(result != ISC_R_SUCCESS);
844 845 846 847
	
	while (!done) {
		switch (pctx->currtok) {
		case L_END_INPUT:
848
			result = ISC_R_SUCCESS;
849 850 851 852
			done = ISC_TRUE;
			break;

		default:
853 854
			result = parse_statement(pctx);
			if (result != ISC_R_SUCCESS) {
855 856 857 858 859 860
				done = ISC_TRUE;
				break;
			}
		}
	}

861
	return (result);
862 863 864
}

static isc_result_t
865
parse_statement(ndcpcontext *pctx) {
866
	isc_result_t result;
867 868 869 870 871 872 873 874
	dns_c_ndcctx_t *ctx = pctx->thecontext;
	dns_c_ndcopts_t *opts = NULL;
	dns_c_ndcopts_t *tmpopts = NULL;
	dns_c_ndcserver_t  *server = NULL;
	dns_c_kdeflist_t *keys = NULL;
	
	switch (pctx->currtok) {
	case L_OPTIONS:
875 876
		result = parse_options(pctx, &opts);
		if (result == ISC_R_SUCCESS) {
877
			(void)dns_c_ndcctx_getoptions(ctx, &tmpopts);
878 879
			result = dns_c_ndcctx_setoptions(ctx, opts);
			if (result == ISC_R_EXISTS) {
880
				parser_warn(pctx, ISC_FALSE,
881
					    "redefining 'options'");
882
				result = ISC_R_SUCCESS;
883 884
				dns_c_ndcopts_destroy(&tmpopts);
			}
885

886 887 888 889 890
			opts = NULL;
		}
		break;

	case L_SERVER:
891 892 893
		result = parse_serverstmt(pctx, &server);
		if (result == ISC_R_SUCCESS)
			result = dns_c_ndcctx_addserver(ctx, &server);
894 895 896 897
		break;

	case L_KEY:
		keys = NULL;
898 899 900 901 902
		result = dns_c_ndcctx_getkeys(ctx, &keys);
		if (result == ISC_R_NOTFOUND) {
			result = dns_c_kdeflist_new(pctx->themem, &keys);
			if (result != ISC_R_SUCCESS)
				return (result);
903 904 905
			dns_c_ndcctx_setkeys(ctx, keys);
		}

906
		result = parse_keystmt(pctx, keys);
907 908 909 910
		break;
		
	default:
		syntax_error(pctx, pctx->currtok);
911
		result = ISC_R_FAILURE;
912 913 914
		break;
	}

915 916 917
	if (result == ISC_R_SUCCESS)
		if (!eat_eos(pctx))
			result = ISC_R_FAILURE;
918

919
	if (server != NULL)
920 921
		dns_c_ndcserver_destroy(&server);

922
	if (opts != NULL)
923 924
		dns_c_ndcopts_destroy(&opts);
							
925
	return (result);
926 927 928
}

static isc_result_t
929 930
parse_options(ndcpcontext *pctx, dns_c_ndcopts_t **opts) {
	isc_result_t result;
931 932 933 934 935 936
	isc_uint32_t option;
	dns_c_ndcopts_t *newopts = NULL;
	dns_c_ndcctx_t *cfgctx = pctx->thecontext;

	REQUIRE(DNS_C_NDCCTX_VALID(cfgctx));
	
937
	if (!eat(pctx, L_OPTIONS) || !eat_lbrace(pctx))
938 939
		return (ISC_R_FAILURE);

940 941 942
	result = dns_c_ndcopts_new(cfgctx->mem, &newopts);
	if (result != ISC_R_SUCCESS)
		return (result);
943
	
944 945
	result = ISC_R_SUCCESS;
	while (result == ISC_R_SUCCESS && pctx->currtok != L_RBRACE) {
946 947
		option = pctx->currtok;

948
		if (!eat(pctx, pctx->currtok))
949 950 951 952
			return (ISC_R_FAILURE);
		
		switch (option) {
		case L_DEFAULT_SERVER:
953 954
			if (!looking_at_anystring(pctx))
				return (result);
955

956 957 958 959
			result = dns_c_ndcopts_setdefserver(newopts,
							    pctx->tokstr);
			if (result == ISC_R_SUCCESS)
				result = getnexttoken(pctx);
960
			
961 962
			if (result != ISC_R_SUCCESS)
				return (result);
963 964 965 966

			break;
				
		case L_DEFAULT_KEY:
967 968
			if (!looking_at_anystring(pctx))
				return (result);
969
			
970 971
			result = dns_c_ndcopts_setdefkey(newopts,
							 pctx->tokstr);
972

973 974
			if (result == ISC_R_SUCCESS)
				result = getnexttoken(pctx);
975
			
976 977
			if (result != ISC_R_SUCCESS)
				return (result);
978 979 980 981
			break;

		default:
			syntax_error(pctx, pctx->currtok);
982
			result = ISC_R_FAILURE;
983 984 985
			break;
		}

986
		if (result == ISC_R_EXISTS) {
987 988
			parser_warn(pctx, ISC_FALSE, "redefining %s",
				    keyword2str(option));
989
			result = ISC_R_SUCCESS;
990

991 992
		} else if (result == ISC_R_SUCCESS && !eat_eos(pctx))
			result = ISC_R_FAILURE;
993 994
	}

995 996 997 998
	if (result == ISC_R_SUCCESS && !eat_rbrace(pctx))
		result = ISC_R_FAILURE;

	if (result == ISC_R_SUCCESS)
999
		*opts = newopts;
1000
	else
1001 1002
		dns_c_ndcopts_destroy(&newopts);
	
1003
	return (result);
1004 1005 1006 1007
}


static isc_result_t
1008 1009
parse_serverstmt(ndcpcontext *pctx, dns_c_ndcserver_t **server) {
	isc_result_t result = ISC_R_FAILURE;
1010 1011 1012 1013 1014
	char *servername = NULL;
	char *keyname = NULL;
	char *hostname = NULL;
	dns_c_ndcserver_t *serv = NULL;
		
1015
	if (!eat(pctx, L_SERVER))
1016 1017
		return (ISC_R_FAILURE);

1018 1019 1020
	if (!looking_at_anystring(pctx))
		return (result);
	else if (pctx->tokstr[0] == '\0') {
1021 1022 1023 1024 1025 1026 1027
		parser_error(pctx, ISC_TRUE,
			     "zero-length server name is illegal");
		return (ISC_R_FAILURE);
	}

	servername = isc_mem_strdup(pctx->themem, pctx->tokstr);
	if (servername == NULL) {
1028
		result = ISC_R_FAILURE;
1029 1030 1031
		goto done;
	}

1032 1033 1034 1035
	result = getnexttoken(pctx);

	if (result != ISC_R_SUCCESS || !eat(pctx, L_LBRACE)) {
		result = ISC_R_FAILURE;
1036 1037 1038 1039 1040 1041 1042
		goto done;
	}

	while (pctx->currtok != L_RBRACE) {
		isc_int32_t field = pctx->currtok;

		if (!eat(pctx, field)) {
1043
			result = ISC_R_FAILURE;
1044 1045 1046 1047 1048 1049
			goto done;
		}
		
		switch (field) {
		case L_KEY:
			if (!looking_at_anystring(pctx)) {
1050
				result = ISC_R_FAILURE;
1051 1052 1053 1054 1055
				goto done;
			}

			if (keyname != NULL) {
				parser_warn(pctx, ISC_FALSE,
1056
					    "multiple 'key' definitions");
1057 1058
				isc_mem_free(pctx->themem, keyname);
			}
1059 1060 1061 1062

			keyname = isc_mem_strdup(pctx->themem, pctx->tokstr);
			if (keyname == NULL)
				result = ISC_R_NOMEMORY;
1063
			
1064 1065
			if (result == ISC_R_SUCCESS)
				result = getnexttoken(pctx);
1066 1067 1068 1069 1070
			
			break;

		case L_HOST:
			if (!looking_at_anystring(pctx)) {
1071
				result = ISC_R_FAILURE;
1072 1073 1074 1075 1076
				goto done;
			}

			if (hostname != NULL) {
				parser_warn(pctx, ISC_FALSE,
1077
					    "multiple 'host' definitions");
1078 1079
				isc_mem_free(pctx->themem, hostname);
			}
1080 1081 1082 1083

			hostname = isc_mem_strdup(pctx->themem, pctx->tokstr);
			if (hostname == NULL)
				result = ISC_R_NOMEMORY;
1084
			
1085 1086
			if (result == ISC_R_SUCCESS)
				result = getnexttoken(pctx);
1087 1088 1089 1090 1091
			
			break;

		default:
			syntax_error(pctx, field);
1092
			result = ISC_R_FAILURE;
1093 1094 1095
			goto done;
		}

1096
		if (result != ISC_R_SUCCESS)
1097 1098 1099
			goto done;
		
		if (!eat_eos(pctx)) {
1100
			result = ISC_R_FAILURE;
1101 1102 1103 1104 1105
			goto done;
		}
	}

	if (!eat(pctx, L_RBRACE)) {
1106
		result = ISC_R_FAILURE;
1107 1108 1109 1110 1111 1112 1113
		goto done;
	}

	REQUIRE(servername != NULL);

	if (keyname == NULL) {
		parser_error(pctx, ISC_FALSE,