Beispiel #1
0
static void
addlookup(char *opt) {
	dig_lookup_t *lookup;
	isc_result_t result;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char store[MXNAME];

	debug("addlookup()");
	tr.base = deftype;
	tr.length = strlen(deftype);
	result = dns_rdatatype_fromtext(&rdtype, &tr);
	if (result != ISC_R_SUCCESS) {
		printf("unknown query type: %s\n", deftype);
		rdclass = dns_rdatatype_a;
	}
	tr.base = defclass;
	tr.length = strlen(defclass);
	result = dns_rdataclass_fromtext(&rdclass, &tr);
	if (result != ISC_R_SUCCESS) {
		printf("unknown query class: %s\n", defclass);
		rdclass = dns_rdataclass_in;
	}
	lookup = make_empty_lookup();
	if (get_reverse(store, sizeof(store), opt, lookup->ip6_int, ISC_TRUE)
	    == ISC_R_SUCCESS) {
		safecpy(lookup->textname, store, sizeof(lookup->textname));
		lookup->rdtype = dns_rdatatype_ptr;
		lookup->rdtypeset = ISC_TRUE;
	} else {
		safecpy(lookup->textname, opt, sizeof(lookup->textname));
		lookup->rdtype = rdtype;
		lookup->rdtypeset = ISC_TRUE;
	}
	lookup->rdclass = rdclass;
	lookup->rdclassset = ISC_TRUE;
	lookup->trace = ISC_FALSE;
	lookup->trace_root = lookup->trace;
	lookup->ns_search_only = ISC_FALSE;
	lookup->identify = identify;
	lookup->recurse = recurse;
	lookup->aaonly = aaonly;
	lookup->retries = tries;
	lookup->udpsize = 0;
	lookup->comments = comments;
	lookup->tcp_mode = tcpmode;
	lookup->stats = stats;
	lookup->section_question = section_question;
	lookup->section_answer = section_answer;
	lookup->section_authority = section_authority;
	lookup->section_additional = section_additional;
	lookup->new_search = ISC_TRUE;
	ISC_LIST_INIT(lookup->q);
	ISC_LINK_INIT(lookup, link);
	ISC_LIST_APPEND(lookup_list, lookup, link);
	lookup->origin = NULL;
	ISC_LIST_INIT(lookup->my_server_list);
	debug("looking up %s", lookup->textname);
}
Beispiel #2
0
/*% load the zone */
isc_result_t
load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
	  dns_masterformat_t fileformat, const char *classname,
	  dns_zone_t **zonep)
{
	isc_result_t result;
	dns_rdataclass_t rdclass;
	isc_textregion_t region;
	isc_buffer_t buffer;
	dns_fixedname_t fixorigin;
	dns_name_t *origin;
	dns_zone_t *zone = NULL;

	REQUIRE(zonep == NULL || *zonep == NULL);

	if (debug)
		fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
			zonename, filename, classname);

	CHECK(dns_zone_create(&zone, mctx));

	dns_zone_settype(zone, dns_zone_master);

	isc_buffer_init(&buffer, zonename, strlen(zonename));
	isc_buffer_add(&buffer, strlen(zonename));
	dns_fixedname_init(&fixorigin);
	origin = dns_fixedname_name(&fixorigin);
	CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
	CHECK(dns_zone_setorigin(zone, origin));
	CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
	CHECK(dns_zone_setfile2(zone, filename, fileformat));

	DE_CONST(classname, region.base);
	region.length = strlen(classname);
	CHECK(dns_rdataclass_fromtext(&rdclass, &region));

	dns_zone_setclass(zone, rdclass);
	dns_zone_setoption(zone, zone_options, ISC_TRUE);
	dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);
	if (docheckmx)
		dns_zone_setcheckmx(zone, checkmx);
	if (docheckns)
		dns_zone_setcheckns(zone, checkns);
	if (dochecksrv)
		dns_zone_setchecksrv(zone, checksrv);

	CHECK(dns_zone_load(zone));
	if (zonep != NULL) {
		*zonep = zone;
		zone = NULL;
	}

 cleanup:
	if (zone != NULL)
		dns_zone_detach(&zone);
	return (result);
}
Beispiel #3
0
static void
setup(const char *zonename, const char *filename, const char *classname) {
	isc_result_t result;
	dns_rdataclass_t rdclass;
	isc_consttextregion_t region;
	isc_buffer_t buffer;
	dns_fixedname_t fixorigin;
	dns_name_t *origin;
	const char *rbt = "rbt";

	if (debug)
		fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
			zonename, filename, classname);
	result = dns_zone_create(&zone, mctx);
	ERRRET(result, "dns_zone_new");

	dns_zone_settype(zone, zonetype);

	isc_buffer_init(&buffer, zonename, strlen(zonename));
	isc_buffer_add(&buffer, strlen(zonename));
	dns_fixedname_init(&fixorigin);
	result = dns_name_fromtext(dns_fixedname_name(&fixorigin),
				   &buffer, dns_rootname, 0, NULL);
	ERRRET(result, "dns_name_fromtext");
	origin = dns_fixedname_name(&fixorigin);

	result = dns_zone_setorigin(zone, origin);
	ERRRET(result, "dns_zone_setorigin");

	result = dns_zone_setdbtype(zone, 1, &rbt);
	ERRRET(result, "dns_zone_setdatabase");

	result = dns_zone_setfile(zone, filename);
	ERRRET(result, "dns_zone_setfile");

	region.base = classname;
	region.length = strlen(classname);
	result = dns_rdataclass_fromtext(&rdclass,
					 (isc_textregion_t *)(void*)&region);
	ERRRET(result, "dns_rdataclass_fromtext");

	dns_zone_setclass(zone, rdclass);

	if (zonetype == dns_zone_slave)
		dns_zone_setmasters(zone, &addr, 1);

	result = dns_zone_load(zone);
	ERRRET(result, "dns_zone_load");

	result = dns_zonemgr_managezone(zonemgr, zone);
	ERRRET(result, "dns_zonemgr_managezone");
}
Beispiel #4
0
static isc_result_t
config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
		dns_rdataclass_t *classp)
{
	isc_textregion_t r;

	if (!cfg_obj_isstring(classobj)) {
		*classp = defclass;
		return (ISC_R_SUCCESS);
	}
	DE_CONST(cfg_obj_asstring(classobj), r.base);
	r.length = strlen(r.base);
	return (dns_rdataclass_fromtext(classp, &r));
}
Beispiel #5
0
dns_rdataclass_t
strtoclass(const char *str) {
	isc_textregion_t r;
	dns_rdataclass_t rdclass;
	isc_result_t ret;

	if (str == NULL)
		return dns_rdataclass_in;
	DE_CONST(str, r.base);
	r.length = strlen(str);
	ret = dns_rdataclass_fromtext(&rdclass, &r);
	if (ret != ISC_R_SUCCESS)
		fatal("unknown class %s", str);
	return (rdclass);
}
Beispiel #6
0
static isc_boolean_t
testclass(char *typetext) {
	isc_result_t result;
	isc_textregion_t tr;
	dns_rdataclass_t rdclass;

	tr.base = typetext;
	tr.length = strlen(typetext);
	result = dns_rdataclass_fromtext(&rdclass, &tr);
	if (result == ISC_R_SUCCESS)
		return (ISC_TRUE);
	else {
		printf("unknown query class: %s\n", typetext);
		return (ISC_FALSE);
	}
}
Beispiel #7
0
isc_result_t
ns_config_getclass(const cfg_obj_t *classobj, dns_rdataclass_t defclass,
		   dns_rdataclass_t *classp) {
	isc_textregion_t r;
	isc_result_t result;

	if (!cfg_obj_isstring(classobj)) {
		*classp = defclass;
		return (ISC_R_SUCCESS);
	}
	DE_CONST(cfg_obj_asstring(classobj), r.base);
	r.length = strlen(r.base);
	result = dns_rdataclass_fromtext(classp, &r);
	if (result != ISC_R_SUCCESS)
		cfg_obj_log(classobj, ns_g_lctx, ISC_LOG_ERROR,
			    "unknown class '%s'", r.base);
	return (result);
}
Beispiel #8
0
static isc_result_t
configure_hint(const char *zfile, const char *zclass, isc_mem_t *mctx) {
	isc_result_t result;
	dns_db_t *db = NULL;
	dns_rdataclass_t rdclass;
	isc_textregion_t r;

	if (zfile == NULL)
		return (ISC_R_FAILURE);

	DE_CONST(zclass, r.base);
	r.length = strlen(zclass);
	result = dns_rdataclass_fromtext(&rdclass, &r);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = dns_rootns_create(mctx, rdclass, zfile, &db);
	if (result != ISC_R_SUCCESS)
		return (result);

	dns_db_detach(&db);
	return (ISC_R_SUCCESS);
}
Beispiel #9
0
static void
parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only,
	   int argc, char **argv) {
	isc_result_t result;
	isc_textregion_t tr;
	isc_boolean_t firstarg = ISC_TRUE;
	dig_lookup_t *lookup = NULL;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	isc_boolean_t open_type_class = ISC_TRUE;
	char batchline[MXNAME];
	int bargc;
	char *bargv[64];
	int rc;
	char **rv;
#ifndef NOPOSIX
	char *homedir;
	char rcfile[256];
#endif
	char *input;
	int i;
	isc_boolean_t need_clone = ISC_TRUE;

	/*
	 * The semantics for parsing the args is a bit complex; if
	 * we don't have a host yet, make the arg apply globally,
	 * otherwise make it apply to the latest host.  This is
	 * a bit different than the previous versions, but should
	 * form a consistent user interface.
	 *
	 * First, create a "default lookup" which won't actually be used
	 * anywhere, except for cloning into new lookups
	 */

	debug("parse_args()");
	if (!is_batchfile) {
		debug("making new lookup");
		default_lookup = make_empty_lookup();
		default_lookup->adflag = ISC_TRUE;
		default_lookup->edns = 0;

#ifndef NOPOSIX
		/*
		 * Treat ${HOME}/.digrc as a special batchfile
		 */
		INSIST(batchfp == NULL);
		homedir = getenv("HOME");
		if (homedir != NULL) {
			unsigned int n;
			n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc",
				     homedir);
			if (n < sizeof(rcfile))
				batchfp = fopen(rcfile, "r");
		}
		if (batchfp != NULL) {
			while (fgets(batchline, sizeof(batchline),
				     batchfp) != 0) {
				debug("config line %s", batchline);
				bargc = 1;
				input = batchline;
				bargv[bargc] = next_token(&input, " \t\r\n");
				while ((bargv[bargc] != NULL) &&
				       (bargc < 62)) {
					bargc++;
					bargv[bargc] =
						next_token(&input, " \t\r\n");
				}

				bargv[0] = argv[0];
				argv0 = argv[0];

				for(i = 0; i < bargc; i++)
					debug(".digrc argv %d: %s",
					      i, bargv[i]);
				parse_args(ISC_TRUE, ISC_TRUE, bargc,
					   (char **)bargv);
			}
			fclose(batchfp);
		}
#endif
	}

	if (is_batchfile && !config_only) {
		/* Processing '-f batchfile'. */
		lookup = clone_lookup(default_lookup, ISC_TRUE);
		need_clone = ISC_FALSE;
	} else
		lookup = default_lookup;

	rc = argc;
	rv = argv;
	for (rc--, rv++; rc > 0; rc--, rv++) {
		debug("main parsing %s", rv[0]);
		if (strncmp(rv[0], "%", 1) == 0)
			break;
		if (strncmp(rv[0], "@", 1) == 0) {
			addresscount = getaddresses(lookup, &rv[0][1], NULL);
		} else if (rv[0][0] == '+') {
			plus_option(&rv[0][1], is_batchfile,
				    lookup);
		} else if (rv[0][0] == '-') {
			if (rc <= 1) {
				if (dash_option(&rv[0][1], NULL,
						&lookup, &open_type_class,
						&need_clone, config_only,
						argc, argv, &firstarg)) {
					rc--;
					rv++;
				}
			} else {
				if (dash_option(&rv[0][1], rv[1],
						&lookup, &open_type_class,
						&need_clone, config_only,
						argc, argv, &firstarg)) {
					rc--;
					rv++;
				}
			}
		} else {
			/*
			 * Anything which isn't an option
			 */
			if (open_type_class) {
				if (strncasecmp(rv[0], "ixfr=", 5) == 0) {
					rdtype = dns_rdatatype_ixfr;
					result = ISC_R_SUCCESS;
				} else {
					tr.base = rv[0];
					tr.length = strlen(rv[0]);
					result = dns_rdatatype_fromtext(&rdtype,
						(isc_textregion_t *)&tr);
					if (result == ISC_R_SUCCESS &&
					    rdtype == dns_rdatatype_ixfr) {
						fprintf(stderr, ";; Warning, "
							"ixfr requires a "
							"serial number\n");
						continue;
					}
				}
				if (result == ISC_R_SUCCESS) {
					if (lookup->rdtypeset) {
						fprintf(stderr, ";; Warning, "
							"extra type option\n");
					}
					if (rdtype == dns_rdatatype_ixfr) {
						isc_uint32_t serial;
						lookup->rdtype =
							dns_rdatatype_ixfr;
						lookup->rdtypeset = ISC_TRUE;
						result = parse_uint(&serial,
								    &rv[0][5],
								    MAXSERIAL,
							      "serial number");
						if (result != ISC_R_SUCCESS)
							fatal("Couldn't parse "
							      "serial number");
						lookup->ixfr_serial = serial;
						lookup->section_question =
							plusquest;
						lookup->comments = pluscomm;
						lookup->tcp_mode = ISC_TRUE;
					} else {
						lookup->rdtype = rdtype;
						lookup->rdtypeset = ISC_TRUE;
						if (rdtype ==
						    dns_rdatatype_axfr) {
						    lookup->section_question =
								plusquest;
						    lookup->comments = pluscomm;
						}
						lookup->ixfr_serial = ISC_FALSE;
					}
					continue;
				}
				result = dns_rdataclass_fromtext(&rdclass,
						     (isc_textregion_t *)&tr);
				if (result == ISC_R_SUCCESS) {
					if (lookup->rdclassset) {
						fprintf(stderr, ";; Warning, "
							"extra class option\n");
					}
					lookup->rdclass = rdclass;
					lookup->rdclassset = ISC_TRUE;
					continue;
				}
			}

			if (!config_only) {
				if (need_clone)
					lookup = clone_lookup(default_lookup,
								      ISC_TRUE);
				need_clone = ISC_TRUE;
				strncpy(lookup->textname, rv[0],
					sizeof(lookup->textname));
				lookup->textname[sizeof(lookup->textname)-1]=0;
				lookup->trace_root = ISC_TF(lookup->trace  ||
						     lookup->ns_search_only);
				lookup->new_search = ISC_TRUE;
				if (firstarg) {
					printgreeting(argc, argv, lookup);
					firstarg = ISC_FALSE;
				}
				ISC_LIST_APPEND(lookup_list, lookup, link);
				debug("looking up %s", lookup->textname);
			}
			/* XXX Error message */
		}
	}

	/*
	 * If we have a batchfile, seed the lookup list with the
	 * first entry, then trust the callback in dighost_shutdown
	 * to get the rest
	 */
	if ((batchname != NULL) && !(is_batchfile)) {
		if (strcmp(batchname, "-") == 0)
			batchfp = stdin;
		else
			batchfp = fopen(batchname, "r");
		if (batchfp == NULL) {
			perror(batchname);
			if (exitcode < 8)
				exitcode = 8;
			fatal("couldn't open specified batch file");
		}
		/* XXX Remove code dup from shutdown code */
	next_line:
		if (fgets(batchline, sizeof(batchline), batchfp) != 0) {
			bargc = 1;
			debug("batch line %s", batchline);
			if (batchline[0] == '\r' || batchline[0] == '\n'
			    || batchline[0] == '#' || batchline[0] == ';')
				goto next_line;
			input = batchline;
			bargv[bargc] = next_token(&input, " \t\r\n");
			while ((bargv[bargc] != NULL) && (bargc < 14)) {
				bargc++;
				bargv[bargc] = next_token(&input, " \t\r\n");
			}

			bargv[0] = argv[0];
			argv0 = argv[0];

			for(i = 0; i < bargc; i++)
				debug("batch argv %d: %s", i, bargv[i]);
			parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv);
			return;
		}
		return;
	}
	/*
	 * If no lookup specified, search for root
	 */
	if ((lookup_list.head == NULL) && !config_only) {
		if (need_clone)
			lookup = clone_lookup(default_lookup, ISC_TRUE);
		need_clone = ISC_TRUE;
		lookup->trace_root = ISC_TF(lookup->trace ||
					    lookup->ns_search_only);
		lookup->new_search = ISC_TRUE;
		strcpy(lookup->textname, ".");
		lookup->rdtype = dns_rdatatype_ns;
		lookup->rdtypeset = ISC_TRUE;
		if (firstarg) {
			printgreeting(argc, argv, lookup);
			firstarg = ISC_FALSE;
		}
		ISC_LIST_APPEND(lookup_list, lookup, link);
	}
	if (!need_clone)
		destroy_lookup(lookup);
}
Beispiel #10
0
static isc_boolean_t
dash_option(char *option, char *next, dig_lookup_t **lookup,
	    isc_boolean_t *open_type_class, isc_boolean_t *need_clone,
	    isc_boolean_t config_only, int argc, char **argv,
	    isc_boolean_t *firstarg)
{
	char opt, *value, *ptr, *ptr2, *ptr3;
	isc_result_t result;
	isc_boolean_t value_from_next;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char textname[MXNAME];
	struct in_addr in4;
	struct in6_addr in6;
	in_port_t srcport;
	char *hash, *cmd;
	isc_uint32_t num;

	while (strpbrk(option, single_dash_opts) == &option[0]) {
		/*
		 * Since the -[46dhimnv] options do not take an argument,
		 * account for them (in any number and/or combination)
		 * if they appear as the first character(s) of a q-opt.
		 */
		opt = option[0];
		switch (opt) {
		case '4':
			if (have_ipv4) {
				isc_net_disableipv6();
				have_ipv6 = ISC_FALSE;
			} else {
				fatal("can't find IPv4 networking");
				/* NOTREACHED */
				return (ISC_FALSE);
			}
			break;
		case '6':
			if (have_ipv6) {
				isc_net_disableipv4();
				have_ipv4 = ISC_FALSE;
			} else {
				fatal("can't find IPv6 networking");
				/* NOTREACHED */
				return (ISC_FALSE);
			}
			break;
		case 'd':
			ptr = strpbrk(&option[1], dash_opts);
			if (ptr != &option[1]) {
				cmd = option;
				FULLCHECK("debug");
				debugging = ISC_TRUE;
				return (ISC_FALSE);
			} else
				debugging = ISC_TRUE;
			break;
		case 'h':
			help();
			exit(0);
			break;
		case 'i':
			ip6_int = ISC_TRUE;
			break;
		case 'm': /* memdebug */
			/* memdebug is handled in preparse_args() */
			break;
		case 'n':
			/* deprecated */
			break;
		case 'v':
			version();
			exit(0);
			break;
		}
		if (strlen(option) > 1U)
			option = &option[1];
		else
			return (ISC_FALSE);
	}
	opt = option[0];
	if (strlen(option) > 1U) {
		value_from_next = ISC_FALSE;
		value = &option[1];
	} else {
		value_from_next = ISC_TRUE;
		value = next;
	}
	if (value == NULL)
		goto invalid_option;
	switch (opt) {
	case 'b':
		hash = strchr(value, '#');
		if (hash != NULL) {
			result = parse_uint(&num, hash + 1, MAXPORT,
					    "port number");
			if (result != ISC_R_SUCCESS)
				fatal("Couldn't parse port number");
			srcport = num;
			*hash = '\0';
		} else
			srcport = 0;
		if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) {
			isc_sockaddr_fromin6(&bind_address, &in6, srcport);
			isc_net_disableipv4();
		} else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) {
			isc_sockaddr_fromin(&bind_address, &in4, srcport);
			isc_net_disableipv6();
		} else {
			if (hash != NULL)
				*hash = '#';
			fatal("invalid address %s", value);
		}
		if (hash != NULL)
			*hash = '#';
		specified_source = ISC_TRUE;
		return (value_from_next);
	case 'c':
		if ((*lookup)->rdclassset) {
			fprintf(stderr, ";; Warning, extra class option\n");
		}
		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdataclass_fromtext(&rdclass,
						 (isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS) {
			(*lookup)->rdclass = rdclass;
			(*lookup)->rdclassset = ISC_TRUE;
		} else
			fprintf(stderr, ";; Warning, ignoring "
				"invalid class %s\n",
				value);
		return (value_from_next);
	case 'f':
		batchname = value;
		return (value_from_next);
	case 'k':
		strncpy(keyfile, value, sizeof(keyfile));
		keyfile[sizeof(keyfile)-1]=0;
		return (value_from_next);
	case 'p':
		result = parse_uint(&num, value, MAXPORT, "port number");
		if (result != ISC_R_SUCCESS)
			fatal("Couldn't parse port number");
		port = num;
		return (value_from_next);
	case 'q':
		if (!config_only) {
			if (*need_clone)
				(*lookup) = clone_lookup(default_lookup,
							 ISC_TRUE);
			*need_clone = ISC_TRUE;
			strncpy((*lookup)->textname, value,
				sizeof((*lookup)->textname));
			(*lookup)->textname[sizeof((*lookup)->textname)-1]=0;
			(*lookup)->trace_root = ISC_TF((*lookup)->trace  ||
						     (*lookup)->ns_search_only);
			(*lookup)->new_search = ISC_TRUE;
			if (*firstarg) {
				printgreeting(argc, argv, *lookup);
				*firstarg = ISC_FALSE;
			}
			ISC_LIST_APPEND(lookup_list, (*lookup), link);
			debug("looking up %s", (*lookup)->textname);
		}
		return (value_from_next);
	case 't':
		*open_type_class = ISC_FALSE;
		if (strncasecmp(value, "ixfr=", 5) == 0) {
			rdtype = dns_rdatatype_ixfr;
			result = ISC_R_SUCCESS;
		} else {
			tr.base = value;
			tr.length = strlen(value);
			result = dns_rdatatype_fromtext(&rdtype,
						(isc_textregion_t *)&tr);
			if (result == ISC_R_SUCCESS &&
			    rdtype == dns_rdatatype_ixfr) {
				result = DNS_R_UNKNOWN;
			}
		}
		if (result == ISC_R_SUCCESS) {
			if ((*lookup)->rdtypeset) {
				fprintf(stderr, ";; Warning, "
						"extra type option\n");
			}
			if (rdtype == dns_rdatatype_ixfr) {
				isc_uint32_t serial;
				(*lookup)->rdtype = dns_rdatatype_ixfr;
				(*lookup)->rdtypeset = ISC_TRUE;
				result = parse_uint(&serial, &value[5],
					   MAXSERIAL, "serial number");
				if (result != ISC_R_SUCCESS)
					fatal("Couldn't parse serial number");
				(*lookup)->ixfr_serial = serial;
				(*lookup)->section_question = plusquest;
				(*lookup)->comments = pluscomm;
				(*lookup)->tcp_mode = ISC_TRUE;
			} else {
				(*lookup)->rdtype = rdtype;
				(*lookup)->rdtypeset = ISC_TRUE;
				if (rdtype == dns_rdatatype_axfr) {
					(*lookup)->section_question = plusquest;
					(*lookup)->comments = pluscomm;
				}
				(*lookup)->ixfr_serial = ISC_FALSE;
			}
		} else
			fprintf(stderr, ";; Warning, ignoring "
				 "invalid type %s\n",
				 value);
		return (value_from_next);
	case 'y':
		ptr = next_token(&value,":");	/* hmac type or name */
		if (ptr == NULL) {
			usage();
		}
		ptr2 = next_token(&value, ":");	/* name or secret */
		if (ptr2 == NULL)
			usage();
		ptr3 = next_token(&value,":"); /* secret or NULL */
		if (ptr3 != NULL) {
			parse_hmac(ptr);
			ptr = ptr2;
			ptr2 = ptr3;
		} else  {
			hmacname = DNS_TSIG_HMACMD5_NAME;
			digestbits = 0;
		}
		strncpy(keynametext, ptr, sizeof(keynametext));
		keynametext[sizeof(keynametext)-1]=0;
		strncpy(keysecret, ptr2, sizeof(keysecret));
		keysecret[sizeof(keysecret)-1]=0;
		return (value_from_next);
	case 'x':
		if (*need_clone)
			*lookup = clone_lookup(default_lookup, ISC_TRUE);
		*need_clone = ISC_TRUE;
		if (get_reverse(textname, sizeof(textname), value,
				ip6_int, ISC_FALSE) == ISC_R_SUCCESS) {
			strncpy((*lookup)->textname, textname,
				sizeof((*lookup)->textname));
			debug("looking up %s", (*lookup)->textname);
			(*lookup)->trace_root = ISC_TF((*lookup)->trace  ||
						(*lookup)->ns_search_only);
			(*lookup)->ip6_int = ip6_int;
			if (!(*lookup)->rdtypeset)
				(*lookup)->rdtype = dns_rdatatype_ptr;
			if (!(*lookup)->rdclassset)
				(*lookup)->rdclass = dns_rdataclass_in;
			(*lookup)->new_search = ISC_TRUE;
			if (*firstarg) {
				printgreeting(argc, argv, *lookup);
				*firstarg = ISC_FALSE;
			}
			ISC_LIST_APPEND(lookup_list, *lookup, link);
		} else {
			fprintf(stderr, "Invalid IP address %s\n", value);
			exit(1);
		}
		return (value_from_next);
	invalid_option:
	default:
		fprintf(stderr, "Invalid option: -%s\n", option);
		usage();
	}
	/* NOTREACHED */
	return (ISC_FALSE);
}
Beispiel #11
0
static void
make_prereq(isc_mem_t *mctx, char *cmdline, isc_boolean_t ispositive,
	    isc_boolean_t isrrset, dns_name_t *name)
{
	isc_result_t result;
	char *word;
	isc_textregion_t region;
	dns_rdataset_t *rdataset = NULL;
	dns_rdatalist_t *rdatalist = NULL;
	dns_rdataclass_t rdataclass;
	dns_rdatatype_t rdatatype;
	dns_rdata_t *rdata = NULL;

	/*
	 * Read the owner name
	 */
	parse_name(&cmdline, name);

	/*
	 * If this is an rrset prereq, read the class or type.
	 */
	if (isrrset) {
		word = nsu_strsep(&cmdline, " \t\r\n");
		if (word == NULL || *word == 0) {
			fprintf(stderr, "could not read class or type\n");
			exit(1);
		}
		region.base = word;
		region.length = strlen(word);
		result = dns_rdataclass_fromtext(&rdataclass, &region);
		if (result == ISC_R_SUCCESS) {
			/*
			 * Now read the type.
			 */
			word = nsu_strsep(&cmdline, " \t\r\n");
			if (word == NULL || *word == 0) {
				fprintf(stderr, "could not read type\n");
				exit(1);
			}
			region.base = word;
			region.length = strlen(word);
			result = dns_rdatatype_fromtext(&rdatatype, &region);
			if (result != ISC_R_SUCCESS) {
				fprintf(stderr, "invalid type: %s\n", word);
				exit(1);
			}
		} else {
			rdataclass = default_rdataclass;
			result = dns_rdatatype_fromtext(&rdatatype, &region);
			if (result != ISC_R_SUCCESS) {
				fprintf(stderr, "invalid type: %s\n", word);
				exit(1);
			}
		}
	} else
		rdatatype = dns_rdatatype_any;

	rdata = isc_mem_get(mctx, sizeof(*rdata));
	if (rdata == NULL) {
		fprintf(stderr, "memory allocation for rdata failed\n");
		exit(1);
	}
	dns_rdata_init(rdata);

	if (isrrset && ispositive)
		parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);
	else
		rdata->flags = DNS_RDATA_UPDATE;

	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
	if (rdatalist == NULL) {
		fprintf(stderr, "memory allocation for rdatalist failed\n");
		exit(1);
	}
	dns_rdatalist_init(rdatalist);
	rdatalist->type = rdatatype;
	if (ispositive) {
		if (isrrset && rdata->data != NULL)
			rdatalist->rdclass = rdataclass;
		else
			rdatalist->rdclass = dns_rdataclass_any;
	} else
		rdatalist->rdclass = dns_rdataclass_none;
	rdatalist->covers = 0;
	rdatalist->ttl = 0;
	rdata->rdclass = rdatalist->rdclass;
	rdata->type = rdatatype;
	ISC_LIST_INIT(rdatalist->rdata);
	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);

	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
	if (rdataset == NULL) {
		fprintf(stderr, "memory allocation for rdataset failed\n");
		exit(1);
	}
	dns_rdataset_init(rdataset);
	dns_rdatalist_tordataset(rdatalist, rdataset);
	ISC_LIST_INIT(name->list);
	ISC_LIST_APPEND(name->list, rdataset, link);
}
Beispiel #12
0
static void
update_addordelete(isc_mem_t *mctx, char *cmdline, isc_boolean_t isdelete,
		   dns_name_t *name)
{
	isc_result_t result;
	isc_uint32_t ttl;
	char *word;
	dns_rdataclass_t rdataclass;
	dns_rdatatype_t rdatatype;
	dns_rdata_t *rdata = NULL;
	dns_rdatalist_t *rdatalist = NULL;
	dns_rdataset_t *rdataset = NULL;
	isc_textregion_t region;

	/*
	 * Read the owner name.
	 */
	parse_name(&cmdline, name);

	rdata = isc_mem_get(mctx, sizeof(*rdata));
	if (rdata == NULL) {
		fprintf(stderr, "memory allocation for rdata failed\n");
		exit(1);
	}
	dns_rdata_init(rdata);

	/*
	 * If this is an add, read the TTL and verify that it's in range.
	 * If it's a delete, ignore a TTL if present (for compatibility).
	 */
	word = nsu_strsep(&cmdline, " \t\r\n");
	if (word == NULL || *word == 0) {
		if (!isdelete) {
			fprintf(stderr, "could not read owner ttl\n");
			exit(1);
		}
		else {
			ttl = 0;
			rdataclass = dns_rdataclass_any;
			rdatatype = dns_rdatatype_any;
			rdata->flags = DNS_RDATA_UPDATE;
			goto doneparsing;
		}
	}
	result = isc_parse_uint32(&ttl, word, 10);
	if (result != ISC_R_SUCCESS) {
		if (isdelete) {
			ttl = 0;
			goto parseclass;
		} else {
			fprintf(stderr, "ttl '%s': %s\n", word,
				isc_result_totext(result));
			exit(1);
		}
	}

	if (isdelete)
		ttl = 0;
	else if (ttl > TTL_MAX) {
		fprintf(stderr, "ttl '%s' is out of range (0 to %u)\n",
			word, TTL_MAX);
		exit(1);
	}

	/*
	 * Read the class or type.
	 */
	word = nsu_strsep(&cmdline, " \t\r\n");
 parseclass:
	if (word == NULL || *word == 0) {
		if (isdelete) {
			rdataclass = dns_rdataclass_any;
			rdatatype = dns_rdatatype_any;
			rdata->flags = DNS_RDATA_UPDATE;
		goto doneparsing;
		} else {
			fprintf(stderr, "could not read class or type\n");
			exit(1);
		}
	}
	region.base = word;
	region.length = strlen(word);
	result = dns_rdataclass_fromtext(&rdataclass, &region);
	if (result == ISC_R_SUCCESS) {
		/*
		 * Now read the type.
		 */
		word = nsu_strsep(&cmdline, " \t\r\n");
		if (word == NULL || *word == 0) {
			if (isdelete) {
				rdataclass = dns_rdataclass_any;
				rdatatype = dns_rdatatype_any;
				rdata->flags = DNS_RDATA_UPDATE;
				goto doneparsing;
			} else {
				fprintf(stderr, "could not read type\n");
				exit(1);
			}
		}
		region.base = word;
		region.length = strlen(word);
		result = dns_rdatatype_fromtext(&rdatatype, &region);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "'%s' is not a valid type: %s\n",
				word, isc_result_totext(result));
			exit(1);
		}
	} else {
		rdataclass = default_rdataclass;
		result = dns_rdatatype_fromtext(&rdatatype, &region);
		if (result != ISC_R_SUCCESS) {
			fprintf(stderr, "'%s' is not a valid class or type: "
				"%s\n", word, isc_result_totext(result));
			exit(1);
		}
	}

	parse_rdata(mctx, &cmdline, rdataclass, rdatatype, rdata);

	if (isdelete) {
		if ((rdata->flags & DNS_RDATA_UPDATE) != 0)
			rdataclass = dns_rdataclass_any;
		else
			rdataclass = dns_rdataclass_none;
	} else {
		if ((rdata->flags & DNS_RDATA_UPDATE) != 0) {
			fprintf(stderr, "could not read rdata\n");
			exit(1);
		}
	}

 doneparsing:

	rdatalist = isc_mem_get(mctx, sizeof(*rdatalist));
	if (rdatalist == NULL) {
		fprintf(stderr, "memory allocation for rdatalist failed\n");
		exit(1);
	}
	dns_rdatalist_init(rdatalist);
	rdatalist->type = rdatatype;
	rdatalist->rdclass = rdataclass;
	rdatalist->covers = rdatatype;
	rdatalist->ttl = (dns_ttl_t)ttl;
	ISC_LIST_INIT(rdatalist->rdata);
	ISC_LIST_APPEND(rdatalist->rdata, rdata, link);
	ISC_LIST_APPEND(usedrdatalists, rdatalist, link);

	rdataset = isc_mem_get(mctx, sizeof(*rdataset));
	if (rdataset == NULL) {
		fprintf(stderr, "memory allocation for rdataset failed\n");
		exit(1);
	}
	dns_rdataset_init(rdataset);
	dns_rdatalist_tordataset(rdatalist, rdataset);
	ISC_LIST_INIT(name->list);
	ISC_LIST_APPEND(name->list, rdataset, link);
}
Beispiel #13
0
/*
 * Argument parsing is based on dig, but simplified: only one
 * QNAME/QCLASS/QTYPE tuple can be specified, and options have
 * been removed that aren't applicable to delv. The interface
 * should be familiar to dig users, however.
 */
static void
parse_args(int argc, char **argv) {
	isc_result_t result;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	isc_boolean_t open_type_class = ISC_TRUE;

	for (; argc > 0; argc--, argv++) {
		if (argv[0][0] == '@') {
			server = &argv[0][1];
		} else if (argv[0][0] == '+') {
			plus_option(&argv[0][1]);
		} else if (argv[0][0] == '-') {
			if (argc <= 1) {
				if (dash_option(&argv[0][1], NULL,
						&open_type_class))
				{
					argc--;
					argv++;
				}
			} else {
				if (dash_option(&argv[0][1], argv[1],
						&open_type_class))
				{
					argc--;
					argv++;
				}
			}
		} else {
			/*
			 * Anything which isn't an option
			 */
			if (open_type_class) {
				tr.base = argv[0];
				tr.length = strlen(argv[0]);
				result = dns_rdatatype_fromtext(&rdtype,
					(isc_textregion_t *)&tr);
				if (result == ISC_R_SUCCESS) {
					if (typeset)
						warn("extra query type");
					if (rdtype == dns_rdatatype_ixfr ||
					    rdtype == dns_rdatatype_axfr)
						fatal("Transfer not supported");
					qtype = rdtype;
					typeset = ISC_TRUE;
					continue;
				}
				result = dns_rdataclass_fromtext(&rdclass,
						     (isc_textregion_t *)&tr);
				if (result == ISC_R_SUCCESS) {
					if (classset)
						warn("extra query class");
					else if (rdclass != dns_rdataclass_in)
						warn("ignoring non-IN "
						     "query class");
					continue;
				}
			}

			if (curqname == NULL) {
				curqname = isc_mem_strdup(mctx, argv[0]);
				if (curqname == NULL)
					fatal("out of memory");
			}
		}
	}

	/*
	 * If no qname or qtype specified, search for root/NS
	 * If no qtype specified, use A
	 */
	if (!typeset)
		qtype = dns_rdatatype_a;

	if (curqname == NULL) {
		qname = isc_mem_strdup(mctx, ".");
		if (qname == NULL)
			fatal("out of memory");

		if (!typeset)
			qtype = dns_rdatatype_ns;
	} else
		qname = curqname;
}
Beispiel #14
0
static int
test_master(char *testfile, char *origin, char *db_class,
	    isc_result_t exp_result)
{
	int			result;
	int			len;
	isc_result_t		isc_result;
	isc_result_t		dns_result;
	dns_name_t		dns_origin;
	isc_buffer_t		source;
	isc_buffer_t		target;
	unsigned char		name_buf[BUFLEN];
	dns_rdatacallbacks_t	callbacks;
	dns_rdataclass_t	rdataclass;
	isc_textregion_t	textregion;

	if (T1_mctx == NULL)
		isc_result = isc_mem_create(0, 0, &T1_mctx);
	else
		isc_result = ISC_R_SUCCESS;
	if (isc_result != ISC_R_SUCCESS) {
		t_info("isc_mem_create failed %d\n", isc_result);
		return(T_UNRESOLVED);
	}

	len = strlen(origin);
	isc_buffer_init(&source, origin, len);
	isc_buffer_add(&source, len);
	isc_buffer_setactive(&source, len);
	isc_buffer_init(&target, name_buf, BUFLEN);
	dns_name_init(&dns_origin, NULL);
	dns_result = dns_name_fromtext(&dns_origin, &source, dns_rootname,
				       0, &target);
	if (dns_result != ISC_R_SUCCESS) {
		t_info("dns_name_fromtext failed %s\n",
				dns_result_totext(dns_result));
		return(T_UNRESOLVED);
	}

	dns_rdatacallbacks_init_stdio(&callbacks);
	callbacks.add = t1_add_callback;

	textregion.base = db_class;
	textregion.length = strlen(db_class);

	dns_result = dns_rdataclass_fromtext(&rdataclass, &textregion);
	if (dns_result != ISC_R_SUCCESS) {
		t_info("dns_rdataclass_fromtext failed %s\n",
				dns_result_totext(dns_result));
		return(T_UNRESOLVED);
	}

	dns_result = dns_master_loadfile(	testfile,
						&dns_origin,
						&dns_origin,
						rdataclass,
						ISC_TRUE,
						&callbacks,
						T1_mctx);

	if (dns_result == exp_result)
		result = T_PASS;
	else {
		t_info("dns_master_loadfile: got %s, expected %s\n",
			dns_result_totext(dns_result),
			dns_result_totext(exp_result));
		result = T_FAIL;
	}
	return(result);
}
Beispiel #15
0
/*% load the zone */
isc_result_t
load_zone(isc_mem_t *mctx, const char *zonename, const char *filename,
	  dns_masterformat_t fileformat, const char *classname,
	  dns_ttl_t maxttl, dns_zone_t **zonep)
{
	isc_result_t result;
	dns_rdataclass_t rdclass;
	isc_textregion_t region;
	isc_buffer_t buffer;
	dns_fixedname_t fixorigin;
	dns_name_t *origin;
	dns_zone_t *zone = NULL;

	REQUIRE(zonep == NULL || *zonep == NULL);

	if (debug)
		fprintf(stderr, "loading \"%s\" from \"%s\" class \"%s\"\n",
			zonename, filename, classname);

	CHECK(dns_zone_create(&zone, mctx));

	dns_zone_settype(zone, dns_zone_master);

	isc_buffer_constinit(&buffer, zonename, strlen(zonename));
	isc_buffer_add(&buffer, strlen(zonename));
	dns_fixedname_init(&fixorigin);
	origin = dns_fixedname_name(&fixorigin);
	CHECK(dns_name_fromtext(origin, &buffer, dns_rootname, 0, NULL));
	CHECK(dns_zone_setorigin(zone, origin));
	CHECK(dns_zone_setdbtype(zone, 1, (const char * const *) dbtype));
	CHECK(dns_zone_setfile2(zone, filename, fileformat));
	if (journal != NULL)
		CHECK(dns_zone_setjournal(zone, journal));

	DE_CONST(classname, region.base);
	region.length = strlen(classname);
	CHECK(dns_rdataclass_fromtext(&rdclass, &region));

	dns_zone_setclass(zone, rdclass);
	dns_zone_setoption(zone, zone_options, ISC_TRUE);
	dns_zone_setoption2(zone, zone_options2, ISC_TRUE);
	dns_zone_setoption(zone, DNS_ZONEOPT_NOMERGE, nomerge);

	dns_zone_setmaxttl(zone, maxttl);

	if (docheckmx)
		dns_zone_setcheckmx(zone, checkmx);
	if (docheckns)
		dns_zone_setcheckns(zone, checkns);
	if (dochecksrv)
		dns_zone_setchecksrv(zone, checksrv);

	CHECK(dns_zone_load(zone));

	/*
	 * When loading map files we can't catch oversize TTLs during
	 * load, so we check for them here.
	 */
	if (fileformat == dns_masterformat_map && maxttl != 0) {
		CHECK(check_ttls(zone, maxttl));
	}

	if (zonep != NULL) {
		*zonep = zone;
		zone = NULL;
	}

 cleanup:
	if (zone != NULL)
		dns_zone_detach(&zone);
	return (result);
}
Beispiel #16
0
/*%
 * Reads a public key from disk
 */
isc_result_t
dst_key_read_public(const char *filename, int type,
		    isc_mem_t *mctx, dst_key_t **keyp)
{
	u_char rdatabuf[DST_KEY_MAXSIZE];
	isc_buffer_t b;
	dns_fixedname_t name;
	isc_lex_t *lex = NULL;
	isc_token_t token;
	isc_result_t ret;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	unsigned int opt = ISC_LEXOPT_DNSMULTILINE;
	dns_rdataclass_t rdclass = dns_rdataclass_in;
	isc_lexspecials_t specials;
	isc_uint32_t ttl = 0;
	isc_result_t result;
	dns_rdatatype_t keytype;

	/*
	 * Open the file and read its formatted contents
	 * File format:
	 *    domain.name [ttl] [class] [KEY|DNSKEY] <flags> <protocol> <algorithm> <key>
	 */

	/* 1500 should be large enough for any key */
	ret = isc_lex_create(mctx, 1500, &lex);
	if (ret != ISC_R_SUCCESS)
		goto cleanup;

	memset(specials, 0, sizeof(specials));
	specials['('] = 1;
	specials[')'] = 1;
	specials['"'] = 1;
	isc_lex_setspecials(lex, specials);
	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);

	ret = isc_lex_openfile(lex, filename);
	if (ret != ISC_R_SUCCESS)
		goto cleanup;

#define NEXTTOKEN(lex, opt, token) { \
	ret = isc_lex_gettoken(lex, opt, token); \
	if (ret != ISC_R_SUCCESS) \
		goto cleanup; \
	}

#define BADTOKEN() { \
	ret = ISC_R_UNEXPECTEDTOKEN; \
	goto cleanup; \
	}

	/* Read the domain name */
	NEXTTOKEN(lex, opt, &token);
	if (token.type != isc_tokentype_string)
		BADTOKEN();

	/*
	 * We don't support "@" in .key files.
	 */
	if (!strcmp(DST_AS_STR(token), "@"))
		BADTOKEN();

	dns_fixedname_init(&name);
	isc_buffer_init(&b, DST_AS_STR(token), strlen(DST_AS_STR(token)));
	isc_buffer_add(&b, strlen(DST_AS_STR(token)));
	ret = dns_name_fromtext(dns_fixedname_name(&name), &b, dns_rootname,
				0, NULL);
	if (ret != ISC_R_SUCCESS)
		goto cleanup;

	/* Read the next word: either TTL, class, or 'KEY' */
	NEXTTOKEN(lex, opt, &token);

	if (token.type != isc_tokentype_string)
		BADTOKEN();

	/* If it's a TTL, read the next one */
	result = dns_ttl_fromtext(&token.value.as_textregion, &ttl);
	if (result == ISC_R_SUCCESS)
		NEXTTOKEN(lex, opt, &token);

	if (token.type != isc_tokentype_string)
		BADTOKEN();

	ret = dns_rdataclass_fromtext(&rdclass, &token.value.as_textregion);
	if (ret == ISC_R_SUCCESS)
		NEXTTOKEN(lex, opt, &token);

	if (token.type != isc_tokentype_string)
		BADTOKEN();

	if (strcasecmp(DST_AS_STR(token), "DNSKEY") == 0)
		keytype = dns_rdatatype_dnskey;
	else if (strcasecmp(DST_AS_STR(token), "KEY") == 0)
		keytype = dns_rdatatype_key; /*%< SIG(0), TKEY */
	else
		BADTOKEN();

	if (((type & DST_TYPE_KEY) != 0 && keytype != dns_rdatatype_key) ||
	    ((type & DST_TYPE_KEY) == 0 && keytype != dns_rdatatype_dnskey)) {
		ret = DST_R_BADKEYTYPE;
		goto cleanup;
	}

	isc_buffer_init(&b, rdatabuf, sizeof(rdatabuf));
	ret = dns_rdata_fromtext(&rdata, rdclass, keytype, lex, NULL,
				 ISC_FALSE, mctx, &b, NULL);
	if (ret != ISC_R_SUCCESS)
		goto cleanup;

	ret = dst_key_fromdns(dns_fixedname_name(&name), rdclass, &b, mctx,
			      keyp);
	if (ret != ISC_R_SUCCESS)
		goto cleanup;

	dst_key_setttl(*keyp, ttl);

 cleanup:
	if (lex != NULL)
		isc_lex_destroy(&lex);
	return (ret);
}
Beispiel #17
0
int
main(int argc, char *argv[]) {
	isc_token_t token;
	isc_result_t result;
	int c;
	unsigned int options = 0;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char text[256*1024];
	char data[64*1024];
	isc_buffer_t tbuf;
	isc_buffer_t dbuf;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	isc_boolean_t doexit = ISC_FALSE;
	isc_boolean_t once = ISC_FALSE;
	isc_boolean_t print = ISC_FALSE;
	isc_boolean_t unknown = ISC_FALSE;
	unsigned int t;
	char *origin = NULL;
	dns_fixedname_t fixed;
	dns_name_t *name = NULL;

	while ((c = isc_commandline_parse(argc, argv, "ho:puCPT")) != -1) {
		switch (c) {
		case 'o':
			origin = isc_commandline_argument;
			break;

		case 'p':
			print = ISC_TRUE;
			break;

		case 'u':
			unknown = ISC_TRUE;
			break;

		case 'C':
			for (t = 1; t <= 0xfeffu; t++) {
				if (dns_rdataclass_ismeta(t))
					continue;
				dns_rdataclass_format(t, text, sizeof(text));
				if (strncmp(text, "CLASS", 4) != 0)
					fprintf(stdout, "%s\n", text);
			}
			exit(0);

		case 'P':
			for (t = 0xff00; t <= 0xfffeu; t++) {
				if (dns_rdatatype_ismeta(t))
					continue;
				dns_rdatatype_format(t, text, sizeof(text));
				if (strncmp(text, "TYPE", 4) != 0)
					fprintf(stdout, "%s\n", text);
			}
			doexit = ISC_TRUE;
			break;

		case 'T':
			for (t = 1; t <= 0xfeffu; t++) {
				if (dns_rdatatype_ismeta(t))
					continue;
				dns_rdatatype_format(t, text, sizeof(text));
				if (strncmp(text, "TYPE", 4) != 0)
					fprintf(stdout, "%s\n", text);
			}
			doexit = ISC_TRUE;
			break;

		case '?':
		case 'h':
			/* Does not return. */
			usage();

		default:
			fprintf(stderr, "%s: unhandled option -%c\n",
				argv[0], isc_commandline_option);
			exit(1);
		}
	}
	if (doexit)
		exit(0);

	RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS);
	RUNTIME_CHECK(isc_lex_create(mctx, 256, &lex) == ISC_R_SUCCESS);

	/*
	 * Set up to lex DNS master file.
	 */

	specials['('] = 1;
	specials[')'] = 1;
	specials['"'] = 1;
	isc_lex_setspecials(lex, specials);
	options = ISC_LEXOPT_EOL;
	isc_lex_setcomments(lex, ISC_LEXCOMMENT_DNSMASTERFILE);

	RUNTIME_CHECK(isc_lex_openstream(lex, stdin) == ISC_R_SUCCESS);

	if (origin != NULL) {
		dns_fixedname_init(&fixed);
		name = dns_fixedname_name(&fixed);
		result = dns_name_fromstring(name, origin, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_name_fromstring: %s",
			      dns_result_totext(result));
		}
	}

	while ((result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
					  &token)) == ISC_R_SUCCESS) {
		if (token.type == isc_tokentype_eof)
			break;
		if (token.type == isc_tokentype_eol)
			continue;
		if (once) {
			fatal("extra data");
		}
		/*
		 * Get class.
		 */
		if (token.type == isc_tokentype_number) {
			rdclass = (dns_rdataclass_t) token.value.as_ulong;
			if (token.value.as_ulong > 0xffffu) {
				fatal("class value too big %lu",
				      token.value.as_ulong);
			}
			if (dns_rdataclass_ismeta(rdclass)) {
				fatal("class %lu is a meta value",
				      token.value.as_ulong);
			}
		} else if (token.type == isc_tokentype_string) {
			result = dns_rdataclass_fromtext(&rdclass,
					&token.value.as_textregion);
			if (result != ISC_R_SUCCESS) {
				fatal("dns_rdataclass_fromtext: %s",
				      dns_result_totext(result));
			}
			if (dns_rdataclass_ismeta(rdclass)) {
				fatal("class %.*s(%d) is a meta value",
				      (int)token.value.as_textregion.length,
				      token.value.as_textregion.base, rdclass);
			}
		} else {
			fatal("unexpected token %u", token.type);
		}

		result = isc_lex_gettoken(lex, options | ISC_LEXOPT_NUMBER,
					  &token);
		if (result != ISC_R_SUCCESS)
			break;
		if (token.type == isc_tokentype_eol)
			continue;
		if (token.type == isc_tokentype_eof)
			break;

		/*
		 * Get type.
		 */
		if (token.type == isc_tokentype_number) {
			rdtype = (dns_rdatatype_t) token.value.as_ulong;
			if (token.value.as_ulong > 0xffffu) {
				fatal("type value too big %lu",
				      token.value.as_ulong);
			}
			if (dns_rdatatype_ismeta(rdtype)) {
				fatal("type %lu is a meta value",
				      token.value.as_ulong);
			}
		} else if (token.type == isc_tokentype_string) {
			result = dns_rdatatype_fromtext(&rdtype,
					&token.value.as_textregion);
			if (result != ISC_R_SUCCESS) {
				fatal("dns_rdatatype_fromtext: %s",
				      dns_result_totext(result));
			}
			if (dns_rdatatype_ismeta(rdtype)) {
				fatal("type %.*s(%d) is a meta value",
				      (int)token.value.as_textregion.length,
				      token.value.as_textregion.base, rdtype);
			}
		} else {
			fatal("unexpected token %u", token.type);
		}

		isc_buffer_init(&dbuf, data, sizeof(data));
		result = dns_rdata_fromtext(&rdata, rdclass, rdtype, lex,
					    name, 0, mctx, &dbuf, NULL);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdata_fromtext: %s",
			      dns_result_totext(result));
		}
		once = ISC_TRUE;
	}
	if (result != ISC_R_EOF) {
		fatal("eof not found");
	}
	if (!once) {
		fatal("no records found");
	}

	if (print) {
		isc_buffer_init(&tbuf, text, sizeof(text));
		result = dns_rdataclass_totext(rdclass, &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdataclass_totext: %s",
			      dns_result_totext(result));
		}
		isc_buffer_putstr(&tbuf, "\t");
		result = dns_rdatatype_totext(rdtype, &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdatatype_totext: %s",
			      dns_result_totext(result));
		}
		isc_buffer_putstr(&tbuf, "\t");
		result = dns_rdata_totext(&rdata, NULL, &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdata_totext: %s",
			      dns_result_totext(result));
		}

		printf("%.*s\n", (int)tbuf.used, (char*)tbuf.base);
		fflush(stdout);
	}

	if (unknown) {
		isc_buffer_init(&tbuf, text, sizeof(text));
		result = dns_rdataclass_tounknowntext(rdclass, &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdataclass_tounknowntext: %s",
			      dns_result_totext(result));
		}
		isc_buffer_putstr(&tbuf, "\t");
		result = dns_rdatatype_tounknowntext(rdtype, &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdatatype_tounknowntext: %s",
			      dns_result_totext(result));
		}
		isc_buffer_putstr(&tbuf, "\t");
		result = dns_rdata_tofmttext(&rdata, NULL,
					     DNS_STYLEFLAG_UNKNOWNFORMAT,
					     0, 0, "", &tbuf);
		if (result != ISC_R_SUCCESS) {
			fatal("dns_rdata_tofmttext: %sn",
			      dns_result_totext(result));
		}

		printf("%.*s\n", (int)tbuf.used, (char*)tbuf.base);
		fflush(stdout);
	}

	isc_lex_close(lex);
	isc_lex_destroy(&lex);
	isc_mem_destroy(&mctx);
	return (0);
}
Beispiel #18
0
static isc_boolean_t
dash_option(char *option, char *next, isc_boolean_t *open_type_class) {
	char opt, *value;
	isc_result_t result;
	isc_boolean_t value_from_next;
	isc_textregion_t tr;
	dns_rdatatype_t rdtype;
	dns_rdataclass_t rdclass;
	char textname[MAXNAME];
	struct in_addr in4;
	struct in6_addr in6;
	in_port_t srcport;
	isc_uint32_t num;
	char *hash;

	while (strpbrk(option, single_dash_opts) == &option[0]) {
		/*
		 * Since the -[46himv] options do not take an argument,
		 * account for them (in any number and/or combination)
		 * if they appear as the first character(s) of a q-opt.
		 */
		opt = option[0];
		switch (opt) {
		case '4':
			if (isc_net_probeipv4() != ISC_R_SUCCESS)
				fatal("IPv4 networking not available");
			if (use_ipv6) {
				isc_net_disableipv6();
				use_ipv6 = ISC_FALSE;
			}
			break;
		case '6':
			if (isc_net_probeipv6() != ISC_R_SUCCESS)
				fatal("IPv6 networking not available");
			if (use_ipv4) {
				isc_net_disableipv4();
				use_ipv4 = ISC_FALSE;
			}
			break;
		case 'h':
			usage();
			exit(0);
			/* NOTREACHED */
		case 'i':
			no_sigs = ISC_TRUE;
			dlv_validation = ISC_FALSE;
			root_validation = ISC_FALSE;
			break;
		case 'm':
			/* handled in preparse_args() */
			break;
		case 'v':
			fputs("delv " VERSION "\n", stderr);
			exit(0);
			/* NOTREACHED */
		default:
			INSIST(0);
		}
		if (strlen(option) > 1U)
			option = &option[1];
		else
			return (ISC_FALSE);
	}
	opt = option[0];
	if (strlen(option) > 1U) {
		value_from_next = ISC_FALSE;
		value = &option[1];
	} else {
		value_from_next = ISC_TRUE;
		value = next;
	}
	if (value == NULL)
		goto invalid_option;
	switch (opt) {
	case 'a':
		anchorfile = isc_mem_strdup(mctx, value);
		if (anchorfile == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 'b':
		hash = strchr(value, '#');
		if (hash != NULL) {
			result = parse_uint(&num, hash + 1, 0xffff, "port");
			if (result != ISC_R_SUCCESS)
				fatal("Couldn't parse port number");
			srcport = num;
			*hash = '\0';
		} else
			srcport = 0;

		if (inet_pton(AF_INET, value, &in4) == 1) {
			if (srcaddr4 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin(&a4, &in4, srcport);
			srcaddr4 = &a4;
		} else if (inet_pton(AF_INET6, value, &in6) == 1) {
			if (srcaddr6 != NULL)
				fatal("Only one local address per family "
				      "can be specified\n");
			isc_sockaddr_fromin6(&a6, &in6, srcport);
			srcaddr6 = &a6;
		} else {
			if (hash != NULL)
				*hash = '#';
			fatal("Invalid address %s", value);
		}
		if (hash != NULL)
			*hash = '#';
		return (value_from_next);
	case 'c':
		if (classset)
			warn("extra query class");

		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdataclass_fromtext(&rdclass,
						 (isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS)
			classset = ISC_TRUE;
		else if (rdclass != dns_rdataclass_in)
			warn("ignoring non-IN query class");
		else
			warn("ignoring invalid class");
		return (value_from_next);
	case 'd':
		result = parse_uint(&num, value, 99, "debug level");
		if (result != ISC_R_SUCCESS)
			fatal("Couldn't parse debug level");
		loglevel = num;
		return (value_from_next);
	case 'p':
		port = value;
		return (value_from_next);
	case 'q':
		if (curqname != NULL) {
			warn("extra query name");
			isc_mem_free(mctx, curqname);
		}
		curqname = isc_mem_strdup(mctx, value);
		if (curqname == NULL)
			fatal("out of memory");
		return (value_from_next);
	case 't':
		*open_type_class = ISC_FALSE;
		tr.base = value;
		tr.length = strlen(value);
		result = dns_rdatatype_fromtext(&rdtype,
					(isc_textregion_t *)&tr);
		if (result == ISC_R_SUCCESS) {
			if (typeset)
				warn("extra query type");
			if (rdtype == dns_rdatatype_ixfr ||
			    rdtype == dns_rdatatype_axfr)
				fatal("Transfer not supported");
			qtype = rdtype;
			typeset = ISC_TRUE;
		} else
			warn("ignoring invalid type");
		return (value_from_next);
	case 'x':
		result = get_reverse(textname, sizeof(textname), value,
				     ISC_FALSE);
		if (result == ISC_R_SUCCESS) {
			if (curqname != NULL) {
				isc_mem_free(mctx, curqname);
				warn("extra query name");
			}
			curqname = isc_mem_strdup(mctx, textname);
			if (curqname == NULL)
				fatal("out of memory");
			if (typeset)
				warn("extra query type");
			qtype = dns_rdatatype_ptr;
			typeset = ISC_TRUE;
		} else {
			fprintf(stderr, "Invalid IP address %s\n", value);
			exit(1);
		}
		return (value_from_next);
	invalid_option:
	default:
		fprintf(stderr, "Invalid option: -%s\n", option);
		usage();
	}
	/* NOTREACHED */
	return (ISC_FALSE);
}