📄 interfacemgr.c
字号:
return (ISC_R_SUCCESS);}static isc_boolean_tlistenon_is_ip6_any(ns_listenelt_t *elt) { if (elt->acl->length != 1) return (ISC_FALSE); if (elt->acl->elements[0].negative == ISC_FALSE && elt->acl->elements[0].type == dns_aclelementtype_any) return (ISC_TRUE); /* listen-on-v6 { any; } */ return (ISC_FALSE); /* All others */}static isc_result_tsetup_locals(ns_interfacemgr_t *mgr, isc_interface_t *interface) { isc_result_t result; dns_aclelement_t elt; unsigned int family; unsigned int prefixlen; family = interface->address.family; elt.type = dns_aclelementtype_ipprefix; elt.negative = ISC_FALSE; elt.u.ip_prefix.address = interface->address; elt.u.ip_prefix.prefixlen = (family == AF_INET) ? 32 : 128; result = dns_acl_appendelement(mgr->aclenv.localhost, &elt); if (result != ISC_R_SUCCESS) return (result); result = isc_netaddr_masktoprefixlen(&interface->netmask, &prefixlen); /* Non contigious netmasks not allowed by IPv6 arch. */ if (result != ISC_R_SUCCESS && family == AF_INET6) return (result); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "omitting IPv4 interface %s from " "localnets ACL: %s", interface->name, isc_result_totext(result)); } else { elt.u.ip_prefix.prefixlen = prefixlen; if (dns_acl_elementmatch(mgr->aclenv.localnets, &elt, NULL) == ISC_R_NOTFOUND) { result = dns_acl_appendelement(mgr->aclenv.localnets, &elt); if (result != ISC_R_SUCCESS) return (result); } } return (ISC_R_SUCCESS);}static voidsetup_listenon(ns_interfacemgr_t *mgr, isc_interface_t *interface, in_port_t port){ isc_sockaddr_t *addr; isc_sockaddr_t *old; addr = isc_mem_get(mgr->mctx, sizeof(*addr)); if (addr == NULL) return; isc_sockaddr_fromnetaddr(addr, &interface->address, port); for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; old = ISC_LIST_NEXT(old, link)) if (isc_sockaddr_equal(addr, old)) break; if (old != NULL) isc_mem_put(mgr->mctx, addr, sizeof(*addr)); else ISC_LIST_APPEND(mgr->listenon, addr, link);}static voidclearlistenon(ns_interfacemgr_t *mgr) { isc_sockaddr_t *old; old = ISC_LIST_HEAD(mgr->listenon); while (old != NULL) { ISC_LIST_UNLINK(mgr->listenon, old, link); isc_mem_put(mgr->mctx, old, sizeof(*old)); old = ISC_LIST_HEAD(mgr->listenon); }}static isc_result_tdo_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) 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);}static voidns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose){ isc_boolean_t purge = ISC_TRUE; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); mgr->generation++; /* Increment the generation count. */ if (do_scan(mgr, ext_listen, verbose) != ISC_R_SUCCESS) purge = ISC_FALSE; /* * Now go through the interface list and delete anything that * does not have the current generation number. This is * how we catch interfaces that go away or change their * addresses. */ if (purge) purge_old_interfaces(mgr); /* * Warn if we are not listening on any interface, unless * we're in lwresd-only mode, in which case that is to * be expected. */ if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "not listening on any interfaces"); }}voidns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) { ns_interfacemgr_scan0(mgr, NULL, verbose);}voidns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, isc_boolean_t verbose){ ns_interfacemgr_scan0(mgr, list, verbose);}voidns_interfacemgr_setlistenon4(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { LOCK(&mgr->lock); ns_listenlist_detach(&mgr->listenon4); ns_listenlist_attach(value, &mgr->listenon4); UNLOCK(&mgr->lock);}voidns_interfacemgr_setlistenon6(ns_interfacemgr_t *mgr, ns_listenlist_t *value) { LOCK(&mgr->lock); ns_listenlist_detach(&mgr->listenon6); ns_listenlist_attach(value, &mgr->listenon6); UNLOCK(&mgr->lock);}voidns_interfacemgr_dumprecursing(FILE *f, ns_interfacemgr_t *mgr) { ns_interface_t *interface; LOCK(&mgr->lock); interface = ISC_LIST_HEAD(mgr->interfaces); while (interface != NULL) { if (interface->clientmgr != NULL) ns_client_dumprecursing(f, interface->clientmgr); interface = ISC_LIST_NEXT(interface, link); } UNLOCK(&mgr->lock);}isc_boolean_tns_interfacemgr_listeningon(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { isc_sockaddr_t *old; old = ISC_LIST_HEAD(mgr->listenon); for (old = ISC_LIST_HEAD(mgr->listenon); old != NULL; old = ISC_LIST_NEXT(old, link)) if (isc_sockaddr_equal(old, addr)) return (ISC_TRUE); return (ISC_FALSE);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -