ATF_TC_BODY(sockaddr_hash, tc) { isc_result_t result; isc_sockaddr_t addr; struct in_addr in; struct in6_addr in6; unsigned int h1, h2, h3, h4; int ret; UNUSED(tc); result = isc_test_begin(NULL, ISC_TRUE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); in.s_addr = inet_addr("127.0.0.1"); isc_sockaddr_fromin(&addr, &in, 1); h1 = isc_sockaddr_hash(&addr, ISC_TRUE); h2 = isc_sockaddr_hash(&addr, ISC_FALSE); ATF_CHECK(h1 != h2); ret = inet_pton(AF_INET6, "::ffff:127.0.0.1", &in6); ATF_CHECK(ret == 1); isc_sockaddr_fromin6(&addr, &in6, 1); h3 = isc_sockaddr_hash(&addr, ISC_TRUE); h4 = isc_sockaddr_hash(&addr, ISC_FALSE); ATF_CHECK(h1 == h3); ATF_CHECK(h2 == h4); isc_test_end(); }
ATF_TC_BODY(sockaddr_isnetzero, tc) { isc_sockaddr_t addr; struct in_addr in; struct in6_addr in6; isc_boolean_t r; int ret; size_t i; struct { const char *string; isc_boolean_t expect; } data4[] = { { "0.0.0.0", ISC_TRUE }, { "0.0.0.1", ISC_TRUE }, { "0.0.1.0", ISC_TRUE }, { "0.1.0.0", ISC_TRUE }, { "1.0.0.0", ISC_FALSE }, { "0.0.0.127", ISC_TRUE }, { "0.0.0.255", ISC_TRUE }, { "127.0.0.1", ISC_FALSE }, { "255.255.255.255", ISC_FALSE }, }; /* * Mapped addresses are currently not netzero. */ struct { const char *string; isc_boolean_t expect; } data6[] = { { "::ffff:0.0.0.0", ISC_FALSE }, { "::ffff:0.0.0.1", ISC_FALSE }, { "::ffff:0.0.0.127", ISC_FALSE }, { "::ffff:0.0.0.255", ISC_FALSE }, { "::ffff:127.0.0.1", ISC_FALSE }, { "::ffff:255.255.255.255", ISC_FALSE }, }; UNUSED(tc); for (i = 0; i < sizeof(data4)/sizeof(data4[0]); i++) { in.s_addr = inet_addr(data4[0].string); isc_sockaddr_fromin(&addr, &in, 1); r = isc_sockaddr_isnetzero(&addr); ATF_CHECK_EQ(r, data4[0].expect); } for (i = 0; i < sizeof(data6)/sizeof(data6[0]); i++) { ret = inet_pton(AF_INET6, "::ffff:127.0.0.1", &in6); ATF_CHECK_EQ(ret, 1); isc_sockaddr_fromin6(&addr, &in6, 1); r = isc_sockaddr_isnetzero(&addr); ATF_CHECK_EQ(r, data6[0].expect); } }
void perf_net_parselocal(int family, const char *name, unsigned int port, isc_sockaddr_t *addr) { struct in_addr in4a; struct in6_addr in6a; if (name == NULL) { isc_sockaddr_anyofpf(addr, family); isc_sockaddr_setport(addr, port); } else if (inet_pton(AF_INET, name, &in4a) == 1) { isc_sockaddr_fromin(addr, &in4a, port); } else if (inet_pton(AF_INET6, name, &in6a) == 1) { isc_sockaddr_fromin6(addr, &in6a, port); } else { fprintf(stderr, "invalid local address %s\n", name); perf_opt_usage(); exit(1); } }
static isc_result_t do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose) { isc_interfaceiter_t *iter = NULL; isc_boolean_t scan_ipv4 = ISC_FALSE; isc_boolean_t scan_ipv6 = ISC_FALSE; isc_boolean_t adjusting = ISC_FALSE; isc_boolean_t ipv6only = ISC_TRUE; isc_boolean_t ipv6pktinfo = ISC_TRUE; isc_result_t result; isc_netaddr_t zero_address, zero_address6; ns_listenelt_t *le; isc_sockaddr_t listen_addr; ns_interface_t *ifp; isc_boolean_t log_explicit = ISC_FALSE; isc_boolean_t dolistenon; if (ext_listen != NULL) adjusting = ISC_TRUE; if (isc_net_probeipv6() == ISC_R_SUCCESS) scan_ipv6 = ISC_TRUE; #ifdef WANT_IPV6 else isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "no IPv6 interfaces found"); #endif if (isc_net_probeipv4() == ISC_R_SUCCESS) scan_ipv4 = ISC_TRUE; else isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "no IPv4 interfaces found"); /* * A special, but typical case; listen-on-v6 { any; }. * When we can make the socket IPv6-only, open a single wildcard * socket for IPv6 communication. Otherwise, make separate socket * for each IPv6 address in order to avoid accepting IPv4 packets * as the form of mapped addresses unintentionally unless explicitly * allowed. */ #ifndef ISC_ALLOW_MAPPED if (scan_ipv6 == ISC_TRUE && isc_net_probe_ipv6only() != ISC_R_SUCCESS) { ipv6only = ISC_FALSE; log_explicit = ISC_TRUE; } #endif if (scan_ipv6 == ISC_TRUE && isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) { ipv6pktinfo = ISC_FALSE; log_explicit = ISC_TRUE; } if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) { for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { struct in6_addr in6a; if (!listenon_is_ip6_any(le)) continue; in6a = in6addr_any; isc_sockaddr_fromin6(&listen_addr, &in6a, le->port); ifp = find_matching_interface(mgr, &listen_addr); if (ifp != NULL) { ifp->generation = mgr->generation; } else { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "listening on IPv6 " "interfaces, port %u", le->port); result = ns_interface_setup(mgr, &listen_addr, "<any>", &ifp, ISC_TRUE); if (result == ISC_R_SUCCESS) ifp->flags |= NS_INTERFACEFLAG_ANYADDR; else isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "listening on all IPv6 " "interfaces failed"); /* Continue. */ } } } isc_netaddr_any(&zero_address); isc_netaddr_any6(&zero_address6); result = isc_interfaceiter_create(mgr->mctx, &iter); if (result != ISC_R_SUCCESS) return (result); if (adjusting == ISC_FALSE) { result = clearacl(mgr->mctx, &mgr->aclenv.localhost); if (result != ISC_R_SUCCESS) goto cleanup_iter; result = clearacl(mgr->mctx, &mgr->aclenv.localnets); if (result != ISC_R_SUCCESS) goto cleanup_iter; clearlistenon(mgr); } for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; result = isc_interfaceiter_next(iter)) { isc_interface_t interface; ns_listenlist_t *ll; unsigned int family; result = isc_interfaceiter_current(iter, &interface); if (result != ISC_R_SUCCESS) break; family = interface.address.family; if (family != AF_INET && family != AF_INET6) continue; if (scan_ipv4 == ISC_FALSE && family == AF_INET) continue; if (scan_ipv6 == ISC_FALSE && family == AF_INET6) continue; /* * Test for the address being nonzero rather than testing * INTERFACE_F_UP, because on some systems the latter * follows the media state and we could end up ignoring * the interface for an entire rescan interval due to * a temporary media glitch at rescan time. */ if (family == AF_INET && isc_netaddr_equal(&interface.address, &zero_address)) { continue; } if (family == AF_INET6 && isc_netaddr_equal(&interface.address, &zero_address6)) { continue; } if (adjusting == ISC_FALSE) { result = setup_locals(mgr, &interface); if (result != ISC_R_SUCCESS) goto ignore_interface; } ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6; dolistenon = ISC_TRUE; for (le = ISC_LIST_HEAD(ll->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { int match; isc_boolean_t ipv6_wildcard = ISC_FALSE; isc_netaddr_t listen_netaddr; isc_sockaddr_t listen_sockaddr; /* * Construct a socket address for this IP/port * combination. */ if (family == AF_INET) { isc_netaddr_fromin(&listen_netaddr, &interface.address.type.in); } else { isc_netaddr_fromin6(&listen_netaddr, &interface.address.type.in6); isc_netaddr_setzone(&listen_netaddr, interface.address.zone); } isc_sockaddr_fromnetaddr(&listen_sockaddr, &listen_netaddr, le->port); /* * See if the address matches the listen-on statement; * if not, ignore the interface. */ (void)dns_acl_match(&listen_netaddr, NULL, le->acl, &mgr->aclenv, &match, NULL); if (match <= 0) continue; if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) { setup_listenon(mgr, &interface, le->port); dolistenon = ISC_FALSE; } /* * The case of "any" IPv6 address will require * special considerations later, so remember it. */ if (family == AF_INET6 && ipv6only && ipv6pktinfo && listenon_is_ip6_any(le)) ipv6_wildcard = ISC_TRUE; /* * When adjusting interfaces with extra a listening * list, see if the address matches the extra list. * If it does, and is also covered by a wildcard * interface, we need to listen on the address * explicitly. */ if (adjusting == ISC_TRUE) { ns_listenelt_t *ele; match = 0; for (ele = ISC_LIST_HEAD(ext_listen->elts); ele != NULL; ele = ISC_LIST_NEXT(ele, link)) { (void)dns_acl_match(&listen_netaddr, NULL, ele->acl, NULL, &match, NULL); if (match > 0 && (ele->port == le->port || ele->port == 0)) break; else match = 0; } if (ipv6_wildcard == ISC_TRUE && match == 0) continue; } ifp = find_matching_interface(mgr, &listen_sockaddr); if (ifp != NULL) { ifp->generation = mgr->generation; } else { char sabuf[ISC_SOCKADDR_FORMATSIZE]; if (adjusting == ISC_FALSE && ipv6_wildcard == ISC_TRUE) continue; if (log_explicit && family == AF_INET6 && !adjusting && listenon_is_ip6_any(le)) { isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "IPv6 socket API is " "incomplete; explicitly " "binding to each IPv6 " "address separately"); log_explicit = ISC_FALSE; } isc_sockaddr_format(&listen_sockaddr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "%s" "listening on %s interface " "%s, %s", (adjusting == ISC_TRUE) ? "additionally " : "", (family == AF_INET) ? "IPv4" : "IPv6", interface.name, sabuf); result = ns_interface_setup(mgr, &listen_sockaddr, interface.name, &ifp, (adjusting == ISC_TRUE) ? ISC_FALSE : ISC_TRUE); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating %s interface " "%s failed; interface " "ignored", (family == AF_INET) ? "IPv4" : "IPv6", interface.name); } /* Continue. */ } } continue; ignore_interface: isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ignoring %s interface %s: %s", (family == AF_INET) ? "IPv4" : "IPv6", interface.name, isc_result_totext(result)); continue; } if (result != ISC_R_NOMORE) UNEXPECTED_ERROR(__FILE__, __LINE__, "interface iteration failed: %s", isc_result_totext(result)); else result = ISC_R_SUCCESS; cleanup_iter: isc_interfaceiter_destroy(&iter); return (result); }
isc_result_t ns_controls_configure(ns_controls_t *cp, const cfg_obj_t *config, cfg_aclconfctx_t *aclconfctx) { controllistener_t *listener; controllistenerlist_t new_listeners; const cfg_obj_t *controlslist = NULL; const cfg_listelt_t *element, *element2; char socktext[ISC_SOCKADDR_FORMATSIZE]; ISC_LIST_INIT(new_listeners); /* * Get the list of named.conf 'controls' statements. */ (void)cfg_map_get(config, "controls", &controlslist); /* * Run through the new control channel list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicate addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ if (controlslist != NULL) { for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *inetcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "inet", &inetcontrols); if (inetcontrols == NULL) continue; for (element2 = cfg_list_first(inetcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *obj; isc_sockaddr_t addr; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); obj = cfg_tuple_get(control, "address"); addr = *cfg_obj_assockaddr(obj); if (isc_sockaddr_getport(&addr) == 0) isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel %s", socktext); update_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } for (element = cfg_list_first(controlslist); element != NULL; element = cfg_list_next(element)) { const cfg_obj_t *controls; const cfg_obj_t *unixcontrols = NULL; controls = cfg_listelt_value(element); (void)cfg_map_get(controls, "unix", &unixcontrols); if (unixcontrols == NULL) continue; for (element2 = cfg_list_first(unixcontrols); element2 != NULL; element2 = cfg_list_next(element2)) { const cfg_obj_t *control; const cfg_obj_t *path; isc_sockaddr_t addr; isc_result_t result; /* * The parser handles BIND 8 configuration file * syntax, so it allows unix phrases as well * inet phrases with no keys{} clause. */ control = cfg_listelt_value(element2); path = cfg_tuple_get(control, "path"); result = isc_sockaddr_frompath(&addr, cfg_obj_asstring(path)); if (result != ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "control channel '%s': %s", cfg_obj_asstring(path), isc_result_totext(result)); continue; } isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_DEBUG(9), "processing control channel '%s'", cfg_obj_asstring(path)); update_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, control, config, &addr, aclconfctx, cfg_obj_asstring(path), isc_sockettype_unix); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } } else { int i; for (i = 0; i < 2; i++) { isc_sockaddr_t addr; if (i == 0) { struct in_addr localhost; if (isc_net_probeipv4() != ISC_R_SUCCESS) continue; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&addr, &localhost, 0); } else { if (isc_net_probeipv6() != ISC_R_SUCCESS) continue; isc_sockaddr_fromin6(&addr, &in6addr_loopback, 0); } isc_sockaddr_setport(&addr, NS_CONTROL_PORT); isc_sockaddr_format(&addr, socktext, sizeof(socktext)); update_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) /* * Remove the listener from the old * list, so it won't be shut down. */ ISC_LIST_UNLINK(cp->listeners, listener, link); else /* * This is a new listener. */ add_listener(cp, &listener, NULL, NULL, &addr, NULL, socktext, isc_sockettype_tcp); if (listener != NULL) ISC_LIST_APPEND(new_listeners, listener, link); } } /* * ns_control_shutdown() will stop whatever is on the global * listeners list, which currently only has whatever sockaddrs * were in the previous configuration (if any) that do not * remain in the current configuration. */ controls_shutdown(cp); /* * Put all of the valid listeners on the listeners list. * Anything already on listeners in the process of shutting * down will be taken care of by listen_done(). */ ISC_LIST_APPENDLIST(cp->listeners, new_listeners, link); return (ISC_R_SUCCESS); }
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); }
isc_result_t bind9_getaddresses(const char *hostname, in_port_t port, isc_sockaddr_t *addrs, int addrsize, int *addrcount) { struct in_addr in4; struct in6_addr in6; isc_boolean_t have_ipv4, have_ipv6; int i; #ifdef USE_GETADDRINFO struct addrinfo *ai = NULL, *tmpai, hints; int result; #else struct hostent *he; #endif REQUIRE(hostname != NULL); REQUIRE(addrs != NULL); REQUIRE(addrcount != NULL); REQUIRE(addrsize > 0); have_ipv4 = ISC_TF((isc_net_probeipv4() == ISC_R_SUCCESS)); have_ipv6 = ISC_TF((isc_net_probeipv6() == ISC_R_SUCCESS)); /* * Try IPv4, then IPv6. In order to handle the extended format * for IPv6 scoped addresses (address%scope_ID), we'll use a local * working buffer of 128 bytes. The length is an ad-hoc value, but * should be enough for this purpose; the buffer can contain a string * of at least 80 bytes for scope_ID in addition to any IPv6 numeric * addresses (up to 46 bytes), the delimiter character and the * terminating NULL character. */ if (inet_pton(AF_INET, hostname, &in4) == 1) { if (have_ipv4) isc_sockaddr_fromin(&addrs[0], &in4, port); else isc_sockaddr_v6fromin(&addrs[0], &in4, port); *addrcount = 1; return (ISC_R_SUCCESS); } else if (strlen(hostname) <= 127U) { char tmpbuf[128], *d; isc_uint32_t zone = 0; strcpy(tmpbuf, hostname); d = strchr(tmpbuf, '%'); if (d != NULL) *d = '\0'; if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { isc_netaddr_t na; if (!have_ipv6) return (ISC_R_FAMILYNOSUPPORT); if (d != NULL) { #ifdef ISC_PLATFORM_HAVESCOPEID isc_result_t result; result = isc_netscope_pton(AF_INET6, d + 1, &in6, &zone); if (result != ISC_R_SUCCESS) return (result); #else /* * The extended format is specified while the * system does not provide the ability to use * it. Throw an explicit error instead of * ignoring the specified value. */ return (ISC_R_BADADDRESSFORM); #endif } isc_netaddr_fromin6(&na, &in6); isc_netaddr_setzone(&na, zone); isc_sockaddr_fromnetaddr(&addrs[0], (const isc_netaddr_t *)&na, port); *addrcount = 1; return (ISC_R_SUCCESS); } } #ifdef USE_GETADDRINFO memset(&hints, 0, sizeof(hints)); if (!have_ipv6) hints.ai_family = PF_INET; else if (!have_ipv4) hints.ai_family = PF_INET6; else { hints.ai_family = PF_UNSPEC; #ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG; #endif } hints.ai_socktype = SOCK_STREAM; #ifdef AI_ADDRCONFIG again: #endif result = getaddrinfo(hostname, NULL, &hints, &ai); switch (result) { case 0: break; case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif return (ISC_R_NOTFOUND); #ifdef AI_ADDRCONFIG case EAI_BADFLAGS: if ((hints.ai_flags & AI_ADDRCONFIG) != 0) { hints.ai_flags &= ~AI_ADDRCONFIG; goto again; } #endif default: return (ISC_R_FAILURE); } for (tmpai = ai, i = 0; tmpai != NULL && i < addrsize; tmpai = tmpai->ai_next) { if (tmpai->ai_family != AF_INET && tmpai->ai_family != AF_INET6) continue; if (tmpai->ai_family == AF_INET) { struct sockaddr_in *sin; sin = (struct sockaddr_in *)tmpai->ai_addr; isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port); } else { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)tmpai->ai_addr; isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr, port); } i++; } freeaddrinfo(ai); *addrcount = i; #else he = gethostbyname(hostname); if (he == NULL) { switch (h_errno) { case HOST_NOT_FOUND: #ifdef NO_DATA case NO_DATA: #endif #if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS)) case NO_ADDRESS: #endif return (ISC_R_NOTFOUND); default: return (ISC_R_FAILURE); } } if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6) return (ISC_R_NOTFOUND); for (i = 0; i < addrsize; i++) { if (he->h_addrtype == AF_INET) { struct in_addr *inp; inp = (struct in_addr *)(he->h_addr_list[i]); if (inp == NULL) break; isc_sockaddr_fromin(&addrs[i], inp, port); } else { struct in6_addr *in6p; in6p = (struct in6_addr *)(he->h_addr_list[i]); if (in6p == NULL) break; isc_sockaddr_fromin6(&addrs[i], in6p, port); } } *addrcount = i; #endif if (*addrcount == 0) return (ISC_R_NOTFOUND); else return (ISC_R_SUCCESS); }
int main(int argc, char *argv[]) { isc_task_t *t1, *t2; isc_timermgr_t *timgr; isc_time_t expires; isc_interval_t interval; isc_timer_t *ti1; unsigned int workers; isc_socketmgr_t *socketmgr; isc_socket_t *so1, *so2; isc_sockaddr_t sockaddr; struct in_addr ina; struct in6_addr in6a; isc_result_t result; int pf; if (argc > 1) workers = atoi(argv[1]); else workers = 2; printf("%d workers\n", workers); if (isc_net_probeipv6() == ISC_R_SUCCESS) pf = PF_INET6; else pf = PF_INET; /* * EVERYTHING needs a memory context. */ mctx = NULL; RUNTIME_CHECK(isc_mem_create(0, 0, &mctx) == ISC_R_SUCCESS); /* * The task manager is independent (other than memory context) */ manager = NULL; RUNTIME_CHECK(isc_taskmgr_create(mctx, workers, 0, &manager) == ISC_R_SUCCESS); /* * Timer manager depends only on the memory context as well. */ timgr = NULL; RUNTIME_CHECK(isc_timermgr_create(mctx, &timgr) == ISC_R_SUCCESS); t1 = NULL; RUNTIME_CHECK(isc_task_create(manager, 0, &t1) == ISC_R_SUCCESS); t2 = NULL; RUNTIME_CHECK(isc_task_create(manager, 0, &t2) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_task_onshutdown(t1, my_shutdown, "1") == ISC_R_SUCCESS); RUNTIME_CHECK(isc_task_onshutdown(t2, my_shutdown, "2") == ISC_R_SUCCESS); printf("task 1 = %p\n", t1); printf("task 2 = %p\n", t2); socketmgr = NULL; RUNTIME_CHECK(isc_socketmgr_create(mctx, &socketmgr) == ISC_R_SUCCESS); /* * Open up a listener socket. */ so1 = NULL; if (pf == PF_INET6) { in6a = in6addr_any; isc_sockaddr_fromin6(&sockaddr, &in6a, 5544); } else { ina.s_addr = INADDR_ANY; isc_sockaddr_fromin(&sockaddr, &ina, 5544); } RUNTIME_CHECK(isc_socket_create(socketmgr, pf, isc_sockettype_tcp, &so1) == ISC_R_SUCCESS); result = isc_socket_bind(so1, &sockaddr, ISC_SOCKET_REUSEADDRESS); RUNTIME_CHECK(result == ISC_R_SUCCESS); RUNTIME_CHECK(isc_socket_listen(so1, 0) == ISC_R_SUCCESS); /* * Queue up the first accept event. */ RUNTIME_CHECK(isc_socket_accept(so1, t1, my_listen, "so1") == ISC_R_SUCCESS); isc_time_settoepoch(&expires); isc_interval_set(&interval, 10, 0); ti1 = NULL; RUNTIME_CHECK(isc_timer_create(timgr, isc_timertype_once, &expires, &interval, t1, timeout, so1, &ti1) == ISC_R_SUCCESS); /* * Open up a socket that will connect to www.flame.org, port 80. * Why not. :) */ so2 = NULL; ina.s_addr = inet_addr("204.152.184.97"); if (0 && pf == PF_INET6) isc_sockaddr_v6fromin(&sockaddr, &ina, 80); else isc_sockaddr_fromin(&sockaddr, &ina, 80); RUNTIME_CHECK(isc_socket_create(socketmgr, isc_sockaddr_pf(&sockaddr), isc_sockettype_tcp, &so2) == ISC_R_SUCCESS); RUNTIME_CHECK(isc_socket_connect(so2, &sockaddr, t2, my_connect, "so2") == ISC_R_SUCCESS); /* * Detaching these is safe, since the socket will attach to the * task for any outstanding requests. */ isc_task_detach(&t1); isc_task_detach(&t2); /* * Wait a short while. */ sleep(10); fprintf(stderr, "Destroying socket manager\n"); isc_socketmgr_destroy(&socketmgr); fprintf(stderr, "Destroying timer manager\n"); isc_timermgr_destroy(&timgr); fprintf(stderr, "Destroying task manager\n"); isc_taskmgr_destroy(&manager); isc_mem_stats(mctx, stdout); isc_mem_destroy(&mctx); return (0); }
int main(int argc, char **argv) { isc_boolean_t show_final_mem = ISC_FALSE; isc_result_t result = ISC_R_SUCCESS; isc_taskmgr_t *taskmgr = NULL; isc_task_t *task = NULL; isc_log_t *log = NULL; isc_logconfig_t *logconfig = NULL; isc_logdestination_t logdest; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const char *keyname = NULL; struct in_addr in; struct in6_addr in6; char *p; size_t argslen; int ch; int i; result = isc_file_progname(*argv, program, sizeof(program)); if (result != ISC_R_SUCCESS) memcpy(program, "rndc", 5); progname = program; admin_conffile = RNDC_CONFFILE; admin_keyfile = RNDC_KEYFILE; isc_sockaddr_any(&local4); isc_sockaddr_any6(&local6); result = isc_app_start(); if (result != ISC_R_SUCCESS) fatal("isc_app_start() failed: %s", isc_result_totext(result)); isc_commandline_errprint = ISC_FALSE; while ((ch = isc_commandline_parse(argc, argv, "b:c:hk:Mmp:s:Vy:")) != -1) { switch (ch) { case 'b': if (inet_pton(AF_INET, isc_commandline_argument, &in) == 1) { isc_sockaddr_fromin(&local4, &in, 0); local4set = ISC_TRUE; } else if (inet_pton(AF_INET6, isc_commandline_argument, &in6) == 1) { isc_sockaddr_fromin6(&local6, &in6, 0); local6set = ISC_TRUE; } break; case 'c': admin_conffile = isc_commandline_argument; break; case 'k': admin_keyfile = isc_commandline_argument; break; case 'M': isc_mem_debugging = ISC_MEM_DEBUGTRACE; break; case 'm': show_final_mem = ISC_TRUE; break; case 'p': remoteport = atoi(isc_commandline_argument); if (remoteport > 65535 || remoteport == 0) fatal("port '%s' out of range", isc_commandline_argument); break; case 's': servername = isc_commandline_argument; break; case 'V': verbose = ISC_TRUE; break; case 'y': keyname = isc_commandline_argument; break; case '?': if (isc_commandline_option != '?') { fprintf(stderr, "%s: invalid argument -%c\n", program, isc_commandline_option); usage(1); } case 'h': usage(0); break; default: fprintf(stderr, "%s: unhandled option -%c\n", program, isc_commandline_option); exit(1); } } argc -= isc_commandline_index; argv += isc_commandline_index; if (argc < 1) usage(1); isc_random_get(&serial); DO("create memory context", isc_mem_create(0, 0, &mctx)); DO("create socket manager", isc_socketmgr_create(mctx, &socketmgr)); DO("create task manager", isc_taskmgr_create(mctx, 1, 0, &taskmgr)); DO("create task", isc_task_create(taskmgr, 0, &task)); DO("create logging context", isc_log_create(mctx, &log, &logconfig)); isc_log_setcontext(log); DO("setting log tag", isc_log_settag(logconfig, progname)); logdest.file.stream = stderr; logdest.file.name = NULL; logdest.file.versions = ISC_LOG_ROLLNEVER; logdest.file.maximum_size = 0; DO("creating log channel", isc_log_createchannel(logconfig, "stderr", ISC_LOG_TOFILEDESC, ISC_LOG_INFO, &logdest, ISC_LOG_PRINTTAG|ISC_LOG_PRINTLEVEL)); DO("enabling log channel", isc_log_usechannel(logconfig, "stderr", NULL, NULL)); parse_config(mctx, log, keyname, &pctx, &config); isccc_result_register(); command = *argv; /* * Convert argc/argv into a space-delimited command string * similar to what the user might enter in interactive mode * (if that were implemented). */ argslen = 0; for (i = 0; i < argc; i++) argslen += strlen(argv[i]) + 1; args = isc_mem_get(mctx, argslen); if (args == NULL) DO("isc_mem_get", ISC_R_NOMEMORY); p = args; for (i = 0; i < argc; i++) { size_t len = strlen(argv[i]); memcpy(p, argv[i], len); p += len; *p++ = ' '; } p--; *p++ = '\0'; INSIST(p == args + argslen); notify("%s", command); if (strcmp(command, "restart") == 0) fatal("'%s' is not implemented", command); if (nserveraddrs == 0) get_addresses(servername, (in_port_t) remoteport); DO("post event", isc_app_onrun(mctx, task, rndc_start, NULL)); result = isc_app_run(); if (result != ISC_R_SUCCESS) fatal("isc_app_run() failed: %s", isc_result_totext(result)); if (connects > 0 || sends > 0 || recvs > 0) isc_socket_cancel(sock, task, ISC_SOCKCANCEL_ALL); isc_task_detach(&task); isc_taskmgr_destroy(&taskmgr); isc_socketmgr_destroy(&socketmgr); isc_log_destroy(&log); isc_log_setcontext(NULL); cfg_obj_destroy(pctx, &config); cfg_parser_destroy(&pctx); isc_mem_put(mctx, args, argslen); isccc_ccmsg_invalidate(&ccmsg); dns_name_destroy(); if (show_final_mem) isc_mem_stats(mctx, stderr); isc_mem_destroy(&mctx); if (failed) return (1); return (0); }
static isc_result_t findserver(dns_client_t *client) { isc_result_t result; irs_resconf_t *resconf = NULL; isc_sockaddrlist_t *nameservers; isc_sockaddr_t *sa, *next; isc_uint32_t destport; result = parse_uint(&destport, port, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", isc_result_totext(result)); goto cleanup; } /* Get nameservers from resolv.conf */ nameservers = irs_resconf_getnameservers(resconf); for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { next = ISC_LIST_NEXT(sa, link); /* Set destination port */ if (sa->type.sa.sa_family == AF_INET && use_ipv4) { sa->type.sin.sin_port = htons(destport); continue; } if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { sa->type.sin6.sin6_port = htons(destport); continue; } /* Incompatible protocol family */ ISC_LIST_UNLINK(*nameservers, sa, link); isc_mem_put(mctx, sa, sizeof(*sa)); } /* None found, use localhost */ if (ISC_LIST_EMPTY(*nameservers)) { if (use_ipv4) { struct in_addr localhost; localhost.s_addr = htonl(INADDR_LOOPBACK); sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin(sa, &localhost, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } if (use_ipv6) { sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } } result = dns_client_setservers(client, dns_rdataclass_in, NULL, nameservers); if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", isc_result_totext(result)); cleanup: if (resconf != NULL) irs_resconf_destroy(&resconf); return (result); }
static isc_result_t addserver(dns_client_t *client) { struct addrinfo hints, *res, *cur; int gaierror; struct in_addr in4; struct in6_addr in6; isc_sockaddr_t *sa; isc_sockaddrlist_t servers; isc_uint32_t destport; isc_result_t result; dns_name_t *name = NULL; result = parse_uint(&destport, port, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); ISC_LIST_INIT(servers); if (inet_pton(AF_INET, server, &in4) == 1) { if (!use_ipv4) { fatal("Use of IPv4 disabled by -6"); } sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) return (ISC_R_NOMEMORY); ISC_LINK_INIT(sa, link); isc_sockaddr_fromin(sa, &in4, destport); ISC_LIST_APPEND(servers, sa, link); } else if (inet_pton(AF_INET6, server, &in6) == 1) { if (!use_ipv6) { fatal("Use of IPv6 disabled by -4"); } sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) return (ISC_R_NOMEMORY); ISC_LINK_INIT(sa, link); isc_sockaddr_fromin6(sa, &in6, destport); ISC_LIST_APPEND(servers, sa, link); } else { memset(&hints, 0, sizeof(hints)); if (!use_ipv6) hints.ai_family = AF_INET; else if (!use_ipv4) hints.ai_family = AF_INET6; else hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; gaierror = getaddrinfo(server, port, &hints, &res); if (gaierror != 0) { delv_log(ISC_LOG_ERROR, "getaddrinfo failed: %s", gai_strerror(gaierror)); return (ISC_R_FAILURE); } result = ISC_R_SUCCESS; for (cur = res; cur != NULL; cur = cur->ai_next) { if (cur->ai_family != AF_INET && cur->ai_family != AF_INET6) continue; sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; break; } memset(sa, 0, sizeof(*sa)); ISC_LINK_INIT(sa, link); memmove(&sa->type, cur->ai_addr, cur->ai_addrlen); sa->length = (unsigned int)cur->ai_addrlen; ISC_LIST_APPEND(servers, sa, link); } freeaddrinfo(res); CHECK(result); } CHECK(dns_client_setservers(client, dns_rdataclass_in, name, &servers)); cleanup: while (!ISC_LIST_EMPTY(servers)) { sa = ISC_LIST_HEAD(servers); ISC_LIST_UNLINK(servers, sa, link); isc_mem_put(mctx, sa, sizeof(*sa)); } if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "addserver: %s", isc_result_totext(result)); return (result); }
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); }