2 Unix SMB/CIFS implementation.
3 Samba utility functions
4 Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
5 Copyright (C) Andrew Tridgell 1992-1998
6 Copyright (C) Jeremy Allison 2001-2007
7 Copyright (C) Simo Sorce 2001
8 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003.
9 Copyright (C) James J Myers 2003
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 3 of the License, or
14 (at your option) any later version.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
21 You should have received a copy of the GNU General Public License
22 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "system/network.h"
27 #include "system/locale.h"
28 #include "system/filesys.h"
34 bool interpret_string_addr_internal(struct addrinfo
**ppres
,
35 const char *str
, int flags
)
38 struct addrinfo hints
;
40 memset(&hints
, '\0', sizeof(hints
));
41 /* By default make sure it supports TCP. */
42 hints
.ai_socktype
= SOCK_STREAM
;
43 hints
.ai_flags
= flags
;
45 /* Linux man page on getaddinfo() says port will be
46 uninitialized when service string in NULL */
48 ret
= getaddrinfo(str
, NULL
,
53 DEBUG(3,("interpret_string_addr_internal: getaddrinfo failed "
63 * Interpret an internet address or name into an IP address in 4 byte form.
64 * RETURNS IN NETWORK BYTE ORDER (big endian).
67 uint32_t interpret_addr(const char *str
)
71 /* If it's in the form of an IP address then
72 * get the lib to interpret it */
73 if (is_ipaddress_v4(str
)) {
76 if (inet_pton(AF_INET
, str
, &dest
) <= 0) {
77 /* Error - this shouldn't happen ! */
78 DEBUG(0,("interpret_addr: inet_pton failed "
83 ret
= dest
.s_addr
; /* NETWORK BYTE ORDER ! */
85 /* Otherwise assume it's a network name of some sort and use
87 struct addrinfo
*res
= NULL
;
88 struct addrinfo
*res_list
= NULL
;
89 if (!interpret_string_addr_internal(&res_list
,
92 DEBUG(3,("interpret_addr: Unknown host. %s\n",str
));
96 /* Find the first IPv4 address. */
97 for (res
= res_list
; res
; res
= res
->ai_next
) {
98 if (res
->ai_family
!= AF_INET
) {
101 if (res
->ai_addr
== NULL
) {
107 DEBUG(3,("interpret_addr: host address is "
108 "invalid for host %s\n",str
));
110 freeaddrinfo(res_list
);
115 &((struct sockaddr_in
*)res
->ai_addr
)->sin_addr
.s_addr
,
118 freeaddrinfo(res_list
);
122 /* This is so bogus - all callers need fixing... JRA. */
123 if (ret
== (uint32_t)-1) {
131 A convenient addition to interpret_addr().
133 _PUBLIC_
struct in_addr
interpret_addr2(const char *str
)
136 uint32_t a
= interpret_addr(str
);
142 Check if an IP is the 0.0.0.0.
145 _PUBLIC_
bool is_zero_ip_v4(struct in_addr ip
)
147 return ip
.s_addr
== 0;
151 Are two IPs on the same subnet?
154 _PUBLIC_
bool same_net_v4(struct in_addr ip1
, struct in_addr ip2
, struct in_addr mask
)
156 uint32_t net1
,net2
,nmask
;
158 nmask
= ntohl(mask
.s_addr
);
159 net1
= ntohl(ip1
.s_addr
);
160 net2
= ntohl(ip2
.s_addr
);
162 return((net1
& nmask
) == (net2
& nmask
));
166 * Return true if a string could be an IPv4 address.
169 bool is_ipaddress_v4(const char *str
)
174 ret
= inet_pton(AF_INET
, str
, &dest
);
182 * Return true if a string could be an IPv4 or IPv6 address.
185 bool is_ipaddress(const char *str
)
187 #if defined(HAVE_IPV6)
190 if (strchr_m(str
, ':')) {
191 char addr
[INET6_ADDRSTRLEN
];
192 struct in6_addr dest6
;
193 const char *sp
= str
;
194 char *p
= strchr_m(str
, '%');
197 * Cope with link-local.
198 * This is IP:v6:addr%ifname.
201 if (p
&& (p
> str
) && (if_nametoindex(p
+1) != 0)) {
203 MIN(PTR_DIFF(p
,str
)+1,
207 ret
= inet_pton(AF_INET6
, sp
, &dest6
);
213 return is_ipaddress_v4(str
);
217 * Is a sockaddr a broadcast address ?
220 bool is_broadcast_addr(const struct sockaddr
*pss
)
222 #if defined(HAVE_IPV6)
223 if (pss
->sa_family
== AF_INET6
) {
224 const struct in6_addr
*sin6
=
225 &((const struct sockaddr_in6
*)pss
)->sin6_addr
;
226 return IN6_IS_ADDR_MULTICAST(sin6
);
229 if (pss
->sa_family
== AF_INET
) {
231 ntohl(((const struct sockaddr_in
*)pss
)->sin_addr
.s_addr
);
232 return addr
== INADDR_BROADCAST
;
238 * Check if an IPv7 is 127.0.0.1
240 bool is_loopback_ip_v4(struct in_addr ip
)
243 a
.s_addr
= htonl(INADDR_LOOPBACK
);
244 return(ip
.s_addr
== a
.s_addr
);
248 * Check if a struct sockaddr is the loopback address.
250 bool is_loopback_addr(const struct sockaddr
*pss
)
252 #if defined(HAVE_IPV6)
253 if (pss
->sa_family
== AF_INET6
) {
254 const struct in6_addr
*pin6
=
255 &((const struct sockaddr_in6
*)pss
)->sin6_addr
;
256 return IN6_IS_ADDR_LOOPBACK(pin6
);
259 if (pss
->sa_family
== AF_INET
) {
260 const struct in_addr
*pin
= &((const struct sockaddr_in
*)pss
)->sin_addr
;
261 return is_loopback_ip_v4(*pin
);
267 * Check if a struct sockaddr has an unspecified address.
269 bool is_zero_addr(const struct sockaddr
*pss
)
271 #if defined(HAVE_IPV6)
272 if (pss
->sa_family
== AF_INET6
) {
273 const struct in6_addr
*pin6
=
274 &((const struct sockaddr_in6
*)pss
)->sin6_addr
;
275 return IN6_IS_ADDR_UNSPECIFIED(pin6
);
278 if (pss
->sa_family
== AF_INET
) {
279 const struct in_addr
*pin
= &((const struct sockaddr_in
*)pss
)->sin_addr
;
280 return is_zero_ip_v4(*pin
);
286 * Set an IP to 0.0.0.0.
288 void zero_ip_v4(struct in_addr
*ip
)
290 memset(ip
, '\0', sizeof(struct in_addr
));
294 * Convert an IPv4 struct in_addr to a struct sockaddr_storage.
296 void in_addr_to_sockaddr_storage(struct sockaddr_storage
*ss
,
299 struct sockaddr_in
*sa
= (struct sockaddr_in
*)ss
;
300 memset(ss
, '\0', sizeof(*ss
));
301 sa
->sin_family
= AF_INET
;
305 #if defined(HAVE_IPV6)
307 * Convert an IPv6 struct in_addr to a struct sockaddr_storage.
309 void in6_addr_to_sockaddr_storage(struct sockaddr_storage
*ss
,
312 struct sockaddr_in6
*sa
= (struct sockaddr_in6
*)ss
;
313 memset(ss
, '\0', sizeof(*ss
));
314 sa
->sin6_family
= AF_INET6
;
320 * Are two IPs on the same subnet?
322 bool same_net(const struct sockaddr
*ip1
,
323 const struct sockaddr
*ip2
,
324 const struct sockaddr
*mask
)
326 if (ip1
->sa_family
!= ip2
->sa_family
) {
327 /* Never on the same net. */
331 #if defined(HAVE_IPV6)
332 if (ip1
->sa_family
== AF_INET6
) {
333 struct sockaddr_in6 ip1_6
= *(const struct sockaddr_in6
*)ip1
;
334 struct sockaddr_in6 ip2_6
= *(const struct sockaddr_in6
*)ip2
;
335 struct sockaddr_in6 mask_6
= *(const struct sockaddr_in6
*)mask
;
336 char *p1
= (char *)&ip1_6
.sin6_addr
;
337 char *p2
= (char *)&ip2_6
.sin6_addr
;
338 char *m
= (char *)&mask_6
.sin6_addr
;
341 for (i
= 0; i
< sizeof(struct in6_addr
); i
++) {
346 return (memcmp(&ip1_6
.sin6_addr
,
348 sizeof(struct in6_addr
)) == 0);
351 if (ip1
->sa_family
== AF_INET
) {
352 return same_net_v4(((const struct sockaddr_in
*)ip1
)->sin_addr
,
353 ((const struct sockaddr_in
*)ip2
)->sin_addr
,
354 ((const struct sockaddr_in
*)mask
)->sin_addr
);
360 * Are two sockaddr 's the same family and address ? Ignore port etc.
363 bool sockaddr_equal(const struct sockaddr
*ip1
,
364 const struct sockaddr
*ip2
)
366 if (ip1
->sa_family
!= ip2
->sa_family
) {
367 /* Never the same. */
371 #if defined(HAVE_IPV6)
372 if (ip1
->sa_family
== AF_INET6
) {
373 return (memcmp(&((const struct sockaddr_in6
*)ip1
)->sin6_addr
,
374 &((const struct sockaddr_in6
*)ip2
)->sin6_addr
,
375 sizeof(struct in6_addr
)) == 0);
378 if (ip1
->sa_family
== AF_INET
) {
379 return (memcmp(&((const struct sockaddr_in
*)ip1
)->sin_addr
,
380 &((const struct sockaddr_in
*)ip2
)->sin_addr
,
381 sizeof(struct in_addr
)) == 0);
387 * Is an IP address the INADDR_ANY or in6addr_any value ?
389 bool is_address_any(const struct sockaddr
*psa
)
391 #if defined(HAVE_IPV6)
392 if (psa
->sa_family
== AF_INET6
) {
393 const struct sockaddr_in6
*si6
= (const struct sockaddr_in6
*)psa
;
394 if (memcmp(&in6addr_any
,
396 sizeof(in6addr_any
)) == 0) {
402 if (psa
->sa_family
== AF_INET
) {
403 const struct sockaddr_in
*si
= (const struct sockaddr_in
*)psa
;
404 if (si
->sin_addr
.s_addr
== INADDR_ANY
) {
412 void set_sockaddr_port(struct sockaddr
*psa
, uint16_t port
)
414 #if defined(HAVE_IPV6)
415 if (psa
->sa_family
== AF_INET6
) {
416 ((struct sockaddr_in6
*)psa
)->sin6_port
= htons(port
);
419 if (psa
->sa_family
== AF_INET
) {
420 ((struct sockaddr_in
*)psa
)->sin_port
= htons(port
);