2.9
[glibc/nacl-glibc.git] / sysdeps / unix / sysv / linux / ifaddrs.c
blob150ec8a9b02a7021d57f2d615c43365fb334d3b6
1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2003-2007, 2008 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, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <alloca.h>
21 #include <assert.h>
22 #include <errno.h>
23 #include <ifaddrs.h>
24 #include <net/if.h>
25 #include <netinet/in.h>
26 #include <netpacket/packet.h>
27 #include <stdbool.h>
28 #include <stdint.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sys/ioctl.h>
32 #include <sys/socket.h>
33 #include <sysdep.h>
34 #include <time.h>
35 #include <unistd.h>
36 #include <kernel-features.h>
38 #include "netlinkaccess.h"
41 /* We don't know if we have NETLINK support compiled in in our
42 Kernel, so include the old implementation as fallback. */
43 #if __ASSUME_NETLINK_SUPPORT == 0
44 int __no_netlink_support attribute_hidden;
46 # define getifaddrs fallback_getifaddrs
47 # include "sysdeps/gnu/ifaddrs.c"
48 # undef getifaddrs
49 #endif
52 /* There is a problem with this type. The address length for
53 Infiniband sockets is much longer than the 8 bytes allocated in the
54 sockaddr_ll definition. Hence we use here a special
55 definition. */
56 struct sockaddr_ll_max
58 unsigned short int sll_family;
59 unsigned short int sll_protocol;
60 int sll_ifindex;
61 unsigned short int sll_hatype;
62 unsigned char sll_pkttype;
63 unsigned char sll_halen;
64 unsigned char sll_addr[24];
68 /* struct to hold the data for one ifaddrs entry, so we can allocate
69 everything at once. */
70 struct ifaddrs_storage
72 struct ifaddrs ifa;
73 union
75 /* Save space for the biggest of the four used sockaddr types and
76 avoid a lot of casts. */
77 struct sockaddr sa;
78 struct sockaddr_ll_max sl;
79 struct sockaddr_in s4;
80 struct sockaddr_in6 s6;
81 } addr, netmask, broadaddr;
82 char name[IF_NAMESIZE + 1];
86 void
87 __netlink_free_handle (struct netlink_handle *h)
89 struct netlink_res *ptr;
90 int saved_errno = errno;
92 ptr = h->nlm_list;
93 while (ptr != NULL)
95 struct netlink_res *tmpptr;
97 tmpptr = ptr->next;
98 free (ptr);
99 ptr = tmpptr;
102 __set_errno (saved_errno);
106 static int
107 __netlink_sendreq (struct netlink_handle *h, int type)
109 struct req
111 struct nlmsghdr nlh;
112 struct rtgenmsg g;
113 char pad[0];
114 } req;
115 struct sockaddr_nl nladdr;
117 if (h->seq == 0)
118 h->seq = time (NULL);
120 req.nlh.nlmsg_len = sizeof (req);
121 req.nlh.nlmsg_type = type;
122 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
123 req.nlh.nlmsg_pid = 0;
124 req.nlh.nlmsg_seq = h->seq;
125 req.g.rtgen_family = AF_UNSPEC;
126 if (sizeof (req) != offsetof (struct req, pad))
127 memset (req.pad, '\0', sizeof (req) - offsetof (struct req, pad));
129 memset (&nladdr, '\0', sizeof (nladdr));
130 nladdr.nl_family = AF_NETLINK;
132 return TEMP_FAILURE_RETRY (__sendto (h->fd, (void *) &req, sizeof (req), 0,
133 (struct sockaddr *) &nladdr,
134 sizeof (nladdr)));
139 __netlink_request (struct netlink_handle *h, int type)
141 struct netlink_res *nlm_next;
142 struct sockaddr_nl nladdr;
143 struct nlmsghdr *nlmh;
144 ssize_t read_len;
145 bool done = false;
147 #ifdef PAGE_SIZE
148 /* Help the compiler optimize out the malloc call if PAGE_SIZE
149 is constant and smaller or equal to PTHREAD_STACK_MIN/4. */
150 const size_t buf_size = PAGE_SIZE;
151 #else
152 const size_t buf_size = __getpagesize ();
153 #endif
154 bool use_malloc = false;
155 char *buf;
157 if (__libc_use_alloca (buf_size))
158 buf = alloca (buf_size);
159 else
161 buf = malloc (buf_size);
162 if (buf != NULL)
163 use_malloc = true;
164 else
165 goto out_fail;
168 struct iovec iov = { buf, buf_size };
170 if (__netlink_sendreq (h, type) < 0)
171 goto out_fail;
173 while (! done)
175 struct msghdr msg =
177 (void *) &nladdr, sizeof (nladdr),
178 &iov, 1,
179 NULL, 0,
183 read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
184 if (read_len < 0)
185 goto out_fail;
187 if (nladdr.nl_pid != 0)
188 continue;
190 if (__builtin_expect (msg.msg_flags & MSG_TRUNC, 0))
191 goto out_fail;
193 size_t count = 0;
194 size_t remaining_len = read_len;
195 for (nlmh = (struct nlmsghdr *) buf;
196 NLMSG_OK (nlmh, remaining_len);
197 nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, remaining_len))
199 if ((pid_t) nlmh->nlmsg_pid != h->pid
200 || nlmh->nlmsg_seq != h->seq)
201 continue;
203 ++count;
204 if (nlmh->nlmsg_type == NLMSG_DONE)
206 /* We found the end, leave the loop. */
207 done = true;
208 break;
210 if (nlmh->nlmsg_type == NLMSG_ERROR)
212 struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh);
213 if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
214 errno = EIO;
215 else
216 errno = -nlerr->error;
217 goto out_fail;
221 /* If there was nothing with the expected nlmsg_pid and nlmsg_seq,
222 there is no point to record it. */
223 if (count == 0)
224 continue;
226 nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
227 + read_len);
228 if (nlm_next == NULL)
229 goto out_fail;
230 nlm_next->next = NULL;
231 nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
232 nlm_next->size = read_len;
233 nlm_next->seq = h->seq;
234 if (h->nlm_list == NULL)
235 h->nlm_list = nlm_next;
236 else
237 h->end_ptr->next = nlm_next;
238 h->end_ptr = nlm_next;
241 if (use_malloc)
242 free (buf);
243 return 0;
245 out_fail:
246 if (use_malloc)
247 free (buf);
248 return -1;
252 void
253 __netlink_close (struct netlink_handle *h)
255 /* Don't modify errno. */
256 INTERNAL_SYSCALL_DECL (err);
257 (void) INTERNAL_SYSCALL (close, err, 1, h->fd);
261 /* Open a NETLINK socket. */
263 __netlink_open (struct netlink_handle *h)
265 struct sockaddr_nl nladdr;
267 h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
268 if (h->fd < 0)
269 goto out;
271 memset (&nladdr, '\0', sizeof (nladdr));
272 nladdr.nl_family = AF_NETLINK;
273 if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
275 close_and_out:
276 __netlink_close (h);
277 out:
278 #if __ASSUME_NETLINK_SUPPORT == 0
279 __no_netlink_support = 1;
280 #endif
281 return -1;
283 /* Determine the ID the kernel assigned for this netlink connection.
284 It is not necessarily the PID if there is more than one socket
285 open. */
286 socklen_t addr_len = sizeof (nladdr);
287 if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0)
288 goto close_and_out;
289 h->pid = nladdr.nl_pid;
290 return 0;
294 /* We know the number of RTM_NEWLINK entries, so we reserve the first
295 # of entries for this type. All RTM_NEWADDR entries have an index
296 pointer to the RTM_NEWLINK entry. To find the entry, create
297 a table to map kernel index entries to our index numbers.
298 Since we get at first all RTM_NEWLINK entries, it can never happen
299 that a RTM_NEWADDR index is not known to this map. */
300 static int
301 internal_function
302 map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
304 int i;
306 for (i = 0; i < max; i++)
308 if (map[i] == -1)
310 map[i] = index;
311 if (i > 0)
312 ifas[i - 1].ifa.ifa_next = &ifas[i].ifa;
313 return i;
315 else if (map[i] == index)
316 return i;
318 /* This should never be reached. If this will be reached, we have
319 a very big problem. */
320 abort ();
324 /* Create a linked list of `struct ifaddrs' structures, one for each
325 network interface on the host machine. If successful, store the
326 list in *IFAP and 2004, 2005, 2006, return 0. On errors, return -1 and set `errno'. */
328 getifaddrs (struct ifaddrs **ifap)
330 struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
331 struct netlink_res *nlp;
332 struct ifaddrs_storage *ifas;
333 unsigned int i, newlink, newaddr, newaddr_idx;
334 int *map_newlink_data;
335 size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */
336 char *ifa_data_ptr; /* Pointer to the unused part of memory for
337 ifa_data. */
338 int result = 0;
340 *ifap = NULL;
342 if (! __no_netlink_support && __netlink_open (&nh) < 0)
344 #if __ASSUME_NETLINK_SUPPORT != 0
345 return -1;
346 #endif
349 #if __ASSUME_NETLINK_SUPPORT == 0
350 if (__no_netlink_support)
351 return fallback_getifaddrs (ifap);
352 #endif
354 /* Tell the kernel that we wish to get a list of all
355 active interfaces, collect all data for every interface. */
356 if (__netlink_request (&nh, RTM_GETLINK) < 0)
358 result = -1;
359 goto exit_free;
362 /* Now ask the kernel for all addresses which are assigned
363 to an interface and collect all data for every interface.
364 Since we store the addresses after the interfaces in the
365 list, we will later always find the interface before the
366 corresponding addresses. */
367 ++nh.seq;
368 if (__netlink_request (&nh, RTM_GETADDR) < 0)
370 result = -1;
371 goto exit_free;
374 /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
375 enough memory. */
376 newlink = newaddr = 0;
377 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
379 struct nlmsghdr *nlh;
380 size_t size = nlp->size;
382 if (nlp->nlh == NULL)
383 continue;
385 /* Walk through all entries we got from the kernel and look, which
386 message type they contain. */
387 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
389 /* Check if the message is what we want. */
390 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
391 continue;
393 if (nlh->nlmsg_type == NLMSG_DONE)
394 break; /* ok */
396 if (nlh->nlmsg_type == RTM_NEWLINK)
398 /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
399 know the size before creating the list to allocate enough
400 memory. */
401 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
402 struct rtattr *rta = IFLA_RTA (ifim);
403 size_t rtasize = IFLA_PAYLOAD (nlh);
405 while (RTA_OK (rta, rtasize))
407 size_t rta_payload = RTA_PAYLOAD (rta);
409 if (rta->rta_type == IFLA_STATS)
411 ifa_data_size += rta_payload;
412 break;
414 else
415 rta = RTA_NEXT (rta, rtasize);
417 ++newlink;
419 else if (nlh->nlmsg_type == RTM_NEWADDR)
420 ++newaddr;
424 /* Return if no interface is up. */
425 if ((newlink + newaddr) == 0)
426 goto exit_free;
428 /* Allocate memory for all entries we have and initialize next
429 pointer. */
430 ifas = (struct ifaddrs_storage *) calloc (1,
431 (newlink + newaddr)
432 * sizeof (struct ifaddrs_storage)
433 + ifa_data_size);
434 if (ifas == NULL)
436 result = -1;
437 goto exit_free;
440 /* Table for mapping kernel index to entry in our list. */
441 map_newlink_data = alloca (newlink * sizeof (int));
442 memset (map_newlink_data, '\xff', newlink * sizeof (int));
444 ifa_data_ptr = (char *) &ifas[newlink + newaddr];
445 newaddr_idx = 0; /* Counter for newaddr index. */
447 /* Walk through the list of data we got from the kernel. */
448 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
450 struct nlmsghdr *nlh;
451 size_t size = nlp->size;
453 if (nlp->nlh == NULL)
454 continue;
456 /* Walk through one message and look at the type: If it is our
457 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
458 the end or we find the end marker (in this case we ignore the
459 following data. */
460 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
462 int ifa_index = 0;
464 /* Check if the message is the one we want */
465 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
466 continue;
468 if (nlh->nlmsg_type == NLMSG_DONE)
469 break; /* ok */
471 if (nlh->nlmsg_type == RTM_NEWLINK)
473 /* We found a new interface. Now extract everything from the
474 interface data we got and need. */
475 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
476 struct rtattr *rta = IFLA_RTA (ifim);
477 size_t rtasize = IFLA_PAYLOAD (nlh);
479 /* Interfaces are stored in the first "newlink" entries
480 of our list, starting in the order as we got from the
481 kernel. */
482 ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
483 map_newlink_data, newlink);
484 ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
486 while (RTA_OK (rta, rtasize))
488 char *rta_data = RTA_DATA (rta);
489 size_t rta_payload = RTA_PAYLOAD (rta);
491 switch (rta->rta_type)
493 case IFLA_ADDRESS:
494 if (rta_payload <= sizeof (ifas[ifa_index].addr))
496 ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
497 memcpy (ifas[ifa_index].addr.sl.sll_addr,
498 (char *) rta_data, rta_payload);
499 ifas[ifa_index].addr.sl.sll_halen = rta_payload;
500 ifas[ifa_index].addr.sl.sll_ifindex
501 = ifim->ifi_index;
502 ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;
504 ifas[ifa_index].ifa.ifa_addr
505 = &ifas[ifa_index].addr.sa;
507 break;
509 case IFLA_BROADCAST:
510 if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
512 ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
513 memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
514 (char *) rta_data, rta_payload);
515 ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
516 ifas[ifa_index].broadaddr.sl.sll_ifindex
517 = ifim->ifi_index;
518 ifas[ifa_index].broadaddr.sl.sll_hatype
519 = ifim->ifi_type;
521 ifas[ifa_index].ifa.ifa_broadaddr
522 = &ifas[ifa_index].broadaddr.sa;
524 break;
526 case IFLA_IFNAME: /* Name of Interface */
527 if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
529 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
530 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
531 rta_payload) = '\0';
533 break;
535 case IFLA_STATS: /* Statistics of Interface */
536 ifas[ifa_index].ifa.ifa_data = ifa_data_ptr;
537 ifa_data_ptr += rta_payload;
538 memcpy (ifas[ifa_index].ifa.ifa_data, rta_data,
539 rta_payload);
540 break;
542 case IFLA_UNSPEC:
543 break;
544 case IFLA_MTU:
545 break;
546 case IFLA_LINK:
547 break;
548 case IFLA_QDISC:
549 break;
550 default:
551 break;
554 rta = RTA_NEXT (rta, rtasize);
557 else if (nlh->nlmsg_type == RTM_NEWADDR)
559 struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
560 struct rtattr *rta = IFA_RTA (ifam);
561 size_t rtasize = IFA_PAYLOAD (nlh);
563 /* New Addresses are stored in the order we got them from
564 the kernel after the interfaces. Theoretically it is possible
565 that we have holes in the interface part of the list,
566 but we always have already the interface for this address. */
567 ifa_index = newlink + newaddr_idx;
568 ifas[ifa_index].ifa.ifa_flags
569 = ifas[map_newlink (ifam->ifa_index - 1, ifas,
570 map_newlink_data, newlink)].ifa.ifa_flags;
571 if (ifa_index > 0)
572 ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
573 ++newaddr_idx;
575 while (RTA_OK (rta, rtasize))
577 char *rta_data = RTA_DATA (rta);
578 size_t rta_payload = RTA_PAYLOAD (rta);
580 switch (rta->rta_type)
582 case IFA_ADDRESS:
584 struct sockaddr *sa;
586 if (ifas[ifa_index].ifa.ifa_addr != NULL)
588 /* In a point-to-poing network IFA_ADDRESS
589 contains the destination address, local
590 address is supplied in IFA_LOCAL attribute.
591 destination address and broadcast address
592 are stored in an union, so it doesn't matter
593 which name we use. */
594 ifas[ifa_index].ifa.ifa_broadaddr
595 = &ifas[ifa_index].broadaddr.sa;
596 sa = &ifas[ifa_index].broadaddr.sa;
598 else
600 ifas[ifa_index].ifa.ifa_addr
601 = &ifas[ifa_index].addr.sa;
602 sa = &ifas[ifa_index].addr.sa;
605 sa->sa_family = ifam->ifa_family;
607 switch (ifam->ifa_family)
609 case AF_INET:
610 /* Size must match that of an address for IPv4. */
611 if (rta_payload == 4)
612 memcpy (&((struct sockaddr_in *) sa)->sin_addr,
613 rta_data, rta_payload);
614 break;
616 case AF_INET6:
617 /* Size must match that of an address for IPv6. */
618 if (rta_payload == 16)
620 memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
621 rta_data, rta_payload);
622 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
623 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
624 ((struct sockaddr_in6 *) sa)->sin6_scope_id
625 = ifam->ifa_index;
627 break;
629 default:
630 if (rta_payload <= sizeof (ifas[ifa_index].addr))
631 memcpy (sa->sa_data, rta_data, rta_payload);
632 break;
635 break;
637 case IFA_LOCAL:
638 if (ifas[ifa_index].ifa.ifa_addr != NULL)
640 /* If ifa_addr is set and we get IFA_LOCAL,
641 assume we have a point-to-point network.
642 Move address to correct field. */
643 ifas[ifa_index].broadaddr = ifas[ifa_index].addr;
644 ifas[ifa_index].ifa.ifa_broadaddr
645 = &ifas[ifa_index].broadaddr.sa;
646 memset (&ifas[ifa_index].addr, '\0',
647 sizeof (ifas[ifa_index].addr));
650 ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
651 ifas[ifa_index].ifa.ifa_addr->sa_family
652 = ifam->ifa_family;
654 switch (ifam->ifa_family)
656 case AF_INET:
657 /* Size must match that of an address for IPv4. */
658 if (rta_payload == 4)
659 memcpy (&ifas[ifa_index].addr.s4.sin_addr,
660 rta_data, rta_payload);
661 break;
663 case AF_INET6:
664 /* Size must match that of an address for IPv6. */
665 if (rta_payload == 16)
667 memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
668 rta_data, rta_payload);
669 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
670 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
671 ifas[ifa_index].addr.s6.sin6_scope_id =
672 ifam->ifa_index;
674 break;
676 default:
677 if (rta_payload <= sizeof (ifas[ifa_index].addr))
678 memcpy (ifas[ifa_index].addr.sa.sa_data,
679 rta_data, rta_payload);
680 break;
682 break;
684 case IFA_BROADCAST:
685 /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */
686 if (ifas[ifa_index].ifa.ifa_broadaddr != NULL)
687 memset (&ifas[ifa_index].broadaddr, '\0',
688 sizeof (ifas[ifa_index].broadaddr));
690 ifas[ifa_index].ifa.ifa_broadaddr
691 = &ifas[ifa_index].broadaddr.sa;
692 ifas[ifa_index].ifa.ifa_broadaddr->sa_family
693 = ifam->ifa_family;
695 switch (ifam->ifa_family)
697 case AF_INET:
698 /* Size must match that of an address for IPv4. */
699 if (rta_payload == 4)
700 memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
701 rta_data, rta_payload);
702 break;
704 case AF_INET6:
705 /* Size must match that of an address for IPv6. */
706 if (rta_payload == 16)
708 memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
709 rta_data, rta_payload);
710 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
711 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
712 ifas[ifa_index].broadaddr.s6.sin6_scope_id
713 = ifam->ifa_index;
715 break;
717 default:
718 if (rta_payload <= sizeof (ifas[ifa_index].addr))
719 memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
720 rta_data, rta_payload);
721 break;
723 break;
725 case IFA_LABEL:
726 if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
728 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
729 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
730 rta_payload) = '\0';
732 else
733 abort ();
734 break;
736 case IFA_UNSPEC:
737 break;
738 case IFA_CACHEINFO:
739 break;
740 default:
741 break;
744 rta = RTA_NEXT (rta, rtasize);
747 /* If we didn't get the interface name with the
748 address, use the name from the interface entry. */
749 if (ifas[ifa_index].ifa.ifa_name == NULL)
750 ifas[ifa_index].ifa.ifa_name
751 = ifas[map_newlink (ifam->ifa_index - 1, ifas,
752 map_newlink_data, newlink)].ifa.ifa_name;
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)
759 uint32_t max_prefixlen = 0;
760 char *cp = NULL;
762 ifas[ifa_index].ifa.ifa_netmask
763 = &ifas[ifa_index].netmask.sa;
765 switch (ifas[ifa_index].ifa.ifa_addr->sa_family)
767 case AF_INET:
768 cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr;
769 max_prefixlen = 32;
770 break;
772 case AF_INET6:
773 cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr;
774 max_prefixlen = 128;
775 break;
778 ifas[ifa_index].ifa.ifa_netmask->sa_family
779 = ifas[ifa_index].ifa.ifa_addr->sa_family;
781 if (cp != NULL)
783 char c;
784 unsigned int preflen;
786 if ((max_prefixlen > 0) &&
787 (ifam->ifa_prefixlen > max_prefixlen))
788 preflen = max_prefixlen;
789 else
790 preflen = ifam->ifa_prefixlen;
792 for (i = 0; i < (preflen / 8); i++)
793 *cp++ = 0xff;
794 c = 0xff;
795 c <<= (8 - (preflen % 8));
796 *cp = c;
803 assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);
805 if (newaddr_idx > 0)
807 for (i = 0; i < newlink; ++i)
808 if (map_newlink_data[i] == -1)
810 /* We have fewer links then we anticipated. Adjust the
811 forward pointer to the first address entry. */
812 ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
815 if (i == 0 && newlink > 0)
816 /* No valid link, but we allocated memory. We have to
817 populate the first entry. */
818 memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
821 *ifap = &ifas[0].ifa;
823 exit_free:
824 __netlink_free_handle (&nh);
825 __netlink_close (&nh);
827 return result;
829 libc_hidden_def (getifaddrs)
832 #if __ASSUME_NETLINK_SUPPORT != 0
833 void
834 freeifaddrs (struct ifaddrs *ifa)
836 free (ifa);
838 libc_hidden_def (freeifaddrs)
839 #endif