1/* 2 * Copyright (c) 1999-2013 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23/* 24 * interfaces.c 25 * - get the list of interfaces in the system 26 */ 27 28/* 29 * Modification History 30 * 02/23/98 Dieter Siegmund (dieter@apple.com) 31 * - initial version 32 */ 33 34#include <stdio.h> 35#include <unistd.h> 36#include <stdlib.h> 37#include <sys/ioctl.h> 38#include <sys/types.h> 39#include <strings.h> 40#include <netdb.h> 41#include "interfaces.h" 42#include <arpa/inet.h> 43#include <net/if_types.h> 44#include <net/if_var.h> 45#include <sys/socket.h> 46#include <sys/sysctl.h> 47#include <net/if_media.h> 48#include <net/route.h> 49#include <ifaddrs.h> 50 51#include "util.h" 52#include "IPConfigurationLog.h" 53 54static boolean_t 55S_get_ifmediareq(const char * name, struct ifmediareq * ifmr_p); 56 57static boolean_t 58S_get_ifmediareq_s(int s, const char * name, struct ifmediareq * ifmr_p); 59 60static boolean_t 61S_is_awdl(int s, const char * name); 62 63static boolean_t 64S_ifmediareq_get_is_wireless(struct ifmediareq * ifmr_p); 65 66static link_status_t 67S_ifmediareq_get_link_status(struct ifmediareq * ifmr_p); 68 69void * 70inet_addrinfo_copy(void * p) 71{ 72 inet_addrinfo_t * src = (inet_addrinfo_t *)p; 73 inet_addrinfo_t * dest; 74 75 dest = malloc(sizeof(*dest)); 76 if (dest) { 77 bcopy(src, dest, sizeof(*dest)); 78 } 79 return (dest); 80} 81 82void 83inet_addrinfo_free(void * p) 84{ 85 free(p); 86 return; 87} 88 89static interface_t * 90S_next_entry(interface_list_t * interfaces, const char * name) 91{ 92 interface_t * entry; 93 94 if (interfaces->count >= interfaces->size) 95 return (NULL); 96 97 entry = interfaces->list + interfaces->count++; 98 bzero(entry, sizeof(*entry)); 99 strlcpy(entry->name, name, sizeof(entry->name)); 100 dynarray_init(&entry->inet, inet_addrinfo_free, 101 inet_addrinfo_copy); 102 return (entry); 103} 104 105static __inline__ int 106count_ifaddrs(const struct ifaddrs * ifap) 107{ 108 int count; 109 110 for (count = 0; ifap != NULL && ifap->ifa_addr != NULL; 111 ifap = ifap->ifa_next) { 112 count++; 113 } 114 return (count); 115} 116 117static boolean_t 118S_build_interface_list(interface_list_t * interfaces) 119{ 120 struct ifaddrs * addrs = NULL; 121 struct ifaddrs * ifap = NULL; 122 struct ifmediareq ifmr; 123 int s = -1; 124 int size; 125 boolean_t success = FALSE; 126 127 if (getifaddrs(&addrs) < 0) { 128 goto done; 129 } 130 size = count_ifaddrs(addrs); 131 interfaces->list 132 = (interface_t *)malloc(size * sizeof(*(interfaces->list))); 133 if (interfaces->list == NULL) { 134 goto done; 135 } 136 137 s = socket(AF_INET, SOCK_DGRAM, 0); 138 if (s < 0) { 139 goto done; 140 } 141 interfaces->count = 0; 142 interfaces->size = size; 143 144 for (ifap = addrs; ifap != NULL; ifap = ifap->ifa_next) { 145 const char * name; 146 if (ifap->ifa_addr == NULL) { 147 continue; 148 } 149 name = ifap->ifa_name; 150 switch (ifap->ifa_addr->sa_family) { 151 case AF_INET: { 152 inet_addrinfo_t info; 153 interface_t * entry; 154 155 entry = ifl_find_name(interfaces, name); 156 if (entry == NULL) { /* new entry */ 157 entry = S_next_entry(interfaces, name); 158 if (entry == NULL) { 159 /* NOT REACHED */ 160 IPConfigLog(LOG_ERR, 161 "interfaces: S_next_entry returns NULL"); 162 continue; 163 } 164 entry->flags = ifap->ifa_flags; 165 } 166 bzero(&info, sizeof(info)); 167 168 /* ALIGN: getifaddrs should align, cast ok. */ 169 info.addr = ((struct sockaddr_in *) 170 (void *)ifap->ifa_addr)->sin_addr; 171 172 if (ifap->ifa_netmask != NULL) { 173 /* ALIGN: getifaddrs should align, cast ok. */ 174 info.mask 175 = ((struct sockaddr_in *) 176 (void *)ifap->ifa_netmask)->sin_addr; 177 } 178 if (entry->flags & IFF_BROADCAST && ifap->ifa_broadaddr != NULL) { 179 /* ALIGN: getifaddrs should align, cast ok. */ 180 info.broadcast 181 = ((struct sockaddr_in *)(void *) 182 ifap->ifa_broadaddr)->sin_addr; 183 } 184 info.netaddr.s_addr = htonl(iptohl(info.addr) 185 & iptohl(info.mask)); 186 dynarray_add(&entry->inet, inet_addrinfo_copy(&info)); 187 break; 188 } 189 case AF_LINK: { 190 struct sockaddr_dl * dl_p; 191 interface_t * entry; 192 struct if_data * if_data; 193 194 /* ALIGN: getifaddrs should align, cast ok. */ 195 dl_p = (struct sockaddr_dl *) 196 (void *)ifap->ifa_addr; 197 198 entry = ifl_find_name(interfaces, name); 199 if (entry == NULL) { /* new entry */ 200 entry = S_next_entry(interfaces, name); 201 if (entry == NULL) { 202 /* NOT REACHED */ 203 IPConfigLog(LOG_ERR, 204 "interfaces: S_next_entry returns NULL"); 205 continue; 206 } 207 entry->flags = ifap->ifa_flags; 208 } 209 if (dl_p->sdl_alen > sizeof(entry->link_address.addr)) { 210 IPConfigLog(LOG_ERR, 211 "%s: link type %d address length %d > %ld", name, 212 dl_p->sdl_type, dl_p->sdl_alen, 213 sizeof(entry->link_address.addr)); 214 entry->link_address.length = sizeof(entry->link_address.addr); 215 } 216 else { 217 entry->link_address.length = dl_p->sdl_alen; 218 } 219 bcopy(dl_p->sdl_data + dl_p->sdl_nlen, 220 entry->link_address.addr, 221 entry->link_address.length); 222 entry->link_address.type = dl_p->sdl_type; 223 entry->link_address.index = dl_p->sdl_index; 224 if_data = (struct if_data *)ifap->ifa_data; 225 if (if_data != NULL) { 226 entry->type = if_data->ifi_type; 227 } 228 else { 229 entry->type = dl_p->sdl_type; 230 } 231 if (S_get_ifmediareq_s(s, name, &ifmr)) { 232 if (entry->type == IFT_ETHER) { 233 234 if (S_ifmediareq_get_is_wireless(&ifmr)) { 235 entry->type_flags |= kInterfaceTypeFlagIsWireless; 236 if (S_is_awdl(s, name)) { 237 entry->type_flags |= kInterfaceTypeFlagIsAWDL; 238 } 239 } 240 } 241 entry->link_status 242 = S_ifmediareq_get_link_status(&ifmr); 243 } 244 break; 245 } 246 } 247 } 248 /* make it the "right" size (plus 1 more in case it's 0) */ 249 interfaces->list = (interface_t *) 250 realloc(interfaces->list, 251 sizeof(*(interfaces->list)) * (interfaces->count + 1)); 252 success = TRUE; 253 254 done: 255 if (addrs != NULL) { 256 freeifaddrs(addrs); 257 } 258 if (success == FALSE) { 259 if (interfaces->list != NULL) { 260 free(interfaces->list); 261 } 262 interfaces->list = NULL; 263 } 264 if (s >= 0) { 265 close(s); 266 } 267 return (success); 268} 269 270int 271ifl_count(interface_list_t * list_p) 272{ 273 return (list_p->count); 274} 275 276interface_t * 277ifl_at_index(interface_list_t * list_p, int i) 278{ 279 if (i >= list_p->count || i < 0) 280 return (NULL); 281 return (list_p->list + i); 282} 283 284int 285ifl_index(interface_list_t * list_p, interface_t * if_p) 286{ 287 return (if_p - list_p->list); 288} 289 290/* 291 * Function: ifl_first_broadcast_inet 292 * 293 * Purpose: 294 * Return the first non-loopback, broadcast capable interface. 295 */ 296interface_t * 297ifl_first_broadcast_inet(interface_list_t * list_p) 298{ 299 int i; 300 for (i = 0; i < list_p->count; i++) { 301 interface_t * if_p = list_p->list + i; 302 303 if (dynarray_count(&if_p->inet) > 0 304 && !(if_p->flags & IFF_LOOPBACK) 305 && (if_p->flags & IFF_BROADCAST)) 306 return (list_p->list + i); 307 } 308 return (NULL); 309} 310 311interface_t * 312ifl_find_ip(interface_list_t * list_p, struct in_addr iaddr) 313{ 314 int i; 315 316 for (i = 0; i < list_p->count; i++) { 317 interface_t * if_p = list_p->list + i; 318 int j; 319 320 for (j = 0; j < dynarray_count(&if_p->inet); j++) { 321 inet_addrinfo_t * info; 322 323 info = dynarray_element(&if_p->inet, j); 324 if (info->addr.s_addr == iaddr.s_addr) 325 return (if_p); 326 } 327 } 328 return (NULL); 329} 330 331interface_t * 332ifl_find_subnet(interface_list_t * list_p, struct in_addr iaddr) 333{ 334 int i; 335 u_long addr_hl = iptohl(iaddr); 336 337 for (i = 0; i < list_p->count; i++) { 338 interface_t * if_p = list_p->list + i; 339 int j; 340 341 for (j = 0; j < dynarray_count(&if_p->inet); j++) { 342 inet_addrinfo_t * info = dynarray_element(&if_p->inet, j); 343 u_long ifnetaddr_hl = iptohl(info->netaddr); 344 u_long ifmask_hl = iptohl(info->mask); 345 346 if ((addr_hl & ifmask_hl) == ifnetaddr_hl) 347 return (if_p); 348 } 349 } 350 return (NULL); 351} 352 353interface_t * 354ifl_find_name(interface_list_t * list_p, const char * name) 355{ 356 int i; 357 358 for (i = 0; i < list_p->count; i++) { 359 if (strcmp(list_p->list[i].name, name) == 0) 360 return (list_p->list + i); 361 } 362 return (NULL); 363} 364 365interface_t * 366ifl_find_link(interface_list_t * list_p, int index) 367{ 368 int i; 369 370 for (i = 0; i < list_p->count; i++) { 371 if (list_p->list[i].link_address.type != 0 372 && list_p->list[i].link_address.index == index) 373 return (list_p->list + i); 374 } 375 return (NULL); 376} 377 378interface_list_t * 379ifl_init() 380{ 381 interface_list_t * list_p = (interface_list_t *)malloc(sizeof(*list_p)); 382 if (list_p == NULL 383 || S_build_interface_list(list_p) == FALSE) { 384 if (list_p) 385 free(list_p); 386 return (NULL); 387 } 388 return (list_p); 389} 390 391void 392ifl_free(interface_list_t * * iflist) 393{ 394 if (iflist != NULL && *iflist != NULL) { 395 int i; 396 interface_list_t * list_p = *iflist; 397 398 for (i = 0; i < list_p->count; i++) { 399 dynarray_free(&list_p->list[i].inet); 400 } 401 if (list_p->list) 402 free(list_p->list); 403 free(list_p); 404 *iflist = NULL; 405 } 406 return; 407} 408 409/* 410 * Functions: if_* 411 * Purpose: 412 * Interface-specific routines. 413 */ 414const char * 415if_name(interface_t * if_p) 416{ 417 return (if_p->name); 418} 419 420uint16_t 421if_flags(interface_t * if_p) 422{ 423 return (if_p->flags); 424} 425 426int 427if_inet_count(interface_t * if_p) 428{ 429 return (dynarray_count(&if_p->inet)); 430} 431 432inet_addrinfo_t * 433if_inet_addr_at(interface_t * if_p, int i) 434{ 435 return (dynarray_element(&if_p->inet, i)); 436} 437 438/* get the primary address, mask, broadcast */ 439struct in_addr 440if_inet_addr(interface_t * if_p) 441{ 442 inet_addrinfo_t * info = if_inet_addr_at(if_p, 0); 443 444 if (info == NULL) { 445 struct in_addr zeroes = { 0 }; 446 return (zeroes); 447 } 448 return (info->addr); 449} 450 451struct in_addr 452if_inet_netmask(interface_t * if_p) 453{ 454 inet_addrinfo_t * info = if_inet_addr_at(if_p, 0); 455 return (info->mask); 456} 457 458struct in_addr 459if_inet_netaddr(interface_t * if_p) 460{ 461 inet_addrinfo_t * info = if_inet_addr_at(if_p, 0); 462 return (info->netaddr); 463} 464 465struct in_addr 466if_inet_broadcast(interface_t * if_p) 467{ 468 inet_addrinfo_t * info = if_inet_addr_at(if_p, 0); 469 return (info->broadcast); 470} 471 472void 473if_setflags(interface_t * if_p, uint16_t flags) 474{ 475 if_p->flags = flags; 476 return; 477} 478 479boolean_t 480if_inet_valid(interface_t * if_p) 481{ 482 return (dynarray_count(&if_p->inet) > 0); 483} 484 485void 486if_free(interface_t * * if_p_p) 487{ 488 interface_t * if_p; 489 490 if (if_p_p == NULL) { 491 return; 492 } 493 if_p = *if_p_p; 494 if (if_p == NULL) { 495 return; 496 } 497 dynarray_free(&if_p->inet); 498 free(if_p); 499 *if_p_p = NULL; 500 return; 501} 502 503interface_t * 504if_dup(interface_t * intface) 505{ 506 interface_t * new_p; 507 508 new_p = (interface_t *)calloc(1, sizeof(*new_p)); 509 if (new_p == NULL) { 510 return (NULL); 511 } 512 *new_p = *intface; 513 (void)dynarray_dup(&new_p->inet, &intface->inet); 514 return (new_p); 515} 516 517int 518if_inet_find_ip(interface_t * if_p, struct in_addr iaddr) 519{ 520 int i; 521 for (i = 0; i < if_inet_count(if_p); i++) { 522 inet_addrinfo_t * info = if_inet_addr_at(if_p, i); 523 if (info->addr.s_addr == iaddr.s_addr) { 524 return (i); 525 } 526 } 527 return (INDEX_BAD); 528} 529 530void 531if_link_copy(interface_t * dest, const interface_t * source) 532{ 533 dest->link_status = source->link_status; 534 dest->link_address = source->link_address; 535 return; 536} 537 538boolean_t 539if_link_update(interface_t * if_p) 540{ 541 void * addr; 542 int addr_length; 543 char * buf = NULL; 544 size_t buf_len = 0; 545 boolean_t changed = FALSE; 546 struct sockaddr_dl * dl_p; 547 struct if_msghdr * ifm; 548 int mib[6]; 549 int type; 550 551 mib[0] = CTL_NET; 552 mib[1] = PF_ROUTE; 553 mib[2] = 0; 554 mib[3] = AF_LINK; 555 mib[4] = NET_RT_IFLIST; 556 mib[5] = if_p->link_address.index; /* ask for exactly one interface */ 557 558 if (sysctl(mib, 6, NULL, &buf_len, NULL, 0) < 0) { 559 fprintf(stderr, "sysctl() size failed: %s", strerror(errno)); 560 goto failed; 561 } 562 buf = malloc(buf_len); 563 if (sysctl(mib, 6, buf, &buf_len, NULL, 0) < 0) { 564 fprintf(stderr, "sysctl() failed: %s", strerror(errno)); 565 goto failed; 566 } 567 /* ALIGN: buf is aligned (from malloc), cast ok. */ 568 ifm = (struct if_msghdr *)(void *)buf; 569 switch (ifm->ifm_type) { 570 case RTM_IFINFO: 571 dl_p = (struct sockaddr_dl *)(ifm + 1); 572 addr = dl_p->sdl_data + dl_p->sdl_nlen; 573 addr_length = dl_p->sdl_alen; 574 type = dl_p->sdl_type; 575 if (addr_length > sizeof(if_p->link_address.addr)) { 576 IPConfigLog(LOG_DEBUG, 577 "%s: link type %d address length %d > %ld", 578 if_name(if_p), 579 type, 580 addr_length, 581 sizeof(if_p->link_address.addr)); 582 addr_length = sizeof(if_p->link_address.addr); 583 } 584 if (if_p->link_address.type != type 585 || addr_length != if_p->link_address.length 586 || (addr_length != 0 587 && bcmp(addr, if_p->link_address.addr, addr_length))) { 588 changed = TRUE; 589 if_p->link_address.length = addr_length; 590 bcopy(addr, if_p->link_address.addr, addr_length); 591 if_p->link_address.type = dl_p->sdl_type; 592 } 593 } 594 failed: 595 if (buf != NULL) { 596 free(buf); 597 } 598 return (changed); 599} 600 601int 602if_ift_type(interface_t * if_p) 603{ 604 return (if_p->type); 605} 606 607int 608if_link_type(interface_t * if_p) 609{ 610 return (if_p->link_address.type); 611} 612 613int 614if_link_dhcptype(interface_t * if_p) 615{ 616 if (if_p->link_address.type == IFT_IEEE1394) { 617 return (ARPHRD_IEEE1394_EUI64); 618 } 619 else { 620 return (dl_to_arp_hwtype(if_p->link_address.type)); 621 } 622} 623 624int 625if_link_arptype(interface_t * if_p) 626{ 627 return (dl_to_arp_hwtype(if_p->link_address.type)); 628} 629 630 631void * 632if_link_address(interface_t * if_p) 633{ 634 return (if_p->link_address.addr); 635} 636 637int 638if_link_length(interface_t * if_p) 639{ 640 return (if_p->link_address.length); 641} 642 643boolean_t 644if_is_wireless(interface_t * if_p) 645{ 646 return ((if_p->type_flags & kInterfaceTypeFlagIsWireless) != 0); 647} 648 649boolean_t 650if_is_awdl(interface_t * if_p) 651{ 652 return ((if_p->type_flags & kInterfaceTypeFlagIsAWDL) != 0); 653} 654 655int 656if_link_index(interface_t * if_p) 657{ 658 return (if_p->link_address.index); 659} 660 661link_status_t 662if_get_link_status(interface_t * if_p) 663{ 664 return (if_p->link_status); 665} 666 667static int 668siocgifmedia(int sockfd, struct ifmediareq * ifmr_p, 669 const char * name) 670{ 671 (void)memset(ifmr_p, 0, sizeof(*ifmr_p)); 672 (void)strlcpy(ifmr_p->ifm_name, name, sizeof(ifmr_p->ifm_name)); 673 return (ioctl(sockfd, SIOCGIFMEDIA, (caddr_t)ifmr_p)); 674} 675 676static boolean_t 677S_get_ifmediareq_s(int s, const char * name, struct ifmediareq * ifmr_p) 678{ 679 boolean_t ret; 680 681 if (siocgifmedia(s, ifmr_p, name) == -1) { 682 if (errno == EOPNOTSUPP) { 683 ifmr_p->ifm_status = IFM_ACTIVE | IFM_AVALID; 684 ifmr_p->ifm_count = 1; 685 ret = TRUE; 686 } 687 else { 688 ret = FALSE; 689 } 690 } 691 else { 692 ret = TRUE; 693 } 694 return (ret); 695} 696 697static boolean_t 698S_get_ifmediareq(const char * name, struct ifmediareq * ifmr_p) 699{ 700 int s; 701 boolean_t success = FALSE; 702 703 s = socket(AF_INET, SOCK_DGRAM, 0); 704 if (s >= 0) { 705 success = S_get_ifmediareq_s(s, name, ifmr_p); 706 close(s); 707 } 708 return (success); 709} 710 711 712static boolean_t 713S_ifmediareq_get_is_wireless(struct ifmediareq * ifmr_p) 714{ 715 return (IFM_TYPE(ifmr_p->ifm_current) == IFM_IEEE80211); 716} 717 718static link_status_t 719S_ifmediareq_get_link_status(struct ifmediareq * ifmr_p) 720{ 721 link_status_t link; 722 723 bzero(&link, sizeof(link)); 724 if (ifmr_p->ifm_count > 0 && (ifmr_p->ifm_status & IFM_AVALID) != 0) { 725 link.valid = TRUE; 726 if ((ifmr_p->ifm_status & IFM_ACTIVE) != 0) { 727 link.active = TRUE; 728 } 729 link.wake_on_same_network 730 = ((ifmr_p->ifm_status & IFM_WAKESAMENET) != 0); 731 } 732 return (link); 733} 734 735static int 736siocgifeflags(int sockfd, struct ifreq * ifr, const char * name) 737{ 738 (void)memset(ifr, 0, sizeof(*ifr)); 739 (void)strlcpy(ifr->ifr_name, name, sizeof(ifr->ifr_name)); 740 return (ioctl(sockfd, SIOCGIFEFLAGS, (caddr_t)ifr)); 741} 742 743static boolean_t 744S_is_awdl(int sockfd, const char * name) 745{ 746 struct ifreq ifr; 747 boolean_t is_awdl = FALSE; 748 749 if (siocgifeflags(sockfd, &ifr, name) == -1) { 750 if (errno != ENXIO && errno != EPWROFF && errno != EINVAL) { 751 IPConfigLogFL(LOG_NOTICE, 752 "%s: SIOCGIFEFLAGS failed status, %s", 753 name, strerror(errno)); 754 } 755 } 756 else if ((ifr.ifr_eflags & IFEF_AWDL) != 0) { 757 is_awdl = TRUE; 758 } 759 return (is_awdl); 760} 761 762link_status_t 763if_link_status_update(interface_t * if_p) 764{ 765 struct ifmediareq ifmr; 766 767 if (S_get_ifmediareq(if_name(if_p), &ifmr) == FALSE) { 768 if (errno != ENXIO && errno != EPWROFF && errno != EINVAL) { 769 IPConfigLogFL(LOG_NOTICE, 770 "%s: failed to get media status, %s", 771 if_name(if_p), strerror(errno)); 772 } 773 } 774 else { 775 if_p->link_status = S_ifmediareq_get_link_status(&ifmr); 776 } 777 return (if_p->link_status); 778} 779 780 781#ifdef TEST_INTERFACES 782 783#if 0 784void 785sockaddr_dl_print(struct sockaddr_dl * dl_p) 786{ 787 int i; 788 789 printf("link: len %d index %d family %d type 0x%x nlen %d alen %d" 790 " slen %d addr ", dl_p->sdl_len, 791 dl_p->sdl_index, dl_p->sdl_family, dl_p->sdl_type, 792 dl_p->sdl_nlen, dl_p->sdl_alen, dl_p->sdl_slen); 793 for (i = 0; i < dl_p->sdl_alen; i++) 794 printf("%s%x", i ? ":" : "", 795 ((unsigned char *)dl_p->sdl_data + dl_p->sdl_nlen)[i]); 796 printf("\n"); 797} 798#endif 799 800void 801link_addr_print(link_addr_t * link) 802{ 803 int i; 804 805 printf("link: index %d type 0x%x alen %d%s", link->index, link->type, 806 link->length, link->length > 0 ? " addr" : ""); 807 for (i = 0; i < link->length; i++) { 808 printf("%c%x", i ? ':' : ' ', link->addr[i]); 809 } 810 printf("\n"); 811} 812 813void 814ifl_print(interface_list_t * list_p) 815{ 816 int i; 817 int count = 0; 818 819 printf("Interface count = %d\n", list_p->count); 820 for (i = 0; i < list_p->count; i++) { 821 interface_t * if_p = list_p->list + i; 822 int j; 823 824 if (i > 0) 825 printf("\n"); 826 827 printf("%s: type %d\n", if_name(if_p), if_ift_type(if_p)); 828 829 for (j = 0; j < if_inet_count(if_p); j++) { 830 inet_addrinfo_t * info = if_inet_addr_at(if_p, j); 831 832 printf("inet: %s", inet_ntoa(info->addr)); 833 printf(" netmask %s", inet_ntoa(info->mask)); 834 if (if_flags(if_p) & IFF_BROADCAST) 835 printf(" %s\n", inet_ntoa(info->broadcast)); 836 else 837 printf("\n"); 838 } 839 if (if_p->link_address.type != 0) { 840 link_addr_print(&if_p->link_address); 841 if (if_p->link_status.valid) { 842 printf("Link is %s%s\n", 843 if_p->link_status.active ? "active" : "inactive", 844 if_p->link_status.wake_on_same_network 845 ? " [wake on same network]" : ""); 846 } 847 if (if_is_wireless(if_p)) { 848 printf("wireless%s\n", 849 if_is_awdl(if_p) ? " AWDL" : ""); 850 } 851 } 852 count++; 853 } 854 return; 855} 856 857int 858main() 859{ 860 interface_list_t * list_p = ifl_init(); 861 if (list_p != NULL) { 862 ifl_print(list_p); 863 } 864 exit(0); 865} 866#endif /* TEST_INTERFACES */ 867