Mercurial > illumos > illumos-gate
changeset 13500:f077aa5fa57c
877 share_nfs cannot share to IPv6 subnets
1554 SMB has no concept of IPv6 host access lists
1592 NFS access checks shouldn't fail if client address can't be resolved
Reviewed by: Gordon Ross <gordon.w.ross@gmail.com>
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Approved by: Richard Lowe <richlowe@richlowe.net>
author | Yuri Pankov <yuri.pankov@nexenta.com> |
---|---|
date | Thu, 03 Nov 2011 11:18:52 +0400 |
parents | cb9d7a417470 |
children | c3a7090dbc16 |
files | usr/src/cmd/fs.d/nfs/mountd/mountd.c usr/src/head/arpa/inet.h usr/src/lib/libnsl/Makefile.com usr/src/lib/libnsl/common/llib-lnsl usr/src/lib/libnsl/common/mapfile-vers usr/src/lib/libnsl/nss/inet_matchaddr.c usr/src/lib/smbsrv/libmlsvc/common/smb_share.c usr/src/lib/smbsrv/libsmb/common/smb_util.c usr/src/uts/common/netinet/in.h |
diffstat | 9 files changed, 387 insertions(+), 321 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/cmd/fs.d/nfs/mountd/mountd.c Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/cmd/fs.d/nfs/mountd/mountd.c Thu Nov 03 11:18:52 2011 +0400 @@ -17,10 +17,9 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ - -/* + * * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -112,7 +111,6 @@ static void sh_free(struct sh_list *); static void umount(struct svc_req *); static void umountall(struct svc_req *); -static int netmatch(struct netbuf *, char *); static void sigexit(int); static int newopts(char *); static tsol_tpent_t *get_client_template(struct sockaddr *); @@ -1711,10 +1709,10 @@ * We match on aliases of the hostname as well as on the canonical name. * Names in the access list may be either hosts or netgroups; they're * not distinguished syntactically. We check for hosts first because - * it's cheaper (just M*N strcmp()s), then try netgroups. + * it's cheaper, then try netgroups. * * If pnb and pclnames are NULL, it means that we have to use transp - * to resolve client's IP address to host name. If they aren't NULL + * to resolve client IP address to hostname. If they aren't NULL * then transp argument won't be used and can be NULL. */ int @@ -1722,84 +1720,112 @@ struct nd_hostservlist **pclnames, char *access_list) /* N.B. we clobber this "input" parameter */ { - int nentries; - char *gr; - char *lasts; + char addr[INET_ADDRSTRLEN]; + char buff[256]; + int nentries = 0; + char *cstr = access_list; + char *gr = access_list; char *host; int off; int i; - int netgroup_match; int response; + int sbr = 0; struct nd_hostservlist *clnames; + struct netent n, *np; - /* - * If no access list - then it's unrestricted - */ + /* If no access list - then it's unrestricted */ if (access_list == NULL || *access_list == '\0') return (1); assert(transp != NULL || (*pnb != NULL && *pclnames != NULL)); - nentries = 0; + /* Get client address if it wasn't provided */ + if (*pnb == NULL) + /* Don't grant access if client address isn't known */ + if ((*pnb = svc_getrpccaller(transp)) == NULL) + return (0); + + /* Try to lookup client hostname if it wasn't provided */ + if (*pclnames == NULL) + getclientsnames(transp, pnb, pclnames); + clnames = *pclnames; - for (gr = strtok_r(access_list, ":", &lasts); - gr != NULL; gr = strtok_r(NULL, ":", &lasts)) { + for (;;) { + if ((cstr = strpbrk(cstr, "[]:")) != NULL) { + switch (*cstr) { + case '[': + case ']': + sbr = !sbr; + cstr++; + continue; + case ':': + if (sbr) { + cstr++; + continue; + } + *cstr = '\0'; + } + } /* - * If the list name has a '-' prepended - * then a match of the following name - * implies failure instead of success. + * If the list name has a '-' prepended then a match of + * the following name implies failure instead of success. */ if (*gr == '-') { response = 0; gr++; - } else + } else { response = 1; + } /* - * If the list name begins with an at - * sign then do a network comparison. + * First check if we have '@' entry, as it doesn't + * require client hostname. */ if (*gr == '@') { - /* - * Just get the netbuf, avoiding the costly name - * lookup. This will suffice for access based - * solely on addresses. - */ - if (*pnb == NULL) { - /* - * Don't grant access if client's address isn't - * known. - */ - if ((*pnb = svc_getrpccaller(transp)) == NULL) - return (0); + gr++; + + /* Netname support */ + if (!isdigit(*gr) && *gr != '[') { + if ((np = getnetbyname_r(gr, &n, buff, + sizeof (buff))) != NULL && + np->n_net != 0) { + while ((np->n_net & 0xFF000000u) == 0) + np->n_net <<= 8; + np->n_net = htonl(np->n_net); + if (inet_ntop(AF_INET, &np->n_net, addr, + INET_ADDRSTRLEN) == NULL) + break; + if (inet_matchaddr((*pnb)->buf, addr)) + return (response); + } + } else { + if (inet_matchaddr((*pnb)->buf, gr)) + return (response); } - if (netmatch(*pnb, gr + 1)) - return (response); + if (cstr == NULL) + break; + + gr = ++cstr; + continue; } /* - * We need to get the host name if we haven't gotten - * it by now! + * No other checks can be performed if client address + * can't be resolved. */ - if (*pclnames == NULL) { - DTRACE_PROBE(mountd, name_by_addrlist); - /* - * Do not grant access if we can't - * get a name! - */ - if (getclientsnames(transp, pnb, pclnames) != 0) - return (0); + if (clnames == NULL) { + if (cstr == NULL) + break; + + gr = ++cstr; + + continue; } - clnames = *pclnames; - - /* - * The following loops through all the - * client's aliases. Usually it's just one name. - */ + /* Otherwise loop through all client hostname aliases */ for (i = 0; i < clnames->h_cnt; i++) { host = clnames->h_hostservs[i].h_host; @@ -1820,120 +1846,25 @@ return (response); } } - } else - - /* - * Just do a hostname match - */ - if (strcasecmp(gr, host) == 0) { - return (response); /* Matched a hostname */ + } else { + /* Just do a hostname match */ + if (strcasecmp(gr, host) == 0) + return (response); } } nentries++; - } - /* - * We need to get the host name if we haven't gotten - * it by now! - */ - if (*pclnames == NULL) { - DTRACE_PROBE(mountd, name_by_netgroup); - /* - * Do not grant access if we can't - * get a name! - */ - if (getclientsnames(transp, pnb, pclnames) != 0) - return (0); + if (cstr == NULL) + break; + + gr = ++cstr; } - netgroup_match = netgroup_check(*pclnames, access_list, nentries); - - return (netgroup_match); -} - -int -netmatch(struct netbuf *nb, char *name) -{ - uint_t claddr; - struct netent n, *np; - char *mp, *p; - uint_t addr, mask; - int i, bits; - char buff[256]; - - /* - * Check if it's an IPv4 addr - */ - if (nb->len != sizeof (struct sockaddr_in)) + if (clnames == NULL) return (0); - (void) memcpy(&claddr, - /* LINTED pointer alignment */ - &((struct sockaddr_in *)nb->buf)->sin_addr.s_addr, - sizeof (struct in_addr)); - claddr = ntohl(claddr); - - mp = strchr(name, '/'); - if (mp) - *mp++ = '\0'; - - if (isdigit(*name)) { - /* - * Convert a dotted IP address - * to an IP address. The conversion - * is not the same as that in inet_addr(). - */ - p = name; - addr = 0; - for (i = 0; i < 4; i++) { - addr |= atoi(p) << ((3-i) * 8); - p = strchr(p, '.'); - if (p == NULL) - break; - p++; - } - } else { - /* - * Turn the netname into - * an IP address. - */ - np = getnetbyname_r(name, &n, buff, sizeof (buff)); - if (np == NULL) { - syslog(LOG_DEBUG, "getnetbyname_r: %s: %m", name); - return (0); - } - addr = np->n_net; - } - - /* - * If the mask is specified explicitly then - * use that value, e.g. - * - * @109.104.56/28 - * - * otherwise assume a mask from the zero octets - * in the least significant bits of the address, e.g. - * - * @109.104 or @109.104.0.0 - */ - if (mp) { - bits = atoi(mp); - mask = bits ? ~0 << ((sizeof (struct in_addr) * NBBY) - bits) - : 0; - addr &= mask; - } else { - if ((addr & IN_CLASSA_HOST) == 0) - mask = IN_CLASSA_NET; - else if ((addr & IN_CLASSB_HOST) == 0) - mask = IN_CLASSB_NET; - else if ((addr & IN_CLASSC_HOST) == 0) - mask = IN_CLASSC_NET; - else - mask = IN_CLASSE_NET; - } - - return ((claddr & mask) == addr); + return (netgroup_check(clnames, access_list, nentries)); }
--- a/usr/src/head/arpa/inet.h Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/head/arpa/inet.h Thu Nov 03 11:18:52 2011 +0400 @@ -17,10 +17,11 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* + * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ @@ -56,6 +57,7 @@ #ifdef __STDC__ #if !defined(_XPG4_2) || defined(__EXTENSIONS__) extern int inet_net_pton(int, const char *, void *, size_t); +extern boolean_t inet_matchaddr(const void *, const char *); #endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */ #if !defined(_XPG4_2) || defined(_XPG6) || defined(__EXTENSIONS__)
--- a/usr/src/lib/libnsl/Makefile.com Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/lib/libnsl/Makefile.com Thu Nov 03 11:18:52 2011 +0400 @@ -21,6 +21,7 @@ # # Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # LIBRARY= libnsl.a @@ -41,8 +42,8 @@ NSS= \ gethostbyname_r.o gethostent.o gethostent_r.o gethostent6.o gethostby_door.o \ -getipnodeby_door.o getipnodeby.o getrpcent.o getrpcent_r.o inet_pton.o \ -inet_ntop.o netdir_inet.o netdir_inet_sundry.o \ +getipnodeby_door.o getipnodeby.o getrpcent.o getrpcent_r.o inet_matchaddr.o \ +inet_pton.o inet_ntop.o netdir_inet.o netdir_inet_sundry.o \ parse.o getauthattr.o getprofattr.o getexecattr.o getuserattr.o getauuser.o NETSELECT= netselect.o
--- a/usr/src/lib/libnsl/common/llib-lnsl Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/lib/libnsl/common/llib-lnsl Thu Nov 03 11:18:52 2011 +0400 @@ -22,6 +22,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ @@ -437,6 +439,9 @@ void endrpcent(void); struct rpcent *getrpcent_r(struct rpcent *result, char *buffer, int buflen); +/* inet_matchaddr.c */ +boolean_t inet_matchaddr(const void *, const char *); + /* inet_ntop.c */ const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
--- a/usr/src/lib/libnsl/common/mapfile-vers Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/lib/libnsl/common/mapfile-vers Thu Nov 03 11:18:52 2011 +0400 @@ -20,7 +20,7 @@ # # # Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. -# +# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # # @@ -467,6 +467,7 @@ SYMBOL_VERSION SUNWprivate_1.5 { global: + inet_matchaddr; clnt_create_service_timed; } SUNWprivate_1.4;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/usr/src/lib/libnsl/nss/inet_matchaddr.c Thu Nov 03 11:18:52 2011 +0400 @@ -0,0 +1,150 @@ +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * inet_matchaddr + * + * Match IPv4 or IPv6 address provided in sa (sockaddr_in/sockaddr_in6) + * against standard text representation specified in name: + * + * IPv4: + * IPv4 + * IPv4/netmask + * + * IPv6: + * [IPv6] + * [IPv6]/prefix + */ + +#include <sys/socket.h> +#include <sys/types.h> + +#include <arpa/inet.h> + +#include <netinet/in.h> + +#include <ctype.h> +#include <err.h> +#include <netdb.h> +#include <stdlib.h> +#include <strings.h> + + +boolean_t +inet_matchaddr(const void *sa, const char *name) +{ + boolean_t ret = B_FALSE; + char *lname, *mp, *p; + uint32_t claddr4 = 0; + + if ((p = lname = strdup(name)) == NULL) + err(1, "strdup"); + + if ((mp = strchr(p, '/')) != NULL) + *mp++ = '\0'; + + switch (((struct sockaddr_in *)sa)->sin_family) { + case AF_INET6: { + char *pp; + int prefix6; + ipaddr_t ipaddr4; + struct in6_addr hcaddr6; + struct in6_addr *claddr6 = + &((struct sockaddr_in6 *)sa)->sin6_addr; + + if (!IN6_IS_ADDR_V4MAPPED(claddr6)) { + /* IPv6 address */ + if ((p = strchr(p, '[')) == NULL) + break; + p++; + + if ((pp = strchr(p, ']')) == NULL) + break; + *pp = '\0'; + + if (inet_pton(AF_INET6, p, &hcaddr6) != 1) + break; + + if (mp != NULL) { + /* Match only first prefix bits */ + if ((prefix6 = (int)strtol(mp, + (char **)NULL, 10)) == 0) + break; + ret = IN6_ARE_PREFIXEDADDR_EQUAL(claddr6, + &hcaddr6, prefix6); + break; + } else { + /* No prefix, exact match */ + ret = IN6_ARE_ADDR_EQUAL(claddr6, &hcaddr6); + break; + } + } else { + /* IPv4-mapped IPv6 address, fallthrough to IPv4 */ + IN6_V4MAPPED_TO_IPADDR(claddr6, ipaddr4); + claddr4 = ntohl(ipaddr4); + } + /*FALLTHROUGH*/ + } + case AF_INET: { + int bits, i; + uint32_t hcaddr4 = 0, mask4; + + if (claddr4 == 0) + claddr4 = ntohl( + ((struct sockaddr_in *)sa)->sin_addr.s_addr); + + for (i = 0; i < 4; i++) { + hcaddr4 |= (int)strtol(p, (char **)NULL, 10) << + ((3 - i) * 8); + if ((p = strchr(p, '.')) == NULL) + break; + p++; + } + + if (hcaddr4 == 0) + break; + + if (mp != NULL) { + /* Mask is specified explicitly */ + if ((bits = (int)strtol(mp, (char **)NULL, 10)) == 0) + break; + mask4 = bits ? ~0 << ((sizeof (struct in_addr) * NBBY) + - bits) : 0; + hcaddr4 &= mask4; + } else { + /* + * Use old-fashioned implicit netmasking by checking + * for lower-end zeroes. On the off chance we don't + * match any well-known prefixes, return an exact- + * match prefix which is misleadingly labelled as + * IN_CLASSE_NET. + */ + if ((hcaddr4 & IN_CLASSA_HOST) == 0) + mask4 = IN_CLASSA_NET; + else if ((hcaddr4 & IN_CLASSB_HOST) == 0) + mask4 = IN_CLASSB_NET; + else if ((hcaddr4 & IN_CLASSC_HOST) == 0) + mask4 = IN_CLASSC_NET; + else + mask4 = IN_CLASSE_NET; + } + + ret = ((claddr4 & mask4) == hcaddr4); + break; + } + } + + free(lname); + + return (ret); +}
--- a/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/lib/smbsrv/libmlsvc/common/smb_share.c Thu Nov 03 11:18:52 2011 +0400 @@ -17,9 +17,9 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* + * * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* @@ -739,9 +739,6 @@ * Precedence is none is checked first followed by ro then rw if * needed. If x is wildcard (< 0) then check to see if the other * values are a match. If a match, that wins. - * - * ipv6 is wide open (returns SMB_SHRF_ACC_OPEN) for now until the underlying - * functions support ipv6. */ uint32_t smb_shr_hostaccess(smb_inaddr_t *ipaddr, char *none_list, char *ro_list, @@ -753,10 +750,6 @@ int rw = 0; if (!smb_inet_iszero(ipaddr)) { - - if (ipaddr->a_family == AF_INET6) - return (SMB_SHRF_ACC_OPEN); - if ((flag & SMB_SHRF_ACC_NONE) != 0) none = smb_chk_hostaccess(ipaddr, none_list); if ((flag & SMB_SHRF_ACC_RO) != 0)
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c Thu Nov 03 11:18:52 2011 +0400 @@ -77,11 +77,9 @@ static smb_log_t *smb_log_get(smb_log_hdl_t); static void smb_log_dump(smb_log_t *); -static uint_t smb_make_mask(char *, uint_t); -static boolean_t smb_netmatch(struct netbuf *, char *); static boolean_t smb_netgroup_match(struct nd_hostservlist *, char *, int); -extern int __multi_innetgr(); +extern int __multi_innetgr(); extern int __netdir_getbyaddr_nosrv(struct netconfig *, struct nd_hostservlist **, struct netbuf *); @@ -413,54 +411,80 @@ int smb_chk_hostaccess(smb_inaddr_t *ipaddr, char *access_list) { - int nentries; - char *gr; - char *lasts; + char addr[INET_ADDRSTRLEN]; + char buff[256]; + char *cstr = access_list, *gr = access_list; char *host; - int off; + int clres; int i; + int nentries = 0; + int off; int response; - int clres; + int sbr = 0; struct nd_hostservlist *clnames; struct in_addr inaddr; struct sockaddr_in sa; + struct sockaddr_in6 sa6; struct netbuf buf; struct netconfig *config; + struct netent n, *np; if (access_list == NULL) return (0); - inaddr.s_addr = ipaddr->a_ipv4; - - /* - * If access list is empty or "*" - then it's "all" - */ + /* If access list is empty or "*" - then it's "all" */ if (*access_list == '\0' || strcmp(access_list, "*") == 0) return (-1); - nentries = 0; + switch (ipaddr->a_family) { + case AF_INET: + inaddr.s_addr = ipaddr->a_ipv4; + sa.sin_family = AF_INET; + sa.sin_port = 0; + sa.sin_addr = inaddr; + buf.len = buf.maxlen = sizeof (sa); + buf.buf = (char *)&sa; + config = getnetconfigent("tcp"); + break; + case AF_INET6: + sa6.sin6_family = AF_INET6; + sa6.sin6_port = 0; + sa6.sin6_addr = ipaddr->a_ipv6; + buf.len = buf.maxlen = sizeof (sa6); + buf.buf = (char *)&sa6; + config = getnetconfigent("tcp6"); + break; + default: + return (1); + } - sa.sin_family = AF_INET; - sa.sin_port = 0; - sa.sin_addr = inaddr; - - buf.len = buf.maxlen = sizeof (sa); - buf.buf = (char *)&sa; - - config = getnetconfigent("tcp"); if (config == NULL) return (1); + /* Try to lookup client hostname */ clres = __netdir_getbyaddr_nosrv(config, &clnames, &buf); freenetconfigent(config); - for (gr = strtok_r(access_list, ":", &lasts); - gr != NULL; gr = strtok_r(NULL, ":", &lasts)) { + for (;;) { + if ((cstr = strpbrk(cstr, "[]:")) != NULL) { + switch (*cstr) { + case '[': + case ']': + sbr = !sbr; + cstr++; + continue; + case ':': + if (sbr) { + cstr++; + continue; + } + *cstr = '\0'; + } + } /* - * If the list name has a '-' prepended - * then a match of the following name - * implies failure instead of success. + * If the list name has a '-' prepended then a match of + * the following name implies failure instead of success. */ if (*gr == '-') { response = 0; @@ -470,21 +494,53 @@ } /* - * First check if we have '@' entry, as smb_netmatch doesn't - * care if client address can be resolved. + * First check if we have '@' entry, as it doesn't + * require client hostname. */ - if (*gr == '@') - if (smb_netmatch(&buf, gr + 1)) - return (response); + if (*gr == '@') { + gr++; + + if (!isdigit(*gr) && *gr != '[') { + /* Netname support */ + if ((np = getnetbyname_r(gr, &n, buff, + sizeof (buff))) != NULL && + np->n_net != 0) { + while ((np->n_net & 0xFF000000u) == 0) + np->n_net <<= 8; + np->n_net = htonl(np->n_net); + if (inet_ntop(AF_INET, &np->n_net, addr, + INET_ADDRSTRLEN) == NULL) + break; + if (inet_matchaddr(buf.buf, addr)) + return (response); + } + } else { + if (inet_matchaddr(buf.buf, gr)) + return (response); + } + + if (cstr == NULL) + break; + + gr = ++cstr; + + continue; + } + /* * No other checks can be performed if client address * can't be resolved. */ - if (clres) + if (clres) { + if (cstr == NULL) + break; + + gr = ++cstr; + continue; - /* - * Otherwise loop through all client hostname aliases. - */ + } + + /* Otherwise loop through all client hostname aliases */ for (i = 0; i < clnames->h_cnt; i++) { host = clnames->h_hostservs[i].h_host; /* @@ -494,7 +550,7 @@ * suffix. */ if (*gr == '.') { - if (*(gr + 1) == '\0') { /* single dot */ + if (*(gr + 1) == '\0') { if (strchr(host, '.') == NULL) return (response); } else { @@ -505,15 +561,18 @@ } } } else { - /* - * Just do a hostname match - */ + /* Just do a hostname match */ if (strcasecmp(gr, host) == 0) return (response); } } nentries++; + + if (cstr == NULL) + break; + + gr = ++cstr; } if (clres) @@ -523,116 +582,6 @@ } /* - * smb_make_mask - * - * Construct a mask for an IPv4 address using the @<dotted-ip>/<len> - * syntax or use the default mask for the IP address. - */ -static uint_t -smb_make_mask(char *maskstr, uint_t addr) -{ - uint_t mask; - uint_t bits; - - /* - * If the mask is specified explicitly then - * use that value, e.g. - * - * @109.104.56/28 - * - * otherwise assume a mask from the zero octets - * in the least significant bits of the address, e.g. - * - * @109.104 or @109.104.0.0 - */ - if (maskstr) { - bits = atoi(maskstr); - mask = bits ? ~0 << ((sizeof (struct in_addr) * NBBY) - bits) - : 0; - addr &= mask; - } else { - if ((addr & IN_CLASSA_HOST) == 0) - mask = IN_CLASSA_NET; - else if ((addr & IN_CLASSB_HOST) == 0) - mask = IN_CLASSB_NET; - else if ((addr & IN_CLASSC_HOST) == 0) - mask = IN_CLASSC_NET; - else - mask = IN_CLASSE_NET; - } - - return (mask); -} - -/* - * smb_netmatch - * - * Check to see if the address in the netbuf matches the "net" - * specified by name. The format of "name" can be: - * fully qualified domain name - * dotted IP address - * dotted IP address followed by '/<len>' - * See sharen_nfs(1M) for details. - */ - -static boolean_t -smb_netmatch(struct netbuf *nb, char *name) -{ - uint_t claddr; - struct netent n, *np; - char *mp, *p; - uint_t addr, mask; - int i; - char buff[256]; - - /* - * Check if it's an IPv4 addr - */ - if (nb->len != sizeof (struct sockaddr_in)) - return (B_FALSE); - - (void) memcpy(&claddr, - /* LINTED pointer alignment */ - &((struct sockaddr_in *)nb->buf)->sin_addr.s_addr, - sizeof (struct in_addr)); - claddr = ntohl(claddr); - - mp = strchr(name, '/'); - if (mp) - *mp++ = '\0'; - - if (isdigit(*name)) { - /* - * Convert a dotted IP address - * to an IP address. The conversion - * is not the same as that in inet_addr(). - */ - p = name; - addr = 0; - for (i = 0; i < 4; i++) { - addr |= atoi(p) << ((3-i) * 8); - p = strchr(p, '.'); - if (p == NULL) - break; - p++; - } - } else { - /* - * Turn the netname into - * an IP address. - */ - np = getnetbyname_r(name, &n, buff, sizeof (buff)); - if (np == NULL) { - return (B_FALSE); - } - addr = np->n_net; - } - - mask = smb_make_mask(mp, addr); - return ((claddr & mask) == addr); -} - -/* * smb_netgroup_match * * Check whether any of the hostnames in clnames are
--- a/usr/src/uts/common/netinet/in.h Tue Nov 01 10:17:46 2011 +0400 +++ b/usr/src/uts/common/netinet/in.h Thu Nov 03 11:18:52 2011 +0400 @@ -1,6 +1,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ /* * Copyright (c) 1982, 1986 Regents of the University of California. @@ -839,6 +841,38 @@ ((addr1)->_S6_un._S6_u32[1] == (addr2)->_S6_un._S6_u32[1]) && \ ((addr1)->_S6_un._S6_u32[0] == (addr2)->_S6_un._S6_u32[0])) +/* + * IN6_ARE_PREFIXEDADDR_EQUAL (not defined in RFCs) + * Compares if prefixed parts of IPv6 addresses are equal. + * + * uint32_t IN6_MASK_FROM_PREFIX(int, int); + * bool IN6_ARE_PREFIXEDADDR_EQUAL(const struct in6_addr *, + * const struct in6_addr *, + * int); + */ +#define IN6_MASK_FROM_PREFIX(qoctet, prefix) \ + ((((qoctet) + 1) * 32 < (prefix)) ? 0xFFFFFFFFu : \ + ((((qoctet) * 32) >= (prefix)) ? 0x00000000u : \ + 0xFFFFFFFFu << (((qoctet) + 1) * 32 - (prefix)))) + +#define IN6_ARE_PREFIXEDADDR_EQUAL(addr1, addr2, prefix) \ + (((ntohl((addr1)->_S6_un._S6_u32[0]) & \ + IN6_MASK_FROM_PREFIX(0, prefix)) == \ + (ntohl((addr2)->_S6_un._S6_u32[0]) & \ + IN6_MASK_FROM_PREFIX(0, prefix))) && \ + ((ntohl((addr1)->_S6_un._S6_u32[1]) & \ + IN6_MASK_FROM_PREFIX(1, prefix)) == \ + (ntohl((addr2)->_S6_un._S6_u32[1]) & \ + IN6_MASK_FROM_PREFIX(1, prefix))) && \ + ((ntohl((addr1)->_S6_un._S6_u32[2]) & \ + IN6_MASK_FROM_PREFIX(2, prefix)) == \ + (ntohl((addr2)->_S6_un._S6_u32[2]) & \ + IN6_MASK_FROM_PREFIX(2, prefix))) && \ + ((ntohl((addr1)->_S6_un._S6_u32[3]) & \ + IN6_MASK_FROM_PREFIX(3, prefix)) == \ + (ntohl((addr2)->_S6_un._S6_u32[3]) & \ + IN6_MASK_FROM_PREFIX(3, prefix)))) + #endif /* !defined(_XPG4_2) || defined(_XPG6) || defined(__EXTENSIONS__) */