(CFLAGS-tst-align.c): Add -mpreferred-stack-boundary=4.
[glibc.git] / sysdeps / unix / sysv / linux / ifaddrs.c
blob8a052e212db41e0513c08d87a9ce5d866e756a82
1 /* getifaddrs -- get names and addresses of all network interfaces
2 Copyright (C) 2003, 2004 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 <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 <stdlib.h>
28 #include <string.h>
29 #include <sys/ioctl.h>
30 #include <sys/socket.h>
31 #include <sysdep.h>
32 #include <time.h>
33 #include <unistd.h>
35 #include "netlinkaccess.h"
38 /* We don't know if we have NETLINK support compiled in in our
39 Kernel, so include the old implementation as fallback. */
40 #if __ASSUME_NETLINK_SUPPORT == 0
41 int __no_netlink_support attribute_hidden;
43 # define getifaddrs fallback_getifaddrs
44 # include "sysdeps/gnu/ifaddrs.c"
45 # undef getifaddrs
46 #endif
49 /* struct to hold the data for one ifaddrs entry, so we can allocate
50 everything at once. */
51 struct ifaddrs_storage
53 struct ifaddrs ifa;
54 union
56 /* Save space for the biggest of the four used sockaddr types and
57 avoid a lot of casts. */
58 struct sockaddr sa;
59 struct sockaddr_ll sl;
60 struct sockaddr_in s4;
61 struct sockaddr_in6 s6;
62 } addr, netmask, broadaddr;
63 char name[IF_NAMESIZE + 1];
67 void
68 __netlink_free_handle (struct netlink_handle *h)
70 struct netlink_res *ptr;
71 int saved_errno = errno;
73 ptr = h->nlm_list;
74 while (ptr != NULL)
76 struct netlink_res *tmpptr;
78 tmpptr = ptr->next;
79 free (ptr);
80 ptr = tmpptr;
83 __set_errno (saved_errno);
87 int
88 __netlink_sendreq (struct netlink_handle *h, int type)
90 struct
92 struct nlmsghdr nlh;
93 struct rtgenmsg g;
94 } req;
95 struct sockaddr_nl nladdr;
97 if (h->seq == 0)
98 h->seq = time (NULL);
100 req.nlh.nlmsg_len = sizeof (req);
101 req.nlh.nlmsg_type = type;
102 req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
103 req.nlh.nlmsg_pid = 0;
104 req.nlh.nlmsg_seq = h->seq;
105 req.g.rtgen_family = AF_UNSPEC;
107 memset (&nladdr, '\0', sizeof (nladdr));
108 nladdr.nl_family = AF_NETLINK;
110 return TEMP_FAILURE_RETRY (__sendto (h->fd, (void *) &req, sizeof (req), 0,
111 (struct sockaddr *) &nladdr,
112 sizeof (nladdr)));
117 __netlink_receive (struct netlink_handle *h)
119 struct netlink_res *nlm_next;
120 char buf[4096];
121 struct iovec iov = { buf, sizeof (buf) };
122 struct sockaddr_nl nladdr;
123 struct nlmsghdr *nlmh;
124 int read_len;
125 bool done = false;
127 while (! done)
129 struct msghdr msg =
131 (void *) &nladdr, sizeof (nladdr),
132 &iov, 1,
133 NULL, 0,
137 read_len = TEMP_FAILURE_RETRY (__recvmsg (h->fd, &msg, 0));
138 if (read_len < 0)
139 return -1;
141 if (msg.msg_flags & MSG_TRUNC)
142 return -1;
144 nlm_next = (struct netlink_res *) malloc (sizeof (struct netlink_res)
145 + read_len);
146 if (nlm_next == NULL)
147 return -1;
148 nlm_next->next = NULL;
149 nlm_next->nlh = memcpy (nlm_next + 1, buf, read_len);
150 nlm_next->size = read_len;
151 nlm_next->seq = h->seq;
152 if (h->nlm_list == NULL)
153 h->nlm_list = nlm_next;
154 else
155 h->end_ptr->next = nlm_next;
156 h->end_ptr = nlm_next;
158 for (nlmh = (struct nlmsghdr *) buf;
159 NLMSG_OK (nlmh, (size_t) read_len);
160 nlmh = (struct nlmsghdr *) NLMSG_NEXT (nlmh, read_len))
162 if (nladdr.nl_pid != 0 || (pid_t) nlmh->nlmsg_pid != h->pid
163 || nlmh->nlmsg_seq != h->seq)
164 continue;
166 if (nlmh->nlmsg_type == NLMSG_DONE)
168 /* We found the end, leave the loop. */
169 done = true;
170 break;
172 if (nlmh->nlmsg_type == NLMSG_ERROR)
174 struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nlmh);
175 if (nlmh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
176 errno = EIO;
177 else
178 errno = -nlerr->error;
179 return -1;
183 return 0;
187 void
188 __netlink_close (struct netlink_handle *h)
190 /* Don't modify errno. */
191 INTERNAL_SYSCALL_DECL (err);
192 (void) INTERNAL_SYSCALL (close, err, 1, h->fd);
196 /* Open a NETLINK socket. */
198 __netlink_open (struct netlink_handle *h)
200 struct sockaddr_nl nladdr;
202 h->fd = __socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
203 if (h->fd < 0)
204 goto out;
206 memset (&nladdr, '\0', sizeof (nladdr));
207 nladdr.nl_family = AF_NETLINK;
208 if (__bind (h->fd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
210 close_and_out:
211 __netlink_close (h);
212 out:
213 #if __ASSUME_NETLINK_SUPPORT == 0
214 __no_netlink_support = 1;
215 #endif
216 return -1;
218 /* Determine the ID the kernel assigned for this netlink connection.
219 It is not necessarily the PID if there is more than one socket
220 open. */
221 socklen_t addr_len = sizeof (nladdr);
222 if (__getsockname (h->fd, (struct sockaddr *) &nladdr, &addr_len) < 0)
223 goto close_and_out;
224 h->pid = nladdr.nl_pid;
225 return 0;
229 /* We know the number of RTM_NEWLINK entries, so we reserve the first
230 # of entries for this type. All RTM_NEWADDR entries have an index
231 pointer to the RTM_NEWLINK entry. To find the entry, create
232 a table to map kernel index entries to our index numbers.
233 Since we get at first all RTM_NEWLINK entries, it can never happen
234 that a RTM_NEWADDR index is not known to this map. */
235 static int
236 internal_function
237 map_newlink (int index, struct ifaddrs_storage *ifas, int *map, int max)
239 int i;
241 for (i = 0; i < max; i++)
243 if (map[i] == -1)
245 map[i] = index;
246 if (i > 0)
247 ifas[i - 1].ifa.ifa_next = &ifas[i].ifa;
248 return i;
250 else if (map[i] == index)
251 return i;
253 /* This should never be reached. If this will be reached, we have
254 a very big problem. */
255 abort ();
259 /* Create a linked list of `struct ifaddrs' structures, one for each
260 network interface on the host machine. If successful, store the
261 list in *IFAP and return 0. On errors, return -1 and set `errno'. */
263 getifaddrs (struct ifaddrs **ifap)
265 struct netlink_handle nh = { 0, 0, 0, NULL, NULL };
266 struct netlink_res *nlp;
267 struct ifaddrs_storage *ifas;
268 unsigned int i, newlink, newaddr, newaddr_idx;
269 int *map_newlink_data;
270 size_t ifa_data_size = 0; /* Size to allocate for all ifa_data. */
271 char *ifa_data_ptr; /* Pointer to the unused part of memory for
272 ifa_data. */
273 int result = 0;
275 if (ifap)
276 *ifap = NULL;
278 if (! __no_netlink_support && __netlink_open (&nh) < 0)
280 #if __ASSUME_NETLINK_SUPPORT != 0
281 return -1;
282 #endif
285 #if __ASSUME_NETLINK_SUPPORT == 0
286 if (__no_netlink_support)
287 return fallback_getifaddrs (ifap);
288 #endif
290 /* Tell the kernel that we wish to get a list of all
291 active interfaces. */
292 if (__netlink_sendreq (&nh, RTM_GETLINK) < 0)
294 result = -1;
295 goto exit_close;
297 /* Collect all data for every interface. */
298 if (__netlink_receive (&nh) < 0)
300 result = -1;
301 goto exit_free;
305 /* Now ask the kernel for all addresses which are assigned
306 to an interface. Since we store the addresses after the
307 interfaces in the list, we will later always find the
308 interface before the corresponding addresses. */
309 ++nh.seq;
310 if (__netlink_sendreq (&nh, RTM_GETADDR) < 0
311 /* Collect all data for every interface. */
312 || __netlink_receive (&nh) < 0)
314 result = -1;
315 goto exit_free;
318 /* Count all RTM_NEWLINK and RTM_NEWADDR entries to allocate
319 enough memory. */
320 newlink = newaddr = 0;
321 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
323 struct nlmsghdr *nlh;
324 size_t size = nlp->size;
326 if (nlp->nlh == NULL)
327 continue;
329 /* Walk through all entries we got from the kernel and look, which
330 message type they contain. */
331 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
333 /* Check if the message is what we want. */
334 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
335 continue;
337 if (nlh->nlmsg_type == NLMSG_DONE)
338 break; /* ok */
340 if (nlh->nlmsg_type == RTM_NEWLINK)
342 /* A RTM_NEWLINK message can have IFLA_STATS data. We need to
343 know the size before creating the list to allocate enough
344 memory. */
345 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
346 struct rtattr *rta = IFLA_RTA (ifim);
347 size_t rtasize = IFLA_PAYLOAD (nlh);
349 while (RTA_OK (rta, rtasize))
351 size_t rta_payload = RTA_PAYLOAD (rta);
353 if (rta->rta_type == IFLA_STATS)
355 ifa_data_size += rta_payload;
356 break;
358 else
359 rta = RTA_NEXT (rta, rtasize);
361 ++newlink;
363 else if (nlh->nlmsg_type == RTM_NEWADDR)
364 ++newaddr;
368 /* Return if no interface is up. */
369 if ((newlink + newaddr) == 0)
370 goto exit_free;
372 /* Allocate memory for all entries we have and initialize next
373 pointer. */
374 ifas = (struct ifaddrs_storage *) calloc (1,
375 (newlink + newaddr)
376 * sizeof (struct ifaddrs_storage)
377 + ifa_data_size);
378 if (ifas == NULL)
380 result = -1;
381 goto exit_free;
384 /* Table for mapping kernel index to entry in our list. */
385 map_newlink_data = alloca (newlink * sizeof (int));
386 memset (map_newlink_data, '\xff', newlink * sizeof (int));
388 ifa_data_ptr = (char *) &ifas[newlink + newaddr];
389 newaddr_idx = 0; /* Counter for newaddr index. */
391 /* Walk through the list of data we got from the kernel. */
392 for (nlp = nh.nlm_list; nlp; nlp = nlp->next)
394 struct nlmsghdr *nlh;
395 size_t size = nlp->size;
397 if (nlp->nlh == NULL)
398 continue;
400 /* Walk through one message and look at the type: If it is our
401 message, we need RTM_NEWLINK/RTM_NEWADDR and stop if we reach
402 the end or we find the end marker (in this case we ignore the
403 following data. */
404 for (nlh = nlp->nlh; NLMSG_OK (nlh, size); nlh = NLMSG_NEXT (nlh, size))
406 int ifa_index = 0;
408 /* Check if the message is the one we want */
409 if ((pid_t) nlh->nlmsg_pid != nh.pid || nlh->nlmsg_seq != nlp->seq)
410 continue;
412 if (nlh->nlmsg_type == NLMSG_DONE)
413 break; /* ok */
415 if (nlh->nlmsg_type == RTM_NEWLINK)
417 /* We found a new interface. Now extract everything from the
418 interface data we got and need. */
419 struct ifinfomsg *ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
420 struct rtattr *rta = IFLA_RTA (ifim);
421 size_t rtasize = IFLA_PAYLOAD (nlh);
423 /* Interfaces are stored in the first "newlink" entries
424 of our list, starting in the order as we got from the
425 kernel. */
426 ifa_index = map_newlink (ifim->ifi_index - 1, ifas,
427 map_newlink_data, newlink);
428 ifas[ifa_index].ifa.ifa_flags = ifim->ifi_flags;
430 while (RTA_OK (rta, rtasize))
432 char *rta_data = RTA_DATA (rta);
433 size_t rta_payload = RTA_PAYLOAD (rta);
435 switch (rta->rta_type)
437 case IFLA_ADDRESS:
438 if (rta_payload <= sizeof (ifas[ifa_index].addr))
440 ifas[ifa_index].addr.sl.sll_family = AF_PACKET;
441 memcpy (ifas[ifa_index].addr.sl.sll_addr,
442 (char *) rta_data, rta_payload);
443 ifas[ifa_index].addr.sl.sll_halen = rta_payload;
444 ifas[ifa_index].addr.sl.sll_ifindex
445 = ifim->ifi_index;
446 ifas[ifa_index].addr.sl.sll_hatype = ifim->ifi_type;
448 ifas[ifa_index].ifa.ifa_addr
449 = &ifas[ifa_index].addr.sa;
451 break;
453 case IFLA_BROADCAST:
454 if (rta_payload <= sizeof (ifas[ifa_index].broadaddr))
456 ifas[ifa_index].broadaddr.sl.sll_family = AF_PACKET;
457 memcpy (ifas[ifa_index].broadaddr.sl.sll_addr,
458 (char *) rta_data, rta_payload);
459 ifas[ifa_index].broadaddr.sl.sll_halen = rta_payload;
460 ifas[ifa_index].broadaddr.sl.sll_ifindex
461 = ifim->ifi_index;
462 ifas[ifa_index].broadaddr.sl.sll_hatype
463 = ifim->ifi_type;
465 ifas[ifa_index].ifa.ifa_broadaddr
466 = &ifas[ifa_index].broadaddr.sa;
468 break;
470 case IFLA_IFNAME: /* Name of Interface */
471 if ((rta_payload + 1) <= sizeof (ifas[ifa_index].name))
473 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
474 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
475 rta_payload) = '\0';
477 break;
479 case IFLA_STATS: /* Statistics of Interface */
480 ifas[ifa_index].ifa.ifa_data = ifa_data_ptr;
481 ifa_data_ptr += rta_payload;
482 memcpy (ifas[ifa_index].ifa.ifa_data, rta_data,
483 rta_payload);
484 break;
486 case IFLA_UNSPEC:
487 break;
488 case IFLA_MTU:
489 break;
490 case IFLA_LINK:
491 break;
492 case IFLA_QDISC:
493 break;
494 default:
495 break;
498 rta = RTA_NEXT (rta, rtasize);
501 else if (nlh->nlmsg_type == RTM_NEWADDR)
503 struct ifaddrmsg *ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
504 struct rtattr *rta = IFA_RTA (ifam);
505 size_t rtasize = IFA_PAYLOAD (nlh);
507 /* New Addresses are stored in the order we got them from
508 the kernel after the interfaces. Theoretically it is possible
509 that we have holes in the interface part of the list,
510 but we always have already the interface for this address. */
511 ifa_index = newlink + newaddr_idx;
512 ifas[ifa_index].ifa.ifa_flags
513 = ifas[map_newlink (ifam->ifa_index - 1, ifas,
514 map_newlink_data, newlink)].ifa.ifa_flags;
515 if (ifa_index > 0)
516 ifas[ifa_index - 1].ifa.ifa_next = &ifas[ifa_index].ifa;
517 ++newaddr_idx;
519 while (RTA_OK (rta, rtasize))
521 char *rta_data = RTA_DATA (rta);
522 size_t rta_payload = RTA_PAYLOAD (rta);
524 switch (rta->rta_type)
526 case IFA_ADDRESS:
528 struct sockaddr *sa;
530 if (ifas[ifa_index].ifa.ifa_addr != NULL)
532 /* In a point-to-poing network IFA_ADDRESS
533 contains the destination address, local
534 address is supplied in IFA_LOCAL attribute.
535 destination address and broadcast address
536 are stored in an union, so it doesn't matter
537 which name we use. */
538 ifas[ifa_index].ifa.ifa_broadaddr
539 = &ifas[ifa_index].broadaddr.sa;
540 sa = &ifas[ifa_index].broadaddr.sa;
542 else
544 ifas[ifa_index].ifa.ifa_addr
545 = &ifas[ifa_index].addr.sa;
546 sa = &ifas[ifa_index].addr.sa;
549 sa->sa_family = ifam->ifa_family;
551 switch (ifam->ifa_family)
553 case AF_INET:
554 /* Size must match that of an address for IPv4. */
555 if (rta_payload == 4)
556 memcpy (&((struct sockaddr_in *) sa)->sin_addr,
557 rta_data, rta_payload);
558 break;
560 case AF_INET6:
561 /* Size must match that of an address for IPv6. */
562 if (rta_payload == 16)
564 memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr,
565 rta_data, rta_payload);
566 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
567 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
568 ((struct sockaddr_in6 *) sa)->sin6_scope_id
569 = ifam->ifa_index;
571 break;
573 default:
574 if (rta_payload <= sizeof (ifas[ifa_index].addr))
575 memcpy (sa->sa_data, rta_data, rta_payload);
576 break;
579 break;
581 case IFA_LOCAL:
582 if (ifas[ifa_index].ifa.ifa_addr != NULL)
584 /* If ifa_addr is set and we get IFA_LOCAL,
585 assume we have a point-to-point network.
586 Move address to correct field. */
587 ifas[ifa_index].broadaddr = ifas[ifa_index].addr;
588 ifas[ifa_index].ifa.ifa_broadaddr
589 = &ifas[ifa_index].broadaddr.sa;
590 memset (&ifas[ifa_index].addr, '\0',
591 sizeof (ifas[ifa_index].addr));
594 ifas[ifa_index].ifa.ifa_addr = &ifas[ifa_index].addr.sa;
595 ifas[ifa_index].ifa.ifa_addr->sa_family
596 = ifam->ifa_family;
598 switch (ifam->ifa_family)
600 case AF_INET:
601 /* Size must match that of an address for IPv4. */
602 if (rta_payload == 4)
603 memcpy (&ifas[ifa_index].addr.s4.sin_addr,
604 rta_data, rta_payload);
605 break;
607 case AF_INET6:
608 /* Size must match that of an address for IPv6. */
609 if (rta_payload == 16)
611 memcpy (&ifas[ifa_index].addr.s6.sin6_addr,
612 rta_data, rta_payload);
613 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
614 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
615 ifas[ifa_index].addr.s6.sin6_scope_id =
616 ifam->ifa_index;
618 break;
620 default:
621 if (rta_payload <= sizeof (ifas[ifa_index].addr))
622 memcpy (ifas[ifa_index].addr.sa.sa_data,
623 rta_data, rta_payload);
624 break;
626 break;
628 case IFA_BROADCAST:
629 /* We get IFA_BROADCAST, so IFA_LOCAL was too much. */
630 if (ifas[ifa_index].ifa.ifa_broadaddr != NULL)
631 memset (&ifas[ifa_index].broadaddr, '\0',
632 sizeof (ifas[ifa_index].broadaddr));
634 ifas[ifa_index].ifa.ifa_broadaddr
635 = &ifas[ifa_index].broadaddr.sa;
636 ifas[ifa_index].ifa.ifa_broadaddr->sa_family
637 = ifam->ifa_family;
639 switch (ifam->ifa_family)
641 case AF_INET:
642 /* Size must match that of an address for IPv4. */
643 if (rta_payload == 4)
644 memcpy (&ifas[ifa_index].broadaddr.s4.sin_addr,
645 rta_data, rta_payload);
646 break;
648 case AF_INET6:
649 /* Size must match that of an address for IPv6. */
650 if (rta_payload == 16)
652 memcpy (&ifas[ifa_index].broadaddr.s6.sin6_addr,
653 rta_data, rta_payload);
654 if (IN6_IS_ADDR_LINKLOCAL (rta_data)
655 || IN6_IS_ADDR_MC_LINKLOCAL (rta_data))
656 ifas[ifa_index].broadaddr.s6.sin6_scope_id
657 = ifam->ifa_index;
659 break;
661 default:
662 if (rta_payload <= sizeof (ifas[ifa_index].addr))
663 memcpy (&ifas[ifa_index].broadaddr.sa.sa_data,
664 rta_data, rta_payload);
665 break;
667 break;
669 case IFA_LABEL:
670 if (rta_payload + 1 <= sizeof (ifas[ifa_index].name))
672 ifas[ifa_index].ifa.ifa_name = ifas[ifa_index].name;
673 *(char *) __mempcpy (ifas[ifa_index].name, rta_data,
674 rta_payload) = '\0';
676 else
677 abort ();
678 break;
680 case IFA_UNSPEC:
681 break;
682 case IFA_CACHEINFO:
683 break;
684 default:
685 break;
688 rta = RTA_NEXT (rta, rtasize);
691 /* If we didn't get the interface name with the
692 address, use the name from the interface entry. */
693 if (ifas[ifa_index].ifa.ifa_name == NULL)
694 ifas[ifa_index].ifa.ifa_name
695 = ifas[map_newlink (ifam->ifa_index - 1, ifas,
696 map_newlink_data, newlink)].ifa.ifa_name;
698 /* Calculate the netmask. */
699 if (ifas[ifa_index].ifa.ifa_addr
700 && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_UNSPEC
701 && ifas[ifa_index].ifa.ifa_addr->sa_family != AF_PACKET)
703 uint32_t max_prefixlen = 0;
704 char *cp = NULL;
706 ifas[ifa_index].ifa.ifa_netmask
707 = &ifas[ifa_index].netmask.sa;
709 switch (ifas[ifa_index].ifa.ifa_addr->sa_family)
711 case AF_INET:
712 cp = (char *) &ifas[ifa_index].netmask.s4.sin_addr;
713 max_prefixlen = 32;
714 break;
716 case AF_INET6:
717 cp = (char *) &ifas[ifa_index].netmask.s6.sin6_addr;
718 max_prefixlen = 128;
719 break;
722 ifas[ifa_index].ifa.ifa_netmask->sa_family
723 = ifas[ifa_index].ifa.ifa_addr->sa_family;
725 if (cp != NULL)
727 char c;
728 unsigned int preflen;
730 if ((max_prefixlen > 0) &&
731 (ifam->ifa_prefixlen > max_prefixlen))
732 preflen = max_prefixlen;
733 else
734 preflen = ifam->ifa_prefixlen;
736 for (i = 0; i < (preflen / 8); i++)
737 *cp++ = 0xff;
738 c = 0xff;
739 c <<= (8 - (preflen % 8));
740 *cp = c;
747 assert (ifa_data_ptr <= (char *) &ifas[newlink + newaddr] + ifa_data_size);
749 if (newaddr_idx > 0)
751 for (i = 0; i < newlink; ++i)
752 if (map_newlink_data[i] == -1)
754 /* We have fewer links then we anticipated. Adjust the
755 forward pointer to the first address entry. */
756 ifas[i - 1].ifa.ifa_next = &ifas[newlink].ifa;
759 if (i == 0 && newlink > 0)
760 /* No valid link, but we allocated memory. We have to
761 populate the first entry. */
762 memmove (ifas, &ifas[newlink], sizeof (struct ifaddrs_storage));
765 if (ifap != NULL)
766 *ifap = &ifas[0].ifa;
768 exit_free:
769 __netlink_free_handle (&nh);
771 exit_close:
772 __netlink_close (&nh);
774 return result;
776 libc_hidden_def (getifaddrs)
779 #if __ASSUME_NETLINK_SUPPORT != 0
780 void
781 freeifaddrs (struct ifaddrs *ifa)
783 free (ifa);
785 libc_hidden_def (freeifaddrs)
786 #endif