From owner-svn-src-user@FreeBSD.ORG Thu Oct 16 10:24:32 2008 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id F0F951065696; Thu, 16 Oct 2008 10:24:31 +0000 (UTC) (envelope-from netchild@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DC2298FC23; Thu, 16 Oct 2008 10:24:31 +0000 (UTC) (envelope-from netchild@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id m9GAOVtE057737; Thu, 16 Oct 2008 10:24:31 GMT (envelope-from netchild@svn.freebsd.org) Received: (from netchild@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id m9GAOV77057733; Thu, 16 Oct 2008 10:24:31 GMT (envelope-from netchild@svn.freebsd.org) Message-Id: <200810161024.m9GAOV77057733@svn.freebsd.org> From: Alexander Leidinger Date: Thu, 16 Oct 2008 10:24:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r183934 - in user/netchild/misc: . src src/contrib src/contrib/bind9 src/contrib/bind9/bin src/contrib/bind9/bin/named src/etc src/etc/rc.d src/lib src/lib/libc src/lib/libc/stdlib src/... X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 16 Oct 2008 10:24:32 -0000 Author: netchild Date: Thu Oct 16 10:24:31 2008 New Revision: 183934 URL: http://svn.freebsd.org/changeset/base/183934 Log: Create a baseline for various fixes/improvements which do not deserve their own branch. Added: user/netchild/misc/ user/netchild/misc/README user/netchild/misc/src/ user/netchild/misc/src/contrib/ user/netchild/misc/src/contrib/bind9/ user/netchild/misc/src/contrib/bind9/bin/ user/netchild/misc/src/contrib/bind9/bin/named/ user/netchild/misc/src/contrib/bind9/bin/named/interfacemgr.c (props changed) - copied unchanged from r183911, head/contrib/bind9/bin/named/interfacemgr.c user/netchild/misc/src/etc/ user/netchild/misc/src/etc/rc.d/ user/netchild/misc/src/etc/rc.d/localpkg (props changed) - copied unchanged from r183911, head/etc/rc.d/localpkg user/netchild/misc/src/lib/ user/netchild/misc/src/lib/libc/ user/netchild/misc/src/lib/libc/stdlib/ user/netchild/misc/src/lib/libc/stdlib/Makefile.inc (props changed) - copied unchanged from r183911, head/lib/libc/stdlib/Makefile.inc user/netchild/misc/src/sbin/ user/netchild/misc/src/sbin/recoverdisk/ user/netchild/misc/src/sbin/recoverdisk/recoverdisk.c (props changed) - copied unchanged from r183911, head/sbin/recoverdisk/recoverdisk.c user/netchild/misc/src/share/ user/netchild/misc/src/share/man/ user/netchild/misc/src/share/man/man4/ user/netchild/misc/src/share/man/man4/tcp.4 (props changed) - copied unchanged from r183911, head/share/man/man4/tcp.4 user/netchild/misc/src/sys/ user/netchild/misc/src/sys/dev/ user/netchild/misc/src/sys/dev/ata/ user/netchild/misc/src/sys/dev/ata/ata-all.c (props changed) - copied unchanged from r183911, head/sys/dev/ata/ata-all.c user/netchild/misc/src/sys/dev/hptmv/ user/netchild/misc/src/sys/dev/hptmv/hptproc.c (props changed) - copied unchanged from r183911, head/sys/dev/hptmv/hptproc.c user/netchild/misc/src/sys/dev/usb/ user/netchild/misc/src/sys/dev/usb/usbdevs (props changed) - copied unchanged from r183911, head/sys/dev/usb/usbdevs user/netchild/misc/src/sys/dev/usb/uscanner.c (props changed) - copied unchanged from r183911, head/sys/dev/usb/uscanner.c user/netchild/misc/src/sys/gnu/ user/netchild/misc/src/sys/gnu/fs/ user/netchild/misc/src/sys/gnu/fs/ext2fs/ user/netchild/misc/src/sys/gnu/fs/ext2fs/ext2_vfsops.c (props changed) - copied unchanged from r183911, head/sys/gnu/fs/ext2fs/ext2_vfsops.c user/netchild/misc/src/sys/gnu/fs/reiserfs/ user/netchild/misc/src/sys/gnu/fs/reiserfs/reiserfs_vfsops.c (props changed) - copied unchanged from r183911, head/sys/gnu/fs/reiserfs/reiserfs_vfsops.c user/netchild/misc/src/sys/i386/ user/netchild/misc/src/sys/i386/i386/ user/netchild/misc/src/sys/i386/i386/support.s (props changed) - copied unchanged from r183911, head/sys/i386/i386/support.s user/netchild/misc/src/sys/i386/i386/sys_machdep.c (props changed) - copied unchanged from r183911, head/sys/i386/i386/sys_machdep.c user/netchild/misc/src/sys/i386/isa/ user/netchild/misc/src/sys/i386/isa/npx.c (props changed) - copied unchanged from r183911, head/sys/i386/isa/npx.c user/netchild/misc/src/sys/kern/ user/netchild/misc/src/sys/kern/kern_sig.c (props changed) - copied unchanged from r183911, head/sys/kern/kern_sig.c user/netchild/misc/src/sys/netinet/ user/netchild/misc/src/sys/netinet/ip_fw2.c (props changed) - copied unchanged from r183911, head/sys/netinet/ip_fw2.c user/netchild/misc/src/sys/netsmb/ user/netchild/misc/src/sys/netsmb/smb_conn.c (props changed) - copied unchanged from r183911, head/sys/netsmb/smb_conn.c user/netchild/misc/src/usr.sbin/ user/netchild/misc/src/usr.sbin/adduser/ user/netchild/misc/src/usr.sbin/adduser/adduser.sh (props changed) - copied unchanged from r183911, head/usr.sbin/adduser/adduser.sh user/netchild/misc/src/usr.sbin/adduser/rmuser.sh (props changed) - copied unchanged from r183911, head/usr.sbin/adduser/rmuser.sh Added: user/netchild/misc/README ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/netchild/misc/README Thu Oct 16 10:24:31 2008 (r183934) @@ -0,0 +1,2 @@ +Various fixes and improvements which are too small to deserve an own +directory. Copied: user/netchild/misc/src/contrib/bind9/bin/named/interfacemgr.c (from r183911, head/contrib/bind9/bin/named/interfacemgr.c) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/netchild/misc/src/contrib/bind9/bin/named/interfacemgr.c Thu Oct 16 10:24:31 2008 (r183934, copy of r183911, head/contrib/bind9/bin/named/interfacemgr.c) @@ -0,0 +1,979 @@ +/* + * Copyright (C) 2004-2006, 2008 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 1999-2002 Internet Software Consortium. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH + * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, + * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM + * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE + * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +/* $Id: interfacemgr.c,v 1.76.18.8.44.3 2008/07/23 23:16:43 marka Exp $ */ + +/*! \file */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#define IFMGR_MAGIC ISC_MAGIC('I', 'F', 'M', 'G') +#define NS_INTERFACEMGR_VALID(t) ISC_MAGIC_VALID(t, IFMGR_MAGIC) + +#define IFMGR_COMMON_LOGARGS \ + ns_g_lctx, NS_LOGCATEGORY_NETWORK, NS_LOGMODULE_INTERFACEMGR + +/*% nameserver interface manager structure */ +struct ns_interfacemgr { + unsigned int magic; /*%< Magic number. */ + int references; + isc_mutex_t lock; + isc_mem_t * mctx; /*%< Memory context. */ + isc_taskmgr_t * taskmgr; /*%< Task manager. */ + isc_socketmgr_t * socketmgr; /*%< Socket manager. */ + dns_dispatchmgr_t * dispatchmgr; + unsigned int generation; /*%< Current generation no. */ + ns_listenlist_t * listenon4; + ns_listenlist_t * listenon6; + dns_aclenv_t aclenv; /*%< Localhost/localnets ACLs */ + ISC_LIST(ns_interface_t) interfaces; /*%< List of interfaces. */ + ISC_LIST(isc_sockaddr_t) listenon; +}; + +static void +purge_old_interfaces(ns_interfacemgr_t *mgr); + +static void +clearlistenon(ns_interfacemgr_t *mgr); + +isc_result_t +ns_interfacemgr_create(isc_mem_t *mctx, isc_taskmgr_t *taskmgr, + isc_socketmgr_t *socketmgr, + dns_dispatchmgr_t *dispatchmgr, + ns_interfacemgr_t **mgrp) +{ + isc_result_t result; + ns_interfacemgr_t *mgr; + + REQUIRE(mctx != NULL); + REQUIRE(mgrp != NULL); + REQUIRE(*mgrp == NULL); + + mgr = isc_mem_get(mctx, sizeof(*mgr)); + if (mgr == NULL) + return (ISC_R_NOMEMORY); + + result = isc_mutex_init(&mgr->lock); + if (result != ISC_R_SUCCESS) + goto cleanup_mem; + + mgr->mctx = mctx; + mgr->taskmgr = taskmgr; + mgr->socketmgr = socketmgr; + mgr->dispatchmgr = dispatchmgr; + mgr->generation = 1; + mgr->listenon4 = NULL; + mgr->listenon6 = NULL; + + ISC_LIST_INIT(mgr->interfaces); + ISC_LIST_INIT(mgr->listenon); + + /* + * The listen-on lists are initially empty. + */ + result = ns_listenlist_create(mctx, &mgr->listenon4); + if (result != ISC_R_SUCCESS) + goto cleanup_mem; + ns_listenlist_attach(mgr->listenon4, &mgr->listenon6); + + result = dns_aclenv_init(mctx, &mgr->aclenv); + if (result != ISC_R_SUCCESS) + goto cleanup_listenon; + + mgr->references = 1; + mgr->magic = IFMGR_MAGIC; + *mgrp = mgr; + return (ISC_R_SUCCESS); + + cleanup_listenon: + ns_listenlist_detach(&mgr->listenon4); + ns_listenlist_detach(&mgr->listenon6); + cleanup_mem: + isc_mem_put(mctx, mgr, sizeof(*mgr)); + return (result); +} + +static void +ns_interfacemgr_destroy(ns_interfacemgr_t *mgr) { + REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + dns_aclenv_destroy(&mgr->aclenv); + ns_listenlist_detach(&mgr->listenon4); + ns_listenlist_detach(&mgr->listenon6); + clearlistenon(mgr); + DESTROYLOCK(&mgr->lock); + mgr->magic = 0; + isc_mem_put(mgr->mctx, mgr, sizeof(*mgr)); +} + +dns_aclenv_t * +ns_interfacemgr_getaclenv(ns_interfacemgr_t *mgr) { + return (&mgr->aclenv); +} + +void +ns_interfacemgr_attach(ns_interfacemgr_t *source, ns_interfacemgr_t **target) { + REQUIRE(NS_INTERFACEMGR_VALID(source)); + LOCK(&source->lock); + INSIST(source->references > 0); + source->references++; + UNLOCK(&source->lock); + *target = source; +} + +void +ns_interfacemgr_detach(ns_interfacemgr_t **targetp) { + isc_result_t need_destroy = ISC_FALSE; + ns_interfacemgr_t *target = *targetp; + REQUIRE(target != NULL); + REQUIRE(NS_INTERFACEMGR_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_interfacemgr_destroy(target); + *targetp = NULL; +} + +void +ns_interfacemgr_shutdown(ns_interfacemgr_t *mgr) { + REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + + /*% + * Shut down and detach all interfaces. + * By incrementing the generation count, we make purge_old_interfaces() + * consider all interfaces "old". + */ + mgr->generation++; + purge_old_interfaces(mgr); +} + + +static isc_result_t +ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, + const char *name, ns_interface_t **ifpret) +{ + ns_interface_t *ifp; + isc_result_t result; + + REQUIRE(NS_INTERFACEMGR_VALID(mgr)); + ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); + if (ifp == NULL) + return (ISC_R_NOMEMORY); + ifp->mgr = NULL; + ifp->generation = mgr->generation; + ifp->addr = *addr; + ifp->flags = 0; + strncpy(ifp->name, name, sizeof(ifp->name)); + ifp->name[sizeof(ifp->name)-1] = '\0'; + ifp->clientmgr = NULL; + + result = isc_mutex_init(&ifp->lock); + if (result != ISC_R_SUCCESS) + goto lock_create_failure; + + result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr, + ns_g_timermgr, + &ifp->clientmgr); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "ns_clientmgr_create() failed: %s", + isc_result_totext(result)); + goto clientmgr_create_failure; + } + + ifp->udpdispatch = NULL; + + ifp->tcpsocket = NULL; + /* + * Create a single TCP client object. It will replace itself + * with a new one as soon as it gets a connection, so the actual + * connections will be handled in parallel even though there is + * only one client initially. + */ + ifp->ntcptarget = 1; + ifp->ntcpcurrent = 0; + + ISC_LINK_INIT(ifp, link); + + ns_interfacemgr_attach(mgr, &ifp->mgr); + ISC_LIST_APPEND(mgr->interfaces, ifp, link); + + ifp->references = 1; + ifp->magic = IFACE_MAGIC; + *ifpret = ifp; + + return (ISC_R_SUCCESS); + + clientmgr_create_failure: + DESTROYLOCK(&ifp->lock); + lock_create_failure: + ifp->magic = 0; + isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); + + return (ISC_R_UNEXPECTED); +} + +static isc_result_t +ns_interface_listenudp(ns_interface_t *ifp) { + isc_result_t result; + unsigned int attrs; + unsigned int attrmask; + + attrs = 0; + attrs |= DNS_DISPATCHATTR_UDP; + if (isc_sockaddr_pf(&ifp->addr) == AF_INET) + attrs |= DNS_DISPATCHATTR_IPV4; + else + attrs |= DNS_DISPATCHATTR_IPV6; + attrs |= DNS_DISPATCHATTR_NOLISTEN; + attrmask = 0; + attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP; + attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6; + result = dns_dispatch_getudp(ifp->mgr->dispatchmgr, ns_g_socketmgr, + ns_g_taskmgr, &ifp->addr, + 4096, 1000, 32768, 8219, 8237, + attrs, attrmask, &ifp->udpdispatch); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "could not listen on UDP socket: %s", + isc_result_totext(result)); + goto udp_dispatch_failure; + } + + result = ns_clientmgr_createclients(ifp->clientmgr, ns_g_cpus, + ifp, ISC_FALSE); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "UDP ns_clientmgr_createclients(): %s", + isc_result_totext(result)); + goto addtodispatch_failure; + } + return (ISC_R_SUCCESS); + + addtodispatch_failure: + dns_dispatch_changeattributes(ifp->udpdispatch, 0, + DNS_DISPATCHATTR_NOLISTEN); + dns_dispatch_detach(&ifp->udpdispatch); + udp_dispatch_failure: + return (result); +} + +static isc_result_t +ns_interface_accepttcp(ns_interface_t *ifp) { + isc_result_t result; + + /* + * Open a TCP socket. + */ + result = isc_socket_create(ifp->mgr->socketmgr, + isc_sockaddr_pf(&ifp->addr), + isc_sockettype_tcp, + &ifp->tcpsocket); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "creating TCP socket: %s", + isc_result_totext(result)); + goto tcp_socket_failure; + } +#ifndef ISC_ALLOW_MAPPED + isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE); +#endif + result = isc_socket_bind(ifp->tcpsocket, &ifp->addr, + ISC_SOCKET_REUSEADDRESS); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "binding TCP socket: %s", + isc_result_totext(result)); + goto tcp_bind_failure; + } + result = isc_socket_listen(ifp->tcpsocket, ns_g_listen); + if (result != ISC_R_SUCCESS) { + isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, + "listening on TCP socket: %s", + isc_result_totext(result)); + goto tcp_listen_failure; + } + + /* + * If/when there a multiple filters listen to the + * result. + */ + (void)isc_socket_filter(ifp->tcpsocket, "dataready"); + + result = ns_clientmgr_createclients(ifp->clientmgr, + ifp->ntcptarget, ifp, + ISC_TRUE); + if (result != ISC_R_SUCCESS) { + UNEXPECTED_ERROR(__FILE__, __LINE__, + "TCP ns_clientmgr_createclients(): %s", + isc_result_totext(result)); + goto accepttcp_failure; + } + return (ISC_R_SUCCESS); + + accepttcp_failure: + tcp_listen_failure: + tcp_bind_failure: + isc_socket_detach(&ifp->tcpsocket); + tcp_socket_failure: + return (ISC_R_SUCCESS); +} + +static isc_result_t +ns_interface_setup(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, + const char *name, ns_interface_t **ifpret, + isc_boolean_t accept_tcp) +{ + isc_result_t result; + ns_interface_t *ifp = NULL; + REQUIRE(ifpret != NULL && *ifpret == NULL); + + result = ns_interface_create(mgr, addr, name, &ifp); + if (result != ISC_R_SUCCESS) + return (result); + + result = ns_interface_listenudp(ifp); + if (result != ISC_R_SUCCESS) + goto cleanup_interface; + + if (accept_tcp == ISC_TRUE) { + result = ns_interface_accepttcp(ifp); + if (result != ISC_R_SUCCESS) { + /* + * XXXRTH We don't currently have a way to easily stop + * dispatch service, so we currently return + * ISC_R_SUCCESS (the UDP stuff will work even if TCP + * creation failed). This will be fixed later. + */ + result = ISC_R_SUCCESS; + } + } + *ifpret = ifp; + return (ISC_R_SUCCESS); + + cleanup_interface: + ISC_LIST_UNLINK(ifp->mgr->interfaces, ifp, link); + ns_interface_detach(&ifp); + return (result); +} + +void +ns_interface_shutdown(ns_interface_t *ifp) { + if (ifp->clientmgr != NULL) + ns_clientmgr_destroy(&ifp->clientmgr); +} + +static void +ns_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)); +} + +void +ns_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; +} + +void +ns_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 void +purge_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_t +clearacl(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_boolean_t +listenon_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_t +setup_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 void +setup_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 void +clearlistenon(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_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, + "", &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 void +ns_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"); + } +} + +void +ns_interfacemgr_scan(ns_interfacemgr_t *mgr, isc_boolean_t verbose) { + ns_interfacemgr_scan0(mgr, NULL, verbose); +} + +void +ns_interfacemgr_adjust(ns_interfacemgr_t *mgr, ns_listenlist_t *list, + isc_boolean_t verbose) +{ + ns_interfacemgr_scan0(mgr, list, verbose); +} + +void +ns_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); +} + +void +ns_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); +} + +void +ns_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_t +ns_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); +} Copied: user/netchild/misc/src/etc/rc.d/localpkg (from r183911, head/etc/rc.d/localpkg) ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ user/netchild/misc/src/etc/rc.d/localpkg Thu Oct 16 10:24:31 2008 (r183934, copy of r183911, head/etc/rc.d/localpkg) @@ -0,0 +1,77 @@ +#!/bin/sh +# +# $FreeBSD$ +# + +# PROVIDE: localpkg +# REQUIRE: abi +# BEFORE: securelevel +# KEYWORD: shutdown + *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***