11077d0bdSPeter Avalos /* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */
21077d0bdSPeter Avalos /*
31077d0bdSPeter Avalos * Copyright (c) 1994, 1995, 1996, 1997, 1998
41077d0bdSPeter Avalos * The Regents of the University of California. All rights reserved.
51077d0bdSPeter Avalos *
61077d0bdSPeter Avalos * Redistribution and use in source and binary forms, with or without
71077d0bdSPeter Avalos * modification, are permitted provided that the following conditions
81077d0bdSPeter Avalos * are met:
91077d0bdSPeter Avalos * 1. Redistributions of source code must retain the above copyright
101077d0bdSPeter Avalos * notice, this list of conditions and the following disclaimer.
111077d0bdSPeter Avalos * 2. Redistributions in binary form must reproduce the above copyright
121077d0bdSPeter Avalos * notice, this list of conditions and the following disclaimer in the
131077d0bdSPeter Avalos * documentation and/or other materials provided with the distribution.
141077d0bdSPeter Avalos * 3. All advertising materials mentioning features or use of this software
151077d0bdSPeter Avalos * must display the following acknowledgement:
161077d0bdSPeter Avalos * This product includes software developed by the Computer Systems
171077d0bdSPeter Avalos * Engineering Group at Lawrence Berkeley Laboratory.
181077d0bdSPeter Avalos * 4. Neither the name of the University nor of the Laboratory may be used
191077d0bdSPeter Avalos * to endorse or promote products derived from this software without
201077d0bdSPeter Avalos * specific prior written permission.
211077d0bdSPeter Avalos *
221077d0bdSPeter Avalos * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
231077d0bdSPeter Avalos * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
241077d0bdSPeter Avalos * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
251077d0bdSPeter Avalos * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
261077d0bdSPeter Avalos * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
271077d0bdSPeter Avalos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
281077d0bdSPeter Avalos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
291077d0bdSPeter Avalos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
301077d0bdSPeter Avalos * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
311077d0bdSPeter Avalos * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
321077d0bdSPeter Avalos * SUCH DAMAGE.
331077d0bdSPeter Avalos */
341077d0bdSPeter Avalos
351077d0bdSPeter Avalos #ifdef HAVE_CONFIG_H
363a289941SAaron LI #include <config.h>
371077d0bdSPeter Avalos #endif
381077d0bdSPeter Avalos
391077d0bdSPeter Avalos #include <sys/types.h>
401077d0bdSPeter Avalos #include <sys/socket.h>
411077d0bdSPeter Avalos #include <netinet/in.h>
421077d0bdSPeter Avalos
431077d0bdSPeter Avalos #include <net/if.h>
441077d0bdSPeter Avalos
451077d0bdSPeter Avalos #include <errno.h>
461077d0bdSPeter Avalos #include <stdio.h>
471077d0bdSPeter Avalos #include <stdlib.h>
481077d0bdSPeter Avalos #include <string.h>
491077d0bdSPeter Avalos #include <ifaddrs.h>
501077d0bdSPeter Avalos
511077d0bdSPeter Avalos #include "pcap-int.h"
521077d0bdSPeter Avalos
531077d0bdSPeter Avalos #ifdef HAVE_OS_PROTO_H
541077d0bdSPeter Avalos #include "os-proto.h"
551077d0bdSPeter Avalos #endif
561077d0bdSPeter Avalos
5797a9217aSAntonio Huete Jimenez /*
5897a9217aSAntonio Huete Jimenez * We don't do this on Solaris 11 and later, as it appears there aren't
5997a9217aSAntonio Huete Jimenez * any AF_PACKET addresses on interfaces, so we don't need this, and
6097a9217aSAntonio Huete Jimenez * we end up including both the OS's <net/bpf.h> and our <pcap/bpf.h>,
6197a9217aSAntonio Huete Jimenez * and their definitions of some data structures collide.
6297a9217aSAntonio Huete Jimenez */
6397a9217aSAntonio Huete Jimenez #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
64a85e14b0SPeter Avalos # ifdef HAVE_NETPACKET_PACKET_H
6597a9217aSAntonio Huete Jimenez /* Linux distributions with newer glibc */
66a85e14b0SPeter Avalos # include <netpacket/packet.h>
67a85e14b0SPeter Avalos # else /* HAVE_NETPACKET_PACKET_H */
68a85e14b0SPeter Avalos /* LynxOS, Linux distributions with older glibc */
691077d0bdSPeter Avalos # ifdef __Lynx__
70a85e14b0SPeter Avalos /* LynxOS */
71a85e14b0SPeter Avalos # include <netpacket/if_packet.h>
72a85e14b0SPeter Avalos # else /* __Lynx__ */
73a85e14b0SPeter Avalos /* Linux */
74a85e14b0SPeter Avalos # include <linux/types.h>
75a85e14b0SPeter Avalos # include <linux/if_packet.h>
76a85e14b0SPeter Avalos # endif /* __Lynx__ */
77a85e14b0SPeter Avalos # endif /* HAVE_NETPACKET_PACKET_H */
7897a9217aSAntonio Huete Jimenez #endif /* (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET) */
791077d0bdSPeter Avalos
801077d0bdSPeter Avalos /*
811077d0bdSPeter Avalos * This is fun.
821077d0bdSPeter Avalos *
831077d0bdSPeter Avalos * In older BSD systems, socket addresses were fixed-length, and
841077d0bdSPeter Avalos * "sizeof (struct sockaddr)" gave the size of the structure.
851077d0bdSPeter Avalos * All addresses fit within a "struct sockaddr".
861077d0bdSPeter Avalos *
871077d0bdSPeter Avalos * In newer BSD systems, the socket address is variable-length, and
881077d0bdSPeter Avalos * there's an "sa_len" field giving the length of the structure;
891077d0bdSPeter Avalos * this allows socket addresses to be longer than 2 bytes of family
901077d0bdSPeter Avalos * and 14 bytes of data.
911077d0bdSPeter Avalos *
921077d0bdSPeter Avalos * Some commercial UNIXes use the old BSD scheme, some use the RFC 2553
931077d0bdSPeter Avalos * variant of the old BSD scheme (with "struct sockaddr_storage" rather
941077d0bdSPeter Avalos * than "struct sockaddr"), and some use the new BSD scheme.
951077d0bdSPeter Avalos *
961077d0bdSPeter Avalos * Some versions of GNU libc use neither scheme, but has an "SA_LEN()"
971077d0bdSPeter Avalos * macro that determines the size based on the address family. Other
981077d0bdSPeter Avalos * versions don't have "SA_LEN()" (as it was in drafts of RFC 2553
991077d0bdSPeter Avalos * but not in the final version). On the latter systems, we explicitly
1001077d0bdSPeter Avalos * check the AF_ type to determine the length; we assume that on
1011077d0bdSPeter Avalos * all those systems we have "struct sockaddr_storage".
1021077d0bdSPeter Avalos */
1031077d0bdSPeter Avalos #ifndef SA_LEN
1043a289941SAaron LI #ifdef HAVE_STRUCT_SOCKADDR_SA_LEN
1051077d0bdSPeter Avalos #define SA_LEN(addr) ((addr)->sa_len)
1063a289941SAaron LI #else /* HAVE_STRUCT_SOCKADDR_SA_LEN */
1073a289941SAaron LI #ifdef HAVE_STRUCT_SOCKADDR_STORAGE
1081077d0bdSPeter Avalos static size_t
get_sa_len(struct sockaddr * addr)1091077d0bdSPeter Avalos get_sa_len(struct sockaddr *addr)
1101077d0bdSPeter Avalos {
1111077d0bdSPeter Avalos switch (addr->sa_family) {
1121077d0bdSPeter Avalos
1131077d0bdSPeter Avalos #ifdef AF_INET
1141077d0bdSPeter Avalos case AF_INET:
1151077d0bdSPeter Avalos return (sizeof (struct sockaddr_in));
1161077d0bdSPeter Avalos #endif
1171077d0bdSPeter Avalos
1181077d0bdSPeter Avalos #ifdef AF_INET6
1191077d0bdSPeter Avalos case AF_INET6:
1201077d0bdSPeter Avalos return (sizeof (struct sockaddr_in6));
1211077d0bdSPeter Avalos #endif
1221077d0bdSPeter Avalos
12397a9217aSAntonio Huete Jimenez #if (defined(linux) || defined(__Lynx__)) && defined(AF_PACKET)
1241077d0bdSPeter Avalos case AF_PACKET:
1251077d0bdSPeter Avalos return (sizeof (struct sockaddr_ll));
1261077d0bdSPeter Avalos #endif
1271077d0bdSPeter Avalos
1281077d0bdSPeter Avalos default:
1291077d0bdSPeter Avalos return (sizeof (struct sockaddr));
1301077d0bdSPeter Avalos }
1311077d0bdSPeter Avalos }
1321077d0bdSPeter Avalos #define SA_LEN(addr) (get_sa_len(addr))
1333a289941SAaron LI #else /* HAVE_STRUCT_SOCKADDR_STORAGE */
1341077d0bdSPeter Avalos #define SA_LEN(addr) (sizeof (struct sockaddr))
1353a289941SAaron LI #endif /* HAVE_STRUCT_SOCKADDR_STORAGE */
1363a289941SAaron LI #endif /* HAVE_STRUCT_SOCKADDR_SA_LEN */
1371077d0bdSPeter Avalos #endif /* SA_LEN */
1381077d0bdSPeter Avalos
1391077d0bdSPeter Avalos /*
1401077d0bdSPeter Avalos * Get a list of all interfaces that are up and that we can open.
1411077d0bdSPeter Avalos * Returns -1 on error, 0 otherwise.
1421077d0bdSPeter Avalos * The list, as returned through "alldevsp", may be null if no interfaces
14397a9217aSAntonio Huete Jimenez * could be opened.
1441077d0bdSPeter Avalos */
1451077d0bdSPeter Avalos int
pcap_findalldevs_interfaces(pcap_if_list_t * devlistp,char * errbuf,int (* check_usable)(const char *),get_if_flags_func get_flags_func)1463a289941SAaron LI pcap_findalldevs_interfaces(pcap_if_list_t *devlistp, char *errbuf,
1473a289941SAaron LI int (*check_usable)(const char *), get_if_flags_func get_flags_func)
1481077d0bdSPeter Avalos {
1491077d0bdSPeter Avalos struct ifaddrs *ifap, *ifa;
1501077d0bdSPeter Avalos struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
1511077d0bdSPeter Avalos size_t addr_size, broadaddr_size, dstaddr_size;
1521077d0bdSPeter Avalos int ret = 0;
1531077d0bdSPeter Avalos char *p, *q;
1541077d0bdSPeter Avalos
1551077d0bdSPeter Avalos /*
1561077d0bdSPeter Avalos * Get the list of interface addresses.
1571077d0bdSPeter Avalos *
1581077d0bdSPeter Avalos * Note: this won't return information about interfaces
15997a9217aSAntonio Huete Jimenez * with no addresses, so, if a platform has interfaces
16097a9217aSAntonio Huete Jimenez * with no interfaces on which traffic can be captured,
16197a9217aSAntonio Huete Jimenez * we must check for those interfaces as well (see, for
16297a9217aSAntonio Huete Jimenez * example, what's done on Linux).
1631077d0bdSPeter Avalos *
1641077d0bdSPeter Avalos * LAN interfaces will probably have link-layer
1651077d0bdSPeter Avalos * addresses; I don't know whether all implementations
1661077d0bdSPeter Avalos * of "getifaddrs()" now, or in the future, will return
1671077d0bdSPeter Avalos * those.
1681077d0bdSPeter Avalos */
1691077d0bdSPeter Avalos if (getifaddrs(&ifap) != 0) {
1703a289941SAaron LI pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE,
1713a289941SAaron LI errno, "getifaddrs");
1721077d0bdSPeter Avalos return (-1);
1731077d0bdSPeter Avalos }
1741077d0bdSPeter Avalos for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
1751077d0bdSPeter Avalos /*
1761077d0bdSPeter Avalos * If this entry has a colon followed by a number at
1771077d0bdSPeter Avalos * the end, we assume it's a logical interface. Those
1781077d0bdSPeter Avalos * are just the way you assign multiple IP addresses to
1791077d0bdSPeter Avalos * a real interface on Linux, so an entry for a logical
1801077d0bdSPeter Avalos * interface should be treated like the entry for the
1811077d0bdSPeter Avalos * real interface; we do that by stripping off the ":"
1821077d0bdSPeter Avalos * and the number.
1831077d0bdSPeter Avalos *
1841077d0bdSPeter Avalos * XXX - should we do this only on Linux?
1851077d0bdSPeter Avalos */
1861077d0bdSPeter Avalos p = strchr(ifa->ifa_name, ':');
1871077d0bdSPeter Avalos if (p != NULL) {
1881077d0bdSPeter Avalos /*
1891077d0bdSPeter Avalos * We have a ":"; is it followed by a number?
1901077d0bdSPeter Avalos */
1911077d0bdSPeter Avalos q = p + 1;
192*ea16f64eSAntonio Huete Jimenez while (PCAP_ISDIGIT(*q))
1931077d0bdSPeter Avalos q++;
1941077d0bdSPeter Avalos if (*q == '\0') {
1951077d0bdSPeter Avalos /*
1961077d0bdSPeter Avalos * All digits after the ":" until the end.
1971077d0bdSPeter Avalos * Strip off the ":" and everything after
1981077d0bdSPeter Avalos * it.
1991077d0bdSPeter Avalos */
2001077d0bdSPeter Avalos *p = '\0';
2011077d0bdSPeter Avalos }
2021077d0bdSPeter Avalos }
2031077d0bdSPeter Avalos
2041077d0bdSPeter Avalos /*
20597a9217aSAntonio Huete Jimenez * Can we capture on this device?
20697a9217aSAntonio Huete Jimenez */
20797a9217aSAntonio Huete Jimenez if (!(*check_usable)(ifa->ifa_name)) {
20897a9217aSAntonio Huete Jimenez /*
20997a9217aSAntonio Huete Jimenez * No.
21097a9217aSAntonio Huete Jimenez */
21197a9217aSAntonio Huete Jimenez continue;
21297a9217aSAntonio Huete Jimenez }
21397a9217aSAntonio Huete Jimenez
21497a9217aSAntonio Huete Jimenez /*
21597a9217aSAntonio Huete Jimenez * "ifa_addr" was apparently null on at least one
21697a9217aSAntonio Huete Jimenez * interface on some system. Therefore, we supply
21797a9217aSAntonio Huete Jimenez * the address and netmask only if "ifa_addr" is
21897a9217aSAntonio Huete Jimenez * non-null (if there's no address, there's obviously
21997a9217aSAntonio Huete Jimenez * no netmask).
22097a9217aSAntonio Huete Jimenez */
22197a9217aSAntonio Huete Jimenez if (ifa->ifa_addr != NULL) {
22297a9217aSAntonio Huete Jimenez addr = ifa->ifa_addr;
22397a9217aSAntonio Huete Jimenez addr_size = SA_LEN(addr);
22497a9217aSAntonio Huete Jimenez netmask = ifa->ifa_netmask;
22597a9217aSAntonio Huete Jimenez } else {
22697a9217aSAntonio Huete Jimenez addr = NULL;
22797a9217aSAntonio Huete Jimenez addr_size = 0;
22897a9217aSAntonio Huete Jimenez netmask = NULL;
22997a9217aSAntonio Huete Jimenez }
23097a9217aSAntonio Huete Jimenez
23197a9217aSAntonio Huete Jimenez /*
23297a9217aSAntonio Huete Jimenez * Note that, on some platforms, ifa_broadaddr and
23397a9217aSAntonio Huete Jimenez * ifa_dstaddr could be the same field (true on at
2343a289941SAaron LI * least some versions of *BSD and macOS), so we
23597a9217aSAntonio Huete Jimenez * can't just check whether the broadcast address
23697a9217aSAntonio Huete Jimenez * is null and add it if so and check whether the
23797a9217aSAntonio Huete Jimenez * destination address is null and add it if so.
23897a9217aSAntonio Huete Jimenez *
23997a9217aSAntonio Huete Jimenez * Therefore, we must also check the IFF_BROADCAST
24097a9217aSAntonio Huete Jimenez * flag, and only add a broadcast address if it's
24197a9217aSAntonio Huete Jimenez * set, and check the IFF_POINTTOPOINT flag, and
24297a9217aSAntonio Huete Jimenez * only add a destination address if it's set (as
24397a9217aSAntonio Huete Jimenez * per man page recommendations on some of those
24497a9217aSAntonio Huete Jimenez * platforms).
24597a9217aSAntonio Huete Jimenez */
24697a9217aSAntonio Huete Jimenez if (ifa->ifa_flags & IFF_BROADCAST &&
24797a9217aSAntonio Huete Jimenez ifa->ifa_broadaddr != NULL) {
24897a9217aSAntonio Huete Jimenez broadaddr = ifa->ifa_broadaddr;
24997a9217aSAntonio Huete Jimenez broadaddr_size = SA_LEN(broadaddr);
25097a9217aSAntonio Huete Jimenez } else {
25197a9217aSAntonio Huete Jimenez broadaddr = NULL;
25297a9217aSAntonio Huete Jimenez broadaddr_size = 0;
25397a9217aSAntonio Huete Jimenez }
25497a9217aSAntonio Huete Jimenez if (ifa->ifa_flags & IFF_POINTOPOINT &&
25597a9217aSAntonio Huete Jimenez ifa->ifa_dstaddr != NULL) {
25697a9217aSAntonio Huete Jimenez dstaddr = ifa->ifa_dstaddr;
25797a9217aSAntonio Huete Jimenez dstaddr_size = SA_LEN(ifa->ifa_dstaddr);
25897a9217aSAntonio Huete Jimenez } else {
25997a9217aSAntonio Huete Jimenez dstaddr = NULL;
26097a9217aSAntonio Huete Jimenez dstaddr_size = 0;
26197a9217aSAntonio Huete Jimenez }
26297a9217aSAntonio Huete Jimenez
26397a9217aSAntonio Huete Jimenez /*
2641077d0bdSPeter Avalos * Add information for this address to the list.
2651077d0bdSPeter Avalos */
2663a289941SAaron LI if (add_addr_to_if(devlistp, ifa->ifa_name, ifa->ifa_flags,
2673a289941SAaron LI get_flags_func,
26897a9217aSAntonio Huete Jimenez addr, addr_size, netmask, addr_size,
2691077d0bdSPeter Avalos broadaddr, broadaddr_size, dstaddr, dstaddr_size,
2701077d0bdSPeter Avalos errbuf) < 0) {
2711077d0bdSPeter Avalos ret = -1;
2721077d0bdSPeter Avalos break;
2731077d0bdSPeter Avalos }
2741077d0bdSPeter Avalos }
2751077d0bdSPeter Avalos
2761077d0bdSPeter Avalos freeifaddrs(ifap);
2771077d0bdSPeter Avalos
2781077d0bdSPeter Avalos return (ret);
2791077d0bdSPeter Avalos }
280