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); }
/*% 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, ®ion)); 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); }
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*)®ion); 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"); }
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)); }
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); }
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); } }
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); }
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); }
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); }
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); }
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, ®ion); 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, ®ion); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid type: %s\n", word); exit(1); } } else { rdataclass = default_rdataclass; result = dns_rdatatype_fromtext(&rdatatype, ®ion); 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); }
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, ®ion); 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, ®ion); 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, ®ion); 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); }
/* * 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; }
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); }
/*% 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, ®ion)); 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); }
/*% * 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); }
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); }
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); }