Replace FSF snail mail address with URLs.
[glibc.git] / sysdeps / unix / sysv / linux / ifaddrs.c
blob51836b0dcd442d6108845104612267fdff51c180
1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2003-2008, 2009, 2010, 2011 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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 <http://www.gnu.org/licenses/>. */
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 #include <kernel-features.h>
37 #include "netlinkaccess.h"
40 /* We don't know if we have NETLINK support compiled into our
41 Kernel, so include the old implementation as fallback. */
42 #if __ASSUME_NETLINK_SUPPORT == 0
43 int __no_netlink_support attribute_hidden;
45 # define getifaddrs fallback_getifaddrs
46 # include "sysdeps/gnu/ifaddrs.c"
47 # undef getifaddrs
48 #endif
51 /* There is a problem with this type. The address length for
52 Infiniband sockets is much longer than the 8 bytes allocated in the
53 sockaddr_ll definition. Hence we use here a special
54 definition. */
55 struct sockaddr_ll_max
57 unsigned short int sll_family;
58 unsigned short int sll_protocol;
59 int sll_ifindex;
60 unsigned short int sll_hatype;
61 unsigned char sll_pkttype;
62 unsigned char sll_halen;
63 unsigned char sll_addr[24];
67 /* struct to hold the data for one ifaddrs entry, so we can allocate
68 everything at once. */
69 struct ifaddrs_storage
71 struct ifaddrs ifa;
72 union
74 /* Save space for the biggest of the four used sockaddr types and
75 avoid a lot of casts. */
76 struct sockaddr sa;
77 struct sockaddr_ll_max sl;
78 struct sockaddr_in s4;
79 struct sockaddr_in6 s6;
80 } addr, netmask, broadaddr;
81 char name[IF_NAMESIZE + 1];
85 void
86 __netlink_free_handle (struct netlink_handle *h)
88 struct netlink_res *ptr;
89 int saved_errno = errno;
91 ptr = h->nlm_list;
92 while (ptr != NULL)
94 struct netlink_res *tmpptr;
96 tmpptr = ptr->next;
97 free (ptr);
98 ptr = tmpptr;
101 __set_errno (saved_errno);
105 static int
106 __netlink_sendreq (struct netlink_handle *h, int type)
108 struct req
110 struct nlmsghdr nlh;
111 struct rtgenmsg g;
112 char pad[0];
113 } req;
114 struct sockaddr_nl nladdr;
116 if (h->seq == 0)
117 h->seq = time (NULL);
119 req.nlh.nlmsg_len = sizeof (req);
120 req.nlh.nlmsg_type = type;
121 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
122 req.nlh.nlmsg_pid = 0;
123 req.nlh.nlmsg_seq = h->seq;
124 req.g.rtgen_family = AF_UNSPEC;
125 if (sizeof (req) != offsetof (struct req, pad))
126 memset (req.pad, '\0', sizeof (req) - offsetof (struct req, pad));
128 memset (&nladdr, '\0', sizeof (nladdr));
129 nladdr.nl_family = AF_NETLINK;
131 return TEMP_FAILURE_RETRY (__sendto (h->fd, (void *) &req, sizeof (req), 0,
132 (struct sockaddr *) &nladdr,
133 sizeof (nladdr)));
138 __netlink_request (struct netlink_handle *h, int type)
140 struct netlink_res *nlm_next;
141 struct sockaddr_nl nladdr;
142 struct nlmsghdr *nlmh;
143 ssize_t read_len;
144 bool done = false;
146 #ifdef PAGE_SIZE
147 /* Help the compiler optimize out the malloc call if PAGE_SIZE
148 is constant and smaller or equal to PTHREAD_STACK_MIN/4. */
149 const size_t buf_size = PAGE_SIZE;
150 #else
151 const size_t buf_size = __getpagesize ();
152 #endif
153 bool use_malloc = false;
154 char *buf;
156 if (__libc_use_alloca (buf_size))
157 buf = alloca (buf_size);
158 else
160 buf = malloc (buf_size);
161 if (buf != NULL)
162 use_malloc = true;
163 else
164 goto out_fail;
167 struct iovec iov = { buf, buf_size };
169 if (__netlink_sendreq (h, type) < 0)
170 goto out_fail;
172 while (! done)
174 struct msghdr msg =
176 (void *) &nladdr, sizeof (nladdr),
177 &iov, 1,
178 NULL, 0,
182 read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
183 if (read_len < 0)
184 goto out_fail;
186 if (nladdr.nl_pid != 0)
187 continue;
189 if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
190 goto out_fail;
192 size_t count = 0;
193 size_t remaining_len = read_len;
194 for (nlmh = (struct nlmsghdr *) buf;
195 NLMSG_OK (nlmh, remaining_len);
196 nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len))
198 if ((pid_t) nlmh->nlmsg_pid != h->pid
199 || nlmh->nlmsg_seq != h->seq)
200 continue;
202 ++count;
203 if (nlmh->nlmsg_type == NLMSG_DONE)
205 /* We found the end, leave the loop. */
206 done = true;
207 break;
209 if (nlmh->nlmsg_type == NLMSG_ERROR)
211 struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh);
212 if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
213 errno = EIO;
214 else
215 errno = -nlerr->error;
216 goto out_fail;
220 /* If there was nothing with the expected nlmsg_pid and nlmsg_seq,
221 there is no point to record it. */
222 if (count == 0)
223 continue;
225 nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
226 + read_len);
227 if (nlm_next == NULL)
228 goto out_fail;
229 nlm_next->next = NULL;
230 nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
231 nlm_next->size = read_len;
232 nlm_next->seq = h->seq;
233 if (h->nlm_list == NULL)
234 h->nlm_list = nlm_next;
235 else
236 h->end_ptr->next = nlm_next;
237 h->end_ptr = nlm_next;
240 if (use_malloc)
241 free (buf);
242 return 0;
244 out_fail:
245 if (use_malloc)
246 free (buf);
247 return -1;
251 void
252 __netlink_close (struct netlink_handle *h)
254 /* Don't modify errno. */
255 INTERNAL_SYSCALL_DECL (err);
256 (void) INTERNAL_SYSCALL (close, err, 1, h->fd);
260 /* Open a NETLINK socket. */
262 __netlink_open (struct netlink_handle *h)
264 struct sockaddr_nl nladdr;
266 h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
267 if (h->fd < 0)
268 goto out;
270 memset (&nladdr, '\0', sizeof (nladdr));
271 nladdr.nl_family = AF_NETLINK;
272 if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
274 close_and_out:
275 __netlink_close (h);
276 out:
277 #if __ASSUME_NETLINK_SUPPORT == 0
278 __no_netlink_support = 1;
279 #endif
280 return -1;
282 /* Determine the ID the kernel assigned for this netlink connection.
283 It is not necessarily the PID if there is more than one socket
284 open. */
285 socklen_t addr_len = sizeof (nladdr);
286 if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0)
287 goto close_and_out;
288 h->pid = nladdr.nl_pid;
289 return 0;
293 /* We know the number of RTM_NEWLINK entries, so we reserve the first
294 # of entries for this type. All RTM_NEWADDR entries have an index
295 pointer to the RTM_NEWLINK entry. To find the entry, create
296 a table to map kernel index entries to our index numbers.
297 Since we get at first all RTM_NEWLINK entries, it can never happen
298 that a RTM_NEWADDR index is not known to this map. */
299 static int
300 internal_function
301 map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
303 int i;
305 for (i = 0; i < max; i++)
307 if (map[i] == -1)
309 map[i] = index;
310 if (i > 0)
311 ifas[i - 1].ifa.ifa_next = &ifas[i].ifa;
312 return i;
314 else if (map[i] == index)
315 return i;
318 /* This means interfaces changed inbetween the reading of the
319 RTM_GETLINK and RTM_GETADDR information. We have to repeat
320 everything. */
321 return -1;
325 /* Create a linked list of `struct ifaddrs' structures, one for each
326 network interface on the host machine. If successful, store the
327 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
328 static int
329 getifaddrs_internal (struct ifaddrs **ifap)
331 struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
332 struct netlink_res *nlp;
333 struct ifaddrs_storage *ifas;
334 unsigned int i, newlink, newaddr, newaddr_idx;
335 int *map_newlink_data;
336 size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */
337 char *ifa_data_ptr; /* Pointer to the unused part of memory for
338 ifa_data. */
339 int result = 0;
341 *ifap = NULL;
343 if (! __no_netlink_support && __netlink_open (&nh) < 0)
345 #if __ASSUME_NETLINK_SUPPORT != 0
346 return -1;
347 #endif
350 #if __ASSUME_NETLINK_SUPPORT == 0
351 if (__no_netlink_support)
352 return fallback_getifaddrs (ifap);
353 #endif
355 /* Tell the kernel that we wish to get a list of all
356 active interfaces, collect all data for every interface. */
357 if (__netlink_request (&nh, RTM_GETLINK) < 0)
359 result = -1;
360 goto exit_free;
363 /* Now ask the kernel for all addresses which are assigned
364 to an interface and collect all data for every interface.
365 Since we store the addresses after the interfaces in the
366 list, we will later always find the interface before the
367 corresponding addresses. */
368 ++nh.seq;
369 if (__netlink_request (&nh, RTM_GETADDR) < 0)
371 result = -1;
372 goto exit_free;
375 /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
376 enough memory. */
377 newlink = newaddr = 0;
378 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
380 struct nlmsghdr *nlh;
381 size_t size = nlp->size;
383 if (nlp->nlh == NULL)
384 continue;
386 /* Walk through all entries we got from the kernel and look, which
387 message type they contain. */
388 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
390 /* Check if the message is what we want. */
391 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
392 continue;
394 if (nlh->nlmsg_type == NLMSG_DONE)
395 break; /* ok */
397 if (nlh->nlmsg_type == RTM_NEWLINK)
399 /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
400 know the size before creating the list to allocate enough
401 memory. */
402 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
403 struct rtattr *rta = IFLA_RTA (ifim);
404 size_t rtasize = IFLA_PAYLOAD (nlh);
406 while (RTA_OK (rta, rtasize))
408 size_t rta_payload = RTA_PAYLOAD (rta);
410 if (rta->rta_type == IFLA_STATS)
412 ifa_data_size += rta_payload;
413 break;
415 else
416 rta = RTA_NEXT (rta, rtasize);
418 ++newlink;
420 else if (nlh->nlmsg_type == RTM_NEWADDR)
421 ++newaddr;
425 /* Return if no interface is up. */
426 if ((newlink + newaddr) == 0)
427 goto exit_free;
429 /* Allocate memory for all entries we have and initialize next
430 pointer. */
431 ifas = (struct ifaddrs_storage *) calloc (1,
432 (newlink + newaddr)
433 * sizeof (struct ifaddrs_storage)
434 + ifa_data_size);
435 if (ifas == NULL)
437 result = -1;
438 goto exit_free;
441 /* Table for mapping kernel index to entry in our list. */
442 map_newlink_data = alloca (newlink * sizeof (int));
443 memset (map_newlink_data, '\xff', newlink * sizeof (int));
445 ifa_data_ptr = (char *) &ifas[newlink + newaddr];
446 newaddr_idx = 0; /* Counter for newaddr index. */
448 /* Walk through the list of data we got from the kernel. */
449 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
451 struct nlmsghdr *nlh;
452 size_t size = nlp->size;
454 if (nlp->nlh == NULL)
455 continue;
457 /* Walk through one message and look at the type: If it is our
458 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
459 the end or we find the end marker (in this case we ignore the
460 following data. */
461 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
463 int ifa_index = 0;
465 /* Check if the message is the one we want */
466 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
467 continue;
469 if (nlh->nlmsg_type == NLMSG_DONE)
470 break; /* ok */
472 if (nlh->nlmsg_type == RTM_NEWLINK)
474 /* We found a new interface. Now extract everything from the
475 interface data we got and need. */
476 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
477 struct rtattr *rta = IFLA_RTA (ifim);
478 size_t rtasize = IFLA_PAYLOAD (nlh);
480 /* Interfaces are stored in the first "newlink" entries
481 of our list, starting in the order as we got from the
482 kernel. */
483 ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
484 map_newlink_data, newlink);
485 if (__builtin_expect (ifa_index == -1, 0))
487 try_again:
488 result = -EAGAIN;
489 free (ifas);
490 goto exit_free;
492 ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
494 while (RTA_OK (rta, rtasize))
496 char *rta_data = RTA_DATA (rta);
497 size_t rta_payload = RTA_PAYLOAD (rta);
499 switch (rta->rta_type)
501 case IFLA_ADDRESS:
502 if (rta_payload <= sizeof (ifas[ifa_index].addr))
504 ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
505 memcpy (ifas[ifa_index].addr.sl.sll_addr,
506 (char *) rta_data, rta_payload);
507 ifas[ifa_index].addr.sl.sll_halen = rta_payload;
508 ifas[ifa_index].addr.sl.sll_ifindex
509 = ifim->ifi_index;
510 ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;
512 ifas[ifa_index].ifa.ifa_addr
513 = &ifas[ifa_index].addr.sa;
515 break;
517 case IFLA_BROADCAST:
518 if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
520 ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
521 memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
522 (char *) rta_data, rta_payload);
523 ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
524 ifas[ifa_index].broadaddr.sl.sll_ifindex
525 = ifim->ifi_index;
526 ifas[ifa_index].broadaddr.sl.sll_hatype
527 = ifim->ifi_type;
529 ifas[ifa_index].ifa.ifa_broadaddr
530 = &ifas[ifa_index].broadaddr.sa;
532 break;
534 case IFLA_IFNAME: /* Name of Interface */
535 if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
537 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
538 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
539 rta_payload) = '\0';
541 break;
543 case IFLA_STATS: /* Statistics of Interface */
544 ifas[ifa_index].ifa.ifa_data = ifa_data_ptr;
545 ifa_data_ptr += rta_payload;
546 memcpy (ifas[ifa_index].ifa.ifa_data, rta_data,
547 rta_payload);
548 break;
550 case IFLA_UNSPEC:
551 break;
552 case IFLA_MTU:
553 break;
554 case IFLA_LINK:
555 break;
556 case IFLA_QDISC:
557 break;
558 default:
559 break;
562 rta = RTA_NEXT (rta, rtasize);
565 else if (nlh->nlmsg_type == RTM_NEWADDR)
567 struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
568 struct rtattr *rta = IFA_RTA (ifam);
569 size_t rtasize = IFA_PAYLOAD (nlh);
571 /* New Addresses are stored in the order we got them from
572 the kernel after the interfaces. Theoretically it is possible
573 that we have holes in the interface part of the list,
574 but we always have already the interface for this address. */
575 ifa_index = newlink + newaddr_idx;
576 int idx = map_newlink (ifam->ifa_index - 1, ifas,
577 map_newlink_data, newlink);
578 if (__builtin_expect (idx == -1, 0))
579 goto try_again;
580 ifas[ifa_index].ifa.ifa_flags = ifas[idx].ifa.ifa_flags;
581 if (ifa_index > 0)
582 ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
583 ++newaddr_idx;
585 while (RTA_OK (rta, rtasize))
587 char *rta_data = RTA_DATA (rta);
588 size_t rta_payload = RTA_PAYLOAD (rta);
590 switch (rta->rta_type)
592 case IFA_ADDRESS:
594 struct sockaddr *sa;
596 if (ifas[ifa_index].ifa.ifa_addr != NULL)
598 /* In a point-to-poing network IFA_ADDRESS
599 contains the destination address, local
600 address is supplied in IFA_LOCAL attribute.
601 destination address and broadcast address
602 are stored in an union, so it doesn't matter
603 which name we use. */
604 ifas[ifa_index].ifa.ifa_broadaddr
605 = &ifas[ifa_index].broadaddr.sa;
606 sa = &ifas[ifa_index].broadaddr.sa;
608 else
610 ifas[ifa_index].ifa.ifa_addr
611 = &ifas[ifa_index].addr.sa;
612 sa = &ifas[ifa_index].addr.sa;
615 sa->sa_family = ifam->ifa_family;
617 switch (ifam->ifa_family)
619 case AF_INET:
620 /* Size must match that of an address for IPv4. */
621 if (rta_payload == 4)
622 memcpy (&((struct sockaddr_in *) sa)->sin_addr,
623 rta_data, rta_payload);
624 break;
626 case AF_INET6:
627 /* Size must match that of an address for IPv6. */
628 if (rta_payload == 16)
630 memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
631 rta_data, rta_payload);
632 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
633 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
634 ((struct sockaddr_in6 *) sa)->sin6_scope_id
635 = ifam->ifa_index;
637 break;
639 default:
640 if (rta_payload <= sizeof (ifas[ifa_index].addr))
641 memcpy (sa->sa_data, rta_data, rta_payload);
642 break;
645 break;
647 case IFA_LOCAL:
648 if (ifas[ifa_index].ifa.ifa_addr != NULL)
650 /* If ifa_addr is set and we get IFA_LOCAL,
651 assume we have a point-to-point network.
652 Move address to correct field. */
653 ifas[ifa_index].broadaddr = ifas[ifa_index].addr;
654 ifas[ifa_index].ifa.ifa_broadaddr
655 = &ifas[ifa_index].broadaddr.sa;
656 memset (&ifas[ifa_index].addr, '\0',
657 sizeof (ifas[ifa_index].addr));
660 ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
661 ifas[ifa_index].ifa.ifa_addr->sa_family
662 = ifam->ifa_family;
664 switch (ifam->ifa_family)
666 case AF_INET:
667 /* Size must match that of an address for IPv4. */
668 if (rta_payload == 4)
669 memcpy (&ifas[ifa_index].addr.s4.sin_addr,
670 rta_data, rta_payload);
671 break;
673 case AF_INET6:
674 /* Size must match that of an address for IPv6. */
675 if (rta_payload == 16)
677 memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
678 rta_data, rta_payload);
679 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
680 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
681 ifas[ifa_index].addr.s6.sin6_scope_id =
682 ifam->ifa_index;
684 break;
686 default:
687 if (rta_payload <= sizeof (ifas[ifa_index].addr))
688 memcpy (ifas[ifa_index].addr.sa.sa_data,
689 rta_data, rta_payload);
690 break;
692 break;
694 case IFA_BROADCAST:
695 /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */
696 if (ifas[ifa_index].ifa.ifa_broadaddr != NULL)
697 memset (&ifas[ifa_index].broadaddr, '\0',
698 sizeof (ifas[ifa_index].broadaddr));
700 ifas[ifa_index].ifa.ifa_broadaddr
701 = &ifas[ifa_index].broadaddr.sa;
702 ifas[ifa_index].ifa.ifa_broadaddr->sa_family
703 = ifam->ifa_family;
705 switch (ifam->ifa_family)
707 case AF_INET:
708 /* Size must match that of an address for IPv4. */
709 if (rta_payload == 4)
710 memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
711 rta_data, rta_payload);
712 break;
714 case AF_INET6:
715 /* Size must match that of an address for IPv6. */
716 if (rta_payload == 16)
718 memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
719 rta_data, rta_payload);
720 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
721 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
722 ifas[ifa_index].broadaddr.s6.sin6_scope_id
723 = ifam->ifa_index;
725 break;
727 default:
728 if (rta_payload <= sizeof (ifas[ifa_index].addr))
729 memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
730 rta_data, rta_payload);
731 break;
733 break;
735 case IFA_LABEL:
736 if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
738 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
739 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
740 rta_payload) = '\0';
742 else
743 abort ();
744 break;
746 case IFA_UNSPEC:
747 break;
748 case IFA_CACHEINFO:
749 break;
750 default:
751 break;
754 rta = RTA_NEXT (rta, rtasize);
757 /* If we didn't get the interface name with the
758 address, use the name from the interface entry. */
759 if (ifas[ifa_index].ifa.ifa_name == NULL)
761 int idx = map_newlink (ifam->ifa_index - 1, ifas,
762 map_newlink_data, newlink);
763 if (__builtin_expect (idx == -1, 0))
764 goto try_again;
765 ifas[ifa_index].ifa.ifa_name = ifas[idx].ifa.ifa_name;
768 /* Calculate the netmask. */
769 if (ifas[ifa_index].ifa.ifa_addr
770 && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC
771 && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET)
773 uint32_t max_prefixlen = 0;
774 char *cp = NULL;
776 ifas[ifa_index].ifa.ifa_netmask
777 = &ifas[ifa_index].netmask.sa;
779 switch (ifas[ifa_index].ifa.ifa_addr->sa_family)
781 case AF_INET:
782 cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr;
783 max_prefixlen = 32;
784 break;
786 case AF_INET6:
787 cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr;
788 max_prefixlen = 128;
789 break;
792 ifas[ifa_index].ifa.ifa_netmask->sa_family
793 = ifas[ifa_index].ifa.ifa_addr->sa_family;
795 if (cp != NULL)
797 char c;
798 unsigned int preflen;
800 if ((max_prefixlen > 0) &&
801 (ifam->ifa_prefixlen > max_prefixlen))
802 preflen = max_prefixlen;
803 else
804 preflen = ifam->ifa_prefixlen;
806 for (i = 0; i < (preflen / 8); i++)
807 *cp++ = 0xff;
808 c = 0xff;
809 c <<= (8 - (preflen % 8));
810 *cp = c;
817 assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);
819 if (newaddr_idx > 0)
821 for (i = 0; i < newlink; ++i)
822 if (map_newlink_data[i] == -1)
824 /* We have fewer links then we anticipated. Adjust the
825 forward pointer to the first address entry. */
826 ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
829 if (i == 0 && newlink > 0)
830 /* No valid link, but we allocated memory. We have to
831 populate the first entry. */
832 memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
835 *ifap = &ifas[0].ifa;
837 exit_free:
838 __netlink_free_handle (&nh);
839 __netlink_close (&nh);
841 return result;
845 /* Create a linked list of `struct ifaddrs' structures, one for each
846 network interface on the host machine. If successful, store the
847 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
849 getifaddrs (struct ifaddrs **ifap)
851 int res;
854 res = getifaddrs_internal (ifap);
855 while (res == -EAGAIN);
857 return res;
859 libc_hidden_def (getifaddrs)
862 #if __ASSUME_NETLINK_SUPPORT != 0
863 void
864 freeifaddrs (struct ifaddrs *ifa)
866 free (ifa);
868 libc_hidden_def (freeifaddrs)
869 #endif