From owner-svn-src-all@FreeBSD.ORG Wed Nov 5 00:58:02 2014 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id C20ED444; Wed, 5 Nov 2014 00:58:02 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id ACBD381; Wed, 5 Nov 2014 00:58:02 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.9/8.14.9) with ESMTP id sA50w2m2018675; Wed, 5 Nov 2014 00:58:02 GMT (envelope-from melifaro@FreeBSD.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.9/8.14.9/Submit) id sA50w1Vc018668; Wed, 5 Nov 2014 00:58:01 GMT (envelope-from melifaro@FreeBSD.org) Message-Id: <201411050058.sA50w1Vc018668@svn.freebsd.org> X-Authentication-Warning: svn.freebsd.org: melifaro set sender to melifaro@FreeBSD.org using -f From: "Alexander V. Chernikov" Date: Wed, 5 Nov 2014 00:58:01 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r274118 - in head/sys: kern netinet netinet6 sys X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 05 Nov 2014 00:58:02 -0000 Author: melifaro Date: Wed Nov 5 00:58:01 2014 New Revision: 274118 URL: https://svnweb.freebsd.org/changeset/base/274118 Log: Remove old hack abusing domattach from NFS code. According to IANA RPC uaddr registry, there are no AFs except IPv4 and IPv6, so it's not worth being too abstract here. Remove ne_rtable[AF_MAX+1] and use explicit per-AF radix tries. Use own initialization without relying on domattach code. While I admit that this was one of the rare places in kernel networking code which really was capable of doing multi-AF without any AF-depended code, it is not possible anymore to rely on dom* code. While here, change terrifying "Invalid radix node head, rn:" message, to different non-understandable "netcred already exists for given addr/mask", but less terrifying. Since we know that rn_addaddr() returns NULL if the same record already exists, we should provide more friendly error. MFC after: 1 month Modified: head/sys/kern/vfs_export.c head/sys/netinet/in_rmx.c head/sys/netinet6/in6_rmx.c head/sys/sys/domain.h Modified: head/sys/kern/vfs_export.c ============================================================================== --- head/sys/kern/vfs_export.c Tue Nov 4 23:51:35 2014 (r274117) +++ head/sys/kern/vfs_export.c Wed Nov 5 00:58:01 2014 (r274118) @@ -37,9 +37,11 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_inet.h" +#include "opt_inet6.h" + #include #include -#include #include #include #include @@ -54,12 +56,16 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include static MALLOC_DEFINE(M_NETADDR, "export_host", "Export host address structure"); +static struct radix_node_head *vfs_create_addrlist_af( + struct radix_node_head **prnh, int off); static void vfs_free_addrlist(struct netexport *nep); static int vfs_free_netcred(struct radix_node *rn, void *w); +static void vfs_free_addrlist_af(struct radix_node_head **prnh); static int vfs_hang_addrlist(struct mount *mp, struct netexport *nep, struct export_args *argp); static struct netcred *vfs_export_lookup(struct mount *, struct sockaddr *); @@ -80,7 +86,8 @@ struct netcred { */ struct netexport { struct netcred ne_defexported; /* Default export */ - struct radix_node_head *ne_rtable[AF_MAX+1]; /* Individual exports */ + struct radix_node_head *ne4; + struct radix_node_head *ne6; }; /* @@ -96,7 +103,7 @@ vfs_hang_addrlist(struct mount *mp, stru register int i; struct radix_node *rn; struct sockaddr *saddr, *smask = 0; - struct domain *dom; + int off; int error; /* @@ -163,46 +170,39 @@ vfs_hang_addrlist(struct mount *mp, stru if (smask->sa_len > argp->ex_masklen) smask->sa_len = argp->ex_masklen; } - i = saddr->sa_family; - if ((rnh = nep->ne_rtable[i]) == NULL) { - /* - * Seems silly to initialize every AF when most are not used, - * do so on demand here - */ - for (dom = domains; dom; dom = dom->dom_next) { - KASSERT(((i == AF_INET) || (i == AF_INET6)), - ("unexpected protocol in vfs_hang_addrlist")); - if (dom->dom_family == i && dom->dom_rtattach) { - /* - * XXX MRT - * The INET and INET6 domains know the - * offset already. We don't need to send it - * So we just use it as a flag to say that - * we are or are not setting up a real routing - * table. Only IP and IPV6 need have this - * be 0 so all other protocols can stay the - * same (ABI compatible). - */ - dom->dom_rtattach( - (void **) &nep->ne_rtable[i], 0); - break; - } + rnh = NULL; + switch (saddr->sa_family) { +#ifdef INET + case AF_INET: + if ((rnh = nep->ne4) == NULL) { + off = offsetof(struct sockaddr_in, sin_addr) << 3; + rnh = vfs_create_addrlist_af(&nep->ne4, off); } - if ((rnh = nep->ne_rtable[i]) == NULL) { - error = ENOBUFS; - vfs_mount_error(mp, "%s %s %d", - "Unable to initialize radix node head ", - "for address family", i); - goto out; + break; +#endif +#ifdef INET6 + case AF_INET6: + if ((rnh = nep->ne6) == NULL) { + off = offsetof(struct sockaddr_in6, sin6_addr) << 3; + rnh = vfs_create_addrlist_af(&nep->ne6, off); } + break; +#endif + } + if (rnh == NULL) { + error = ENOBUFS; + vfs_mount_error(mp, "%s %s %d", + "Unable to initialize radix node head ", + "for address family", saddr->sa_family); + goto out; } RADIX_NODE_HEAD_LOCK(rnh); rn = (*rnh->rnh_addaddr)(saddr, smask, rnh, np->netc_rnodes); RADIX_NODE_HEAD_UNLOCK(rnh); if (rn == NULL || np != (struct netcred *)rn) { /* already exists */ error = EPERM; - vfs_mount_error(mp, "Invalid radix node head, rn: %p %p", - rn, np); + vfs_mount_error(mp, + "netcred already exists for given addr/mask"); goto out; } np->netc_exflags = argp->ex_flags; @@ -237,26 +237,43 @@ vfs_free_netcred(struct radix_node *rn, return (0); } +static struct radix_node_head * +vfs_create_addrlist_af(struct radix_node_head **prnh, int off) +{ + + if (rn_inithead((void **)prnh, off) == 0) + return (NULL); + RADIX_NODE_HEAD_LOCK_INIT(*prnh); + return (*prnh); +} + +static void +vfs_free_addrlist_af(struct radix_node_head **prnh) +{ + struct radix_node_head *rnh; + + rnh = *prnh; + RADIX_NODE_HEAD_LOCK(rnh); + (*rnh->rnh_walktree) (rnh, vfs_free_netcred, rnh); + RADIX_NODE_HEAD_UNLOCK(rnh); + RADIX_NODE_HEAD_DESTROY(rnh); + free(rnh, M_RTABLE); + prnh = NULL; +} + /* * Free the net address hash lists that are hanging off the mount points. */ static void vfs_free_addrlist(struct netexport *nep) { - int i; - struct radix_node_head *rnh; struct ucred *cred; - for (i = 0; i <= AF_MAX; i++) { - if ((rnh = nep->ne_rtable[i])) { - RADIX_NODE_HEAD_LOCK(rnh); - (*rnh->rnh_walktree) (rnh, vfs_free_netcred, rnh); - RADIX_NODE_HEAD_UNLOCK(rnh); - RADIX_NODE_HEAD_DESTROY(rnh); - free(rnh, M_RTABLE); - nep->ne_rtable[i] = NULL; /* not SMP safe XXX */ - } - } + if (nep->ne4 != NULL) + vfs_free_addrlist_af(&nep->ne4); + if (nep->ne6 != NULL) + vfs_free_addrlist_af(&nep->ne6); + cred = nep->ne_defexported.netc_anon; if (cred != NULL) crfree(cred); @@ -439,7 +456,15 @@ vfs_export_lookup(struct mount *mp, stru */ if (nam != NULL) { saddr = nam; - rnh = nep->ne_rtable[saddr->sa_family]; + rnh = NULL; + switch (saddr->sa_family) { + case AF_INET: + rnh = nep->ne4; + break; + case AF_INET6: + rnh = nep->ne6; + break; + } if (rnh != NULL) { RADIX_NODE_HEAD_RLOCK(rnh); np = (struct netcred *) Modified: head/sys/netinet/in_rmx.c ============================================================================== --- head/sys/netinet/in_rmx.c Tue Nov 4 23:51:35 2014 (r274117) +++ head/sys/netinet/in_rmx.c Wed Nov 5 00:58:01 2014 (r274118) @@ -341,23 +341,12 @@ in_inithead(void **head, int off) { struct radix_node_head *rnh; - /* XXX MRT - * This can be called from vfs_export.c too in which case 'off' - * will be 0. We know the correct value so just use that and - * return directly if it was 0. - * This is a hack that replaces an even worse hack on a bad hack - * on a bad design. After RELENG_7 this should be fixed but that - * will change the ABI, so for now do it this way. - */ if (!rn_inithead(head, 32)) return 0; rnh = *head; RADIX_NODE_HEAD_LOCK_INIT(rnh); - if (off == 0) /* XXX MRT see above */ - return 1; /* only do the rest for a real routing table */ - rnh->rnh_addaddr = in_addroute; in_setmatchfunc(rnh, V_drop_redirect); rnh->rnh_close = in_clsroute; Modified: head/sys/netinet6/in6_rmx.c ============================================================================== --- head/sys/netinet6/in6_rmx.c Tue Nov 4 23:51:35 2014 (r274117) +++ head/sys/netinet6/in6_rmx.c Wed Nov 5 00:58:01 2014 (r274118) @@ -254,10 +254,6 @@ in6_mtutimo(void *rock) /* * Initialize our routing tree. - * XXX MRT When off == 0, we are being called from vfs_export.c - * so just set up their table and leave. (we know what the correct - * value should be so just use that).. FIX AFTER RELENG_7 is MFC'd - * see also comments in in_inithead() vfs_export.c and domain.h */ static VNET_DEFINE(int, _in6_rt_was_here); #define V__in6_rt_was_here VNET(_in6_rt_was_here) @@ -268,14 +264,11 @@ in6_inithead(void **head, int off) struct radix_node_head *rnh; if (!rn_inithead(head, offsetof(struct sockaddr_in6, sin6_addr) << 3)) - return 0; /* See above */ + return (0); rnh = *head; RADIX_NODE_HEAD_LOCK_INIT(rnh); - if (off == 0) /* See above */ - return 1; /* only do the rest for the real thing */ - rnh->rnh_addaddr = in6_addroute; if (V__in6_rt_was_here == 0) { @@ -284,7 +277,7 @@ in6_inithead(void **head, int off) V__in6_rt_was_here = 1; } - return 1; + return (1); } #ifdef VIMAGE Modified: head/sys/sys/domain.h ============================================================================== --- head/sys/sys/domain.h Tue Nov 4 23:51:35 2014 (r274117) +++ head/sys/sys/domain.h Wed Nov 5 00:58:01 2014 (r274118) @@ -61,12 +61,6 @@ struct domain { int (*dom_rtdetach) /* clean up routing table */ (void **, int); int dom_rtoffset; /* an arg to rtattach, in bits */ - /* XXX MRT. - * rtoffset May be 0 if the domain supplies its own rtattach(), - * in which case, a 0 indicates it's being called from - * vfs_export.c (HACK) Only for AF_INET{,6} at this time. - * Temporary ABI compat hack.. fix post RELENG_7 - */ int dom_maxrtkey; /* for routing layer */ void *(*dom_ifattach)(struct ifnet *); void (*dom_ifdetach)(struct ifnet *, void *);