static isc_result_t to_netaddr (t_addr_t * addr, isc_netaddr_t * na) { int r; struct in_addr in; struct in6_addr in6; switch (addr->family) { case AF_INET: r = inet_pton (AF_INET, addr->addr, (unsigned char *) &in); if (r != 1) return (ISC_R_FAILURE); isc_netaddr_fromin (na, &in); break; case AF_INET6: r = inet_pton (AF_INET6, addr->addr, (unsigned char *) &in6); if (r != 1) return (ISC_R_FAILURE); isc_netaddr_fromin6 (na, &in6); break; default: return (ISC_R_UNEXPECTED); } return (ISC_R_SUCCESS); }
static int test_isc_netaddr_masktoprefixlen(void) { struct in_addr na_a; struct in_addr na_b; struct in_addr na_c; struct in_addr na_d; isc_netaddr_t ina_a; isc_netaddr_t ina_b; isc_netaddr_t ina_c; isc_netaddr_t ina_d; unsigned int plen; if (inet_pton(AF_INET, "0.0.0.0", &na_a) < 0) return T_FAIL; if (inet_pton(AF_INET, "255.255.255.254", &na_b) < 0) return T_FAIL; if (inet_pton(AF_INET, "255.255.255.255", &na_c) < 0) return T_FAIL; if (inet_pton(AF_INET, "255.255.255.0", &na_d) < 0) return T_FAIL; isc_netaddr_fromin(&ina_a, &na_a); isc_netaddr_fromin(&ina_b, &na_b); isc_netaddr_fromin(&ina_c, &na_c); isc_netaddr_fromin(&ina_d, &na_d); if (isc_netaddr_masktoprefixlen(&ina_a, &plen) != ISC_R_SUCCESS) return T_FAIL; if (plen != 0) return T_FAIL; if (isc_netaddr_masktoprefixlen(&ina_b, &plen) != ISC_R_SUCCESS) return T_FAIL; if (plen != 31) return T_FAIL; if (isc_netaddr_masktoprefixlen(&ina_c, &plen) != ISC_R_SUCCESS) return T_FAIL; if (plen != 32) return T_FAIL; if (isc_netaddr_masktoprefixlen(&ina_d, &plen) != ISC_R_SUCCESS) return T_FAIL; if (plen != 24) return T_FAIL; return T_PASS; }
/*% * Convert addresses from lwres to isc format. */ isc_result_t lwaddr_netaddr_fromlwresaddr(isc_netaddr_t *na, lwres_addr_t *la) { if (la->family != LWRES_ADDRTYPE_V4 && la->family != LWRES_ADDRTYPE_V6) return (ISC_R_FAMILYNOSUPPORT); if (la->family == LWRES_ADDRTYPE_V4) { struct in_addr ina; memcpy(&ina.s_addr, la->address, 4); isc_netaddr_fromin(na, &ina); } else { struct in6_addr ina6; memcpy(&ina6.s6_addr, la->address, 16); isc_netaddr_fromin6(na, &ina6); } return (ISC_R_SUCCESS); }
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); }
ATF_TC_BODY(dscp, tc) { isc_result_t result; isc_netaddr_t netaddr; struct in_addr ina; dns_peer_t *peer = NULL; isc_dscp_t dscp; result = dns_test_begin(NULL, ISC_TRUE); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); /* * Create peer structure for the loopback address. */ ina.s_addr = INADDR_LOOPBACK; isc_netaddr_fromin(&netaddr, &ina); result = dns_peer_new(mctx, &netaddr, &peer); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); /* * All should be not set on creation. * 'dscp' should remain unchanged. */ dscp = 100; result = dns_peer_getquerydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); result = dns_peer_getnotifydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); result = dns_peer_gettransferdscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); /* * Test that setting query dscp does not affect the other * dscp values. 'dscp' should remain unchanged until * dns_peer_getquerydscp is called. */ dscp = 100; result = dns_peer_setquerydscp(peer, 1); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_peer_getnotifydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); result = dns_peer_gettransferdscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); result = dns_peer_getquerydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 1); /* * Test that setting notify dscp does not affect the other * dscp values. 'dscp' should remain unchanged until * dns_peer_getquerydscp is called then should change again * on dns_peer_getnotifydscp. */ dscp = 100; result = dns_peer_setnotifydscp(peer, 2); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_peer_gettransferdscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_NOTFOUND); ATF_REQUIRE_EQ(dscp, 100); result = dns_peer_getquerydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 1); result = dns_peer_getnotifydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 2); /* * Test that setting notify dscp does not affect the other * dscp values. Check that appropriate values are returned. */ dscp = 100; result = dns_peer_settransferdscp(peer, 3); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); result = dns_peer_getquerydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 1); result = dns_peer_getnotifydscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 2); result = dns_peer_gettransferdscp(peer, &dscp); ATF_REQUIRE_EQ(result, ISC_R_SUCCESS); ATF_REQUIRE_EQ(dscp, 3); dns_peer_detach(&peer); dns_test_end(); }