1 /*-------------------------------------------------------------------------
4 * IP netmask calculations, and enumerating network interfaces.
6 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/libpq/ifaddr.c
13 * This file and the IPV6 implementation were initially provided by
14 * Nigel Kukard <nkukard@lbsd.net>, Linux Based Systems Design
15 * http://www.lbsd.net.
17 *-------------------------------------------------------------------------
24 #include <sys/socket.h>
26 #include <netinet/in.h>
27 #ifdef HAVE_NETINET_TCP_H
28 #include <netinet/tcp.h>
32 #include "libpq/ifaddr.h"
33 #include "port/pg_bswap.h"
35 static int range_sockaddr_AF_INET(const struct sockaddr_in
*addr
,
36 const struct sockaddr_in
*netaddr
,
37 const struct sockaddr_in
*netmask
);
40 static int range_sockaddr_AF_INET6(const struct sockaddr_in6
*addr
,
41 const struct sockaddr_in6
*netaddr
,
42 const struct sockaddr_in6
*netmask
);
47 * pg_range_sockaddr - is addr within the subnet specified by netaddr/netmask ?
49 * Note: caller must already have verified that all three addresses are
50 * in the same address family; and AF_UNIX addresses are not supported.
53 pg_range_sockaddr(const struct sockaddr_storage
*addr
,
54 const struct sockaddr_storage
*netaddr
,
55 const struct sockaddr_storage
*netmask
)
57 if (addr
->ss_family
== AF_INET
)
58 return range_sockaddr_AF_INET((const struct sockaddr_in
*) addr
,
59 (const struct sockaddr_in
*) netaddr
,
60 (const struct sockaddr_in
*) netmask
);
62 else if (addr
->ss_family
== AF_INET6
)
63 return range_sockaddr_AF_INET6((const struct sockaddr_in6
*) addr
,
64 (const struct sockaddr_in6
*) netaddr
,
65 (const struct sockaddr_in6
*) netmask
);
72 range_sockaddr_AF_INET(const struct sockaddr_in
*addr
,
73 const struct sockaddr_in
*netaddr
,
74 const struct sockaddr_in
*netmask
)
76 if (((addr
->sin_addr
.s_addr
^ netaddr
->sin_addr
.s_addr
) &
77 netmask
->sin_addr
.s_addr
) == 0)
87 range_sockaddr_AF_INET6(const struct sockaddr_in6
*addr
,
88 const struct sockaddr_in6
*netaddr
,
89 const struct sockaddr_in6
*netmask
)
93 for (i
= 0; i
< 16; i
++)
95 if (((addr
->sin6_addr
.s6_addr
[i
] ^ netaddr
->sin6_addr
.s6_addr
[i
]) &
96 netmask
->sin6_addr
.s6_addr
[i
]) != 0)
102 #endif /* HAVE_IPV6 */
105 * pg_sockaddr_cidr_mask - make a network mask of the appropriate family
106 * and required number of significant bits
108 * numbits can be null, in which case the mask is fully set.
110 * The resulting mask is placed in *mask, which had better be big enough.
112 * Return value is 0 if okay, -1 if not.
115 pg_sockaddr_cidr_mask(struct sockaddr_storage
*mask
, char *numbits
, int family
)
122 bits
= (family
== AF_INET
) ? 32 : 128;
126 bits
= strtol(numbits
, &endptr
, 10);
127 if (*numbits
== '\0' || *endptr
!= '\0')
135 struct sockaddr_in mask4
;
138 if (bits
< 0 || bits
> 32)
140 memset(&mask4
, 0, sizeof(mask4
));
141 /* avoid "x << 32", which is not portable */
143 maskl
= (0xffffffffUL
<< (32 - (int) bits
))
147 mask4
.sin_addr
.s_addr
= pg_hton32(maskl
);
148 memcpy(mask
, &mask4
, sizeof(mask4
));
155 struct sockaddr_in6 mask6
;
158 if (bits
< 0 || bits
> 128)
160 memset(&mask6
, 0, sizeof(mask6
));
161 for (i
= 0; i
< 16; i
++)
164 mask6
.sin6_addr
.s6_addr
[i
] = 0;
166 mask6
.sin6_addr
.s6_addr
[i
] = 0xff;
169 mask6
.sin6_addr
.s6_addr
[i
] =
170 (0xff << (8 - (int) bits
)) & 0xff;
174 memcpy(mask
, &mask6
, sizeof(mask6
));
182 mask
->ss_family
= family
;
188 * Run the callback function for the addr/mask, after making sure the
189 * mask is sane for the addr.
192 run_ifaddr_callback(PgIfAddrCallback callback
, void *cb_data
,
193 struct sockaddr
*addr
, struct sockaddr
*mask
)
195 struct sockaddr_storage fullmask
;
200 /* Check that the mask is valid */
203 if (mask
->sa_family
!= addr
->sa_family
)
207 else if (mask
->sa_family
== AF_INET
)
209 if (((struct sockaddr_in
*) mask
)->sin_addr
.s_addr
== INADDR_ANY
)
213 else if (mask
->sa_family
== AF_INET6
)
215 if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6
*) mask
)->sin6_addr
))
221 /* If mask is invalid, generate our own fully-set mask */
224 pg_sockaddr_cidr_mask(&fullmask
, NULL
, addr
->sa_family
);
225 mask
= (struct sockaddr
*) &fullmask
;
228 (*callback
) (addr
, mask
, cb_data
);
233 #include <winsock2.h>
234 #include <ws2tcpip.h>
237 * Enumerate the system's network interface addresses and call the callback
238 * for each one. Returns 0 if successful, -1 if trouble.
240 * This version is for Win32. Uses the Winsock 2 functions (ie: ws2_32.dll)
243 pg_foreach_ifaddr(PgIfAddrCallback callback
, void *cb_data
)
247 unsigned long length
,
249 unsigned long n_ii
= 0;
253 sock
= WSASocket(AF_INET
, SOCK_DGRAM
, 0, 0, 0, 0);
254 if (sock
== INVALID_SOCKET
)
260 ptr
= realloc(ii
, sizeof(INTERFACE_INFO
) * n_ii
);
270 if (WSAIoctl(sock
, SIO_GET_INTERFACE_LIST
, 0, 0,
271 ii
, n_ii
* sizeof(INTERFACE_INFO
),
272 &length
, 0, 0) == SOCKET_ERROR
)
274 error
= WSAGetLastError();
275 if (error
== WSAEFAULT
|| error
== WSAENOBUFS
)
276 continue; /* need to make the buffer bigger */
285 for (i
= 0; i
< length
/ sizeof(INTERFACE_INFO
); ++i
)
286 run_ifaddr_callback(callback
, cb_data
,
287 (struct sockaddr
*) &ii
[i
].iiAddress
,
288 (struct sockaddr
*) &ii
[i
].iiNetmask
);
294 #elif HAVE_GETIFADDRS /* && !WIN32 */
296 #ifdef HAVE_IFADDRS_H
301 * Enumerate the system's network interface addresses and call the callback
302 * for each one. Returns 0 if successful, -1 if trouble.
304 * This version uses the getifaddrs() interface, which is available on
305 * BSDs, AIX, and modern Linux.
308 pg_foreach_ifaddr(PgIfAddrCallback callback
, void *cb_data
)
313 if (getifaddrs(&ifa
) < 0)
316 for (l
= ifa
; l
; l
= l
->ifa_next
)
317 run_ifaddr_callback(callback
, cb_data
,
318 l
->ifa_addr
, l
->ifa_netmask
);
323 #else /* !HAVE_GETIFADDRS && !WIN32 */
325 #include <sys/ioctl.h>
331 #ifdef HAVE_SYS_SOCKIO_H
332 #include <sys/sockio.h>
336 * SIOCGIFCONF does not return IPv6 addresses on Solaris
337 * and HP/UX. So we prefer SIOCGLIFCONF if it's available.
339 * On HP/UX, however, it *only* returns IPv6 addresses,
340 * and the structs are named slightly differently too.
341 * We'd have to do another call with SIOCGIFCONF to get the
342 * IPv4 addresses as well. We don't currently bother, just
343 * fall back to SIOCGIFCONF on HP/UX.
346 #if defined(SIOCGLIFCONF) && !defined(__hpux)
349 * Enumerate the system's network interface addresses and call the callback
350 * for each one. Returns 0 if successful, -1 if trouble.
352 * This version uses ioctl(SIOCGLIFCONF).
355 pg_foreach_ifaddr(PgIfAddrCallback callback
, void *cb_data
)
360 struct sockaddr
*addr
,
364 size_t n_buffer
= 1024;
374 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
375 if (sock
== PGINVALID_SOCKET
)
378 while (n_buffer
< 1024 * 100)
381 ptr
= realloc(buffer
, n_buffer
);
390 memset(&lifc
, 0, sizeof(lifc
));
391 lifc
.lifc_family
= AF_UNSPEC
;
392 lifc
.lifc_buf
= buffer
= ptr
;
393 lifc
.lifc_len
= n_buffer
;
395 if (ioctl(sock
, SIOCGLIFCONF
, &lifc
) < 0)
405 * Some Unixes try to return as much data as possible, with no
406 * indication of whether enough space allocated. Don't believe we have
407 * it all unless there's lots of slop.
409 if (lifc
.lifc_len
< n_buffer
- 1024)
414 /* We'll need an IPv6 socket too for the SIOCGLIFNETMASK ioctls */
415 sock6
= socket(AF_INET6
, SOCK_DGRAM
, 0);
416 if (sock6
== PGINVALID_SOCKET
)
424 total
= lifc
.lifc_len
/ sizeof(struct lifreq
);
425 lifr
= lifc
.lifc_req
;
426 for (i
= 0; i
< total
; ++i
)
428 addr
= (struct sockaddr
*) &lifr
[i
].lifr_addr
;
429 memcpy(&lmask
, &lifr
[i
], sizeof(struct lifreq
));
431 fd
= (addr
->sa_family
== AF_INET6
) ? sock6
: sock
;
435 if (ioctl(fd
, SIOCGLIFNETMASK
, &lmask
) < 0)
438 mask
= (struct sockaddr
*) &lmask
.lifr_addr
;
439 run_ifaddr_callback(callback
, cb_data
, addr
, mask
);
449 #elif defined(SIOCGIFCONF)
452 * Remaining Unixes use SIOCGIFCONF. Some only return IPv4 information
453 * here, so this is the least preferred method. Note that there is no
454 * standard way to iterate the struct ifreq returned in the array.
455 * On some OSs the structures are padded large enough for any address,
456 * on others you have to calculate the size of the struct ifreq.
459 /* Some OSs have _SIZEOF_ADDR_IFREQ, so just use that */
460 #ifndef _SIZEOF_ADDR_IFREQ
462 /* Calculate based on sockaddr.sa_len */
463 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
464 #define _SIZEOF_ADDR_IFREQ(ifr) \
465 ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
466 (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
467 (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
469 /* Padded ifreq structure, simple */
471 #define _SIZEOF_ADDR_IFREQ(ifr) \
472 sizeof (struct ifreq)
474 #endif /* !_SIZEOF_ADDR_IFREQ */
477 * Enumerate the system's network interface addresses and call the callback
478 * for each one. Returns 0 if successful, -1 if trouble.
480 * This version uses ioctl(SIOCGIFCONF).
483 pg_foreach_ifaddr(PgIfAddrCallback callback
, void *cb_data
)
492 size_t n_buffer
= 1024;
495 sock
= socket(AF_INET
, SOCK_DGRAM
, 0);
496 if (sock
== PGINVALID_SOCKET
)
499 while (n_buffer
< 1024 * 100)
502 ptr
= realloc(buffer
, n_buffer
);
511 memset(&ifc
, 0, sizeof(ifc
));
512 ifc
.ifc_buf
= buffer
= ptr
;
513 ifc
.ifc_len
= n_buffer
;
515 if (ioctl(sock
, SIOCGIFCONF
, &ifc
) < 0)
525 * Some Unixes try to return as much data as possible, with no
526 * indication of whether enough space allocated. Don't believe we have
527 * it all unless there's lots of slop.
529 if (ifc
.ifc_len
< n_buffer
- 1024)
533 end
= (struct ifreq
*) (buffer
+ ifc
.ifc_len
);
534 for (ifr
= ifc
.ifc_req
; ifr
< end
;)
536 memcpy(&addr
, ifr
, sizeof(addr
));
537 memcpy(&mask
, ifr
, sizeof(mask
));
538 if (ioctl(sock
, SIOCGIFADDR
, &addr
, sizeof(addr
)) == 0 &&
539 ioctl(sock
, SIOCGIFNETMASK
, &mask
, sizeof(mask
)) == 0)
540 run_ifaddr_callback(callback
, cb_data
,
541 &addr
.ifr_addr
, &mask
.ifr_addr
);
542 ifr
= (struct ifreq
*) ((char *) ifr
+ _SIZEOF_ADDR_IFREQ(*ifr
));
549 #else /* !defined(SIOCGIFCONF) */
552 * Enumerate the system's network interface addresses and call the callback
553 * for each one. Returns 0 if successful, -1 if trouble.
555 * This version is our fallback if there's no known way to get the
556 * interface addresses. Just return the standard loopback addresses.
559 pg_foreach_ifaddr(PgIfAddrCallback callback
, void *cb_data
)
561 struct sockaddr_in addr
;
562 struct sockaddr_storage mask
;
565 struct sockaddr_in6 addr6
;
568 /* addr 127.0.0.1/8 */
569 memset(&addr
, 0, sizeof(addr
));
570 addr
.sin_family
= AF_INET
;
571 addr
.sin_addr
.s_addr
= pg_ntoh32(0x7f000001);
572 memset(&mask
, 0, sizeof(mask
));
573 pg_sockaddr_cidr_mask(&mask
, "8", AF_INET
);
574 run_ifaddr_callback(callback
, cb_data
,
575 (struct sockaddr
*) &addr
,
576 (struct sockaddr
*) &mask
);
580 memset(&addr6
, 0, sizeof(addr6
));
581 addr6
.sin6_family
= AF_INET6
;
582 addr6
.sin6_addr
.s6_addr
[15] = 1;
583 memset(&mask
, 0, sizeof(mask
));
584 pg_sockaddr_cidr_mask(&mask
, "128", AF_INET6
);
585 run_ifaddr_callback(callback
, cb_data
,
586 (struct sockaddr
*) &addr6
,
587 (struct sockaddr
*) &mask
);
592 #endif /* !defined(SIOCGIFCONF) */
594 #endif /* !HAVE_GETIFADDRS */