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 */ 3 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. 11 * 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. 16 * 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 20 */ 21 22#include <string.h> 23#include <time.h> 24#include <malloc.h> 25#include <errno.h> 26#include <unistd.h> 27 28#define __set_errno(x) errno = (x) 29 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> 43 44#ifdef _USAGI_LIBINET6 45#include "libc-compat.h" 46#endif 47 48/* ====================================================================== */ 49struct nlmsg_list 50{ 51 struct nlmsg_list *nlm_next; 52 struct nlmsghdr *nlh; 53 int size; 54 time_t seq; 55}; 56 57struct rtmaddr_ifamap 58{ 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 77}; 78 79/* ====================================================================== */ 80static size_t 81ifa_sa_len (sa_family_t family, int len) 82{ 83 size_t size; 84 switch (family) 85 { 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); 101 } 102 return size; 103} 104 105static void 106ifa_make_sockaddr (sa_family_t family, 107 struct sockaddr *sa, 108 void *p, size_t len, uint32_t scope, uint32_t scopeid) 109{ 110 if (sa == NULL) 111 return; 112 switch (family) 113 { 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)) 120 { 121 ((struct sockaddr_in6 *) sa)->sin6_scope_id = scopeid; 122 } 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; 131 } 132 sa->sa_family = family; 133#ifdef HAVE_SOCKADDR_SA_LEN 134 sa->sa_len = ifa_sa_len (family, len); 135#endif 136} 137 138static struct sockaddr * 139ifa_make_sockaddr_mask (sa_family_t family, 140 struct sockaddr *sa, uint32_t prefixlen) 141{ 142 int i; 143 char *p = NULL, c; 144 uint32_t max_prefixlen = 0; 145 146 if (sa == NULL) 147 return NULL; 148 switch (family) 149 { 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; 164 } 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) 170 { 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; 178 } 179 return sa; 180} 181 182/* ====================================================================== */ 183static int 184nl_sendreq (int sd, int request, int flags, int *seq) 185{ 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); 192 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))); 208} 209 210static int 211nl_recvmsg (int sd, int request, int seq, 212 void *buf, size_t buflen, int *flags) 213{ 214 struct msghdr msg; 215 struct iovec iov = { buf, buflen }; 216 struct sockaddr_nl nladdr; 217 int read_len; 218 219 for (;;) 220 { 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; 234 } 235 return read_len; 236} 237 238static int 239nl_getmsg (int sd, int request, int seq, pid_t pid, struct nlmsghdr **nlhp, int *done) 240{ 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 for (;;) 247 { 248 void *newbuff = realloc (buff, bufsize); 249 if (newbuff == NULL || bufsize < lastbufsize) 250 { 251 result = -1; 252 break; 253 } 254 buff = newbuff; 255 result = read_size = 256 nl_recvmsg (sd, request, seq, buff, bufsize, &msg_flags); 257 if (read_size < 0 || (msg_flags & MSG_TRUNC)) 258 { 259 lastbufsize = bufsize; 260 bufsize *= 2; 261 continue; 262 } 263 if (read_size == 0) 264 break; 265 nh = (struct nlmsghdr *) buff; 266 for (nh = (struct nlmsghdr *) buff; 267 NLMSG_OK (nh, read_size); 268 nh = (struct nlmsghdr *) NLMSG_NEXT (nh, read_size)) 269 { 270 if (nh->nlmsg_pid != pid || nh->nlmsg_seq != seq) 271 continue; 272 if (nh->nlmsg_type == NLMSG_DONE) 273 { 274 (*done)++; 275 break; /* ok */ 276 } 277 if (nh->nlmsg_type == NLMSG_ERROR) 278 { 279 struct nlmsgerr *nlerr = (struct nlmsgerr *) NLMSG_DATA (nh); 280 result = -1; 281 if (nh->nlmsg_len < NLMSG_LENGTH (sizeof (struct nlmsgerr))) 282 __set_errno (EIO); 283 else 284 __set_errno (-nlerr->error); 285 break; 286 } 287 } 288 break; 289 } 290 if (result < 0) 291 if (buff) 292 { 293 int saved_errno = errno; 294 free (buff); 295 __set_errno (saved_errno); 296 } 297 *nlhp = (struct nlmsghdr *) buff; 298 return result; 299} 300 301static int 302nl_getlist (int sd, int seq, pid_t pid, 303 int request, 304 struct nlmsg_list **nlm_list, struct nlmsg_list **nlm_end) 305{ 306 struct nlmsghdr *nlh = NULL; 307 int status; 308 int done = 0; 309 310 status = nl_sendreq (sd, request, NLM_F_ROOT | NLM_F_MATCH, &seq); 311 if (status < 0) 312 return status; 313 if (seq == 0) 314 seq = (int) time (NULL); 315 while (!done) 316 { 317 status = nl_getmsg (sd, request, seq, pid, &nlh, &done); 318 if (status < 0) 319 return status; 320 if (nlh) 321 { 322 struct nlmsg_list *nlm_next = 323 (struct nlmsg_list *) malloc (sizeof (struct nlmsg_list)); 324 if (nlm_next == NULL) 325 { 326 int saved_errno = errno; 327 free (nlh); 328 __set_errno (saved_errno); 329 status = -1; 330 } 331 else 332 { 333 nlm_next->nlm_next = NULL; 334 nlm_next->nlh = (struct nlmsghdr *) nlh; 335 nlm_next->size = status; 336 nlm_next->seq = seq; 337 if (*nlm_list == NULL) 338 { 339 *nlm_list = nlm_next; 340 *nlm_end = nlm_next; 341 } 342 else 343 { 344 (*nlm_end)->nlm_next = nlm_next; 345 *nlm_end = nlm_next; 346 } 347 } 348 } 349 } 350 return status >= 0 ? seq : status; 351} 352 353/* ---------------------------------------------------------------------- */ 354static void 355free_nlmsglist (struct nlmsg_list *nlm0) 356{ 357 struct nlmsg_list *nlm, *nlm_next; 358 int saved_errno; 359 if (!nlm0) 360 return; 361 saved_errno = errno; 362 nlm = nlm0; 363 while (nlm) 364 { 365 if (nlm->nlh) 366 free (nlm->nlh); 367 nlm_next = nlm->nlm_next; 368 free(nlm); 369 nlm = nlm_next; 370 } 371 __set_errno (saved_errno); 372} 373 374static void 375free_data (void *data, void *ifdata) 376{ 377 int saved_errno = errno; 378 if (data != NULL) 379 free (data); 380 if (ifdata != NULL) 381 free (ifdata); 382 __set_errno (saved_errno); 383} 384 385/* ---------------------------------------------------------------------- */ 386static void 387nl_close (int sd) 388{ 389 int saved_errno = errno; 390 if (sd >= 0) 391 close (sd); 392 __set_errno (saved_errno); 393} 394 395/* ---------------------------------------------------------------------- */ 396static int 397nl_open (pid_t *pid) 398{ 399 struct sockaddr_nl nladdr; 400 int sd; 401 402 sd = socket (PF_NETLINK, SOCK_RAW, NETLINK_ROUTE); 403 if (sd < 0) 404 return -1; 405 memset (&nladdr, 0, sizeof (nladdr)); 406 nladdr.nl_family = AF_NETLINK; 407 if (bind (sd, (struct sockaddr *) &nladdr, sizeof (nladdr)) < 0) 408 { 409 nl_close (sd); 410 return -1; 411 } 412 if (pid) 413 { 414 socklen_t len = sizeof(nladdr); 415 if (getsockname (sd, (struct sockaddr *) &nladdr, &len) < 0) 416 { 417 nl_close (sd); 418 return -1; 419 } 420 *pid = nladdr.nl_pid; 421 } 422 return sd; 423} 424 425/* ====================================================================== */ 426int 427getifaddrs (struct ifaddrs **ifap) 428{ 429 int sd; 430 struct nlmsg_list *nlmsg_list, *nlmsg_end, *nlm; 431 /* - - - - - - - - - - - - - - - */ 432 int icnt; 433 size_t dlen, xlen, nlen; 434 uint32_t max_ifindex = 0; 435 436 pid_t pid; 437 int seq; 438 int result; 439 int build; /* 0 or 1 */ 440 441/* ---------------------------------- */ 442 /* initialize */ 443 icnt = dlen = xlen = nlen = 0; 444 nlmsg_list = nlmsg_end = NULL; 445 446 if (ifap) 447 *ifap = NULL; 448 449/* ---------------------------------- */ 450 /* open socket and bind */ 451 sd = nl_open (&pid); 452 if (sd < 0) 453 return -1; 454 455/* ---------------------------------- */ 456 /* gather info */ 457 if ((seq = nl_getlist (sd, 0, pid, RTM_GETLINK, &nlmsg_list, &nlmsg_end)) < 0) 458 { 459 free_nlmsglist (nlmsg_list); 460 nl_close (sd); 461 return -1; 462 } 463 if ((seq = nl_getlist (sd, seq + 1, pid, RTM_GETADDR, 464 &nlmsg_list, &nlmsg_end)) < 0) 465 { 466 free_nlmsglist (nlmsg_list); 467 nl_close (sd); 468 return -1; 469 } 470 471/* ---------------------------------- */ 472 /* Estimate size of result buffer and fill it */ 473 for (build = 0; build <= 1; build++) 474 { 475 struct ifaddrs *ifl = NULL, *ifa = NULL; 476 struct nlmsghdr *nlh, *nlh0; 477 void *data = NULL, *xdata = NULL, *ifdata = NULL; 478 char *ifname = NULL, **iflist = NULL; 479 uint16_t *ifflist = NULL; 480 struct rtmaddr_ifamap ifamap; 481 482 if (build) 483 { 484 ifa = data = calloc (1, 485 NLMSG_ALIGN (sizeof (struct ifaddrs[icnt])) 486 + dlen + xlen + nlen); 487 ifdata = calloc (1, 488 NLMSG_ALIGN (sizeof (char *[max_ifindex + 1])) 489 + 490 NLMSG_ALIGN (sizeof (uint16_t[max_ifindex + 1]))); 491 if (ifap != NULL) 492 *ifap = (ifdata != NULL) ? ifa : NULL; 493 else 494 { 495 free_data (data, ifdata); 496 result = 0; 497 break; 498 } 499 if (data == NULL || ifdata == NULL) 500 { 501 free_data (data, ifdata); 502 result = -1; 503 break; 504 } 505 ifl = NULL; 506 data += NLMSG_ALIGN (sizeof (struct ifaddrs)) * icnt; 507 xdata = data + dlen; 508 ifname = xdata + xlen; 509 iflist = ifdata; 510 ifflist = 511 ((void *) iflist) + 512 NLMSG_ALIGN (sizeof (char *[max_ifindex + 1])); 513 } 514 515 for (nlm = nlmsg_list; nlm; nlm = nlm->nlm_next) 516 { 517 int nlmlen = nlm->size; 518 if (!(nlh0 = nlm->nlh)) 519 continue; 520 for (nlh = nlh0; 521 NLMSG_OK (nlh, nlmlen); nlh = NLMSG_NEXT (nlh, nlmlen)) 522 { 523 struct ifinfomsg *ifim = NULL; 524 struct ifaddrmsg *ifam = NULL; 525 struct rtattr *rta; 526 527 size_t nlm_struct_size = 0; 528 sa_family_t nlm_family = 0; 529 uint32_t nlm_scope = 0, nlm_index = 0; 530#ifndef IFA_NETMASK 531 size_t sockaddr_size = 0; 532 uint32_t nlm_prefixlen = 0; 533#endif 534 size_t rtasize; 535 536 memset (&ifamap, 0, sizeof (ifamap)); 537 538 /* check if the message is what we want */ 539 if (nlh->nlmsg_pid != pid || nlh->nlmsg_seq != nlm->seq) 540 continue; 541 if (nlh->nlmsg_type == NLMSG_DONE) 542 { 543 break; /* ok */ 544 } 545 switch (nlh->nlmsg_type) 546 { 547 case RTM_NEWLINK: 548 ifim = (struct ifinfomsg *) NLMSG_DATA (nlh); 549 nlm_struct_size = sizeof (*ifim); 550 nlm_family = ifim->ifi_family; 551 nlm_scope = 0; 552 nlm_index = ifim->ifi_index; 553 nlm_prefixlen = 0; 554 if (build) 555 ifflist[nlm_index] = ifa->ifa_flags = ifim->ifi_flags; 556 break; 557 case RTM_NEWADDR: 558 ifam = (struct ifaddrmsg *) NLMSG_DATA (nlh); 559 nlm_struct_size = sizeof (*ifam); 560 nlm_family = ifam->ifa_family; 561 nlm_scope = ifam->ifa_scope; 562 nlm_index = ifam->ifa_index; 563 nlm_prefixlen = ifam->ifa_prefixlen; 564 if (build) 565 ifa->ifa_flags = ifflist[nlm_index]; 566 break; 567 default: 568 continue; 569 } 570 571 if (!build) 572 { 573 if (max_ifindex < nlm_index) 574 max_ifindex = nlm_index; 575 } 576 else 577 { 578 if (ifl != NULL) 579 ifl->ifa_next = ifa; 580 } 581 582 rtasize = 583 NLMSG_PAYLOAD (nlh, nlmlen) - NLMSG_ALIGN (nlm_struct_size); 584 for (rta = 585 (struct rtattr *) (((char *) NLMSG_DATA (nlh)) + 586 NLMSG_ALIGN (nlm_struct_size)); 587 RTA_OK (rta, rtasize); rta = RTA_NEXT (rta, rtasize)) 588 { 589 struct sockaddr **sap = NULL; 590 void *rtadata = RTA_DATA (rta); 591 size_t rtapayload = RTA_PAYLOAD (rta); 592 socklen_t sa_len; 593 594 switch (nlh->nlmsg_type) 595 { 596 case RTM_NEWLINK: 597 switch (rta->rta_type) 598 { 599 case IFLA_ADDRESS: 600 case IFLA_BROADCAST: 601 if (build) 602 { 603 sap = 604 (rta->rta_type == 605 IFLA_ADDRESS) ? &ifa->ifa_addr : &ifa-> 606 ifa_broadaddr; 607 *sap = (struct sockaddr *) data; 608 } 609 sa_len = ifa_sa_len (AF_PACKET, rtapayload); 610 if (rta->rta_type == IFLA_ADDRESS) 611 sockaddr_size = NLMSG_ALIGN (sa_len); 612 if (!build) 613 { 614 dlen += NLMSG_ALIGN (sa_len); 615 } 616 else 617 { 618 memset (*sap, 0, sa_len); 619 ifa_make_sockaddr (AF_PACKET, *sap, rtadata, 620 rtapayload, 0, 0); 621 ((struct sockaddr_ll *) *sap)->sll_ifindex = 622 nlm_index; 623 ((struct sockaddr_ll *) *sap)->sll_hatype = 624 ifim->ifi_type; 625 data += NLMSG_ALIGN (sa_len); 626 } 627 break; 628 case IFLA_IFNAME: /* Name of Interface */ 629 if (!build) 630 nlen += NLMSG_ALIGN (rtapayload + 1); 631 else 632 { 633 ifa->ifa_name = ifname; 634 if (iflist[nlm_index] == NULL) 635 iflist[nlm_index] = ifa->ifa_name; 636 strncpy (ifa->ifa_name, rtadata, rtapayload); 637 ifa->ifa_name[rtapayload] = '\0'; 638 ifname += NLMSG_ALIGN (rtapayload + 1); 639 } 640 break; 641 case IFLA_STATS: /* Statistics of Interface */ 642 if (!build) 643 xlen += NLMSG_ALIGN (rtapayload); 644 else 645 { 646 ifa->ifa_data = xdata; 647 memcpy (ifa->ifa_data, rtadata, rtapayload); 648 xdata += NLMSG_ALIGN (rtapayload); 649 } 650 break; 651 case IFLA_UNSPEC: 652 break; 653 case IFLA_MTU: 654 break; 655 case IFLA_LINK: 656 break; 657 case IFLA_QDISC: 658 break; 659 default: 660 ; 661 } 662 break; 663 case RTM_NEWADDR: 664 if (nlm_family == AF_PACKET) 665 break; 666 switch (rta->rta_type) 667 { 668 case IFA_ADDRESS: 669 ifamap.address = rtadata; 670 ifamap.address_len = rtapayload; 671 break; 672 case IFA_LOCAL: 673 ifamap.local = rtadata; 674 ifamap.local_len = rtapayload; 675 break; 676 case IFA_BROADCAST: 677 ifamap.broadcast = rtadata; 678 ifamap.broadcast_len = rtapayload; 679 break; 680#ifdef HAVE_IFADDRS_IFA_ANYCAST 681 case IFA_ANYCAST: 682 ifamap.anycast = rtadata; 683 ifamap.anycast_len = rtapayload; 684 break; 685#endif 686 case IFA_LABEL: 687 if (!build) 688 nlen += NLMSG_ALIGN (rtapayload + 1); 689 else 690 { 691 ifa->ifa_name = ifname; 692 if (iflist[nlm_index] == NULL) 693 iflist[nlm_index] = ifname; 694 strncpy (ifa->ifa_name, rtadata, rtapayload); 695 ifa->ifa_name[rtapayload] = '\0'; 696 ifname += NLMSG_ALIGN (rtapayload + 1); 697 } 698 break; 699 case IFA_UNSPEC: 700 break; 701 case IFA_CACHEINFO: 702 break; 703 default: 704 ; 705 } 706 } 707 } 708 if (nlh->nlmsg_type == RTM_NEWADDR && nlm_family != AF_PACKET) 709 { 710 if (!ifamap.local) 711 { 712 ifamap.local = ifamap.address; 713 ifamap.local_len = ifamap.address_len; 714 } 715 if (!ifamap.address) 716 { 717 ifamap.address = ifamap.local; 718 ifamap.address_len = ifamap.local_len; 719 } 720 if (ifamap.address_len != ifamap.local_len || 721 (ifamap.address != NULL && 722 memcmp (ifamap.address, ifamap.local, 723 ifamap.address_len))) 724 { 725 /* p2p; address is peer and local is ours */ 726 ifamap.broadcast = ifamap.address; 727 ifamap.broadcast_len = ifamap.address_len; 728 ifamap.address = ifamap.local; 729 ifamap.address_len = ifamap.local_len; 730 } 731 if (ifamap.address) 732 { 733#ifndef IFA_NETMASK 734 sockaddr_size = 735 NLMSG_ALIGN (ifa_sa_len 736 (nlm_family, ifamap.address_len)); 737#endif 738 if (!build) 739 dlen += 740 NLMSG_ALIGN (ifa_sa_len 741 (nlm_family, ifamap.address_len)); 742 else 743 { 744 ifa->ifa_addr = (struct sockaddr *) data; 745 ifa_make_sockaddr (nlm_family, ifa->ifa_addr, 746 ifamap.address, 747 ifamap.address_len, nlm_scope, 748 nlm_index); 749 data += 750 NLMSG_ALIGN (ifa_sa_len 751 (nlm_family, ifamap.address_len)); 752 } 753 } 754#ifdef IFA_NETMASK 755 if (ifamap.netmask) 756 { 757 if (!build) 758 dlen += 759 NLMSG_ALIGN (ifa_sa_len 760 (nlm_family, ifamap.netmask_len)); 761 else 762 { 763 ifa->ifa_netmask = (struct sockaddr *) data; 764 ifa_make_sockaddr (nlm_family, ifa->ifa_netmask, 765 ifamap.netmask, 766 ifamap.netmask_len, nlm_scope, 767 nlm_index); 768 data += 769 NLMSG_ALIGN (ifa_sa_len 770 (nlm_family, ifamap.netmask_len)); 771 } 772 } 773#endif 774 if (ifamap.broadcast) 775 { 776 if (!build) 777 dlen += 778 NLMSG_ALIGN (ifa_sa_len 779 (nlm_family, ifamap.broadcast_len)); 780 else 781 { 782 ifa->ifa_broadaddr = (struct sockaddr *) data; 783 ifa_make_sockaddr (nlm_family, ifa->ifa_broadaddr, 784 ifamap.broadcast, 785 ifamap.broadcast_len, nlm_scope, 786 nlm_index); 787 data += 788 NLMSG_ALIGN (ifa_sa_len 789 (nlm_family, ifamap.broadcast_len)); 790 } 791 } 792#ifdef HAVE_IFADDRS_IFA_ANYCAST 793 if (ifamap.anycast) 794 { 795 if (!build) 796 dlen += 797 NLMSG_ALIGN (ifa_sa_len 798 (nlm_family, ifamap.anycast_len)); 799 else 800 { 801 ifa->ifa_anycast = (struct sockaddr *) data; 802 ifa_make_sockaddr (nlm_family, ifa->ifa_anyaddr, 803 ifamap.anycast, 804 ifamap.anycast_len, nlm_scope, 805 nlm_index); 806 data += 807 NLMSG_ALIGN (ifa_sa_len 808 (nlm_family, ifamap.anycast_len)); 809 } 810 } 811#endif 812 } 813 if (!build) 814 { 815#ifndef IFA_NETMASK 816 dlen += sockaddr_size; 817#endif 818 icnt++; 819 } 820 else 821 { 822 if (ifa->ifa_name == NULL) 823 ifa->ifa_name = iflist[nlm_index]; 824#ifndef IFA_NETMASK 825 if (ifa->ifa_addr && 826 ifa->ifa_addr->sa_family != AF_UNSPEC && 827 ifa->ifa_addr->sa_family != AF_PACKET) 828 { 829 ifa->ifa_netmask = (struct sockaddr *) data; 830 ifa_make_sockaddr_mask (ifa->ifa_addr->sa_family, 831 ifa->ifa_netmask, 832 nlm_prefixlen); 833 } 834 data += sockaddr_size; 835#endif 836 ifl = ifa++; 837 } 838 } 839 } 840 if (!build) 841 { 842 if (icnt == 0 && (dlen + nlen + xlen == 0)) 843 { 844 if (ifap != NULL) 845 *ifap = NULL; 846 break; /* cannot found any addresses */ 847 } 848 } 849 else 850 free_data (NULL, ifdata); 851 } 852 853/* ---------------------------------- */ 854 /* Finalize */ 855 free_nlmsglist (nlmsg_list); 856 nl_close (sd); 857 return 0; 858} 859 860/* ---------------------------------------------------------------------- */ 861void 862freeifaddrs (struct ifaddrs *ifa) 863{ 864 free (ifa); 865} 866