1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 *
26 * Copyright 2019 Nexenta by DDN, Inc. All rights reserved.
27 */
28
29 /*
30 * Wrappers for inet address manipulation to do what SMB needs.
31 */
32
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
36
37 #if !defined(_KERNEL)
38 #include <errno.h>
39 #include <string.h>
40 #include <strings.h>
41 #include <arpa/inet.h>
42 #else /* !_KERNEL */
43 #include <sys/errno.h>
44 #include <sys/sunddi.h>
45 /* Don't want the rest of what's in inet/ip.h */
46 #define inet_ntop _inet_ntop // illumos.org/issues/5980
47 extern char *inet_ntop(int, const void *, char *, int);
48 extern int inet_pton(int, char *, void *);
49 #endif /* !_KERNEL */
50
51 #include <smbsrv/smb_inet.h>
52
53 const struct in6_addr ipv6addr_any = IN6ADDR_ANY_INIT;
54
55 boolean_t
smb_inet_equal(smb_inaddr_t * ip1,smb_inaddr_t * ip2)56 smb_inet_equal(smb_inaddr_t *ip1, smb_inaddr_t *ip2)
57 {
58 if ((ip1->a_family == AF_INET) &&
59 (ip2->a_family == AF_INET) &&
60 (ip1->a_ipv4 == ip2->a_ipv4))
61 return (B_TRUE);
62
63 if ((ip1->a_family == AF_INET6) &&
64 (ip2->a_family == AF_INET6) &&
65 (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, sizeof (in6_addr_t))))
66 return (B_TRUE);
67 else
68 return (B_FALSE);
69 }
70
71 boolean_t
smb_inet_same_subnet(smb_inaddr_t * ip1,smb_inaddr_t * ip2,uint32_t v4mask)72 smb_inet_same_subnet(smb_inaddr_t *ip1, smb_inaddr_t *ip2, uint32_t v4mask)
73 {
74 if ((ip1->a_family == AF_INET) &&
75 (ip2->a_family == AF_INET) &&
76 ((ip1->a_ipv4 & v4mask) == (ip2->a_ipv4 & v4mask)))
77 return (B_TRUE);
78
79 if ((ip1->a_family == AF_INET6) &&
80 (ip2->a_family == AF_INET6) &&
81 (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, sizeof (in6_addr_t))))
82 return (B_TRUE);
83 else
84 return (B_FALSE);
85 }
86
87 boolean_t
smb_inet_iszero(smb_inaddr_t * ipaddr)88 smb_inet_iszero(smb_inaddr_t *ipaddr)
89 {
90 const void *ipsz = (const void *)&ipv6addr_any;
91
92 if ((ipaddr->a_family == AF_INET) &&
93 (ipaddr->a_ipv4 == 0))
94 return (B_TRUE);
95
96 if ((ipaddr->a_family == AF_INET6) &&
97 !memcmp(&ipaddr->a_ipv6, ipsz, sizeof (in6_addr_t)))
98 return (B_TRUE);
99 else
100 return (B_FALSE);
101 }
102
103 const char *
smb_inet_ntop(smb_inaddr_t * addr,char * buf,int size)104 smb_inet_ntop(smb_inaddr_t *addr, char *buf, int size)
105 {
106 /* Lint avoidance */
107 #ifdef _KERNEL
108 int sz = size;
109 #else
110 size_t sz = (size_t)size;
111 #endif
112
113 return ((char *)inet_ntop(addr->a_family, addr, buf, sz));
114 }
115