summaryrefslogtreecommitdiff
path: root/usr/src/lib/libnsl
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2016-04-05 12:05:18 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2016-04-05 12:05:18 +0000
commit68aa949ea1a29ae26140b73702400eae92ab9a6f (patch)
treec9fdf4465cfce8b5b0ffd1d17fc4a588874c6207 /usr/src/lib/libnsl
parentf5823ecdf8884e3132129eab9723e0ac848d8322 (diff)
parenta48d81205a4295fd3f979e8ab98212a784b8f9e9 (diff)
downloadillumos-joyent-68aa949ea1a29ae26140b73702400eae92ab9a6f.tar.gz
[illumos-gate merge]
commit a48d81205a4295fd3f979e8ab98212a784b8f9e9 6829 Would like boot_time and init_pid for zones exposed to GZ kstats commit 5dee1fa64fd5ddfe4221aaa94bc981e0b9d78b92 6771 end-of-loop code not reached in common/dnssd_clientstub.c commit 03b59f7842b50eda32f941744a5d94a55e47ba26 5868 Make checks in inet_matchaddr() more robust commit 043dd586a30a181228ae6d69b6b80c02f2277df7 5866 "wrong authentication" messages with root=@0.0.0.0/0 set, result in loss of client access commit d1e631af56641f21cde1f1efe3a9623ff9d6ee7c 6853 built in fonts are exposing internal data commit 9468939ef8704ee9aba7596c1e9ff9b059109cac 6823 need per-zone kstat to track pageins Conflicts: usr/src/uts/common/sys/zone.h usr/src/uts/common/os/zone.c
Diffstat (limited to 'usr/src/lib/libnsl')
-rw-r--r--usr/src/lib/libnsl/common/llib-lnsl4
-rw-r--r--usr/src/lib/libnsl/nss/inet_matchaddr.c98
2 files changed, 73 insertions, 29 deletions
diff --git a/usr/src/lib/libnsl/common/llib-lnsl b/usr/src/lib/libnsl/common/llib-lnsl
index 582eecef95..46f74824eb 100644
--- a/usr/src/lib/libnsl/common/llib-lnsl
+++ b/usr/src/lib/libnsl/common/llib-lnsl
@@ -23,7 +23,7 @@
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2016 Nexenta Systems, Inc.
*/
@@ -440,7 +440,7 @@ 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 *);
+int inet_matchaddr(const void *, const char *);
/* inet_ntop.c */
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
diff --git a/usr/src/lib/libnsl/nss/inet_matchaddr.c b/usr/src/lib/libnsl/nss/inet_matchaddr.c
index 566c1ae1ad..4a510ea01b 100644
--- a/usr/src/lib/libnsl/nss/inet_matchaddr.c
+++ b/usr/src/lib/libnsl/nss/inet_matchaddr.c
@@ -7,8 +7,10 @@
* 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.
+ */
+
+/*
+ * Copyright 2016 Nexenta Systems, Inc.
*/
/*
@@ -24,6 +26,14 @@
* IPv6:
* [IPv6]
* [IPv6]/prefix
+ *
+ * Return values:
+ *
+ * 0 mismatch
+ * 1 match
+ * -1 error occured, caller should check errno:
+ * EINVAL access list entry is invalid
+ * ENOMEM failed to allocate memory
*/
#include <sys/socket.h>
@@ -34,21 +44,24 @@
#include <netinet/in.h>
#include <ctype.h>
-#include <err.h>
+#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
-
-boolean_t
+int
inet_matchaddr(const void *sa, const char *name)
{
- boolean_t ret = B_FALSE;
+ int ret = -1;
char *lname, *mp, *p;
+ char *ep;
+ int serrno = errno;
uint32_t claddr4 = 0;
- if ((p = lname = strdup(name)) == NULL)
- err(1, "strdup");
+ if ((p = lname = strdup(name)) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
if ((mp = strchr(p, '/')) != NULL)
*mp++ = '\0';
@@ -56,7 +69,6 @@ inet_matchaddr(const void *sa, const char *name)
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 =
@@ -64,28 +76,43 @@ inet_matchaddr(const void *sa, const char *name)
if (!IN6_IS_ADDR_V4MAPPED(claddr6)) {
/* IPv6 address */
- if ((p = strchr(p, '[')) == NULL)
+ if (*p != '[') {
+ errno = EINVAL;
break;
+ }
p++;
- if ((pp = strchr(p, ']')) == NULL)
+ if ((pp = strchr(p, ']')) == NULL ||
+ (mp != NULL && pp != mp - 2) ||
+ (mp == NULL && *(pp + 1) != '\0')) {
+ errno = EINVAL;
break;
+ }
*pp = '\0';
- if (inet_pton(AF_INET6, p, &hcaddr6) != 1)
+ if (inet_pton(AF_INET6, p, &hcaddr6) != 1) {
+ errno = EINVAL;
break;
+ }
if (mp != NULL) {
/* Match only first prefix bits */
- if ((prefix6 = (int)strtol(mp,
- (char **)NULL, 10)) == 0)
+ long prefix6;
+
+ errno = 0;
+ prefix6 = strtol(mp, &ep, 10);
+ if (errno != 0 || prefix6 < 0 ||
+ prefix6 > 128 || *ep != '\0') {
+ errno = EINVAL;
break;
+ }
ret = IN6_ARE_PREFIXEDADDR_EQUAL(claddr6,
- &hcaddr6, prefix6);
+ &hcaddr6, prefix6) ? 1 : 0;
break;
} else {
/* No prefix, exact match */
- ret = IN6_ARE_ADDR_EQUAL(claddr6, &hcaddr6);
+ ret = IN6_ARE_ADDR_EQUAL(claddr6,
+ &hcaddr6) ? 1 : 0;
break;
}
} else {
@@ -96,30 +123,45 @@ inet_matchaddr(const void *sa, const char *name)
/*FALLTHROUGH*/
}
case AF_INET: {
- int bits, i;
+ int i;
uint32_t hcaddr4 = 0, mask4;
- if (claddr4 == 0)
+ 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)
+ long qaddr4;
+
+ errno = 0;
+ qaddr4 = strtol(p, &ep, 10);
+ if (errno != 0 || qaddr4 < 0 || qaddr4 > 255 ||
+ (*ep != '.' && *ep != '\0')) {
+ errno = EINVAL;
break;
- p++;
+ }
+ hcaddr4 |= qaddr4 << ((3 - i) * 8);
+ if (*ep == '\0')
+ break;
+ p = ep + 1;
}
- if (hcaddr4 == 0)
+ if (errno != 0)
break;
if (mp != NULL) {
/* Mask is specified explicitly */
- if ((bits = (int)strtol(mp, (char **)NULL, 10)) == 0)
+ long mb;
+
+ errno = 0;
+ mb = strtol(mp, &ep, 10);
+ if (errno != 0 || mb < 0 || mb > 32 || *ep != '\0') {
+ errno = EINVAL;
break;
- mask4 = bits ? ~0 << ((sizeof (struct in_addr) * NBBY)
- - bits) : 0;
+ }
+ mask4 = mb ? ~0 << ((sizeof (struct in_addr) * NBBY)
+ - mb) : 0;
hcaddr4 &= mask4;
} else {
/*
@@ -139,12 +181,14 @@ inet_matchaddr(const void *sa, const char *name)
mask4 = IN_CLASSE_NET;
}
- ret = ((claddr4 & mask4) == hcaddr4);
+ ret = ((claddr4 & mask4) == hcaddr4) ? 1 : 0;
break;
}
}
free(lname);
+ if (ret != -1)
+ errno = serrno;
return (ret);
}