PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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-2017, 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 #ifdef HAVE_NETINET_TCP_H
28 #include <netinet/tcp.h>
29 #endif
30 #include <arpa/inet.h>
31 #include <sys/file.h>
32 
33 #include "libpq/ifaddr.h"
34 
35 static int range_sockaddr_AF_INET(const struct sockaddr_in *addr,
36  const struct sockaddr_in *netaddr,
37  const struct sockaddr_in *netmask);
38 
39 #ifdef HAVE_IPV6
40 static int range_sockaddr_AF_INET6(const struct sockaddr_in6 *addr,
41  const struct sockaddr_in6 *netaddr,
42  const struct sockaddr_in6 *netmask);
43 #endif
44 
45 
46 /*
47  * pg_range_sockaddr - is addr within the subnet specified by netaddr/netmask ?
48  *
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.
51  */
52 int
54  const struct sockaddr_storage *netaddr,
55  const struct sockaddr_storage *netmask)
56 {
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);
61 #ifdef HAVE_IPV6
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);
66 #endif
67  else
68  return 0;
69 }
70 
71 static int
72 range_sockaddr_AF_INET(const struct sockaddr_in *addr,
73  const struct sockaddr_in *netaddr,
74  const struct sockaddr_in *netmask)
75 {
76  if (((addr->sin_addr.s_addr ^ netaddr->sin_addr.s_addr) &
77  netmask->sin_addr.s_addr) == 0)
78  return 1;
79  else
80  return 0;
81 }
82 
83 
84 #ifdef HAVE_IPV6
85 
86 static int
87 range_sockaddr_AF_INET6(const struct sockaddr_in6 *addr,
88  const struct sockaddr_in6 *netaddr,
89  const struct sockaddr_in6 *netmask)
90 {
91  int i;
92 
93  for (i = 0; i < 16; i++)
94  {
95  if (((addr->sin6_addr.s6_addr[i] ^ netaddr->sin6_addr.s6_addr[i]) &
96  netmask->sin6_addr.s6_addr[i]) != 0)
97  return 0;
98  }
99 
100  return 1;
101 }
102 #endif /* HAVE_IPV6 */
103 
104 /*
105  * pg_sockaddr_cidr_mask - make a network mask of the appropriate family
106  * and required number of significant bits
107  *
108  * numbits can be null, in which case the mask is fully set.
109  *
110  * The resulting mask is placed in *mask, which had better be big enough.
111  *
112  * Return value is 0 if okay, -1 if not.
113  */
114 int
115 pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
116 {
117  long bits;
118  char *endptr;
119 
120  if (numbits == NULL)
121  {
122  bits = (family == AF_INET) ? 32 : 128;
123  }
124  else
125  {
126  bits = strtol(numbits, &endptr, 10);
127  if (*numbits == '\0' || *endptr != '\0')
128  return -1;
129  }
130 
131  switch (family)
132  {
133  case AF_INET:
134  {
135  struct sockaddr_in mask4;
136  long maskl;
137 
138  if (bits < 0 || bits > 32)
139  return -1;
140  memset(&mask4, 0, sizeof(mask4));
141  /* avoid "x << 32", which is not portable */
142  if (bits > 0)
143  maskl = (0xffffffffUL << (32 - (int) bits))
144  & 0xffffffffUL;
145  else
146  maskl = 0;
147  mask4.sin_addr.s_addr = htonl(maskl);
148  memcpy(mask, &mask4, sizeof(mask4));
149  break;
150  }
151 
152 #ifdef HAVE_IPV6
153  case AF_INET6:
154  {
155  struct sockaddr_in6 mask6;
156  int i;
157 
158  if (bits < 0 || bits > 128)
159  return -1;
160  memset(&mask6, 0, sizeof(mask6));
161  for (i = 0; i < 16; i++)
162  {
163  if (bits <= 0)
164  mask6.sin6_addr.s6_addr[i] = 0;
165  else if (bits >= 8)
166  mask6.sin6_addr.s6_addr[i] = 0xff;
167  else
168  {
169  mask6.sin6_addr.s6_addr[i] =
170  (0xff << (8 - (int) bits)) & 0xff;
171  }
172  bits -= 8;
173  }
174  memcpy(mask, &mask6, sizeof(mask6));
175  break;
176  }
177 #endif
178  default:
179  return -1;
180  }
181 
182  mask->ss_family = family;
183  return 0;
184 }
185 
186 
187 /*
188  * Run the callback function for the addr/mask, after making sure the
189  * mask is sane for the addr.
190  */
191 static void
193  struct sockaddr *addr, struct sockaddr *mask)
194 {
195  struct sockaddr_storage fullmask;
196 
197  if (!addr)
198  return;
199 
200  /* Check that the mask is valid */
201  if (mask)
202  {
203  if (mask->sa_family != addr->sa_family)
204  {
205  mask = NULL;
206  }
207  else if (mask->sa_family == AF_INET)
208  {
209  if (((struct sockaddr_in *) mask)->sin_addr.s_addr == INADDR_ANY)
210  mask = NULL;
211  }
212 #ifdef HAVE_IPV6
213  else if (mask->sa_family == AF_INET6)
214  {
215  if (IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) mask)->sin6_addr))
216  mask = NULL;
217  }
218 #endif
219  }
220 
221  /* If mask is invalid, generate our own fully-set mask */
222  if (!mask)
223  {
224  pg_sockaddr_cidr_mask(&fullmask, NULL, addr->sa_family);
225  mask = (struct sockaddr *) &fullmask;
226  }
227 
228  (*callback) (addr, mask, cb_data);
229 }
230 
231 #ifdef WIN32
232 
233 #include <winsock2.h>
234 #include <ws2tcpip.h>
235 
236 /*
237  * Enumerate the system's network interface addresses and call the callback
238  * for each one. Returns 0 if successful, -1 if trouble.
239  *
240  * This version is for Win32. Uses the Winsock 2 functions (ie: ws2_32.dll)
241  */
242 int
244 {
245  INTERFACE_INFO *ptr,
246  *ii = NULL;
247  unsigned long length,
248  i;
249  unsigned long n_ii = 0;
250  SOCKET sock;
251  int error;
252 
253  sock = WSASocket(AF_INET, SOCK_DGRAM, 0, 0, 0, 0);
254  if (sock == INVALID_SOCKET)
255  return -1;
256 
257  while (n_ii < 1024)
258  {
259  n_ii += 64;
260  ptr = realloc(ii, sizeof(INTERFACE_INFO) * n_ii);
261  if (!ptr)
262  {
263  free(ii);
264  closesocket(sock);
265  errno = ENOMEM;
266  return -1;
267  }
268 
269  ii = ptr;
270  if (WSAIoctl(sock, SIO_GET_INTERFACE_LIST, 0, 0,
271  ii, n_ii * sizeof(INTERFACE_INFO),
272  &length, 0, 0) == SOCKET_ERROR)
273  {
274  error = WSAGetLastError();
275  if (error == WSAEFAULT || error == WSAENOBUFS)
276  continue; /* need to make the buffer bigger */
277  closesocket(sock);
278  free(ii);
279  return -1;
280  }
281 
282  break;
283  }
284 
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);
289 
290  closesocket(sock);
291  free(ii);
292  return 0;
293 }
294 #elif HAVE_GETIFADDRS /* && !WIN32 */
295 
296 #ifdef HAVE_IFADDRS_H
297 #include <ifaddrs.h>
298 #endif
299 
300 /*
301  * Enumerate the system's network interface addresses and call the callback
302  * for each one. Returns 0 if successful, -1 if trouble.
303  *
304  * This version uses the getifaddrs() interface, which is available on
305  * BSDs, AIX, and modern Linux.
306  */
307 int
308 pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
309 {
310  struct ifaddrs *ifa,
311  *l;
312 
313  if (getifaddrs(&ifa) < 0)
314  return -1;
315 
316  for (l = ifa; l; l = l->ifa_next)
317  run_ifaddr_callback(callback, cb_data,
318  l->ifa_addr, l->ifa_netmask);
319 
320  freeifaddrs(ifa);
321  return 0;
322 }
323 #else /* !HAVE_GETIFADDRS && !WIN32 */
324 
325 #include <sys/ioctl.h>
326 
327 #ifdef HAVE_NET_IF_H
328 #include <net/if.h>
329 #endif
330 
331 #ifdef HAVE_SYS_SOCKIO_H
332 #include <sys/sockio.h>
333 #endif
334 
335 /*
336  * SIOCGIFCONF does not return IPv6 addresses on Solaris
337  * and HP/UX. So we prefer SIOCGLIFCONF if it's available.
338  *
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.
344  */
345 
346 #if defined(SIOCGLIFCONF) && !defined(__hpux)
347 
348 /*
349  * Enumerate the system's network interface addresses and call the callback
350  * for each one. Returns 0 if successful, -1 if trouble.
351  *
352  * This version uses ioctl(SIOCGLIFCONF).
353  */
354 int
355 pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
356 {
357  struct lifconf lifc;
358  struct lifreq *lifr,
359  lmask;
360  struct sockaddr *addr,
361  *mask;
362  char *ptr,
363  *buffer = NULL;
364  size_t n_buffer = 1024;
365  pgsocket sock,
366  fd;
367 
368 #ifdef HAVE_IPV6
369  pgsocket sock6;
370 #endif
371  int i,
372  total;
373 
374  sock = socket(AF_INET, SOCK_DGRAM, 0);
375  if (sock == PGINVALID_SOCKET)
376  return -1;
377 
378  while (n_buffer < 1024 * 100)
379  {
380  n_buffer += 1024;
381  ptr = realloc(buffer, n_buffer);
382  if (!ptr)
383  {
384  free(buffer);
385  close(sock);
386  errno = ENOMEM;
387  return -1;
388  }
389 
390  memset(&lifc, 0, sizeof(lifc));
391  lifc.lifc_family = AF_UNSPEC;
392  lifc.lifc_buf = buffer = ptr;
393  lifc.lifc_len = n_buffer;
394 
395  if (ioctl(sock, SIOCGLIFCONF, &lifc) < 0)
396  {
397  if (errno == EINVAL)
398  continue;
399  free(buffer);
400  close(sock);
401  return -1;
402  }
403 
404  /*
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.
408  */
409  if (lifc.lifc_len < n_buffer - 1024)
410  break;
411  }
412 
413 #ifdef HAVE_IPV6
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)
417  {
418  free(buffer);
419  close(sock);
420  return -1;
421  }
422 #endif
423 
424  total = lifc.lifc_len / sizeof(struct lifreq);
425  lifr = lifc.lifc_req;
426  for (i = 0; i < total; ++i)
427  {
428  addr = (struct sockaddr *) &lifr[i].lifr_addr;
429  memcpy(&lmask, &lifr[i], sizeof(struct lifreq));
430 #ifdef HAVE_IPV6
431  fd = (addr->sa_family == AF_INET6) ? sock6 : sock;
432 #else
433  fd = sock;
434 #endif
435  if (ioctl(fd, SIOCGLIFNETMASK, &lmask) < 0)
436  mask = NULL;
437  else
438  mask = (struct sockaddr *) &lmask.lifr_addr;
439  run_ifaddr_callback(callback, cb_data, addr, mask);
440  }
441 
442  free(buffer);
443  close(sock);
444 #ifdef HAVE_IPV6
445  close(sock6);
446 #endif
447  return 0;
448 }
449 #elif defined(SIOCGIFCONF)
450 
451 /*
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.
457  */
458 
459 /* Some OSs have _SIZEOF_ADDR_IFREQ, so just use that */
460 #ifndef _SIZEOF_ADDR_IFREQ
461 
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))
468 
469 /* Padded ifreq structure, simple */
470 #else
471 #define _SIZEOF_ADDR_IFREQ(ifr) \
472  sizeof (struct ifreq)
473 #endif
474 #endif /* !_SIZEOF_ADDR_IFREQ */
475 
476 /*
477  * Enumerate the system's network interface addresses and call the callback
478  * for each one. Returns 0 if successful, -1 if trouble.
479  *
480  * This version uses ioctl(SIOCGIFCONF).
481  */
482 int
483 pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
484 {
485  struct ifconf ifc;
486  struct ifreq *ifr,
487  *end,
488  addr,
489  mask;
490  char *ptr,
491  *buffer = NULL;
492  size_t n_buffer = 1024;
493  pgsocket sock;
494 
495  sock = socket(AF_INET, SOCK_DGRAM, 0);
496  if (sock == PGINVALID_SOCKET)
497  return -1;
498 
499  while (n_buffer < 1024 * 100)
500  {
501  n_buffer += 1024;
502  ptr = realloc(buffer, n_buffer);
503  if (!ptr)
504  {
505  free(buffer);
506  close(sock);
507  errno = ENOMEM;
508  return -1;
509  }
510 
511  memset(&ifc, 0, sizeof(ifc));
512  ifc.ifc_buf = buffer = ptr;
513  ifc.ifc_len = n_buffer;
514 
515  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
516  {
517  if (errno == EINVAL)
518  continue;
519  free(buffer);
520  close(sock);
521  return -1;
522  }
523 
524  /*
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.
528  */
529  if (ifc.ifc_len < n_buffer - 1024)
530  break;
531  }
532 
533  end = (struct ifreq *) (buffer + ifc.ifc_len);
534  for (ifr = ifc.ifc_req; ifr < end;)
535  {
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));
543  }
544 
545  free(buffer);
546  close(sock);
547  return 0;
548 }
549 #else /* !defined(SIOCGIFCONF) */
550 
551 /*
552  * Enumerate the system's network interface addresses and call the callback
553  * for each one. Returns 0 if successful, -1 if trouble.
554  *
555  * This version is our fallback if there's no known way to get the
556  * interface addresses. Just return the standard loopback addresses.
557  */
558 int
559 pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
560 {
561  struct sockaddr_in addr;
562  struct sockaddr_storage mask;
563 
564 #ifdef HAVE_IPV6
565  struct sockaddr_in6 addr6;
566 #endif
567 
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 = ntohl(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);
577 
578 #ifdef HAVE_IPV6
579  /* addr ::1/128 */
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);
588 #endif
589 
590  return 0;
591 }
592 #endif /* !defined(SIOCGIFCONF) */
593 
594 #endif /* !HAVE_GETIFADDRS */
int length(const List *list)
Definition: list.c:1271
static void error(void)
Definition: sql-dyntest.c:147
static int range_sockaddr_AF_INET(const struct sockaddr_in *addr, const struct sockaddr_in *netaddr, const struct sockaddr_in *netmask)
Definition: ifaddr.c:72
static void run_ifaddr_callback(PgIfAddrCallback callback, void *cb_data, struct sockaddr *addr, struct sockaddr *mask)
Definition: ifaddr.c:192
#define closesocket
Definition: port.h:331
#define socket(af, type, protocol)
Definition: win32.h:369
static int fd(const char *x, int i)
Definition: preproc-init.c:105
int pg_foreach_ifaddr(PgIfAddrCallback callback, void *cb_data)
Definition: ifaddr.c:559
void(* PgIfAddrCallback)(struct sockaddr *addr, struct sockaddr *netmask, void *cb_data)
Definition: ifaddr.h:17
int pg_range_sockaddr(const struct sockaddr_storage *addr, const struct sockaddr_storage *netaddr, const struct sockaddr_storage *netmask)
Definition: ifaddr.c:53
int pg_sockaddr_cidr_mask(struct sockaddr_storage *mask, char *numbits, int family)
Definition: ifaddr.c:115
static void callback(struct sockaddr *addr, struct sockaddr *mask, void *unused)
Definition: test_ifaddrs.c:48
int pgsocket
Definition: port.h:22
#define PGINVALID_SOCKET
Definition: port.h:24
#define free(a)
Definition: header.h:65
#define NULL
Definition: c.h:229
WalTimeSample buffer[LAG_TRACKER_BUFFER_SIZE]
Definition: walsender.c:214
#define realloc(a, b)
Definition: header.h:60
int i
#define close(a)
Definition: win32.h:12