samba-3.5.8 for ARM
[tomato.git] / release / src-rt-6.x.4708 / router / samba-3.5.8 / source3 / lib / ifaddrs.c
blob8199308fd10d2186d53f975edfba55af8d1d14e8
1 /* $Id: ifaddrs.c 241182 2011-02-17 21:50:03Z $ */
2 /* from USAGI: ifaddrs.c,v 1.20.2.1 2002/12/08 08:22:23 yoshfuji Exp */
4 /*
5 * Copyright (C)2000 YOSHIFUJI Hideaki
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include <string.h>
23 #include <time.h>
24 #include <malloc.h>
25 #include <errno.h>
26 #include <unistd.h>
28 #define __set_errno(x) errno = (x)
30 #include <sys/socket.h>
31 #include <asm/types.h>
32 #include <linux/netlink.h>
33 #include <linux/rtnetlink.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netpacket/packet.h>
37 #include <net/ethernet.h> /* the L2 protocols */
38 #include <sys/uio.h>
39 #include <net/if.h>
40 #include <net/if_arp.h>
41 #include "ifaddrs.h"
42 #include <netinet/in.h>
44 #ifdef _USAGI_LIBINET6
45 #include "libc-compat.h"
46 #endif
48 /* ====================================================================== */
49 struct nlmsg_list
51 struct nlmsg_list *nlm_next;
52 struct nlmsghdr *nlh;
53 int size;
54 time_t seq;
57 struct rtmaddr_ifamap
59 void *address;
60 void *local;
61 #ifdef IFA_NETMASK
62 void *netmask;
63 #endif
64 void *broadcast;
65 #ifdef HAVE_IFADDRS_IFA_ANYCAST
66 void *anycast;
67 #endif
68 int address_len;
69 int local_len;
70 #ifdef IFA_NETMASK
71 int netmask_len;
72 #endif
73 int broadcast_len;
74 #ifdef HAVE_IFADDRS_IFA_ANYCAST
75 int anycast_len;
76 #endif
79 /* ====================================================================== */
80 static size_t
81 ifa_sa_len (sa_family_t family, int len)
83 size_t size;
84 switch (family)
86 case AF_INET:
87 size = sizeof (struct sockaddr_in);
88 break;
89 case AF_INET6:
90 size = sizeof (struct sockaddr_in6);
91 break;
92 case AF_PACKET:
93 size = (size_t) (((struct sockaddr_ll *) NULL)->sll_addr) + len;
94 if (size < sizeof (struct sockaddr_ll))
95 size = sizeof (struct sockaddr_ll);
96 break;
97 default:
98 size = (size_t) (((struct sockaddr *) NULL)->sa_data) + len;
99 if (size < sizeof (struct sockaddr))
100 size = sizeof (struct sockaddr);
102 return size;
105 static void
106 ifa_make_sockaddr (sa_family_t family,
107 struct sockaddr *sa,
108 void *p, size_t len, uint32_t scope, uint32_t scopeid)
110 if (sa == NULL)
111 return;
112 switch (family)
114 case AF_INET:
115 memcpy (&((struct sockaddr_in *) sa)->sin_addr, (char *) p, len);
116 break;
117 case AF_INET6:
118 memcpy (&((struct sockaddr_in6 *) sa)->sin6_addr, (char *) p, len);
119 if (IN6_IS_ADDR_LINKLOCAL (p) || IN6_IS_ADDR_MC_LINKLOCAL (p))
121 ((struct sockaddr_in6 *) sa)->sin6_scope_id = scopeid;
123 break;
124 case AF_PACKET:
125 memcpy (((struct sockaddr_ll *) sa)->sll_addr, (char *) p, len);
126 ((struct sockaddr_ll *) sa)->sll_halen = len;
127 break;
128 default:
129 memcpy (sa->sa_data, p, len);
130 break;
132 sa->sa_family = family;
133 #ifdef HAVE_SOCKADDR_SA_LEN
134 sa->sa_len = ifa_sa_len (family, len);
135 #endif
138 static struct sockaddr *
139 ifa_make_sockaddr_mask (sa_family_t family,
140 struct sockaddr *sa, uint32_t prefixlen)
142 int i;
143 char *p = NULL, c;
144 uint32_t max_prefixlen = 0;
146 if (sa == NULL)
147 return NULL;
148 switch (family)
150 case AF_INET:
151 memset (&((struct sockaddr_in *) sa)->sin_addr, 0,
152 sizeof (((struct sockaddr_in *) sa)->sin_addr));
153 p = (char *) &((struct sockaddr_in *) sa)->sin_addr;
154 max_prefixlen = 32;
155 break;
156 case AF_INET6:
157 memset (&((struct sockaddr_in6 *) sa)->sin6_addr, 0,
158 sizeof (((struct sockaddr_in6 *) sa)->sin6_addr));
159 p = (char *) &((struct sockaddr_in6 *) sa)->sin6_addr;
160 max_prefixlen = 128;
161 break;
162 default:
163 return NULL;
165 sa->sa_family = family;
166 #ifdef HAVE_SOCKADDR_SA_LEN
167 sa->sa_len = ifa_sa_len (family, len);
168 #endif
169 if (p)
171 if (prefixlen > max_prefixlen)
172 prefixlen = max_prefixlen;
173 for (i = 0; i < (prefixlen / 8); i++)
174 *p++ = 0xff;
175 c = 0xff;
176 c <<= (8 - (prefixlen % 8));
177 *p = c;
179 return sa;
182 /* ====================================================================== */
183 static int
184 nl_sendreq (int sd, int request, int flags, int *seq)
186 char reqbuf[NLMSG_ALIGN (sizeof (struct nlmsghdr)) +
187 NLMSG_ALIGN (sizeof (struct rtgenmsg))];
188 struct sockaddr_nl nladdr;
189 struct nlmsghdr *req_hdr;
190 struct rtgenmsg *req_msg;
191 time_t t = time (NULL);
193 if (seq)
194 *seq = t;
195 memset (&reqbuf, 0, sizeof (reqbuf));
196 req_hdr = (struct nlmsghdr *) reqbuf;
197 req_msg = (struct rtgenmsg *) NLMSG_DATA (req_hdr);
198 req_hdr->nlmsg_len = NLMSG_LENGTH (sizeof (*req_msg));
199 req_hdr->nlmsg_type = request;
200 req_hdr->nlmsg_flags = flags | NLM_F_REQUEST;
201 req_hdr->nlmsg_pid = 0;
202 req_hdr->nlmsg_seq = t;
203 req_msg->rtgen_family = AF_UNSPEC;
204 memset (&nladdr, 0, sizeof (nladdr));
205 nladdr.nl_family = AF_NETLINK;
206 return (sendto (sd, (void *) req_hdr, req_hdr->nlmsg_len, 0,
207 (struct sockaddr *) &nladdr, sizeof (nladdr)));
210 static int
211 nl_recvmsg (int sd, int request, int seq,
212 void *buf, size_t buflen, int *flags)
214 struct msghdr msg;
215 struct iovec iov = { buf, buflen };
216 struct sockaddr_nl nladdr;
217 int read_len;
219 for (;;)
221 msg.msg_name = (void *) &nladdr;
222 msg.msg_namelen = sizeof (nladdr);
223 msg.msg_iov = &iov;
224 msg.msg_iovlen = 1;
225 msg.msg_control = NULL;
226 msg.msg_controllen = 0;
227 msg.msg_flags = 0;
228 read_len = recvmsg (sd, &msg, 0);
229 if ((read_len < 0 && errno == EINTR) || (msg.msg_flags & MSG_TRUNC))
230 continue;
231 if (flags)
232 *flags = msg.msg_flags;
233 break;
235 return read_len;
238 static int
239 nl_getmsg (int sd, int request, int seq, struct nlmsghdr **nlhp, int *done)
241 struct nlmsghdr *nh;
242 size_t bufsize = 65536, lastbufsize = 0;
243 void *buff = NULL;
244 int result = 0, read_size;
245 int msg_flags;
246 pid_t pid = getpid ();
247 for (;;)
249 void *newbuff = realloc (buff, bufsize);
250 if (newbuff == NULL || bufsize < lastbufsize)
252 result = -1;
253 break;
255 buff = newbuff;
256 result = read_size =
257 nl_recvmsg (sd, request, seq, buff, bufsize, &msg_flags);
258 if (read_size < 0 || (msg_flags & MSG_TRUNC))
260 lastbufsize = bufsize;
261 bufsize *= 2;
262 continue;
264 if (read_size == 0)
265 break;
266 nh = (struct nlmsghdr *) buff;
267 for (nh = (struct nlmsghdr *) buff;
268 NLMSG_OK (nh, read_size);
269 nh = (struct nlmsghdr *) NLMSG_NEXT (nh, read_size))
271 if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq)
272 continue;
273 if (nh->nlmsg_type == NLMSG_DONE)
275 (*done)++;
276 break; /* ok */
278 if (nh->nlmsg_type == NLMSG_ERROR)
280 struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nh);
281 result = -1;
282 if (nh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr)))
283 __set_errno (EIO);
284 else
285 __set_errno (-nlerr->error);
286 break;
289 break;
291 if (result < 0)
292 if (buff)
294 int saved_errno = errno;
295 free (buff);
296 __set_errno (saved_errno);
298 *nlhp = (struct nlmsghdr *) buff;
299 return result;
302 static int
303 nl_getlist (int sd, int seq,
304 int request,
305 struct nlmsg_list **nlm_list, struct nlmsg_list **nlm_end)
307 struct nlmsghdr *nlh = NULL;
308 int status;
309 int done = 0;
311 status = nl_sendreq (sd, request, NLM_F_ROOT | NLM_F_MATCH, &seq);
312 if (status < 0)
313 return status;
314 if (seq == 0)
315 seq = (int) time (NULL);
316 while (!done)
318 status = nl_getmsg (sd, request, seq, &nlh, &done);
319 if (status < 0)
320 return status;
321 if (nlh)
323 struct nlmsg_list *nlm_next =
324 (struct nlmsg_list *) malloc (sizeof (struct nlmsg_list));
325 if (nlm_next == NULL)
327 int saved_errno = errno;
328 free (nlh);
329 __set_errno (saved_errno);
330 status = -1;
332 else
334 nlm_next->nlm_next = NULL;
335 nlm_next->nlh = (struct nlmsghdr *) nlh;
336 nlm_next->size = status;
337 nlm_next->seq = seq;
338 if (*nlm_list == NULL)
340 *nlm_list = nlm_next;
341 *nlm_end = nlm_next;
343 else
345 (*nlm_end)->nlm_next = nlm_next;
346 *nlm_end = nlm_next;
351 return status >= 0 ? seq : status;
354 /* ---------------------------------------------------------------------- */
355 static void
356 free_nlmsglist (struct nlmsg_list *nlm0)
358 struct nlmsg_list *nlm, *nlm_next;
359 int saved_errno;
360 if (!nlm0)
361 return;
362 saved_errno = errno;
363 nlm = nlm0;
364 while (nlm)
366 if (nlm->nlh)
367 free (nlm->nlh);
368 nlm_next = nlm->nlm_next;
369 free(nlm);
370 nlm = nlm_next;
372 __set_errno (saved_errno);
375 static void
376 free_data (void *data, void *ifdata)
378 int saved_errno = errno;
379 if (data != NULL)
380 free (data);
381 if (ifdata != NULL)
382 free (ifdata);
383 __set_errno (saved_errno);
386 /* ---------------------------------------------------------------------- */
387 static void
388 nl_close (int sd)
390 int saved_errno = errno;
391 if (sd >= 0)
392 close (sd);
393 __set_errno (saved_errno);
396 /* ---------------------------------------------------------------------- */
397 static int
398 nl_open (void)
400 struct sockaddr_nl nladdr;
401 int sd;
403 sd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
404 if (sd < 0)
405 return -1;
406 memset (&nladdr, 0, sizeof (nladdr));
407 nladdr.nl_family = AF_NETLINK;
408 if (bind (sd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0)
410 nl_close (sd);
411 return -1;
413 return sd;
416 /* ====================================================================== */
418 getifaddrs_local (struct ifaddrs **ifap)
420 int sd;
421 struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm;
422 /* - - - - - - - - - - - - - - - */
423 int icnt;
424 size_t dlen, xlen, nlen;
425 uint32_t max_ifindex = 0;
427 pid_t pid = getpid ();
428 int seq;
429 int result;
430 int build; /* 0 or 1 */
432 /* ---------------------------------- */
433 /* initialize */
434 icnt = dlen = xlen = nlen = 0;
435 nlmsg_list = nlmsg_end = NULL;
437 if (ifap)
438 *ifap = NULL;
440 /* ---------------------------------- */
441 /* open socket and bind */
442 sd = nl_open ();
443 if (sd < 0)
444 return -1;
446 /* ---------------------------------- */
447 /* gather info */
448 if ((seq = nl_getlist (sd, 0, RTM_GETLINK, &nlmsg_list, &nlmsg_end)) < 0)
450 free_nlmsglist (nlmsg_list);
451 nl_close (sd);
452 return -1;
454 if ((seq = nl_getlist (sd, seq + 1, RTM_GETADDR,
455 &nlmsg_list, &nlmsg_end)) < 0)
457 free_nlmsglist (nlmsg_list);
458 nl_close (sd);
459 return -1;
462 /* ---------------------------------- */
463 /* Estimate size of result buffer and fill it */
464 for (build = 0; build <= 1; build++)
466 struct ifaddrs *ifl = NULL, *ifa = NULL;
467 struct nlmsghdr *nlh, *nlh0;
468 void *data = NULL, *xdata = NULL, *ifdata = NULL;
469 char *ifname = NULL, **iflist = NULL;
470 uint16_t *ifflist = NULL;
471 struct rtmaddr_ifamap ifamap;
473 if (build)
475 ifa = data = calloc (1,
476 NLMSG_ALIGN (sizeof (struct ifaddrs[icnt]))
477 + dlen + xlen + nlen);
478 ifdata = calloc (1,
479 NLMSG_ALIGN (sizeof (char *[max_ifindex + 1]))
481 NLMSG_ALIGN (sizeof (uint16_t[max_ifindex + 1])));
482 if (ifap != NULL)
483 *ifap = (ifdata != NULL) ? ifa : NULL;
484 else
486 free_data (data, ifdata);
487 result = 0;
488 break;
490 if (data == NULL || ifdata == NULL)
492 free_data (data, ifdata);
493 result = -1;
494 break;
496 ifl = NULL;
497 data += NLMSG_ALIGN (sizeof (struct ifaddrs)) * icnt;
498 xdata = data + dlen;
499 ifname = xdata + xlen;
500 iflist = ifdata;
501 ifflist =
502 ((void *) iflist) +
503 NLMSG_ALIGN (sizeof (char *[max_ifindex + 1]));
506 for (nlm = nlmsg_list; nlm; nlm = nlm->nlm_next)
508 int nlmlen = nlm->size;
509 if (!(nlh0 = nlm->nlh))
510 continue;
511 for (nlh = nlh0;
512 NLMSG_OK (nlh, nlmlen); nlh = NLMSG_NEXT (nlh, nlmlen))
514 struct ifinfomsg *ifim = NULL;
515 struct ifaddrmsg *ifam = NULL;
516 struct rtattr *rta;
518 size_t nlm_struct_size = 0;
519 sa_family_t nlm_family = 0;
520 uint32_t nlm_scope = 0, nlm_index = 0;
521 #ifndef IFA_NETMASK
522 size_t sockaddr_size = 0;
523 uint32_t nlm_prefixlen = 0;
524 #endif
525 size_t rtasize;
527 memset (&ifamap, 0, sizeof (ifamap));
529 /* check if the message is what we want */
530 if (nlh->nlmsg_pid != pid || nlh->nlmsg_seq != nlm->seq)
531 continue;
532 if (nlh->nlmsg_type == NLMSG_DONE)
534 break; /* ok */
536 switch (nlh->nlmsg_type)
538 case RTM_NEWLINK:
539 ifim = (struct ifinfomsg *) NLMSG_DATA (nlh);
540 nlm_struct_size = sizeof (*ifim);
541 nlm_family = ifim->ifi_family;
542 nlm_scope = 0;
543 nlm_index = ifim->ifi_index;
544 nlm_prefixlen = 0;
545 if (build)
546 ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags;
547 break;
548 case RTM_NEWADDR:
549 ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh);
550 nlm_struct_size = sizeof (*ifam);
551 nlm_family = ifam->ifa_family;
552 nlm_scope = ifam->ifa_scope;
553 nlm_index = ifam->ifa_index;
554 nlm_prefixlen = ifam->ifa_prefixlen;
555 if (build)
556 ifa->ifa_flags = ifflist[nlm_index];
557 break;
558 default:
559 continue;
562 if (!build)
564 if (max_ifindex < nlm_index)
565 max_ifindex = nlm_index;
567 else
569 if (ifl != NULL)
570 ifl->ifa_next = ifa;
573 rtasize =
574 NLMSG_PAYLOAD (nlh, nlmlen) - NLMSG_ALIGN (nlm_struct_size);
575 for (rta =
576 (struct rtattr *) (((char *) NLMSG_DATA (nlh)) +
577 NLMSG_ALIGN (nlm_struct_size));
578 RTA_OK (rta, rtasize); rta = RTA_NEXT (rta, rtasize))
580 struct sockaddr **sap = NULL;
581 void *rtadata = RTA_DATA (rta);
582 size_t rtapayload = RTA_PAYLOAD (rta);
583 socklen_t sa_len;
585 switch (nlh->nlmsg_type)
587 case RTM_NEWLINK:
588 switch (rta->rta_type)
590 case IFLA_ADDRESS:
591 case IFLA_BROADCAST:
592 if (build)
594 sap =
595 (rta->rta_type ==
596 IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa->
597 ifa_broadaddr;
598 *sap = (struct sockaddr *) data;
600 sa_len = ifa_sa_len (AF_PACKET, rtapayload);
601 if (rta->rta_type == IFLA_ADDRESS)
602 sockaddr_size = NLMSG_ALIGN (sa_len);
603 if (!build)
605 dlen += NLMSG_ALIGN (sa_len);
607 else
609 memset (*sap, 0, sa_len);
610 ifa_make_sockaddr (AF_PACKET, *sap, rtadata,
611 rtapayload, 0, 0);
612 ((struct sockaddr_ll *) *sap)->sll_ifindex =
613 nlm_index;
614 ((struct sockaddr_ll *) *sap)->sll_hatype =
615 ifim->ifi_type;
616 data += NLMSG_ALIGN (sa_len);
618 break;
619 case IFLA_IFNAME: /* Name of Interface */
620 if (!build)
621 nlen += NLMSG_ALIGN (rtapayload + 1);
622 else
624 ifa->ifa_name = ifname;
625 if (iflist[nlm_index] == NULL)
626 iflist[nlm_index] = ifa->ifa_name;
627 strncpy (ifa->ifa_name, rtadata, rtapayload);
628 ifa->ifa_name[rtapayload] = '\0';
629 ifname += NLMSG_ALIGN (rtapayload + 1);
631 break;
632 case IFLA_STATS: /* Statistics of Interface */
633 if (!build)
634 xlen += NLMSG_ALIGN (rtapayload);
635 else
637 ifa->ifa_data = xdata;
638 memcpy (ifa->ifa_data, rtadata, rtapayload);
639 xdata += NLMSG_ALIGN (rtapayload);
641 break;
642 case IFLA_UNSPEC:
643 break;
644 case IFLA_MTU:
645 break;
646 case IFLA_LINK:
647 break;
648 case IFLA_QDISC:
649 break;
650 default:
653 break;
654 case RTM_NEWADDR:
655 if (nlm_family == AF_PACKET)
656 break;
657 switch (rta->rta_type)
659 case IFA_ADDRESS:
660 ifamap.address = rtadata;
661 ifamap.address_len = rtapayload;
662 break;
663 case IFA_LOCAL:
664 ifamap.local = rtadata;
665 ifamap.local_len = rtapayload;
666 break;
667 case IFA_BROADCAST:
668 ifamap.broadcast = rtadata;
669 ifamap.broadcast_len = rtapayload;
670 break;
671 #ifdef HAVE_IFADDRS_IFA_ANYCAST
672 case IFA_ANYCAST:
673 ifamap.anycast = rtadata;
674 ifamap.anycast_len = rtapayload;
675 break;
676 #endif
677 case IFA_LABEL:
678 if (!build)
679 nlen += NLMSG_ALIGN (rtapayload + 1);
680 else
682 ifa->ifa_name = ifname;
683 if (iflist[nlm_index] == NULL)
684 iflist[nlm_index] = ifname;
685 strncpy (ifa->ifa_name, rtadata, rtapayload);
686 ifa->ifa_name[rtapayload] = '\0';
687 ifname += NLMSG_ALIGN (rtapayload + 1);
689 break;
690 case IFA_UNSPEC:
691 break;
692 case IFA_CACHEINFO:
693 break;
694 default:
699 if (nlh->nlmsg_type == RTM_NEWADDR && nlm_family != AF_PACKET)
701 if (!ifamap.local)
703 ifamap.local = ifamap.address;
704 ifamap.local_len = ifamap.address_len;
706 if (!ifamap.address)
708 ifamap.address = ifamap.local;
709 ifamap.address_len = ifamap.local_len;
711 if (ifamap.address_len != ifamap.local_len ||
712 (ifamap.address != NULL &&
713 memcmp (ifamap.address, ifamap.local,
714 ifamap.address_len)))
716 /* p2p; address is peer and local is ours */
717 ifamap.broadcast = ifamap.address;
718 ifamap.broadcast_len = ifamap.address_len;
719 ifamap.address = ifamap.local;
720 ifamap.address_len = ifamap.local_len;
722 if (ifamap.address)
724 #ifndef IFA_NETMASK
725 sockaddr_size =
726 NLMSG_ALIGN (ifa_sa_len
727 (nlm_family, ifamap.address_len));
728 #endif
729 if (!build)
730 dlen +=
731 NLMSG_ALIGN (ifa_sa_len
732 (nlm_family, ifamap.address_len));
733 else
735 ifa->ifa_addr = (struct sockaddr *) data;
736 ifa_make_sockaddr (nlm_family, ifa->ifa_addr,
737 ifamap.address,
738 ifamap.address_len, nlm_scope,
739 nlm_index);
740 data +=
741 NLMSG_ALIGN (ifa_sa_len
742 (nlm_family, ifamap.address_len));
745 #ifdef IFA_NETMASK
746 if (ifamap.netmask)
748 if (!build)
749 dlen +=
750 NLMSG_ALIGN (ifa_sa_len
751 (nlm_family, ifamap.netmask_len));
752 else
754 ifa->ifa_netmask = (struct sockaddr *) data;
755 ifa_make_sockaddr (nlm_family, ifa->ifa_netmask,
756 ifamap.netmask,
757 ifamap.netmask_len, nlm_scope,
758 nlm_index);
759 data +=
760 NLMSG_ALIGN (ifa_sa_len
761 (nlm_family, ifamap.netmask_len));
764 #endif
765 if (ifamap.broadcast)
767 if (!build)
768 dlen +=
769 NLMSG_ALIGN (ifa_sa_len
770 (nlm_family, ifamap.broadcast_len));
771 else
773 ifa->ifa_broadaddr = (struct sockaddr *) data;
774 ifa_make_sockaddr (nlm_family, ifa->ifa_broadaddr,
775 ifamap.broadcast,
776 ifamap.broadcast_len, nlm_scope,
777 nlm_index);
778 data +=
779 NLMSG_ALIGN (ifa_sa_len
780 (nlm_family, ifamap.broadcast_len));
783 #ifdef HAVE_IFADDRS_IFA_ANYCAST
784 if (ifamap.anycast)
786 if (!build)
787 dlen +=
788 NLMSG_ALIGN (ifa_sa_len
789 (nlm_family, ifamap.anycast_len));
790 else
792 ifa->ifa_anycast = (struct sockaddr *) data;
793 ifa_make_sockaddr (nlm_family, ifa->ifa_anyaddr,
794 ifamap.anycast,
795 ifamap.anycast_len, nlm_scope,
796 nlm_index);
797 data +=
798 NLMSG_ALIGN (ifa_sa_len
799 (nlm_family, ifamap.anycast_len));
802 #endif
804 if (!build)
806 #ifndef IFA_NETMASK
807 dlen += sockaddr_size;
808 #endif
809 icnt++;
811 else
813 if (ifa->ifa_name == NULL)
814 ifa->ifa_name = iflist[nlm_index];
815 #ifndef IFA_NETMASK
816 if (ifa->ifa_addr &&
817 ifa->ifa_addr->sa_family != AF_UNSPEC &&
818 ifa->ifa_addr->sa_family != AF_PACKET)
820 ifa->ifa_netmask = (struct sockaddr *) data;
821 ifa_make_sockaddr_mask (ifa->ifa_addr->sa_family,
822 ifa->ifa_netmask,
823 nlm_prefixlen);
825 data += sockaddr_size;
826 #endif
827 ifl = ifa++;
831 if (!build)
833 if (icnt == 0 && (dlen + nlen + xlen == 0))
835 if (ifap != NULL)
836 *ifap = NULL;
837 break; /* cannot found any addresses */
840 else
841 free_data (NULL, ifdata);
844 /* ---------------------------------- */
845 /* Finalize */
846 free_nlmsglist (nlmsg_list);
847 nl_close (sd);
848 return 0;
851 /* ---------------------------------------------------------------------- */
852 void
853 freeifaddrs_local (struct ifaddrs *ifa)
855 free (ifa);