1 /* getifaddrs -- get names and addresses of all network interfaces
2    Copyright (C) 2003-2022 Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4 
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9 
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14 
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, see
17    <https://www.gnu.org/licenses/>.  */
18 
19 #include <alloca.h>
20 #include <assert.h>
21 #include <errno.h>
22 #include <ifaddrs.h>
23 #include <net/if.h>
24 #include <netinet/in.h>
25 #include <netpacket/packet.h>
26 #include <stdbool.h>
27 #include <stdint.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/ioctl.h>
31 #include <sys/socket.h>
32 #include <sysdep.h>
33 #include <time.h>
34 #include <unistd.h>
35 
36 #include "netlinkaccess.h"
37 
38 
39 /* There is a problem with this type.  The address length for
40    Infiniband sockets is much longer than the 8 bytes allocated in the
41    sockaddr_ll definition.  Hence we use here a special
42    definition.  */
43 struct sockaddr_ll_max
44   {
45     unsigned short int sll_family;
46     unsigned short int sll_protocol;
47     int sll_ifindex;
48     unsigned short int sll_hatype;
49     unsigned char sll_pkttype;
50     unsigned char sll_halen;
51     unsigned char sll_addr[24];
52   };
53 
54 
55 /* struct to hold the data for one ifaddrs entry, so we can allocate
56    everything at once.  */
57 struct ifaddrs_storage
58 {
59   struct ifaddrs ifa;
60   union
61   {
62     /* Save space for the biggest of the four used sockaddr types and
63        avoid a lot of casts.  */
64     struct sockaddr sa;
65     struct sockaddr_ll_max sl;
66     struct sockaddr_in s4;
67     struct sockaddr_in6 s6;
68   } addr, netmask, broadaddr;
69   char name[IF_NAMESIZE + 1];
70 };
71 
72 
73 void
__netlink_free_handle(struct netlink_handle * h)74 __netlink_free_handle (struct netlink_handle *h)
75 {
76   struct netlink_res *ptr;
77   int saved_errno = errno;
78 
79   ptr = h->nlm_list;
80   while (ptr != NULL)
81     {
82       struct netlink_res *tmpptr;
83 
84       tmpptr = ptr->next;
85       free (ptr);
86       ptr = tmpptr;
87     }
88 
89   __set_errno (saved_errno);
90 }
91 
92 
93 static int
__netlink_sendreq(struct netlink_handle * h,int type)94 __netlink_sendreq (struct netlink_handle *h, int type)
95 {
96   struct req
97   {
98     struct nlmsghdr nlh;
99     struct rtgenmsg g;
100     char pad[0];
101   } req;
102   struct sockaddr_nl nladdr;
103 
104   if (h->seq == 0)
105     h->seq = time_now ();
106 
107   req.nlh.nlmsg_len = sizeof (req);
108   req.nlh.nlmsg_type = type;
109   req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
110   req.nlh.nlmsg_pid = 0;
111   req.nlh.nlmsg_seq = h->seq;
112   req.g.rtgen_family = AF_UNSPEC;
113   if (sizeof (req) != offsetof (struct req, pad))
114     memset (req.pad, '\0', sizeof (req) - offsetof (struct req, pad));
115 
116   memset (&nladdr, '\0', sizeof (nladdr));
117   nladdr.nl_family = AF_NETLINK;
118 
119   return TEMP_FAILURE_RETRY (__sendto (h->fd, (void *) &req, sizeof (req), 0,
120 				       (struct sockaddr *) &nladdr,
121 				       sizeof (nladdr)));
122 }
123 
124 
125 int
__netlink_request(struct netlink_handle * h,int type)126 __netlink_request (struct netlink_handle *h, int type)
127 {
128   struct netlink_res *nlm_next;
129   struct sockaddr_nl nladdr;
130   struct nlmsghdr *nlmh;
131   ssize_t read_len;
132   bool done = false;
133 
134 #ifdef PAGE_SIZE
135   /* Help the compiler optimize out the malloc call if PAGE_SIZE
136      is constant and smaller or equal to PTHREAD_STACK_MIN/4.  */
137   const size_t buf_size = PAGE_SIZE;
138 #else
139   const size_t buf_size = __getpagesize ();
140 #endif
141   bool use_malloc = false;
142   char *buf;
143 
144   if (__libc_use_alloca (buf_size))
145     buf = alloca (buf_size);
146   else
147     {
148       buf = malloc (buf_size);
149       if (buf != NULL)
150 	use_malloc = true;
151       else
152 	goto out_fail;
153     }
154 
155   struct iovec iov = { buf, buf_size };
156 
157   if (__netlink_sendreq (h, type) < 0)
158     goto out_fail;
159 
160   while (! done)
161     {
162       struct msghdr msg =
163 	{
164 	  .msg_name = (void *) &nladdr,
165 	  .msg_namelen =  sizeof (nladdr),
166 	  .msg_iov = &iov,
167 	  .msg_iovlen = 1,
168 	  .msg_control = NULL,
169 	  .msg_controllen = 0,
170 	  .msg_flags = 0
171 	};
172 
173       read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
174       __netlink_assert_response (h->fd, read_len);
175       if (read_len < 0)
176 	goto out_fail;
177 
178       if (nladdr.nl_pid != 0)
179 	continue;
180 
181       if (__glibc_unlikely (msg.msg_flags & MSG_TRUNC))
182 	goto out_fail;
183 
184       size_t count = 0;
185       size_t remaining_len = read_len;
186       for (nlmh = (struct nlmsghdr *) buf;
187 	   NLMSG_OK (nlmh, remaining_len);
188 	   nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len))
189 	{
190 	  if ((pid_t) nlmh->nlmsg_pid != h->pid
191 	      || nlmh->nlmsg_seq != h->seq)
192 	    continue;
193 
194 	  ++count;
195 	  if (nlmh->nlmsg_type == NLMSG_DONE)
196 	    {
197 	      /* We found the end, leave the loop.  */
198 	      done = true;
199 	      break;
200 	    }
201 	  if (nlmh->nlmsg_type == NLMSG_ERROR)
202 	    {
203 	      struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh);
204 	      if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
205 		errno = EIO;
206 	      else
207 		errno = -nlerr->error;
208 	      goto out_fail;
209 	    }
210 	}
211 
212       /* If there was nothing with the expected nlmsg_pid and nlmsg_seq,
213 	 there is no point to record it.  */
214       if (count == 0)
215 	continue;
216 
217       nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
218 						+ read_len);
219       if (nlm_next == NULL)
220 	goto out_fail;
221       nlm_next->next = NULL;
222       nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
223       nlm_next->size = read_len;
224       nlm_next->seq = h->seq;
225       if (h->nlm_list == NULL)
226 	h->nlm_list = nlm_next;
227       else
228 	h->end_ptr->next = nlm_next;
229       h->end_ptr = nlm_next;
230     }
231 
232   if (use_malloc)
233     free (buf);
234   return 0;
235 
236 out_fail:
237   if (use_malloc)
238     free (buf);
239   return -1;
240 }
241 
242 
243 void
__netlink_close(struct netlink_handle * h)244 __netlink_close (struct netlink_handle *h)
245 {
246   /* Don't modify errno.  */
247   INTERNAL_SYSCALL_CALL (close, h->fd);
248 }
249 
250 
251 /* Open a NETLINK socket.  */
252 int
__netlink_open(struct netlink_handle * h)253 __netlink_open (struct netlink_handle *h)
254 {
255   struct sockaddr_nl nladdr;
256 
257   h->fd = __socket (PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_ROUTE);
258   if (h->fd < 0)
259     goto out;
260 
261   memset (&nladdr, '\0', sizeof (nladdr));
262   nladdr.nl_family = AF_NETLINK;
263   if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
264     {
265     close_and_out:
266       __netlink_close (h);
267     out:
268       return -1;
269     }
270   /* Determine the ID the kernel assigned for this netlink connection.
271      It is not necessarily the PID if there is more than one socket
272      open.  */
273   socklen_t addr_len = sizeof (nladdr);
274   if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0)
275     goto close_and_out;
276   h->pid = nladdr.nl_pid;
277   return 0;
278 }
279 
280 
281 /* We know the number of RTM_NEWLINK entries, so we reserve the first
282    # of entries for this type. All RTM_NEWADDR entries have an index
283    pointer to the RTM_NEWLINK entry.  To find the entry, create
284    a table to map kernel index entries to our index numbers.
285    Since we get at first all RTM_NEWLINK entries, it can never happen
286    that a RTM_NEWADDR index is not known to this map.  */
287 static int
map_newlink(int index,struct ifaddrs_storage * ifas,int * map,int max)288 map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
289 {
290   int i;
291 
292   for (i = 0; i < max; i++)
293     {
294       if (map[i] == -1)
295 	{
296 	  map[i] = index;
297 	  if (i > 0)
298 	    ifas[i - 1].ifa.ifa_next = &ifas[i].ifa;
299 	  return i;
300 	}
301       else if (map[i] == index)
302 	return i;
303     }
304 
305   /* This means interfaces changed between the reading of the
306      RTM_GETLINK and RTM_GETADDR information.  We have to repeat
307      everything.  */
308   return -1;
309 }
310 
311 
312 /* Create a linked list of `struct ifaddrs' structures, one for each
313    network interface on the host machine.  If successful, store the
314    list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
315 static int
getifaddrs_internal(struct ifaddrs ** ifap)316 getifaddrs_internal (struct ifaddrs **ifap)
317 {
318   struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
319   struct netlink_res *nlp;
320   struct ifaddrs_storage *ifas;
321   unsigned int i, newlink, newaddr, newaddr_idx;
322   int *map_newlink_data;
323   size_t ifa_data_size = 0;  /* Size to allocate for all ifa_data.  */
324   char *ifa_data_ptr;	/* Pointer to the unused part of memory for
325 				ifa_data.  */
326   int result = 0;
327 
328   *ifap = NULL;
329 
330   if (__netlink_open (&nh) < 0)
331     return -1;
332 
333   /* Tell the kernel that we wish to get a list of all
334      active interfaces, collect all data for every interface.  */
335   if (__netlink_request (&nh, RTM_GETLINK) < 0)
336     {
337       result = -1;
338       goto exit_free;
339     }
340 
341   /* Now ask the kernel for all addresses which are assigned
342      to an interface and collect all data for every interface.
343      Since we store the addresses after the interfaces in the
344      list, we will later always find the interface before the
345      corresponding addresses.  */
346   ++nh.seq;
347   if (__netlink_request (&nh, RTM_GETADDR) < 0)
348     {
349       result = -1;
350       goto exit_free;
351     }
352 
353   /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
354      enough memory.  */
355   newlink = newaddr = 0;
356   for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
357     {
358       struct nlmsghdr *nlh;
359       size_t size = nlp->size;
360 
361       if (nlp->nlh == NULL)
362 	continue;
363 
364       /* Walk through all entries we got from the kernel and look, which
365 	 message type they contain.  */
366       for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
367 	{
368 	  /* Check if the message is what we want.  */
369 	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
370 	    continue;
371 
372 	  /* If the dump got interrupted, we can't rely on the results
373 	     so try again. */
374 	  if (nlh->nlmsg_flags & NLM_F_DUMP_INTR)
375 	    {
376 	      result = -EAGAIN;
377 	      goto exit_free;
378 	    }
379 
380 	  if (nlh->nlmsg_type == NLMSG_DONE)
381 	    break;		/* ok */
382 
383 	  if (nlh->nlmsg_type == RTM_NEWLINK)
384 	    {
385 	      /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
386 		 know the size before creating the list to allocate enough
387 		 memory.  */
388 	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
389 	      struct rtattr *rta = IFLA_RTA (ifim);
390 	      size_t rtasize = IFLA_PAYLOAD (nlh);
391 
392 	      while (RTA_OK (rta, rtasize))
393 		{
394 		  size_t rta_payload = RTA_PAYLOAD (rta);
395 
396 		  if (rta->rta_type == IFLA_STATS)
397 		    {
398 		      ifa_data_size += rta_payload;
399 		      break;
400 		    }
401 		  else
402 		    rta = RTA_NEXT (rta, rtasize);
403 		}
404 	      ++newlink;
405 	    }
406 	  else if (nlh->nlmsg_type == RTM_NEWADDR)
407 	    ++newaddr;
408 	}
409     }
410 
411   /* Return if no interface is up.  */
412   if ((newlink + newaddr) == 0)
413     goto exit_free;
414 
415   /* Allocate memory for all entries we have and initialize next
416      pointer.  */
417   ifas = (struct ifaddrs_storage *) calloc (1,
418 					    (newlink + newaddr)
419 					    * sizeof (struct ifaddrs_storage)
420 					    + ifa_data_size);
421   if (ifas == NULL)
422     {
423       result = -1;
424       goto exit_free;
425     }
426 
427   /* Table for mapping kernel index to entry in our list.  */
428   map_newlink_data = alloca (newlink * sizeof (int));
429   memset (map_newlink_data, '\xff', newlink * sizeof (int));
430 
431   ifa_data_ptr = (char *) &ifas[newlink + newaddr];
432   newaddr_idx = 0;		/* Counter for newaddr index.  */
433 
434   /* Walk through the list of data we got from the kernel.  */
435   for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
436     {
437       struct nlmsghdr *nlh;
438       size_t size = nlp->size;
439 
440       if (nlp->nlh == NULL)
441 	continue;
442 
443       /* Walk through one message and look at the type: If it is our
444 	 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
445 	 the end or we find the end marker (in this case we ignore the
446 	 following data.  */
447       for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
448 	{
449 	  int ifa_index = 0;
450 
451 	  /* Check if the message is the one we want */
452 	  if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
453 	    continue;
454 
455 	  if (nlh->nlmsg_type == NLMSG_DONE)
456 	    break;		/* ok */
457 
458 	  if (nlh->nlmsg_type == RTM_NEWLINK)
459 	    {
460 	      /* We found a new interface. Now extract everything from the
461 		 interface data we got and need.  */
462 	      struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
463 	      struct rtattr *rta = IFLA_RTA (ifim);
464 	      size_t rtasize = IFLA_PAYLOAD (nlh);
465 
466 	      /* Interfaces are stored in the first "newlink" entries
467 		 of our list, starting in the order as we got from the
468 		 kernel.  */
469 	      ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
470 				       map_newlink_data, newlink);
471 	      if (__glibc_unlikely (ifa_index == -1))
472 		{
473 		try_again:
474 		  result = -EAGAIN;
475 		  free (ifas);
476 		  goto exit_free;
477 		}
478 	      ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
479 
480 	      while (RTA_OK (rta, rtasize))
481 		{
482 		  char *rta_data = RTA_DATA (rta);
483 		  size_t rta_payload = RTA_PAYLOAD (rta);
484 
485 		  switch (rta->rta_type)
486 		    {
487 		    case IFLA_ADDRESS:
488 		      if (rta_payload <= sizeof (ifas[ifa_index].addr))
489 			{
490 			  ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
491 			  memcpy (ifas[ifa_index].addr.sl.sll_addr,
492 				  (char *) rta_data, rta_payload);
493 			  ifas[ifa_index].addr.sl.sll_halen = rta_payload;
494 			  ifas[ifa_index].addr.sl.sll_ifindex
495 			    = ifim->ifi_index;
496 			  ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;
497 
498 			  ifas[ifa_index].ifa.ifa_addr
499 			    = &ifas[ifa_index].addr.sa;
500 			}
501 		      break;
502 
503 		    case IFLA_BROADCAST:
504 		      if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
505 			{
506 			  ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
507 			  memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
508 				  (char *) rta_data, rta_payload);
509 			  ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
510 			  ifas[ifa_index].broadaddr.sl.sll_ifindex
511 			    = ifim->ifi_index;
512 			  ifas[ifa_index].broadaddr.sl.sll_hatype
513 			    = ifim->ifi_type;
514 
515 			  ifas[ifa_index].ifa.ifa_broadaddr
516 			    = &ifas[ifa_index].broadaddr.sa;
517 			}
518 		      break;
519 
520 		    case IFLA_IFNAME:	/* Name of Interface */
521 		      if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
522 			{
523 			  ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
524 			  *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
525 					       rta_payload) = '\0';
526 			}
527 		      break;
528 
529 		    case IFLA_STATS:	/* Statistics of Interface */
530 		      ifas[ifa_index].ifa.ifa_data = ifa_data_ptr;
531 		      ifa_data_ptr += rta_payload;
532 		      memcpy (ifas[ifa_index].ifa.ifa_data, rta_data,
533 			      rta_payload);
534 		      break;
535 
536 		    case IFLA_UNSPEC:
537 		      break;
538 		    case IFLA_MTU:
539 		      break;
540 		    case IFLA_LINK:
541 		      break;
542 		    case IFLA_QDISC:
543 		      break;
544 		    default:
545 		      break;
546 		    }
547 
548 		  rta = RTA_NEXT (rta, rtasize);
549 		}
550 	    }
551 	  else if (nlh->nlmsg_type == RTM_NEWADDR)
552 	    {
553 	      struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
554 	      struct rtattr *rta = IFA_RTA (ifam);
555 	      size_t rtasize = IFA_PAYLOAD (nlh);
556 
557 	      /* New Addresses are stored in the order we got them from
558 		 the kernel after the interfaces. Theoretically it is possible
559 		 that we have holes in the interface part of the list,
560 		 but we always have already the interface for this address.  */
561 	      ifa_index = newlink + newaddr_idx;
562 	      int idx = map_newlink (ifam->ifa_index - 1, ifas,
563 				     map_newlink_data, newlink);
564 	      if (__glibc_unlikely (idx == -1))
565 		goto try_again;
566 	      ifas[ifa_index].ifa.ifa_flags = ifas[idx].ifa.ifa_flags;
567 	      if (ifa_index > 0)
568 		ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
569 	      ++newaddr_idx;
570 
571 	      while (RTA_OK (rta, rtasize))
572 		{
573 		  char *rta_data = RTA_DATA (rta);
574 		  size_t rta_payload = RTA_PAYLOAD (rta);
575 
576 		  switch (rta->rta_type)
577 		    {
578 		    case IFA_ADDRESS:
579 		      {
580 			struct sockaddr *sa;
581 
582 			if (ifas[ifa_index].ifa.ifa_addr != NULL)
583 			  {
584 			    /* In a point-to-poing network IFA_ADDRESS
585 			       contains the destination address, local
586 			       address is supplied in IFA_LOCAL attribute.
587 			       destination address and broadcast address
588 			       are stored in an union, so it doesn't matter
589 			       which name we use.  */
590 			    ifas[ifa_index].ifa.ifa_broadaddr
591 			      = &ifas[ifa_index].broadaddr.sa;
592 			    sa = &ifas[ifa_index].broadaddr.sa;
593 			  }
594 			else
595 			  {
596 			    ifas[ifa_index].ifa.ifa_addr
597 			      = &ifas[ifa_index].addr.sa;
598 			    sa = &ifas[ifa_index].addr.sa;
599 			  }
600 
601 			sa->sa_family = ifam->ifa_family;
602 
603 			switch (ifam->ifa_family)
604 			  {
605 			  case AF_INET:
606 			    /* Size must match that of an address for IPv4.  */
607 			    if (rta_payload == 4)
608 			      memcpy (&((struct sockaddr_in *) sa)->sin_addr,
609 				      rta_data, rta_payload);
610 			    break;
611 
612 			  case AF_INET6:
613 			    /* Size must match that of an address for IPv6.  */
614 			    if (rta_payload == 16)
615 			      {
616 				memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
617 					rta_data, rta_payload);
618 				if (IN6_IS_ADDR_LINKLOCAL (rta_data)
619 				    || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
620 				  ((struct sockaddr_in6 *) sa)->sin6_scope_id
621 				    = ifam->ifa_index;
622 			      }
623 			    break;
624 
625 			  default:
626 			    if (rta_payload <= sizeof (ifas[ifa_index].addr))
627 			      memcpy (sa->sa_data, rta_data, rta_payload);
628 			    break;
629 			  }
630 		      }
631 		      break;
632 
633 		    case IFA_LOCAL:
634 		      if (ifas[ifa_index].ifa.ifa_addr != NULL)
635 			{
636 			  /* If ifa_addr is set and we get IFA_LOCAL,
637 			     assume we have a point-to-point network.
638 			     Move address to correct field.  */
639 			  ifas[ifa_index].broadaddr = ifas[ifa_index].addr;
640 			  ifas[ifa_index].ifa.ifa_broadaddr
641 			    = &ifas[ifa_index].broadaddr.sa;
642 			  memset (&ifas[ifa_index].addr, '\0',
643 				  sizeof (ifas[ifa_index].addr));
644 			}
645 
646 		      ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
647 		      ifas[ifa_index].ifa.ifa_addr->sa_family
648 			= ifam->ifa_family;
649 
650 		      switch (ifam->ifa_family)
651 			{
652 			case AF_INET:
653 			  /* Size must match that of an address for IPv4.  */
654 			  if (rta_payload == 4)
655 			    memcpy (&ifas[ifa_index].addr.s4.sin_addr,
656 				  rta_data, rta_payload);
657 			  break;
658 
659 			case AF_INET6:
660 			  /* Size must match that of an address for IPv6.  */
661 			  if (rta_payload == 16)
662 			    {
663 			      memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
664 				      rta_data, rta_payload);
665 			      if (IN6_IS_ADDR_LINKLOCAL (rta_data)
666 				  || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
667 				ifas[ifa_index].addr.s6.sin6_scope_id =
668 				  ifam->ifa_index;
669 			    }
670 			  break;
671 
672 			default:
673 			  if (rta_payload <= sizeof (ifas[ifa_index].addr))
674 			    memcpy (ifas[ifa_index].addr.sa.sa_data,
675 				    rta_data, rta_payload);
676 			  break;
677 			}
678 		      break;
679 
680 		    case IFA_BROADCAST:
681 		      /* We get IFA_BROADCAST, so IFA_LOCAL was too much.  */
682 		      if (ifas[ifa_index].ifa.ifa_broadaddr != NULL)
683 			memset (&ifas[ifa_index].broadaddr, '\0',
684 				sizeof (ifas[ifa_index].broadaddr));
685 
686 		      ifas[ifa_index].ifa.ifa_broadaddr
687 			= &ifas[ifa_index].broadaddr.sa;
688 		      ifas[ifa_index].ifa.ifa_broadaddr->sa_family
689 			= ifam->ifa_family;
690 
691 		      switch (ifam->ifa_family)
692 			{
693 			case AF_INET:
694 			  /* Size must match that of an address for IPv4.  */
695 			  if (rta_payload == 4)
696 			    memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
697 				    rta_data, rta_payload);
698 			  break;
699 
700 			case AF_INET6:
701 			  /* Size must match that of an address for IPv6.  */
702 			  if (rta_payload == 16)
703 			    {
704 			      memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
705 				      rta_data, rta_payload);
706 			      if (IN6_IS_ADDR_LINKLOCAL (rta_data)
707 				  || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
708 				ifas[ifa_index].broadaddr.s6.sin6_scope_id
709 				  = ifam->ifa_index;
710 			    }
711 			  break;
712 
713 			default:
714 			  if (rta_payload <= sizeof (ifas[ifa_index].addr))
715 			    memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
716 				    rta_data, rta_payload);
717 			  break;
718 			}
719 		      break;
720 
721 		    case IFA_LABEL:
722 		      if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
723 			{
724 			  ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
725 			  *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
726 					       rta_payload) = '\0';
727 			}
728 		      else
729 			abort ();
730 		      break;
731 
732 		    case IFA_UNSPEC:
733 		      break;
734 		    case IFA_CACHEINFO:
735 		      break;
736 		    default:
737 		      break;
738 		    }
739 
740 		  rta = RTA_NEXT (rta, rtasize);
741 		}
742 
743 	      /* If we didn't get the interface name with the
744 		 address, use the name from the interface entry.  */
745 	      if (ifas[ifa_index].ifa.ifa_name == NULL)
746 		{
747 		  int idx = map_newlink (ifam->ifa_index - 1, ifas,
748 					 map_newlink_data, newlink);
749 		  if (__glibc_unlikely (idx == -1))
750 		    goto try_again;
751 		  ifas[ifa_index].ifa.ifa_name = ifas[idx].ifa.ifa_name;
752 		}
753 
754 	      /* Calculate the netmask.  */
755 	      if (ifas[ifa_index].ifa.ifa_addr
756 		  && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC
757 		  && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET)
758 		{
759 		  uint32_t max_prefixlen = 0;
760 		  char *cp = NULL;
761 
762 		  ifas[ifa_index].ifa.ifa_netmask
763 		    = &ifas[ifa_index].netmask.sa;
764 
765 		  switch (ifas[ifa_index].ifa.ifa_addr->sa_family)
766 		    {
767 		    case AF_INET:
768 		      cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr;
769 		      max_prefixlen = 32;
770 		      break;
771 
772 		    case AF_INET6:
773 		      cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr;
774 		      max_prefixlen = 128;
775 		      break;
776 		    }
777 
778 		  ifas[ifa_index].ifa.ifa_netmask->sa_family
779 		    = ifas[ifa_index].ifa.ifa_addr->sa_family;
780 
781 		  if (cp != NULL)
782 		    {
783 		      unsigned int preflen;
784 
785 		      if (ifam->ifa_prefixlen > max_prefixlen)
786 			preflen = max_prefixlen;
787 		      else
788 			preflen = ifam->ifa_prefixlen;
789 
790 		      for (i = 0; i < preflen / 8; i++)
791 			*cp++ = 0xff;
792 		      if (preflen % 8)
793 			*cp = 0xff << (8 - preflen % 8);
794 		    }
795 		}
796 	    }
797 	}
798     }
799 
800   assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);
801 
802   if (newaddr_idx > 0)
803     {
804       for (i = 0; i < newlink; ++i)
805 	if (map_newlink_data[i] == -1)
806 	  {
807 	    /* We have fewer links then we anticipated.  Adjust the
808 	       forward pointer to the first address entry.  */
809 	    ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
810 	  }
811 
812       if (i == 0 && newlink > 0)
813 	/* No valid link, but we allocated memory.  We have to
814 	   populate the first entry.  */
815 	memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
816     }
817 
818   *ifap = &ifas[0].ifa;
819 
820  exit_free:
821   __netlink_free_handle (&nh);
822   __netlink_close (&nh);
823 
824   return result;
825 }
826 
827 
828 /* Create a linked list of `struct ifaddrs' structures, one for each
829    network interface on the host machine.  If successful, store the
830    list in *IFAP and return 0.  On errors, return -1 and set `errno'.  */
831 int
__getifaddrs(struct ifaddrs ** ifap)832 __getifaddrs (struct ifaddrs **ifap)
833 {
834   int res;
835 
836   do
837     res = getifaddrs_internal (ifap);
838   while (res == -EAGAIN);
839 
840   return res;
841 }
weak_alias(__getifaddrs,getifaddrs)842 weak_alias (__getifaddrs, getifaddrs)
843 libc_hidden_def (__getifaddrs)
844 libc_hidden_weak (getifaddrs)
845 
846 
847 void
848 __freeifaddrs (struct ifaddrs *ifa)
849 {
850   free (ifa);
851 }
852 weak_alias (__freeifaddrs, freeifaddrs)
853 libc_hidden_def (__freeifaddrs)
854 libc_hidden_weak (freeifaddrs)
855