📄 interfacemgr.c
字号:
static voidns_interface_destroy(ns_interface_t *ifp) { isc_mem_t *mctx = ifp->mgr->mctx; REQUIRE(NS_INTERFACE_VALID(ifp)); ns_interface_shutdown(ifp); if (ifp->udpdispatch != NULL) { dns_dispatch_changeattributes(ifp->udpdispatch, 0, DNS_DISPATCHATTR_NOLISTEN); dns_dispatch_detach(&ifp->udpdispatch); } if (ifp->tcpsocket != NULL) isc_socket_detach(&ifp->tcpsocket); DESTROYLOCK(&ifp->lock); ns_interfacemgr_detach(&ifp->mgr); ifp->magic = 0; isc_mem_put(mctx, ifp, sizeof(*ifp));}voidns_interface_attach(ns_interface_t *source, ns_interface_t **target) { REQUIRE(NS_INTERFACE_VALID(source)); LOCK(&source->lock); INSIST(source->references > 0); source->references++; UNLOCK(&source->lock); *target = source;}voidns_interface_detach(ns_interface_t **targetp) { isc_result_t need_destroy = ISC_FALSE; ns_interface_t *target = *targetp; REQUIRE(target != NULL); REQUIRE(NS_INTERFACE_VALID(target)); LOCK(&target->lock); REQUIRE(target->references > 0); target->references--; if (target->references == 0) need_destroy = ISC_TRUE; UNLOCK(&target->lock); if (need_destroy) ns_interface_destroy(target); *targetp = NULL;}/* * Search the interface list for an interface whose address and port * both match those of 'addr'. Return a pointer to it, or NULL if not found. */static ns_interface_t *find_matching_interface(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr) { ns_interface_t *ifp; for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = ISC_LIST_NEXT(ifp, link)) { if (isc_sockaddr_equal(&ifp->addr, addr)) break; } return (ifp);}/* * Remove any interfaces whose generation number is not the current one. */static voidpurge_old_interfaces(ns_interfacemgr_t *mgr) { ns_interface_t *ifp, *next; for (ifp = ISC_LIST_HEAD(mgr->interfaces); ifp != NULL; ifp = next) { INSIST(NS_INTERFACE_VALID(ifp)); next = ISC_LIST_NEXT(ifp, link); if (ifp->generation != mgr->generation) { char sabuf[256]; ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); isc_sockaddr_format(&ifp->addr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "no longer listening on %s", sabuf); ns_interface_shutdown(ifp); ns_interface_detach(&ifp); } }}static isc_result_tclearacl(isc_mem_t *mctx, dns_acl_t **aclp) { dns_acl_t *newacl = NULL; isc_result_t result; result = dns_acl_create(mctx, 10, &newacl); if (result != ISC_R_SUCCESS) return (result); dns_acl_detach(aclp); dns_acl_attach(newacl, aclp); dns_acl_detach(&newacl); return (ISC_R_SUCCESS);}static isc_result_tdo_ipv4(ns_interfacemgr_t *mgr) { isc_interfaceiter_t *iter = NULL; isc_result_t result; result = isc_interfaceiter_create(mgr->mctx, &iter); if (result != ISC_R_SUCCESS) return (result); 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; for (result = isc_interfaceiter_first(iter); result == ISC_R_SUCCESS; result = isc_interfaceiter_next(iter)) { ns_interface_t *ifp; isc_interface_t interface; ns_listenelt_t *le; dns_aclelement_t elt; unsigned int prefixlen; result = isc_interfaceiter_current(iter, &interface); if (result != ISC_R_SUCCESS) break; if (interface.address.family != AF_INET) continue; if ((interface.flags & INTERFACE_F_UP) == 0) continue; elt.type = dns_aclelementtype_ipprefix; elt.negative = ISC_FALSE; elt.u.ip_prefix.address = interface.address; elt.u.ip_prefix.prefixlen = 32; result = dns_acl_appendelement(mgr->aclenv.localhost, &elt); if (result != ISC_R_SUCCESS) goto ignore_interface; result = isc_netaddr_masktoprefixlen(&interface.netmask, &prefixlen); 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; /* XXX suppress duplicates */ result = dns_acl_appendelement(mgr->aclenv.localnets, &elt); if (result != ISC_R_SUCCESS) goto ignore_interface; } for (le = ISC_LIST_HEAD(mgr->listenon4->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { int match; isc_netaddr_t listen_netaddr; isc_sockaddr_t listen_sockaddr; /* * Construct a socket address for this IP/port * combination. */ isc_netaddr_fromin(&listen_netaddr, &interface.address.type.in); isc_sockaddr_fromnetaddr(&listen_sockaddr, &listen_netaddr, le->port); /* * See if the address matches the listen-on statement; * if not, ignore the interface. */ result = dns_acl_match(&listen_netaddr, NULL, le->acl, &mgr->aclenv, &match, NULL); if (match <= 0) continue; ifp = find_matching_interface(mgr, &listen_sockaddr); if (ifp != NULL) { ifp->generation = mgr->generation; } else { char sabuf[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_format(&listen_sockaddr, sabuf, sizeof(sabuf)); isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_INFO, "listening on IPv4 interface " "%s, %s", interface.name, sabuf); result = ns_interface_setup(mgr, &listen_sockaddr, interface.name, &ifp); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "creating IPv4 interface %s " "failed; interface ignored", interface.name); } /* Continue. */ } } continue; ignore_interface: isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ignoring IPv4 interface %s: %s", interface.name, isc_result_totext(result)); continue; } if (result != ISC_R_NOMORE) UNEXPECTED_ERROR(__FILE__, __LINE__, "IPv4: interface iteration failed: %s", isc_result_totext(result)); else result = ISC_R_SUCCESS; cleanup_iter: isc_interfaceiter_destroy(&iter); return (result);}static isc_boolean_tlistenon_is_ip6_none(ns_listenelt_t *elt) { if (elt->acl->length == 0) return (ISC_TRUE); /* listen-on-v6 { } */ if (elt->acl->length > 1) return (ISC_FALSE); /* listen-on-v6 { ...; ...; } */ if (elt->acl->elements[0].negative == ISC_TRUE && elt->acl->elements[0].type == dns_aclelementtype_any) return (ISC_TRUE); /* listen-on-v6 { none; } */ return (ISC_FALSE); /* All others */}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_tdo_ipv6(ns_interfacemgr_t *mgr) { isc_result_t result; ns_interface_t *ifp; isc_sockaddr_t listen_addr; struct in6_addr in6a; ns_listenelt_t *le; for (le = ISC_LIST_HEAD(mgr->listenon6->elts); le != NULL; le = ISC_LIST_NEXT(le, link)) { if (listenon_is_ip6_none(le)) continue; if (! listenon_is_ip6_any(le)) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "bad IPv6 listen-on list: " "must be 'any' or 'none'"); return (ISC_R_FAILURE); } 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); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "listening on IPv6 interfaces " "failed"); /* Continue. */ } } } return (ISC_R_SUCCESS);}voidns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) { isc_boolean_t purge = ISC_TRUE; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); mgr->generation++; /* Increment the generation count. */ if (isc_net_probeipv6() == ISC_R_SUCCESS) { if (do_ipv6(mgr) != ISC_R_SUCCESS) purge = ISC_FALSE; }#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) { if (do_ipv4(mgr) != ISC_R_SUCCESS) purge = ISC_FALSE; } else isc_log_write(IFMGR_COMMON_LOGARGS, verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1), "no IPv4 interfaces found"); /* * 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 (ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "not listening on any interfaces");}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);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -