fad-getad.c revision 147894
1264377Sdes/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ 257429Smarkm/* 357429Smarkm * Copyright (c) 1994, 1995, 1996, 1997, 1998 457429Smarkm * The Regents of the University of California. All rights reserved. 557429Smarkm * 657429Smarkm * Redistribution and use in source and binary forms, with or without 757429Smarkm * modification, are permitted provided that the following conditions 860576Skris * are met: 965674Skris * 1. Redistributions of source code must retain the above copyright 1065674Skris * notice, this list of conditions and the following disclaimer. 1165674Skris * 2. Redistributions in binary form must reproduce the above copyright 1265674Skris * notice, this list of conditions and the following disclaimer in the 1365674Skris * documentation and/or other materials provided with the distribution. 1465674Skris * 3. All advertising materials mentioning features or use of this software 1565674Skris * must display the following acknowledgement: 16262566Sdes * This product includes software developed by the Computer Systems 1765674Skris * Engineering Group at Lawrence Berkeley Laboratory. 1865674Skris * 4. Neither the name of the University nor of the Laboratory may be used 1965674Skris * to endorse or promote products derived from this software without 2065674Skris * specific prior written permission. 2165674Skris * 2265674Skris * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2365674Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2465674Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2565674Skris * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2665674Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2765674Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2865674Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2965674Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3065674Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3165674Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3265674Skris * SUCH DAMAGE. 3365674Skris */ 3465674Skris 3565674Skris#ifndef lint 3665674Skrisstatic const char rcsid[] _U_ = 3757429Smarkm "@(#) $Header: /tcpdump/master/libpcap/fad-getad.c,v 1.10.2.1 2005/04/10 18:04:49 hannes Exp $ (LBL)"; 3857429Smarkm#endif 3957429Smarkm 4057429Smarkm#ifdef HAVE_CONFIG_H 41162856Sdes#include "config.h" 42162856Sdes#endif 43162856Sdes 44162856Sdes#include <sys/types.h> 45162856Sdes#include <sys/socket.h> 4676262Sgreen#include <netinet/in.h> 4776262Sgreen 4860576Skris#include <net/if.h> 4960576Skris 50204917Sdes#include <ctype.h> 51204917Sdes#include <errno.h> 52204917Sdes#include <stdio.h> 53262566Sdes#include <stdlib.h> 54262566Sdes#include <string.h> 55162856Sdes#include <ifaddrs.h> 56162856Sdes 57162856Sdes#include "pcap-int.h" 58162856Sdes 59162856Sdes#ifdef HAVE_OS_PROTO_H 60162856Sdes#include "os-proto.h" 61162856Sdes#endif 62162856Sdes 63262566Sdes#ifdef AF_PACKET 64262566Sdes# include <linux/if_packet.h> 65262566Sdes#endif 66262566Sdes 67162856Sdes/* 6876262Sgreen * This is fun. 6957429Smarkm * 7076262Sgreen * In older BSD systems, socket addresses were fixed-length, and 7157429Smarkm * "sizeof (struct sockaddr)" gave the size of the structure. 7276262Sgreen * All addresses fit within a "struct sockaddr". 7376262Sgreen * 7492559Sdes * In newer BSD systems, the socket address is variable-length, and 75147005Sdes * there's an "sa_len" field giving the length of the structure; 76149753Sdes * this allows socket addresses to be longer than 2 bytes of family 77262566Sdes * and 14 bytes of data. 7857429Smarkm * 79262566Sdes * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553 80262566Sdes * variant of the old BSD scheme (with "struct sockaddr_storage" rather 81262566Sdes * than "struct sockaddr"), and some use the new BSD scheme. 82262566Sdes * 83262566Sdes * Some versions of GNU libc use neither scheme, but has an "SA_LEN()" 84262566Sdes * macro that determines the size based on the address family. Other 85262566Sdes * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553 86262566Sdes * but not in the final version). On the latter systems, we explicitly 87262566Sdes * check the AF_ type to determine the length; we assume that on 88226046Sdes * all those systems we have "struct sockaddr_storage". 89226046Sdes */ 9076262Sgreen#ifndef SA_LEN 9176262Sgreen#ifdef HAVE_SOCKADDR_SA_LEN 9276262Sgreen#define SA_LEN(addr) ((addr)->sa_len) 9357429Smarkm#else /* HAVE_SOCKADDR_SA_LEN */ 94262566Sdes#ifdef HAVE_SOCKADDR_STORAGE 95262566Sdesstatic size_t 96262566Sdesget_sa_len(struct sockaddr *addr) 97262566Sdes{ 98262566Sdes switch (addr->sa_family) { 99262566Sdes 100262566Sdes#ifdef AF_INET 101262566Sdes case AF_INET: 102262566Sdes return (sizeof (struct sockaddr_in)); 103262566Sdes#endif 104262566Sdes 105262566Sdes#ifdef AF_INET6 106262566Sdes case AF_INET6: 107262566Sdes return (sizeof (struct sockaddr_in6)); 108262566Sdes#endif 109262566Sdes 110262566Sdes#ifdef AF_PACKET 111262566Sdes case AF_PACKET: 112262566Sdes return (sizeof (struct sockaddr_ll)); 113262566Sdes#endif 114262566Sdes 115262566Sdes default: 116262566Sdes return (sizeof (struct sockaddr)); 117262566Sdes } 118262566Sdes} 119262566Sdes#define SA_LEN(addr) (get_sa_len(addr)) 120262566Sdes#else /* HAVE_SOCKADDR_STORAGE */ 121262566Sdes#define SA_LEN(addr) (sizeof (struct sockaddr)) 122262566Sdes#endif /* HAVE_SOCKADDR_STORAGE */ 123262566Sdes#endif /* HAVE_SOCKADDR_SA_LEN */ 124262566Sdes#endif /* SA_LEN */ 125262566Sdes 126262566Sdes/* 127262566Sdes * Get a list of all interfaces that are up and that we can open. 128262566Sdes * Returns -1 on error, 0 otherwise. 129262566Sdes * The list, as returned through "alldevsp", may be null if no interfaces 130262566Sdes * were up and could be opened. 131262566Sdes * 132262566Sdes * This is the implementation used on platforms that have "getifaddrs()". 133262566Sdes */ 134264377Sdesint 135262566Sdespcap_findalldevs(pcap_if_t **alldevsp, char *errbuf) 136262566Sdes{ 137262566Sdes pcap_if_t *devlist = NULL; 138262566Sdes struct ifaddrs *ifap, *ifa; 139262566Sdes struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; 140262566Sdes size_t addr_size, broadaddr_size, dstaddr_size; 141262566Sdes int ret = 0; 142262566Sdes char *p, *q; 143262566Sdes 144262566Sdes /* 145262566Sdes * Get the list of interface addresses. 146264377Sdes * 147262566Sdes * Note: this won't return information about interfaces 148262566Sdes * with no addresses; are there any such interfaces 149262566Sdes * that would be capable of receiving packets? 150262566Sdes * (Interfaces incapable of receiving packets aren't 151262566Sdes * very interesting from libpcap's point of view.) 152262566Sdes * 153262566Sdes * LAN interfaces will probably have link-layer 154262566Sdes * addresses; I don't know whether all implementations 155262566Sdes * of "getifaddrs()" now, or in the future, will return 156262566Sdes * those. 157262566Sdes */ 158262566Sdes if (getifaddrs(&ifap) != 0) { 159262566Sdes (void)snprintf(errbuf, PCAP_ERRBUF_SIZE, 160262566Sdes "getifaddrs: %s", pcap_strerror(errno)); 161262566Sdes return (-1); 162262566Sdes } 163262566Sdes for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 164262566Sdes /* 165262566Sdes * Is this interface up? 166262566Sdes */ 167262566Sdes if (!(ifa->ifa_flags & IFF_UP)) { 168262566Sdes /* 169262566Sdes * No, so don't add it to the list. 170262566Sdes */ 171262566Sdes continue; 172262566Sdes } 173262566Sdes 174262566Sdes /* 175262566Sdes * "ifa_addr" was apparently null on at least one 176262566Sdes * interface on some system. 177262566Sdes * 178262566Sdes * "ifa_broadaddr" may be non-null even on 179262566Sdes * non-broadcast interfaces, and was null on 180262566Sdes * at least one OpenBSD 3.4 system on at least 181262566Sdes * one interface with IFF_BROADCAST set. 182262566Sdes * 183262566Sdes * "ifa_dstaddr" was, on at least one FreeBSD 4.1 184262566Sdes * system, non-null on a non-point-to-point 185262566Sdes * interface. 186262566Sdes * 187262566Sdes * Therefore, we supply the address and netmask only 188262566Sdes * if "ifa_addr" is non-null (if there's no address, 189262566Sdes * there's obviously no netmask), and supply the 190262566Sdes * broadcast and destination addresses if the appropriate 191262566Sdes * flag is set *and* the appropriate "ifa_" entry doesn't 192262566Sdes * evaluate to a null pointer. 193262566Sdes */ 194262566Sdes if (ifa->ifa_addr != NULL) { 195262566Sdes addr = ifa->ifa_addr; 196262566Sdes addr_size = SA_LEN(addr); 197262566Sdes netmask = ifa->ifa_netmask; 198262566Sdes } else { 199262566Sdes addr = NULL; 200262566Sdes addr_size = 0; 201262566Sdes netmask = NULL; 202262566Sdes } 203262566Sdes if (ifa->ifa_flags & IFF_BROADCAST && 204262566Sdes ifa->ifa_broadaddr != NULL) { 205262566Sdes broadaddr = ifa->ifa_broadaddr; 206262566Sdes broadaddr_size = SA_LEN(broadaddr); 207262566Sdes } else { 208262566Sdes broadaddr = NULL; 209262566Sdes broadaddr_size = 0; 210262566Sdes } 211262566Sdes if (ifa->ifa_flags & IFF_POINTOPOINT && 212262566Sdes ifa->ifa_dstaddr != NULL) { 213262566Sdes dstaddr = ifa->ifa_dstaddr; 214262566Sdes dstaddr_size = SA_LEN(ifa->ifa_dstaddr); 215262566Sdes } else { 216262566Sdes dstaddr = NULL; 217262566Sdes dstaddr_size = 0; 218262566Sdes } 219262566Sdes 220262566Sdes /* 221262566Sdes * If this entry has a colon followed by a number at 222262566Sdes * the end, we assume it's a logical interface. Those 223262566Sdes * are just the way you assign multiple IP addresses to 224262566Sdes * a real interface on Linux, so an entry for a logical 225262566Sdes * interface should be treated like the entry for the 226262566Sdes * real interface; we do that by stripping off the ":" 227262566Sdes * and the number. 228262566Sdes * 229262566Sdes * XXX - should we do this only on Linux? 230262566Sdes */ 231262566Sdes p = strchr(ifa->ifa_name, ':'); 232262566Sdes if (p != NULL) { 233262566Sdes /* 234262566Sdes * We have a ":"; is it followed by a number? 235262566Sdes */ 236262566Sdes q = p + 1; 237262566Sdes while (isdigit((unsigned char)*q)) 238262566Sdes q++; 239262566Sdes if (*q == '\0') { 240262566Sdes /* 241262566Sdes * All digits after the ":" until the end. 242262566Sdes * Strip off the ":" and everything after 243262566Sdes * it. 244262566Sdes */ 245262566Sdes *p = '\0'; 246262566Sdes } 247262566Sdes } 248262566Sdes 249262566Sdes /* 250262566Sdes * Add information for this address to the list. 251262566Sdes */ 252262566Sdes if (add_addr_to_iflist(&devlist, ifa->ifa_name, 253262566Sdes ifa->ifa_flags, addr, addr_size, netmask, addr_size, 254262566Sdes broadaddr, broadaddr_size, dstaddr, dstaddr_size, 255262566Sdes errbuf) < 0) { 256262566Sdes ret = -1; 257262566Sdes break; 258262566Sdes } 259262566Sdes } 260262566Sdes 261262566Sdes freeifaddrs(ifap); 262262566Sdes 263262566Sdes if (ret != -1) { 264262566Sdes /* 265262566Sdes * We haven't had any errors yet; do any platform-specific 266262566Sdes * operations to add devices. 267262566Sdes */ 268262566Sdes if (pcap_platform_finddevs(&devlist, errbuf) < 0) 269262566Sdes ret = -1; 270262566Sdes } 271262566Sdes 272262566Sdes if (ret == -1) { 273262566Sdes /* 274262566Sdes * We had an error; free the list we've been constructing. 275262566Sdes */ 276262566Sdes if (devlist != NULL) { 277262566Sdes pcap_freealldevs(devlist); 278262566Sdes devlist = NULL; 279262566Sdes } 280262566Sdes } 281262566Sdes 282262566Sdes *alldevsp = devlist; 283262566Sdes return (ret); 284262566Sdes} 285262566Sdes