1a878b819Sdjm /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 2a878b819Sdjm /* 3a878b819Sdjm * Copyright (c) 1994, 1995, 1996, 1997, 1998 4a878b819Sdjm * The Regents of the University of California. All rights reserved. 5a878b819Sdjm * 6a878b819Sdjm * Redistribution and use in source and binary forms, with or without 7a878b819Sdjm * modification, are permitted provided that the following conditions 8a878b819Sdjm * are met: 9a878b819Sdjm * 1. Redistributions of source code must retain the above copyright 10a878b819Sdjm * notice, this list of conditions and the following disclaimer. 11a878b819Sdjm * 2. Redistributions in binary form must reproduce the above copyright 12a878b819Sdjm * notice, this list of conditions and the following disclaimer in the 13a878b819Sdjm * documentation and/or other materials provided with the distribution. 14a878b819Sdjm * 3. All advertising materials mentioning features or use of this software 15a878b819Sdjm * must display the following acknowledgement: 16a878b819Sdjm * This product includes software developed by the Computer Systems 17a878b819Sdjm * Engineering Group at Lawrence Berkeley Laboratory. 18a878b819Sdjm * 4. Neither the name of the University nor of the Laboratory may be used 19a878b819Sdjm * to endorse or promote products derived from this software without 20a878b819Sdjm * specific prior written permission. 21a878b819Sdjm * 22a878b819Sdjm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23a878b819Sdjm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24a878b819Sdjm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25a878b819Sdjm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26a878b819Sdjm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27a878b819Sdjm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28a878b819Sdjm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29a878b819Sdjm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30a878b819Sdjm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31a878b819Sdjm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32a878b819Sdjm * SUCH DAMAGE. 33a878b819Sdjm */ 34a878b819Sdjm 35a878b819Sdjm #include <sys/types.h> 36a878b819Sdjm #include <sys/socket.h> 37a878b819Sdjm #include <netinet/in.h> 38a878b819Sdjm 39a878b819Sdjm #include <net/if.h> 40a878b819Sdjm 41a878b819Sdjm #include <ctype.h> 42a878b819Sdjm #include <errno.h> 43a878b819Sdjm #include <stdio.h> 44a878b819Sdjm #include <stdlib.h> 45a878b819Sdjm #include <string.h> 46a878b819Sdjm #include <ifaddrs.h> 47a878b819Sdjm #include <limits.h> 48a878b819Sdjm 49a878b819Sdjm #include "pcap-int.h" 50a878b819Sdjm 51a878b819Sdjm static struct sockaddr * 52a878b819Sdjm dup_sockaddr(struct sockaddr *sa, size_t sa_length) 53a878b819Sdjm { 54a878b819Sdjm struct sockaddr *newsa; 55a878b819Sdjm 56a878b819Sdjm if ((newsa = malloc(sa_length)) == NULL) 57a878b819Sdjm return (NULL); 58a878b819Sdjm return (memcpy(newsa, sa, sa_length)); 59a878b819Sdjm } 60a878b819Sdjm 61a878b819Sdjm static int 62a878b819Sdjm get_instance(const char *name) 63a878b819Sdjm { 64*99d1c811Sop const char *cp, *endcp, *errstr; 65a878b819Sdjm int n; 66a878b819Sdjm 67a878b819Sdjm if (strcmp(name, "any") == 0) { 68a878b819Sdjm /* 69a878b819Sdjm * Give the "any" device an artificially high instance 70a878b819Sdjm * number, so it shows up after all other non-loopback 71a878b819Sdjm * interfaces. 72a878b819Sdjm */ 73a878b819Sdjm return INT_MAX; 74a878b819Sdjm } 75a878b819Sdjm 76a878b819Sdjm endcp = name + strlen(name); 77a878b819Sdjm for (cp = name; cp < endcp && !isdigit((unsigned char)*cp); ++cp) 78a878b819Sdjm continue; 79a878b819Sdjm 80*99d1c811Sop n = strtonum(cp, 0, INT_MAX, &errstr); 81*99d1c811Sop if (errstr != NULL) 82*99d1c811Sop return -1; 83*99d1c811Sop return n; 84a878b819Sdjm } 85a878b819Sdjm 86a878b819Sdjm static int 87a878b819Sdjm add_or_find_if(pcap_if_t **curdev_ret, pcap_if_t **alldevs, const char *name, 88a878b819Sdjm u_int flags, const char *description, char *errbuf) 89a878b819Sdjm { 90a878b819Sdjm pcap_t *p; 91a878b819Sdjm pcap_if_t *curdev, *prevdev, *nextdev; 92a878b819Sdjm int this_instance; 93a878b819Sdjm size_t len; 94a878b819Sdjm 95a878b819Sdjm /* 96a878b819Sdjm * Can we open this interface for live capture? 97a878b819Sdjm * 98a878b819Sdjm * We do this check so that interfaces that are supplied 99a878b819Sdjm * by the interface enumeration mechanism we're using 100a878b819Sdjm * but that don't support packet capture aren't included 101a878b819Sdjm * in the list. An example of this is loopback interfaces 102a878b819Sdjm * on Solaris; we don't just omit loopback interfaces 1032c53affbSjmc * because you *can* capture on loopback interfaces on some 104a878b819Sdjm * OSes. 105a878b819Sdjm */ 106a878b819Sdjm p = pcap_open_live(name, 68, 0, 0, errbuf); 107a878b819Sdjm if (p == NULL) { 108a878b819Sdjm /* 109a878b819Sdjm * No. Don't bother including it. 110a878b819Sdjm * Don't treat this as an error, though. 111a878b819Sdjm */ 112a878b819Sdjm *curdev_ret = NULL; 113a878b819Sdjm return (0); 114a878b819Sdjm } 115a878b819Sdjm pcap_close(p); 116a878b819Sdjm 117a878b819Sdjm /* 118a878b819Sdjm * Is there already an entry in the list for this interface? 119a878b819Sdjm */ 120a878b819Sdjm for (curdev = *alldevs; curdev != NULL; curdev = curdev->next) { 121a878b819Sdjm if (strcmp(name, curdev->name) == 0) 122a878b819Sdjm break; /* yes, we found it */ 123a878b819Sdjm } 124a878b819Sdjm if (curdev == NULL) { 125a878b819Sdjm /* 126a878b819Sdjm * No, we didn't find it. 127a878b819Sdjm * Allocate a new entry. 128a878b819Sdjm */ 1291492bed3Sjaredy curdev = calloc(1, sizeof(pcap_if_t)); 130a878b819Sdjm if (curdev == NULL) { 131a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 1321492bed3Sjaredy "calloc: %s", pcap_strerror(errno)); 1331492bed3Sjaredy goto fail; 134a878b819Sdjm } 135a878b819Sdjm 136a878b819Sdjm /* 137a878b819Sdjm * Fill in the entry. 138a878b819Sdjm */ 139a878b819Sdjm curdev->next = NULL; 140a878b819Sdjm len = strlen(name) + 1; 141a878b819Sdjm curdev->name = malloc(len); 1421492bed3Sjaredy if (curdev->name == NULL) { 1431492bed3Sjaredy (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 1441492bed3Sjaredy "malloc: %s", pcap_strerror(errno)); 1451492bed3Sjaredy goto fail; 1461492bed3Sjaredy } 147a878b819Sdjm strlcpy(curdev->name, name, len); 148a878b819Sdjm if (description != NULL) { 149a878b819Sdjm /* 150a878b819Sdjm * We have a description for this interface. 151a878b819Sdjm */ 152a878b819Sdjm len = strlen(description) + 1; 153a878b819Sdjm curdev->description = malloc(len); 1541492bed3Sjaredy if (curdev->description == NULL) { 1551492bed3Sjaredy (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 1561492bed3Sjaredy "malloc: %s", pcap_strerror(errno)); 1571492bed3Sjaredy goto fail; 1581492bed3Sjaredy } 159a878b819Sdjm strlcpy(curdev->description, description, len); 160a878b819Sdjm } 161a878b819Sdjm curdev->addresses = NULL; /* list starts out as empty */ 162a878b819Sdjm curdev->flags = 0; 163a878b819Sdjm if (ISLOOPBACK(name, flags)) 164a878b819Sdjm curdev->flags |= PCAP_IF_LOOPBACK; 165a878b819Sdjm 166a878b819Sdjm /* 167a878b819Sdjm * Add it to the list, in the appropriate location. 168a878b819Sdjm * First, get the instance number of this interface. 169a878b819Sdjm */ 170*99d1c811Sop if ((this_instance = get_instance(name)) == -1) { 171*99d1c811Sop (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 172*99d1c811Sop "malformed device name: %s", name); 173*99d1c811Sop goto fail; 174*99d1c811Sop } 175a878b819Sdjm 176a878b819Sdjm /* 177a878b819Sdjm * Now look for the last interface with an instance number 178a878b819Sdjm * less than or equal to the new interface's instance 179a878b819Sdjm * number - except that non-loopback interfaces are 180a878b819Sdjm * arbitrarily treated as having interface numbers less 181a878b819Sdjm * than those of loopback interfaces, so the loopback 182a878b819Sdjm * interfaces are put at the end of the list. 183a878b819Sdjm * 184a878b819Sdjm * We start with "prevdev" being NULL, meaning we're before 185a878b819Sdjm * the first element in the list. 186a878b819Sdjm */ 187a878b819Sdjm prevdev = NULL; 188a878b819Sdjm for (;;) { 189a878b819Sdjm /* 190a878b819Sdjm * Get the interface after this one. 191a878b819Sdjm */ 192a878b819Sdjm if (prevdev == NULL) { 193a878b819Sdjm /* 194a878b819Sdjm * The next element is the first element. 195a878b819Sdjm */ 196a878b819Sdjm nextdev = *alldevs; 197a878b819Sdjm } else 198a878b819Sdjm nextdev = prevdev->next; 199a878b819Sdjm 200a878b819Sdjm /* 201a878b819Sdjm * Are we at the end of the list? 202a878b819Sdjm */ 203a878b819Sdjm if (nextdev == NULL) { 204a878b819Sdjm /* 205a878b819Sdjm * Yes - we have to put the new entry 206a878b819Sdjm * after "prevdev". 207a878b819Sdjm */ 208a878b819Sdjm break; 209a878b819Sdjm } 210a878b819Sdjm 211a878b819Sdjm /* 212a878b819Sdjm * Is the new interface a non-loopback interface 213a878b819Sdjm * and the next interface a loopback interface? 214a878b819Sdjm */ 215a878b819Sdjm if (!(curdev->flags & PCAP_IF_LOOPBACK) && 216a878b819Sdjm (nextdev->flags & PCAP_IF_LOOPBACK)) { 217a878b819Sdjm /* 218a878b819Sdjm * Yes, we should put the new entry 219a878b819Sdjm * before "nextdev", i.e. after "prevdev". 220a878b819Sdjm */ 221a878b819Sdjm break; 222a878b819Sdjm } 223a878b819Sdjm 224a878b819Sdjm /* 225a878b819Sdjm * Is the new interface's instance number less 226a878b819Sdjm * than the next interface's instance number, 227a878b819Sdjm * and is it the case that the new interface is a 228a878b819Sdjm * non-loopback interface or the next interface is 229a878b819Sdjm * a loopback interface? 230a878b819Sdjm * 231a878b819Sdjm * (The goal of both loopback tests is to make 232a878b819Sdjm * sure that we never put a loopback interface 233a878b819Sdjm * before any non-loopback interface and that we 234a878b819Sdjm * always put a non-loopback interface before all 235a878b819Sdjm * loopback interfaces.) 236a878b819Sdjm */ 237a878b819Sdjm if (this_instance < get_instance(nextdev->name) && 238a878b819Sdjm (!(curdev->flags & PCAP_IF_LOOPBACK) || 239a878b819Sdjm (nextdev->flags & PCAP_IF_LOOPBACK))) { 240a878b819Sdjm /* 241a878b819Sdjm * Yes - we should put the new entry 242a878b819Sdjm * before "nextdev", i.e. after "prevdev". 243a878b819Sdjm */ 244a878b819Sdjm break; 245a878b819Sdjm } 246a878b819Sdjm 247a878b819Sdjm prevdev = nextdev; 248a878b819Sdjm } 249a878b819Sdjm 250a878b819Sdjm /* 251a878b819Sdjm * Insert before "nextdev". 252a878b819Sdjm */ 253a878b819Sdjm curdev->next = nextdev; 254a878b819Sdjm 255a878b819Sdjm /* 256a878b819Sdjm * Insert after "prevdev" - unless "prevdev" is null, 257a878b819Sdjm * in which case this is the first interface. 258a878b819Sdjm */ 259a878b819Sdjm if (prevdev == NULL) { 260a878b819Sdjm /* 261a878b819Sdjm * This is the first interface. Pass back a 262a878b819Sdjm * pointer to it, and put "curdev" before 263a878b819Sdjm * "nextdev". 264a878b819Sdjm */ 265a878b819Sdjm *alldevs = curdev; 266a878b819Sdjm } else 267a878b819Sdjm prevdev->next = curdev; 268a878b819Sdjm } 269a878b819Sdjm 270a878b819Sdjm *curdev_ret = curdev; 271a878b819Sdjm return (0); 2721492bed3Sjaredy 2731492bed3Sjaredy fail: 2741492bed3Sjaredy if (curdev != NULL) { 2751492bed3Sjaredy free(curdev->name); 2761492bed3Sjaredy free(curdev->description); 2771492bed3Sjaredy free(curdev); 2781492bed3Sjaredy } 2791492bed3Sjaredy return (-1); 280a878b819Sdjm } 281a878b819Sdjm 282a878b819Sdjm static int 283a878b819Sdjm add_addr_to_iflist(pcap_if_t **alldevs, const char *name, u_int flags, 284a878b819Sdjm struct sockaddr *addr, size_t addr_size, 285a878b819Sdjm struct sockaddr *netmask, size_t netmask_size, 286a878b819Sdjm struct sockaddr *broadaddr, size_t broadaddr_size, 287a878b819Sdjm struct sockaddr *dstaddr, size_t dstaddr_size, 288a878b819Sdjm char *errbuf) 289a878b819Sdjm { 290a878b819Sdjm pcap_if_t *curdev; 291a878b819Sdjm pcap_addr_t *curaddr, *prevaddr, *nextaddr; 292a878b819Sdjm 293a878b819Sdjm if (add_or_find_if(&curdev, alldevs, name, flags, NULL, errbuf) == -1) { 294a878b819Sdjm /* 295a878b819Sdjm * Error - give up. 296a878b819Sdjm */ 297a878b819Sdjm return (-1); 298a878b819Sdjm } 299a878b819Sdjm if (curdev == NULL) { 300a878b819Sdjm /* 301a878b819Sdjm * Device wasn't added because it can't be opened. 302a878b819Sdjm * Not a fatal error. 303a878b819Sdjm */ 304a878b819Sdjm return (0); 305a878b819Sdjm } 306a878b819Sdjm 307a878b819Sdjm /* 308a878b819Sdjm * "curdev" is an entry for this interface; add an entry for this 309a878b819Sdjm * address to its list of addresses. 310a878b819Sdjm * 311a878b819Sdjm * Allocate the new entry and fill it in. 312a878b819Sdjm */ 3131492bed3Sjaredy curaddr = calloc(1, sizeof(pcap_addr_t)); 314a878b819Sdjm if (curaddr == NULL) { 315a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 3161492bed3Sjaredy "calloc: %s", pcap_strerror(errno)); 3171492bed3Sjaredy goto fail; 318a878b819Sdjm } 319a878b819Sdjm 320a878b819Sdjm curaddr->next = NULL; 321a878b819Sdjm if (addr != NULL) { 322a878b819Sdjm curaddr->addr = dup_sockaddr(addr, addr_size); 323a878b819Sdjm if (curaddr->addr == NULL) { 324a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 325a878b819Sdjm "malloc: %s", pcap_strerror(errno)); 3261492bed3Sjaredy goto fail; 327a878b819Sdjm } 3281492bed3Sjaredy } 329a878b819Sdjm 330a878b819Sdjm if (netmask != NULL) { 331a878b819Sdjm curaddr->netmask = dup_sockaddr(netmask, netmask_size); 332a878b819Sdjm if (curaddr->netmask == NULL) { 333a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 334a878b819Sdjm "malloc: %s", pcap_strerror(errno)); 3351492bed3Sjaredy goto fail; 336a878b819Sdjm } 3371492bed3Sjaredy } 338a878b819Sdjm 339a878b819Sdjm if (broadaddr != NULL) { 340a878b819Sdjm curaddr->broadaddr = dup_sockaddr(broadaddr, broadaddr_size); 341a878b819Sdjm if (curaddr->broadaddr == NULL) { 342a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 343a878b819Sdjm "malloc: %s", pcap_strerror(errno)); 3441492bed3Sjaredy goto fail; 345a878b819Sdjm } 3461492bed3Sjaredy } 347a878b819Sdjm 348a878b819Sdjm if (dstaddr != NULL) { 349a878b819Sdjm curaddr->dstaddr = dup_sockaddr(dstaddr, dstaddr_size); 350a878b819Sdjm if (curaddr->dstaddr == NULL) { 351a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 352a878b819Sdjm "malloc: %s", pcap_strerror(errno)); 3531492bed3Sjaredy goto fail; 354a878b819Sdjm } 3551492bed3Sjaredy } 356a878b819Sdjm 357a878b819Sdjm /* 358a878b819Sdjm * Find the end of the list of addresses. 359a878b819Sdjm */ 360a878b819Sdjm for (prevaddr = curdev->addresses; prevaddr != NULL; 361a878b819Sdjm prevaddr = nextaddr) { 362a878b819Sdjm nextaddr = prevaddr->next; 363a878b819Sdjm if (nextaddr == NULL) { 364a878b819Sdjm /* 365a878b819Sdjm * This is the end of the list. 366a878b819Sdjm */ 367a878b819Sdjm break; 368a878b819Sdjm } 369a878b819Sdjm } 370a878b819Sdjm 371a878b819Sdjm if (prevaddr == NULL) { 372a878b819Sdjm /* 373a878b819Sdjm * The list was empty; this is the first member. 374a878b819Sdjm */ 375a878b819Sdjm curdev->addresses = curaddr; 376a878b819Sdjm } else { 377a878b819Sdjm /* 378a878b819Sdjm * "prevaddr" is the last member of the list; append 379a878b819Sdjm * this member to it. 380a878b819Sdjm */ 381a878b819Sdjm prevaddr->next = curaddr; 382a878b819Sdjm } 383a878b819Sdjm 384a878b819Sdjm return (0); 3851492bed3Sjaredy 3861492bed3Sjaredy fail: 3871492bed3Sjaredy if (curaddr != NULL) { 3881492bed3Sjaredy free(curaddr->addr); 3891492bed3Sjaredy free(curaddr->netmask); 3901492bed3Sjaredy free(curaddr->broadaddr); 3911492bed3Sjaredy free(curaddr->dstaddr); 3921492bed3Sjaredy free(curaddr); 3931492bed3Sjaredy } 3941492bed3Sjaredy return (-1); 395a878b819Sdjm } 396a878b819Sdjm 397a878b819Sdjm /* 398a878b819Sdjm * Get a list of all interfaces that are up and that we can open. 399a878b819Sdjm * Returns -1 on error, 0 otherwise. 400a878b819Sdjm * The list, as returned through "alldevsp", may be null if no interfaces 401a878b819Sdjm * were up and could be opened. 402a878b819Sdjm * 403a878b819Sdjm * This is the implementation used on platforms that have "getifaddrs()". 404a878b819Sdjm */ 405a878b819Sdjm int 406a878b819Sdjm pcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) 407a878b819Sdjm { 408a878b819Sdjm pcap_if_t *devlist = NULL; 409a878b819Sdjm struct ifaddrs *ifap, *ifa; 410a878b819Sdjm struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; 411a878b819Sdjm size_t addr_size, broadaddr_size, dstaddr_size; 412a878b819Sdjm int ret = 0; 413a878b819Sdjm 414a878b819Sdjm /* 415a878b819Sdjm * Get the list of interface addresses. 416a878b819Sdjm * 417a878b819Sdjm * Note: this won't return information about interfaces 418a878b819Sdjm * with no addresses; are there any such interfaces 419a878b819Sdjm * that would be capable of receiving packets? 420a878b819Sdjm * (Interfaces incapable of receiving packets aren't 421a878b819Sdjm * very interesting from libpcap's point of view.) 422a878b819Sdjm * 423a878b819Sdjm * LAN interfaces will probably have link-layer 424a878b819Sdjm * addresses; I don't know whether all implementations 425a878b819Sdjm * of "getifaddrs()" now, or in the future, will return 426a878b819Sdjm * those. 427a878b819Sdjm */ 428a878b819Sdjm if (getifaddrs(&ifap) != 0) { 429a878b819Sdjm (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 430a878b819Sdjm "getifaddrs: %s", pcap_strerror(errno)); 431a878b819Sdjm return (-1); 432a878b819Sdjm } 433a878b819Sdjm for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 434a878b819Sdjm /* 435a878b819Sdjm * Is this interface up? 436a878b819Sdjm */ 437a878b819Sdjm if (!(ifa->ifa_flags & IFF_UP)) { 438a878b819Sdjm /* 439a878b819Sdjm * No, so don't add it to the list. 440a878b819Sdjm */ 441a878b819Sdjm continue; 442a878b819Sdjm } 443a878b819Sdjm 444a878b819Sdjm /* 445a878b819Sdjm * "ifa_addr" was apparently null on at least one 446a878b819Sdjm * interface on some system. 447a878b819Sdjm * 448a878b819Sdjm * "ifa_broadaddr" may be non-null even on 449a878b819Sdjm * non-broadcast interfaces, and was null on 450a878b819Sdjm * at least one OpenBSD 3.4 system on at least 451a878b819Sdjm * one interface with IFF_BROADCAST set. 452a878b819Sdjm * 453a878b819Sdjm * "ifa_dstaddr" was, on at least one FreeBSD 4.1 454a878b819Sdjm * system, non-null on a non-point-to-point 455a878b819Sdjm * interface. 456a878b819Sdjm * 457a878b819Sdjm * Therefore, we supply the address and netmask only 458a878b819Sdjm * if "ifa_addr" is non-null (if there's no address, 459a878b819Sdjm * there's obviously no netmask), and supply the 460a878b819Sdjm * broadcast and destination addresses if the appropriate 461a878b819Sdjm * flag is set *and* the appropriate "ifa_" entry doesn't 462a878b819Sdjm * evaluate to a null pointer. 463a878b819Sdjm */ 464a878b819Sdjm if (ifa->ifa_addr != NULL) { 465a878b819Sdjm addr = ifa->ifa_addr; 466a878b819Sdjm addr_size = SA_LEN(addr); 467a878b819Sdjm netmask = ifa->ifa_netmask; 468a878b819Sdjm } else { 469a878b819Sdjm addr = NULL; 470a878b819Sdjm addr_size = 0; 471a878b819Sdjm netmask = NULL; 472a878b819Sdjm } 473a878b819Sdjm if (ifa->ifa_flags & IFF_BROADCAST && 474a878b819Sdjm ifa->ifa_broadaddr != NULL) { 475a878b819Sdjm broadaddr = ifa->ifa_broadaddr; 476a878b819Sdjm broadaddr_size = SA_LEN(broadaddr); 477a878b819Sdjm } else { 478a878b819Sdjm broadaddr = NULL; 479a878b819Sdjm broadaddr_size = 0; 480a878b819Sdjm } 481a878b819Sdjm if (ifa->ifa_flags & IFF_POINTOPOINT && 482a878b819Sdjm ifa->ifa_dstaddr != NULL) { 483a878b819Sdjm dstaddr = ifa->ifa_dstaddr; 484a878b819Sdjm dstaddr_size = SA_LEN(ifa->ifa_dstaddr); 485a878b819Sdjm } else { 486a878b819Sdjm dstaddr = NULL; 487a878b819Sdjm dstaddr_size = 0; 488a878b819Sdjm } 489a878b819Sdjm 490a878b819Sdjm /* 491a878b819Sdjm * Add information for this address to the list. 492a878b819Sdjm */ 493a878b819Sdjm if (add_addr_to_iflist(&devlist, ifa->ifa_name, 494a878b819Sdjm ifa->ifa_flags, addr, addr_size, netmask, addr_size, 495a878b819Sdjm broadaddr, broadaddr_size, dstaddr, dstaddr_size, 496a878b819Sdjm errbuf) < 0) { 497a878b819Sdjm ret = -1; 498a878b819Sdjm break; 499a878b819Sdjm } 500a878b819Sdjm } 501a878b819Sdjm 502a878b819Sdjm freeifaddrs(ifap); 503a878b819Sdjm 504a878b819Sdjm if (ret == -1) { 505a878b819Sdjm /* 506a878b819Sdjm * We had an error; free the list we've been constructing. 507a878b819Sdjm */ 508a878b819Sdjm if (devlist != NULL) { 509a878b819Sdjm pcap_freealldevs(devlist); 510a878b819Sdjm devlist = NULL; 511a878b819Sdjm } 512a878b819Sdjm } 513a878b819Sdjm 514a878b819Sdjm *alldevsp = devlist; 515a878b819Sdjm return (ret); 516a878b819Sdjm } 517