PostgreSQL Source Code  git master
ifaddr.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * ifaddr.c
4  * IP netmask calculations, and enumerating network interfaces.
5  *
6  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/libpq/ifaddr.c
12  *
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.
16  *
17  *-------------------------------------------------------------------------
18  */
19 
20 #include "postgres.h"
21 
22 #include <unistd.h>
23 #include <sys/stat.h>
24 #include <sys/socket.h>
25 #include <netdb.h>
26 #include <netinet/in.h>
27 #include <netinet/tcp.h>
28 #include <sys/file.h>
29 
30 #include "libpq/ifaddr.h"
31 #include "port/pg_bswap.h"
32 
33 static int range_sockaddr_AF_INET(const struct sockaddr_in *addr,
34  const struct sockaddr_in *netaddr,
35  const struct sockaddr_in *netmask);
36 
37 static int range_sockaddr_AF_INET6(const struct sockaddr_in6 *addr,
38  const struct sockaddr_in6 *netaddr,
39  const struct sockaddr_in6 *netmask);
40 
41 
42 /*
43  * pg_range_sockaddr - is addr within the subnet specified by netaddr/netmask ?
44  *
45  * Note: caller must already have verified that all three addresses are
46  * in the same address family; and AF_UNIX addresses are not supported.
47  */
48 int
49 pg_range_sockaddr(const struct sockaddr_storage *addr,
50  const struct sockaddr_storage *netaddr,
51  const struct sockaddr_storage *netmask)
52 {
53  if (addr->ss_family == AF_INET)
54  return range_sockaddr_AF_INET((const struct sockaddr_in *) addr,
55  (const struct sockaddr_in *) netaddr,
56  (const struct sockaddr_in *) netmask);
57  else if (addr->ss_family == AF_INET6)
58  return range_sockaddr_AF_INET6((const struct sockaddr_in6 *) addr,
59  (const struct sockaddr_in6 *) netaddr,
60  (const struct sockaddr_in6 *) netmask);
61  else
62  return 0;
63 }
64 
65 static int
66 range_sockaddr_AF_INET(const struct sockaddr_in *addr,
67  const struct sockaddr_in *netaddr,
68  const struct sockaddr_in *netmask)
69 {
70  if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) &
71  netmask->sin_addr.s_addr) == 0)
72  return 1;
73  else
74  return 0;
75 }
76 
77 static int
78 range_sockaddr_AF_INET6(const struct sockaddr_in6 *addr,
79  const struct sockaddr_in6 *netaddr,
80  const struct sockaddr_in6 *netmask)
81 {
82  int i;
83 
84  for (i = 0; i < 16; i++)
85  {
86  if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) &
87  netmask->sin6_addr.s6_addr[i]) != 0)
88  return 0;
89  }
90 
91  return 1;
92 }
93 
94 /*
95  * pg_sockaddr_cidr_mask - make a network mask of the appropriate family
96  * and required number of significant bits
97  *
98  * numbits can be null, in which case the mask is fully set.
99  *
100  * The resulting mask is placed in *mask, which had better be big enough.
101  *
102  * Return value is 0 if okay, -1 if not.
103  */
104 int
105 pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
106 {
107  long bits;
108  char *endptr;
109 
110  if (numbits == NULL)
111  {
112  bits = (family == AF_INET) ? 32 : 128;
113  }
114  else
115  {
116  bits = strtol(numbits, &endptr, 10);
117  if (*numbits == '\0' || *endptr != '\0')
118  return -1;
119  }
120 
121  switch (family)
122  {
123  case AF_INET:
124  {
125  struct sockaddr_in mask4;
126  long maskl;
127 
128  if (bits < 0 || bits > 32)
129  return -1;
130  memset(&mask4, 0, sizeof(mask4));
131  /* avoid "x << 32", which is not portable */
132  if (bits > 0)
133  maskl = (0xffffffffUL << (32 - (int) bits))
134  & 0xffffffffUL;
135  else
136  maskl = 0;
137  mask4.sin_addr.s_addr = pg_hton32(maskl);
138  memcpy(mask, &mask4, sizeof(mask4));
139  break;
140  }
141 
142  case AF_INET6:
143  {
144  struct sockaddr_in6 mask6;
145  int i;
146 
147  if (bits < 0 || bits > 128)
148  return -1;
149  memset(&mask6, 0, sizeof(mask6));
150  for (i = 0; i < 16; i++)
151  {
152  if (bits <= 0)
153  mask6.sin6_addr.s6_addr[i] = 0;
154  else if (bits >= 8)
155  mask6.sin6_addr.s6_addr[i] = 0xff;
156  else
157  {
158  mask6.sin6_addr.s6_addr[i] =
159  (0xff << (8 - (int) bits)) & 0xff;
160  }
161  bits -= 8;
162  }
163  memcpy(mask, &mask6, sizeof(mask6));
164  break;
165  }
166 
167  default:
168  return -1;
169  }
170 
171  mask->ss_family = family;
172  return 0;
173 }
174 
175 
176 /*
177  * Run the callback function for the addr/mask, after making sure the
178  * mask is sane for the addr.
179  */
180 static void
182  struct sockaddr *addr, struct sockaddr *mask)
183 {
184  struct sockaddr_storage fullmask;
185 
186  if (!addr)
187  return;
188 
189  /* Check that the mask is valid */
190  if (mask)
191  {
192  if (mask->sa_family != addr->sa_family)
193  {
194  mask = NULL;
195  }
196  else if (mask->sa_family == AF_INET)
197  {
198  if (((struct sockaddr_in *) mask)->sin_addr.s_addr == INADDR_ANY)
199  mask = NULL;
200  }
201  else if (mask->sa_family == AF_INET6)
202  {
203  if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) mask)->sin6_addr))
204  mask = NULL;
205  }
206  }
207 
208  /* If mask is invalid, generate our own fully-set mask */
209  if (!mask)
210  {
211  pg_sockaddr_cidr_mask(&fullmask, NULL, addr->sa_family);
212  mask = (struct sockaddr *) &fullmask;
213  }
214 
215  (*callback) (addr, mask, cb_data);
216 }
217 
218 #ifdef WIN32
219 
220 #include <winsock2.h>
221 #include <ws2tcpip.h>
222 
223 /*
224  * Enumerate the system's network interface addresses and call the callback
225  * for each one. Returns 0 if successful, -1 if trouble.
226  *
227  * This version is for Win32. Uses the Winsock 2 functions (ie: ws2_32.dll)
228  */
229 int
231 {
232  INTERFACE_INFO *ptr,
233  *ii = NULL;
234  unsigned long length,
235  i;
236  unsigned long n_ii = 0;
237  SOCKET sock;
238  int error;
239 
240  sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
241  if (sock == INVALID_SOCKET)
242  return -1;
243 
244  while (n_ii < 1024)
245  {
246  n_ii += 64;
247  ptr = realloc(ii, sizeof(INTERFACE_INFO) * n_ii);
248  if (!ptr)
249  {
250  free(ii);
251  closesocket(sock);
252  errno = ENOMEM;
253  return -1;
254  }
255 
256  ii = ptr;
257  if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0,
258  ii, n_ii * sizeof(INTERFACE_INFO),
259  &length, 0, 0) == SOCKET_ERROR)
260  {
261  error = WSAGetLastError();
262  if (error == WSAEFAULT || error == WSAENOBUFS)
263  continue; /* need to make the buffer bigger */
264  closesocket(sock);
265  free(ii);
266  return -1;
267  }
268 
269  break;
270  }
271 
272  for (i = 0; i < length / sizeof(INTERFACE_INFO); ++i)
273  run_ifaddr_callback(callback, cb_data,
274  (struct sockaddr *) &ii[i].iiAddress,
275  (struct sockaddr *) &ii[i].iiNetmask);
276 
277  closesocket(sock);
278  free(ii);
279  return 0;
280 }
281 #elif HAVE_GETIFADDRS /* && !WIN32 */
282 
283 #ifdef HAVE_IFADDRS_H
284 #include <ifaddrs.h>
285 #endif
286 
287 /*
288  * Enumerate the system's network interface addresses and call the callback
289  * for each one. Returns 0 if successful, -1 if trouble.
290  *
291  * This version uses the getifaddrs() interface, which is available on
292  * BSDs, macOS, Solaris, illumos and Linux.
293  */
294 int
296 {
297  struct ifaddrs *ifa,
298  *l;
299 
300  if (getifaddrs(&ifa) < 0)
301  return -1;
302 
303  for (l = ifa; l; l = l->ifa_next)
304  run_ifaddr_callback(callback, cb_data,
305  l->ifa_addr, l->ifa_netmask);
306 
307  freeifaddrs(ifa);
308  return 0;
309 }
310 #else /* !HAVE_GETIFADDRS && !WIN32 */
311 
312 #include <sys/ioctl.h>
313 #include <net/if.h>
314 
315 #if defined(SIOCGIFCONF)
316 
317 /*
318  * Remaining Unixes use SIOCGIFCONF. Some only return IPv4 information
319  * here, so this is the least preferred method. Note that there is no
320  * standard way to iterate the struct ifreq returned in the array.
321  * On some OSs the structures are padded large enough for any address,
322  * on others you have to calculate the size of the struct ifreq.
323  */
324 
325 /* Some OSs have _SIZEOF_ADDR_IFREQ, so just use that */
326 #ifndef _SIZEOF_ADDR_IFREQ
327 
328 /* Calculate based on sockaddr.sa_len */
329 #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
330 #define _SIZEOF_ADDR_IFREQ(ifr) \
331  ((ifr).ifr_addr.sa_len > sizeof(struct sockaddr) ? \
332  (sizeof(struct ifreq) - sizeof(struct sockaddr) + \
333  (ifr).ifr_addr.sa_len) : sizeof(struct ifreq))
334 
335 /* Padded ifreq structure, simple */
336 #else
337 #define _SIZEOF_ADDR_IFREQ(ifr) \
338  sizeof (struct ifreq)
339 #endif
340 #endif /* !_SIZEOF_ADDR_IFREQ */
341 
342 /*
343  * Enumerate the system's network interface addresses and call the callback
344  * for each one. Returns 0 if successful, -1 if trouble.
345  *
346  * This version uses ioctl(SIOCGIFCONF).
347  */
348 int
350 {
351  struct ifconf ifc;
352  struct ifreq *ifr,
353  *end,
354  addr,
355  mask;
356  char *ptr,
357  *buffer = NULL;
358  size_t n_buffer = 1024;
359  pgsocket sock;
360 
361  sock = socket(AF_INET, SOCK_DGRAM, 0);
362  if (sock == PGINVALID_SOCKET)
363  return -1;
364 
365  while (n_buffer < 1024 * 100)
366  {
367  n_buffer += 1024;
368  ptr = realloc(buffer, n_buffer);
369  if (!ptr)
370  {
371  free(buffer);
372  close(sock);
373  errno = ENOMEM;
374  return -1;
375  }
376 
377  memset(&ifc, 0, sizeof(ifc));
378  ifc.ifc_buf = buffer = ptr;
379  ifc.ifc_len = n_buffer;
380 
381  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
382  {
383  if (errno == EINVAL)
384  continue;
385  free(buffer);
386  close(sock);
387  return -1;
388  }
389 
390  /*
391  * Some Unixes try to return as much data as possible, with no
392  * indication of whether enough space allocated. Don't believe we have
393  * it all unless there's lots of slop.
394  */
395  if (ifc.ifc_len < n_buffer - 1024)
396  break;
397  }
398 
399  end = (struct ifreq *) (buffer + ifc.ifc_len);
400  for (ifr = ifc.ifc_req; ifr < end;)
401  {
402  memcpy(&addr, ifr, sizeof(addr));
403  memcpy(&mask, ifr, sizeof(mask));
404  if (ioctl(sock, SIOCGIFADDR, &addr, sizeof(addr)) == 0 &&
405  ioctl(sock, SIOCGIFNETMASK, &mask, sizeof(mask)) == 0)
406  run_ifaddr_callback(callback, cb_data,
407  &addr.ifr_addr, &mask.ifr_addr);
408  ifr = (struct ifreq *) ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr));
409  }
410 
411  free(buffer);
412  close(sock);
413  return 0;
414 }
415 #else /* !defined(SIOCGIFCONF) */
416 
417 /*
418  * Enumerate the system's network interface addresses and call the callback
419  * for each one. Returns 0 if successful, -1 if trouble.
420  *
421  * This version is our fallback if there's no known way to get the
422  * interface addresses. Just return the standard loopback addresses.
423  */
424 int
426 {
427  struct sockaddr_in addr;
428  struct sockaddr_storage mask;
429  struct sockaddr_in6 addr6;
430 
431  /* addr 127.0.0.1/8 */
432  memset(&addr, 0, sizeof(addr));
433  addr.sin_family = AF_INET;
434  addr.sin_addr.s_addr = pg_ntoh32(0x7f000001);
435  memset(&mask, 0, sizeof(mask));
436  pg_sockaddr_cidr_mask(&mask, "8", AF_INET);
437  run_ifaddr_callback(callback, cb_data,
438  (struct sockaddr *) &addr,
439  (struct sockaddr *) &mask);
440 
441  /* addr ::1/128 */
442  memset(&addr6, 0, sizeof(addr6));
443  addr6.sin6_family = AF_INET6;
444  addr6.sin6_addr.s6_addr[15] = 1;
445  memset(&mask, 0, sizeof(mask));
446  pg_sockaddr_cidr_mask(&mask, "128", AF_INET6);
447  run_ifaddr_callback(callback, cb_data,
448  (struct sockaddr *) &addr6,
449  (struct sockaddr *) &mask);
450 
451  return 0;
452 }
453 #endif /* !defined(SIOCGIFCONF) */
454 
455 #endif /* !HAVE_GETIFADDRS */
#define realloc(a, b)
Definition: header.h:60
#define free(a)
Definition: header.h:65
static int range_sockaddr_AF_INET6(const struct sockaddr_in6 *addr, const struct sockaddr_in6 *netaddr, const struct sockaddr_in6 *netmask)
Definition: ifaddr.c:78
int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
Definition: ifaddr.c:105
int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
Definition: ifaddr.c:425
static int range_sockaddr_AF_INET(const struct sockaddr_in *addr, const struct sockaddr_in *netaddr, const struct sockaddr_in *netmask)
Definition: ifaddr.c:66
static void run_ifaddr_callback(PgIfAddrCallback callback, void *cb_data, struct sockaddr *addr, struct sockaddr *mask)
Definition: ifaddr.c:181
int pg_range_sockaddr(const struct sockaddr_storage *addr, const struct sockaddr_storage *netaddr, const struct sockaddr_storage *netmask)
Definition: ifaddr.c:49
void(* PgIfAddrCallback)(struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
Definition: ifaddr.h:17
#define close(a)
Definition: win32.h:12
int i
Definition: isn.c:73
#define pg_ntoh32(x)
Definition: pg_bswap.h:125
#define pg_hton32(x)
Definition: pg_bswap.h:121
int pgsocket
Definition: port.h:29
#define PGINVALID_SOCKET
Definition: port.h:31
#define closesocket
Definition: port.h:349
static void error(void)
Definition: sql-dyntest.c:147
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:46
#define socket(af, type, protocol)
Definition: win32_port.h:490