1478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
2478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  pcap-linux.c: Packet capture interface to the Linux kernel
3478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
4478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  Copyright (c) 2000 Torsten Landschoff <torsten@debian.org>
5478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  		       Sebastian Krahmer  <krahmer@cs.uni-potsdam.de>
6478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
7478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  License: BSD
8478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
9478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  Redistribution and use in source and binary forms, with or without
10478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  modification, are permitted provided that the following conditions
11478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  are met:
12478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
13478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  1. Redistributions of source code must retain the above copyright
14478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     notice, this list of conditions and the following disclaimer.
15478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  2. Redistributions in binary form must reproduce the above copyright
16478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     notice, this list of conditions and the following disclaimer in
17478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     the documentation and/or other materials provided with the
18478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     distribution.
19478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  3. The names of the authors may not be used to endorse or promote
20478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     products derived from this software without specific prior
21478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     written permission.
22478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
23478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
24478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
25478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
27511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Modifications:     Added PACKET_MMAP support
28511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     Paolo Abeni <paolo.abeni@email.it>
29511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     Added TPACKET_V3 support
30511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     Gabor Tatarka <gabor.tatarka@ericsson.com>
31511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
32511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     based on previous works of:
33511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     Simon Patarin <patarin@cs.unibo.it>
34511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *                     Phil Wood <cpw@lanl.gov>
35511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
36511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Monitor-mode support for mac80211 includes code taken from the iw
37511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * command; the copyright notice for that code is
38511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
39511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2007, 2008	Johannes Berg
40511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2007		Andy Lutomirski
41511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2007		Mike Kershaw
42511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Copyright (c) 2008		Gábor Stefanik
43511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
44511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * All rights reserved.
45511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
46511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Redistribution and use in source and binary forms, with or without
47511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * modification, are permitted provided that the following conditions
48511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * are met:
49511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 1. Redistributions of source code must retain the above copyright
50511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *    notice, this list of conditions and the following disclaimer.
51511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 2. Redistributions in binary form must reproduce the above copyright
52511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *    notice, this list of conditions and the following disclaimer in the
53511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *    documentation and/or other materials provided with the distribution.
54511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 3. The name of the author may not be used to endorse or promote products
55511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *    derived from this software without specific prior written permission.
56511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
57511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
58511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
59511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
60511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
61511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
62511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
63511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
64511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
65511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
66511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
67511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * SUCH DAMAGE.
68478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
69478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
70478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef lint
71478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic const char rcsid[] _U_ =
72511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    "@(#) $Header: /tcpdump/master/libpcap/pcap-linux.c,v 1.164 2008-12-14 22:00:57 guy Exp $ (LBL)";
73478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
74478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
75478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
76478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Known problems with 2.0[.x] kernels:
77478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
78478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *   - The loopback device gives every packet twice; on 2.2[.x] kernels,
79478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     if we use PF_PACKET, we can filter out the transmitted version
80478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     of the packet by using data in the "sockaddr_ll" returned by
81478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     "recvfrom()", but, on 2.0[.x] kernels, we have to use
82478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a
83478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     "sockaddr_pkt" which doesn't give us enough information to let
84478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     us do that.
85478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
86478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *   - We have to set the interface's IFF_PROMISC flag ourselves, if
87478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     we're to run in promiscuous mode, which means we have to turn
88478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     it off ourselves when we're done; the kernel doesn't keep track
89478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     of how many sockets are listening promiscuously, which means
90478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     it won't get turned off automatically when no sockets are
91478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     listening promiscuously.  We catch "pcap_close()" and, for
92478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     interfaces we put into promiscuous mode, take them out of
93478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     promiscuous mode - which isn't necessarily the right thing to
94478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     do, if another socket also requested promiscuous mode between
95478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     the time when we opened the socket and the time when we close
96478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     the socket.
97478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
98478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *   - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()"
99478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     return the amount of data that you could have read, rather than
100478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     the amount that was returned, so we can't just allocate a buffer
101478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     whose size is the snapshot length and pass the snapshot length
102478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     as the byte count, and also pass MSG_TRUNC, so that the return
103478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     value tells us how long the packet was on the wire.
104478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
105478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     This means that, if we want to get the actual size of the packet,
106478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     so we can return it in the "len" field of the packet header,
107478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     we have to read the entire packet, not just the part that fits
108478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     within the snapshot length, and thus waste CPU time copying data
109478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     from the kernel that our caller won't see.
110478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
111478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     We have to get the actual size, and supply it in "len", because
112478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     otherwise, the IP dissector in tcpdump, for example, will complain
113478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     about "truncated-ip", as the packet will appear to have been
114478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *     shorter, on the wire, than the IP header said it should have been.
115478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
116478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
117478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define _GNU_SOURCE
119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
120478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_CONFIG_H
121478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include "config.h"
122478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
123478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
124478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <errno.h>
125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdio.h>
126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <stdlib.h>
127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <ctype.h>
128478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <unistd.h>
129478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <fcntl.h>
130478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <string.h>
131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <limits.h>
132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/stat.h>
133478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/socket.h>
134478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/ioctl.h>
135478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <sys/utsname.h>
136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <sys/mman.h>
137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/if.h>
138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/if_packet.h>
139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/sockios.h>
140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <netinet/in.h>
141478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <linux/if_ether.h>
142478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <net/if_arp.h>
143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <poll.h>
144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <dirent.h>
145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap-int.h"
147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap/sll.h"
148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include "pcap/vlan.h"
149478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
151478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET
152478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * sockets rather than SOCK_PACKET sockets.
153478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * To use them, we include <linux/if_packet.h> rather than
155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * <netpacket/packet.h>; we do so because
156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
157478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	some Linux distributions (e.g., Slackware 4.0) have 2.2 or
158478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	later kernels and libc5, and don't provide a <netpacket/packet.h>
159478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	file;
160478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	not all versions of glibc2 have a <netpacket/packet.h> file
162478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	that defines stuff needed for some of the 2.4-or-later-kernel
163478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	features, so if the system has a 2.4 or later kernel, we
164478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *	still can't use those features.
165478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
166478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * We're already including a number of other <linux/XXX.h> headers, and
167478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * this code is Linux-specific (no other OS has PF_PACKET sockets as
168478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * a raw packet capture mechanism), so it's not as if you gain any
169478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * useful portability by using <netpacket/packet.h>
170478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
171478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * XXX - should we just include <linux/if_packet.h> even if PF_PACKET
172478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * isn't defined?  It only defines one data structure in 2.0.x, so
173478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * it shouldn't cause any problems.
174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef PF_PACKET
176478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# include <linux/if_packet.h>
177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
178478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project /*
179478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * On at least some Linux distributions (for example, Red Hat 5.2),
180478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * there's no <netpacket/packet.h> file, but PF_PACKET is defined if
181478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define
182478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of
183478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * the PACKET_xxx stuff.
184478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  *
185478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * So we check whether PACKET_HOST is defined, and assume that we have
186478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  * PF_PACKET sockets only if it is defined.
187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project  */
188478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# ifdef PACKET_HOST
189478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#  define HAVE_PF_PACKET_SOCKETS
190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  ifdef PACKET_AUXDATA
191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#   define HAVE_PACKET_AUXDATA
192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  endif /* PACKET_AUXDATA */
193478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project# endif /* PACKET_HOST */
194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall /* check for memory mapped access avaibility. We assume every needed
197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall  * struct is defined if the macro TPACKET_HDRLEN is defined, because it
198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall  * uses many ring related structs and macros */
199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall# ifdef TPACKET_HDRLEN
200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  define HAVE_PACKET_RING
201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  ifdef TPACKET3_HDRLEN
202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#   define HAVE_TPACKET3
203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  endif /* TPACKET3_HDRLEN */
204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  ifdef TPACKET2_HDRLEN
205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#   define HAVE_TPACKET2
206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  else  /* TPACKET2_HDRLEN */
207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#   define TPACKET_V1	0    /* Old kernel with only V1, so no TPACKET_Vn defined */
208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#  endif /* TPACKET2_HDRLEN */
209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall# endif /* TPACKET_HDRLEN */
210478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif /* PF_PACKET */
211478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
212478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef SO_ATTACH_FILTER
213478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <linux/types.h>
214478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#include <linux/filter.h>
215478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
216478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LINUX_NET_TSTAMP_H
218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/net_tstamp.h>
219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Got Wireless Extensions?
223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LINUX_WIRELESS_H
225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/wireless.h>
226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LINUX_WIRELESS_H */
227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Got libnl?
230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/nl80211.h>
233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netlink/genl/genl.h>
235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netlink/genl/family.h>
236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netlink/genl/ctrl.h>
237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netlink/msg.h>
238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <netlink/attr.h>
239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LIBNL */
240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Got ethtool support?
243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LINUX_ETHTOOL_H
245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#include <linux/ethtool.h>
246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef HAVE_SOCKLEN_T
249478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projecttypedef int		socklen_t;
250478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
251478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
252478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef MSG_TRUNC
253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is being compiled on a system that lacks MSG_TRUNC; define it
255478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * with the value it has in the 2.2 and later kernels, so that, on
256478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * those kernels, when we pass it in the flags argument to "recvfrom()"
257478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * we're passing the right value and thus get the MSG_TRUNC behavior
258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * we want.  (We don't get that behavior on 2.0[.x] kernels, because
259478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * they didn't support MSG_TRUNC.)
260478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
261478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define MSG_TRUNC	0x20
262478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
263478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
264478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifndef SOL_PACKET
265478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
266478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * This is being compiled on a system that lacks SOL_PACKET; define it
267478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * with the value it has in the 2.2 and later kernels, so that we can
268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * set promiscuous mode in the good modern way rather than the old
269478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 2.0-kernel crappy way.
270478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
271478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define SOL_PACKET	263
272478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
273478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
274478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define MAX_LINKHEADER_SIZE	256
275478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
276478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
277478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * When capturing on all interfaces we use this as the buffer size.
278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Should be bigger then all MTUs that occur in real life.
279478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * 64kB should be enough for now.
280478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
281478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#define BIGGER_THAN_ALL_MTUS	(64*1024)
282478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
283478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets.
285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct pcap_linux {
287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int	packets_read;	/* count of packets read with recvfrom() */
288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	long	proc_dropped;	/* packets reported dropped by /proc/net/dev */
289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_stat stat;
290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char	*device;	/* device name */
292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	filter_in_userland; /* must filter in userland */
293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	blocks_to_filter_in_userland;
294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	must_do_on_close; /* stuff we must do when we close */
295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	timeout;	/* timeout for buffering */
296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	sock_packet;	/* using Linux 2.0 compatible interface */
297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	cooked;		/* using SOCK_DGRAM rather than SOCK_RAW */
298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	ifindex;	/* interface index of device we're bound to */
299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	lo_ifindex;	/* interface index of the loopback device */
300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	bpf_u_int32 oldmode;	/* mode to restore when turning monitor mode off */
301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char	*mondevice;	/* mac80211 monitor device we created */
302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char	*mmapbuf;	/* memory-mapped region pointer */
303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	size_t	mmapbuflen;	/* size of region */
304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int	vlan_offset;	/* offset at which to insert vlan tags; if -1, don't insert */
305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int	tp_version;	/* version of tpacket_hdr for mmaped ring */
306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int	tp_hdrlen;	/* hdrlen of tpacket_hdr for mmaped ring */
307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char	*oneshot_buffer; /* buffer for copy of packet */
308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned char *current_packet; /* Current packet within the TPACKET_V3 block. Move to next block if NULL. */
310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int packets_left; /* Unhandled packets left within the block from previous call to pcap_read_linux_mmap_v3 in case of TPACKET_V3. */
311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Stuff to do when we close.
316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MUST_CLEAR_PROMISC	0x00000001	/* clear promiscuous mode */
318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MUST_CLEAR_RFMON	0x00000002	/* clear rfmon (monitor) mode */
319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define MUST_DELETE_MONIF	0x00000004	/* delete monitor-mode interface */
320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Prototypes for internal functions and methods.
323478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
324478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic void map_arphrd_to_dlt(pcap_t *, int, int);
325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic short int map_packet_type_to_sll_type(short int);
327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_activate_linux(pcap_t *);
329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int activate_old(pcap_t *);
330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int activate_new(pcap_t *);
331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int activate_mmap(pcap_t *, int *);
332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_can_set_rfmon_linux(pcap_t *);
333478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *);
334478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_read_packet(pcap_t *, pcap_handler, u_char *);
335478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_inject_linux(pcap_t *, const void *, size_t);
336478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_stats_linux(pcap_t *, struct pcap_stat *);
337478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_setfilter_linux(pcap_t *, struct bpf_program *);
338478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int pcap_setdirection_linux(pcap_t *, pcap_direction_t);
339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_set_datalink_linux(pcap_t *, int);
340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_cleanup_linux(pcap_t *);
341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallunion thdr {
343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_hdr		*h1;
344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket2_hdr		*h2;
346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_block_desc	*h3;
349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	void				*raw;
351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PACKET_RING
354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define RING_GET_FRAME(h) (((union thdr **)h->buffer)[h->offset])
355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void destroy_ring(pcap_t *handle);
357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int create_ring(pcap_t *handle, int *status);
358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int prepare_tpacket_socket(pcap_t *handle);
359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_cleanup_linux_mmap(pcap_t *);
360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *);
361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *);
363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *);
366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *);
368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf);
369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_getnonblock_mmap(pcap_t *p, char *errbuf);
370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    const u_char *bytes);
372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
373478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
374478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
375478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project * Wrap some ioctl calls
376478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
377478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_PF_PACKET_SOCKETS
378478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	iface_get_id(int fd, const char *device, char *ebuf);
379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PF_PACKET_SOCKETS */
380478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	iface_get_mtu(int fd, const char *device, char *ebuf);
381478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int 	iface_get_arptype(int fd, const char *device, char *ebuf);
382478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef HAVE_PF_PACKET_SOCKETS
383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int 	iface_bind(int fd, int ifindex, char *ebuf);
384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int	has_wext(int sock_fd, const char *device, char *ebuf);
386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* IW_MODE_MONITOR */
387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int	enter_rfmon_mode(pcap_t *handle, int sock_fd,
388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    const char *device);
389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PF_PACKET_SOCKETS */
390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int	iface_get_offload(pcap_t *handle);
391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int 	iface_bind_old(int fd, const char *device, char *ebuf);
392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef SO_ATTACH_FILTER
394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int	fix_program(pcap_t *handle, struct sock_fprog *fcode,
395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    int is_mapped);
396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	fix_offset(struct bpf_insn *p);
397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode);
398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int	reset_kernel_filter(pcap_t *handle);
399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct sock_filter	total_insn
401478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	= BPF_STMT(BPF_RET | BPF_K, 0);
402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic struct sock_fprog	total_fcode
403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	= { 1, &total_insn };
404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* SO_ATTACH_FILTER */
405478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
406478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectpcap_t *
407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_create_interface(const char *device, char *ebuf)
408478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_t *handle;
410478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle = pcap_create_common(device, ebuf, sizeof (struct pcap_linux));
412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle == NULL)
413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->activate_op = pcap_activate_linux;
416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->can_set_rfmon_op = pcap_can_set_rfmon_linux;
417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We claim that we support:
420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	software time stamps, with no details about their precision;
422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	hardware time stamps, synced to the host time;
423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	hardware time stamps, not synced to the host time.
424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - we can't ask a device whether it supports
426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * hardware time stamps, so we just claim all devices do.
427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_type_count = 3;
429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_type_list = malloc(3 * sizeof(u_int));
430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->tstamp_type_list == NULL) {
431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handle);
432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return NULL;
433478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_type_list[0] = PCAP_TSTAMP_HOST;
435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_type_list[1] = PCAP_TSTAMP_ADAPTER;
436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_type_list[2] = PCAP_TSTAMP_ADAPTER_UNSYNCED;
437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
438478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We claim that we support microsecond and nanosecond time
442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * stamps.
443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - with adapter-supplied time stamps, can we choose
445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * microsecond or nanosecond time stamps on arbitrary
446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * adapters?
447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_precision_count = 2;
449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_precision_list = malloc(2 * sizeof(u_int));
450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->tstamp_precision_list == NULL) {
451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->tstamp_type_list != NULL)
452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			free(handle->tstamp_type_list);
453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handle);
454478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return NULL;
455478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO;
457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO;
458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return handle;
461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
462478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * If interface {if} is a mac80211 driver, the file
466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * /sys/class/net/{if}/phy80211 is a symlink to
467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * /sys/class/ieee80211/{phydev}, for some {phydev}.
468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * least, has a "wmaster0" device and a "wlan0" device; the
471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * latter is the one with the IP address.  Both show up in
472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * "tcpdump -D" output.  Capturing on the wmaster0 device
473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * captures with 802.11 headers.
474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * airmon-ng searches through /sys/class/net for devices named
476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * monN, starting with mon0; as soon as one *doesn't* exist,
477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * it chooses that as the monitor device name.  If the "iw"
478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * command exists, it does "iw dev {if} interface add {monif}
479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * type monitor", where {monif} is the monitor device.  It
480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * then (sigh) sleeps .1 second, and then configures the
481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * is a file, it writes {mondev}, without a newline, to that file,
483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * and again (sigh) sleeps .1 second, and then iwconfig's that
484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * device into monitor mode and configures it up.  Otherwise,
485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * you can't do monitor mode.
486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * All these devices are "glued" together by having the
488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * /sys/class/net/{device}/phy80211 links pointing to the same
489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * place, so, given a wmaster, wlan, or mon device, you can
490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * find the other devices by looking for devices with
491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the same phy80211 link.
492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * To turn monitor mode off, delete the monitor interface,
494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * either with "iw dev {monif} interface del" or by sending
495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Note: if you try to create a monitor device named "monN", and
498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * there's already a "monN" device, it fails, as least with
499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the netlink interface (which is what iw uses), with a return
500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * value of -ENFILE.  (Return values are negative errnos.)  We
501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * could probably use that to find an unused device.
502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Yes, you can have multiple monitor devices for a given
504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * physical device.
505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall*/
506478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Is this a mac80211 device?  If so, fill in the physical device path and
509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * return 1; if not, return 0.  On an error, fill in handle->errbuf and
510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * return PCAP_ERROR.
511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallget_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path,
514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    size_t phydev_max_pathlen)
515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *pathstr;
517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ssize_t bytes_read;
518478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
519478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Generate the path string for the symlink to the physical device.
521478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) {
523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: Can't generate path name string for /sys/class/net device",
525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    device);
526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen);
529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (bytes_read == -1) {
530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOENT || errno == EINVAL) {
531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Doesn't exist, or not a symlink; assume that
533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * means it's not a mac80211 device.
534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			free(pathstr);
536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
537478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: Can't readlink %s: %s", device, pathstr,
540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    strerror(errno));
541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(pathstr);
542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	free(pathstr);
545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	phydev_path[bytes_read] = '\0';
546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL_SOCKETS
550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define get_nl_errmsg	nl_geterror
551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* libnl 2.x compatibility code */
553478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define nl_sock nl_handle
555478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline struct nl_handle *
557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnl_socket_alloc(void)
558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return nl_handle_alloc();
560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline void
563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnl_socket_free(struct nl_handle *h)
564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl_handle_destroy(h);
566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
567478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define get_nl_errmsg	strerror
569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline int
571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache)
572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl_cache *tmp = genl_ctrl_alloc_cache(h);
574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!tmp)
575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -ENOMEM;
576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*cache = tmp;
577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache
580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* !HAVE_LIBNL_SOCKETS */
581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstruct nl80211_state {
583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl_sock *nl_sock;
584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl_cache *nl_cache;
585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct genl_family *nl80211;
586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall};
587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device)
590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int err;
592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	state->nl_sock = nl_socket_alloc();
594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!state->nl_sock) {
595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: failed to allocate netlink handle", device);
597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
598478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
599478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (genl_connect(state->nl_sock)) {
601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: failed to connect to generic netlink", device);
603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto out_handle_destroy;
604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
605478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache);
607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err < 0) {
608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: failed to allocate generic netlink cache: %s",
610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    device, get_nl_errmsg(-err));
611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto out_handle_destroy;
612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
613478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211");
615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!state->nl80211) {
616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: nl80211 not found", device);
618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto out_cache_free;
619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
620478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
622478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallout_cache_free:
624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl_cache_free(state->nl_cache);
625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallout_handle_destroy:
626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl_socket_free(state->nl_sock);
627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return PCAP_ERROR;
628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
629478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnl80211_cleanup(struct nl80211_state *state)
632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	genl_family_put(state->nl80211);
634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl_cache_free(state->nl_cache);
635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl_socket_free(state->nl_sock);
636478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
637478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
638478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralladd_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    const char *device, const char *mondevice)
641478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ifindex;
643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl_msg *msg;
644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int err;
645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ifindex = iface_get_id(sock_fd, device, handle->errbuf);
647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ifindex == -1)
648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg = nlmsg_alloc();
651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!msg) {
652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: failed to allocate netlink msg", device);
654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    0, NL80211_CMD_NEW_INTERFACE, 0);
659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice);
661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR);
662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = nl_send_auto_complete(state->nl_sock, msg);
664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err < 0) {
665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined HAVE_LIBNL_NLE
666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (err == -NLE_FAILURE) {
667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (err == -ENFILE) {
669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Device not available; our caller should just
672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * keep trying.  (libnl 2.x maps ENFILE to
673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * NLE_FAILURE; it can also map other errors
674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * to that, but there's not much we can do
675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * about that.)
676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			nlmsg_free(msg);
678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Real failure, not just "that device is not
682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * available.
683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: nl_send_auto_complete failed adding %s interface: %s",
686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    device, mondevice, get_nl_errmsg(-err));
687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			nlmsg_free(msg);
688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = nl_wait_for_ack(state->nl_sock);
692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err < 0) {
693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined HAVE_LIBNL_NLE
694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (err == -NLE_FAILURE) {
695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (err == -ENFILE) {
697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Device not available; our caller should just
700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * keep trying.  (libnl 2.x maps ENFILE to
701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * NLE_FAILURE; it can also map other errors
702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * to that, but there's not much we can do
703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * about that.)
704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			nlmsg_free(msg);
706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Real failure, not just "that device is not
710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * available.
711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: nl_wait_for_ack failed adding %s interface: %s",
714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    device, mondevice, get_nl_errmsg(-err));
715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			nlmsg_free(msg);
716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
720478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Success.
722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nlmsg_free(msg);
724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnla_put_failure:
727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    "%s: nl_put failed adding %s interface",
729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    device, mondevice);
730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nlmsg_free(msg);
731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return PCAP_ERROR;
732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
733478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
734478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralldel_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state,
736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    const char *device, const char *mondevice)
737478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ifindex;
739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl_msg *msg;
740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int err;
741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ifindex = iface_get_id(sock_fd, mondevice, handle->errbuf);
743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ifindex == -1)
744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg = nlmsg_alloc();
747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!msg) {
748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: failed to allocate netlink msg", device);
750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0,
754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    0, NL80211_CMD_DEL_INTERFACE, 0);
755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex);
756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = nl_send_auto_complete(state->nl_sock, msg);
758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err < 0) {
759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: nl_send_auto_complete failed deleting %s interface: %s",
761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    device, mondevice, get_nl_errmsg(-err));
762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		nlmsg_free(msg);
763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = nl_wait_for_ack(state->nl_sock);
766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err < 0) {
767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: nl_wait_for_ack failed adding %s interface: %s",
769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    device, mondevice, get_nl_errmsg(-err));
770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		nlmsg_free(msg);
771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Success.
776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nlmsg_free(msg);
778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallnla_put_failure:
781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    "%s: nl_put failed deleting %s interface",
783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    device, mondevice);
784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nlmsg_free(msg);
785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return PCAP_ERROR;
786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallenter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device)
790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char phydev_path[PATH_MAX+1];
794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl80211_state nlstate;
795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq ifr;
796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_int n;
797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Is this a mac80211 device?
800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX);
802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;	/* error */
804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 0)
805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;	/* no error, but not mac80211 device */
806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - is this already a monN device?
809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If so, we're done.
810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Is that determined by old Wireless Extensions ioctls?
811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * OK, it's apparently a mac80211 device.
815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Try to find an unused monN device for it.
816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = nl80211_init(handle, &nlstate, device);
818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret != 0)
819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (n = 0; n < UINT_MAX; n++) {
821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Try mon{n}.
823478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		char mondevice[3+10+1];	/* mon{UINT_MAX}\0 */
825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(mondevice, sizeof mondevice, "mon%u", n);
827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice);
828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret == 1) {
829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->mondevice = strdup(mondevice);
830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			goto added;
831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret < 0) {
833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Hard failure.  Just return ret; handle->errbuf
835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * has already been set.
836478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			nl80211_cleanup(&nlstate);
838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return ret;
839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    "%s: No free monN interfaces", device);
844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl80211_cleanup(&nlstate);
845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return PCAP_ERROR;
846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralladded:
848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if 0
850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Sleep for .1 seconds.
852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	delay.tv_sec = 0;
854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	delay.tv_nsec = 500000000;
855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nanosleep(&delay, NULL);
856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we haven't already done so, arrange to have
860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "pcap_close_all()" called when we exit.
861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!pcap_do_addexit(handle)) {
863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "atexit()" failed; don't put the interface
865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in rfmon mode, just give up.
866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_RFMON_NOTSUP;
868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
870478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Now configure the monitor interface up.
872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&ifr, 0, sizeof(ifr));
874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name));
875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: Can't get flags for %s: %s", device,
878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handlep->mondevice, strerror(errno));
879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		del_mon_if(handle, sock_fd, &nlstate, device,
880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handlep->mondevice);
881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		nl80211_cleanup(&nlstate);
882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
883478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ifr.ifr_flags |= IFF_UP|IFF_RUNNING;
885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: Can't set flags for %s: %s", device,
888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handlep->mondevice, strerror(errno));
889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		del_mon_if(handle, sock_fd, &nlstate, device,
890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handlep->mondevice);
891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		nl80211_cleanup(&nlstate);
892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
893478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
894478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
895478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Success.  Clean up the libnl state.
897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	nl80211_cleanup(&nlstate);
899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Note that we have to delete the monitor device when we close
902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the handle.
903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->must_do_on_close |= MUST_DELETE_MONIF;
905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Add this to the list of pcaps to close when we exit.
908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_add_to_pcaps_to_close(handle);
910478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 1;
912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LIBNL */
914478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_can_set_rfmon_linux(pcap_t *handle)
917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char phydev_path[PATH_MAX+1];
920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ret;
921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int sock_fd;
924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iwreq ireq;
925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (strcmp(handle->opt.source, "any") == 0) {
928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Monitor mode makes no sense on the "any" device.
930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Bleah.  There doesn't seem to be a way to ask a mac80211
937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * device, through libnl, whether it supports monitor mode;
938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we'll just check whether the device appears to be a
939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mac80211 device and, if so, assume the device supports
940511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * monitor mode.
941511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
942511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * wmaster devices don't appear to support the Wireless
943511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Extensions, but we can create a mon device for a
944511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * wmaster device, so we don't bother checking whether
945511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * a mac80211 device supports the Wireless Extensions.
946511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
947511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = get_mac80211_phydev(handle, handle->opt.source, phydev_path,
948511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    PATH_MAX);
949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;	/* error */
951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 1)
952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* mac80211 device */
953478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
954478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
956511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
957511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Bleah.  There doesn't appear to be an ioctl to use to ask
958511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * whether a device supports monitor mode; we'll just do
959511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * SIOCGIWMODE and, if it succeeds, assume the device supports
960511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * monitor mode.
961511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Open a socket on which to attempt to get the mode.
963511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * (We assume that if we have Wireless Extensions support
964511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we also have PF_PACKET support.)
965511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
966511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sock_fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
967511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sock_fd == -1) {
968511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
969511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "socket: %s", pcap_strerror(errno));
970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
974511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Attempt to get the current mode.
975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
976511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ireq.ifr_ifrn.ifrn_name, handle->opt.source,
977511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    sizeof ireq.ifr_ifrn.ifrn_name);
978511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
979511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) {
980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Well, we got the mode; assume we can set it.
982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		close(sock_fd);
984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;
985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (errno == ENODEV) {
987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* The device doesn't even exist. */
988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "SIOCGIWMODE failed: %s", pcap_strerror(errno));
990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		close(sock_fd);
991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_NO_SUCH_DEVICE;
992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	close(sock_fd);
994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Grabs the number of dropped packets by the interface from /proc/net/dev.
1000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
1001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * XXX - what about /sys/class/net/{interface name}/rx_*?  There are
1002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * individual devices giving, in ASCII, various rx_ and tx_ statistics.
1003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
1004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Or can we get them in binary form from netlink?
1005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic long int
1007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralllinux_if_drops(const char * if_name)
1008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1009511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char buffer[512];
1010511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char * bufptr;
1011511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	FILE * file;
1012511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int field_to_convert = 3, if_name_sz = strlen(if_name);
1013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	long int dropped_pkts = 0;
1014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	file = fopen("/proc/net/dev", "r");
1016511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!file)
1017511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
1018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1019511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while (!dropped_pkts && fgets( buffer, sizeof(buffer), file ))
1020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
1021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* 	search for 'bytes' -- if its in there, then
1022511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			that means we need to grab the fourth field. otherwise
1023511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			grab the third field. */
1024511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (field_to_convert != 4 && strstr(buffer, "bytes"))
1025511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
1026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			field_to_convert = 4;
1027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
1028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1030511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* find iface and make sure it actually matches -- space before the name and : after it */
1031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((bufptr = strstr(buffer, if_name)) &&
1032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(bufptr == buffer || *(bufptr-1) == ' ') &&
1033511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			*(bufptr + if_name_sz) == ':')
1034511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
1035511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bufptr = bufptr + if_name_sz + 1;
1036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* grab the nth field from it */
1038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			while( --field_to_convert && *bufptr != '\0')
1039511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			{
1040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				while (*bufptr != '\0' && *(bufptr++) == ' ');
1041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				while (*bufptr != '\0' && *(bufptr++) != ' ');
1042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* get rid of any final spaces */
1045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			while (*bufptr != '\0' && *bufptr == ' ') bufptr++;
1046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1047511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (*bufptr != '\0')
1048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				dropped_pkts = strtol(bufptr, NULL, 10);
1049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
1051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
1053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1054511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	fclose(file);
1055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return dropped_pkts;
1056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * With older kernels promiscuous mode is kind of interesting because we
1061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * have to reset the interface before exiting. The problem can't really
1062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * be solved without some daemon taking care of managing usage counts.
1063511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * If we put the interface into promiscuous mode, we set a flag indicating
1064511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * that we must take it out of that mode when the interface is closed,
1065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * and, when closing the interface, if that flag is set we take it out
1066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * of promiscuous mode.
1067511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
1068511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Even with newer kernels, we have the same issue with rfmon mode.
1069511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1071511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void	pcap_cleanup_linux( pcap_t *handle )
1072511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1073511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
1074511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq	ifr;
1075511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
1076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct nl80211_state nlstate;
1077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
1078511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LIBNL */
1079511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
1080511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int oldflags;
1081511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iwreq ireq;
1082511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* IW_MODE_MONITOR */
1083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->must_do_on_close != 0) {
1085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1086511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * There's something we have to do when closing this
1087511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * pcap_t.
1088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1089511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) {
1090478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1091511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We put the interface into promiscuous mode;
1092511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * take it out of promiscuous mode.
1093511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
1094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - if somebody else wants it in promiscuous
1095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * mode, this code cannot know that, so it'll take
1096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * it out of promiscuous mode.  That's not fixable
1097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * in 2.0[.x] kernels.
1098478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			memset(&ifr, 0, sizeof(ifr));
1100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			strncpy(ifr.ifr_name, handlep->device,
1101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    sizeof(ifr.ifr_name));
1102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
1103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				fprintf(stderr,
1104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n"
1105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Please adjust manually.\n"
1106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Hint: This can't happen with Linux >= 2.2.0.\n",
1107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    handlep->device, strerror(errno));
1108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else {
1109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (ifr.ifr_flags & IFF_PROMISC) {
1110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
1111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * Promiscuous mode is currently on;
1112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * turn it off.
1113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
1114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					ifr.ifr_flags &= ~IFF_PROMISC;
1115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					if (ioctl(handle->fd, SIOCSIFFLAGS,
1116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					    &ifr) == -1) {
1117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						fprintf(stderr,
1118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						    "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n"
1119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						    "Please adjust manually.\n"
1120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						    "Hint: This can't happen with Linux >= 2.2.0.\n",
1121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						    handlep->device,
1122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						    strerror(errno));
1123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					}
1124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
1125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1127478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
1129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->must_do_on_close & MUST_DELETE_MONIF) {
1130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = nl80211_init(handle, &nlstate, handlep->device);
1131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ret >= 0) {
1132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				ret = del_mon_if(handle, handle->fd, &nlstate,
1133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    handlep->device, handlep->mondevice);
1134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				nl80211_cleanup(&nlstate);
1135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ret < 0) {
1137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				fprintf(stderr,
1138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Can't delete monitor interface %s (%s).\n"
1139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Please delete manually.\n",
1140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    handlep->mondevice, handle->errbuf);
1141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LIBNL */
1144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
1146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->must_do_on_close & MUST_CLEAR_RFMON) {
1147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We put the interface into rfmon mode;
1149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * take it out of rfmon mode.
1150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
1151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - if somebody else wants it in rfmon
1152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * mode, this code cannot know that, so it'll take
1153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * it out of rfmon mode.
1154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * First, take the interface down if it's up;
1158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * otherwise, we might get EBUSY.
1159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If we get errors, just drive on and print
1160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * a warning if we can't restore the mode.
1161478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			oldflags = 0;
1163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			memset(&ifr, 0, sizeof(ifr));
1164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			strncpy(ifr.ifr_name, handlep->device,
1165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    sizeof(ifr.ifr_name));
1166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) {
1167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (ifr.ifr_flags & IFF_UP) {
1168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					oldflags = ifr.ifr_flags;
1169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					ifr.ifr_flags &= ~IFF_UP;
1170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1)
1171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						oldflags = 0;	/* didn't set, don't restore */
1172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
1173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1174478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1175478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
1176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Now restore the mode.
1177478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
1178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			strncpy(ireq.ifr_ifrn.ifrn_name, handlep->device,
1179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    sizeof ireq.ifr_ifrn.ifrn_name);
1180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1]
1181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    = 0;
1182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ireq.u.mode = handlep->oldmode;
1183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
1184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
1185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Scientist, you've failed.
1186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
1187478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				fprintf(stderr,
1188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n"
1189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Please adjust manually.\n",
1190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    handlep->device, strerror(errno));
1191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
1192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Now bring the interface back up if we brought
1195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * it down.
1196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (oldflags != 0) {
1198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				ifr.ifr_flags = oldflags;
1199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
1200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					fprintf(stderr,
1201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					    "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n"
1202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					    "Please adjust manually.\n",
1203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					    handlep->device, strerror(errno));
1204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
1205478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
1206478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
1207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* IW_MODE_MONITOR */
1208478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Take this pcap out of the list of pcaps for which we
1211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * have to take the interface out of some mode.
1212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_remove_from_pcaps_to_close(handle);
1214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->mondevice != NULL) {
1217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->mondevice);
1218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->mondevice = NULL;
1219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->device != NULL) {
1221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->device);
1222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->device = NULL;
1223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_cleanup_live_common(handle);
1225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Get a handle for a live capture from the given device. You can
1229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  pass NULL as device to get all packages (without link level
1230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  information of course). If you pass 1 as promisc the interface
1231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  will be set to promiscous mode (XXX: I think this usage should
1232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  be deprecated and functions be added to select that later allow
1233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  modification of that values -- Torsten).
1234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
1236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_activate_linux(pcap_t *handle)
1237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
1239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	const char	*device;
1240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int		status = 0;
1241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	device = handle->opt.source;
1243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->inject_op = pcap_inject_linux;
1245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setfilter_op = pcap_setfilter_linux;
1246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setdirection_op = pcap_setdirection_linux;
1247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->set_datalink_op = pcap_set_datalink_linux;
1248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->getnonblock_op = pcap_getnonblock_fd;
1249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setnonblock_op = pcap_setnonblock_fd;
1250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->cleanup_op = pcap_cleanup_linux;
1251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->read_op = pcap_read_linux;
1252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->stats_op = pcap_stats_linux;
1253478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1254478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
1255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The "any" device is a special device which causes us not
1256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to bind to a particular device and thus to look at all
1257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * devices.
1258478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
1259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (strcmp(device, "any") == 0) {
1260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->opt.promisc) {
1261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->opt.promisc = 0;
1262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* Just a warning. */
1263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Promiscuous mode not supported on the \"any\" device");
1265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			status = PCAP_WARNING_PROMISC_NOTSUP;
1266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1268478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->device	= strdup(device);
1270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->device == NULL) {
1271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "strdup: %s",
1272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 pcap_strerror(errno) );
1273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
1274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* copy timeout value */
1277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->timeout = handle->opt.timeout;
1278478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we're in promiscuous mode, then we probably want
1281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to see when the interface drops packets too, so get an
1282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * initial count from /proc/net/dev
1283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.promisc)
1285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->proc_dropped = linux_if_drops(handlep->device);
1286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Current Linux kernels use the protocol family PF_PACKET to
1289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * allow direct access to all packets on the network while
1290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * older kernels had a special socket type SOCK_PACKET to
1291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * implement this feature.
1292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * While this old implementation is kind of obsolete we need
1293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to be compatible with older kernels for a while so we are
1294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * trying both methods with the newer method preferred.
1295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	status = activate_new(handle);
1297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (status < 0) {
1298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Fatal error with the new way; just fail.
1300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * status has the error return; if it's PCAP_ERROR,
1301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * handle->errbuf has been set appropriately.
1302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto fail;
1304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (status == 1) {
1306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Success.
1308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Try to use memory-mapped access.
1309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (activate_mmap(handle, &status)) {
1311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case 1:
1313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We succeeded.  status has been
1315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * set to the status to return,
1316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * which might be 0, or might be
1317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * a PCAP_WARNING_ value.
1318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return status;
1320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case 0:
1322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Kernel doesn't support it - just continue
1324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * with non-memory-mapped access.
1325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
1327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case -1:
1329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We failed to set up to use it, or the kernel
1331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * supports it, but we failed to enable it.
1332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * status has been set to the error status to
1333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * return and, if it's PCAP_ERROR, handle->errbuf
1334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * contains the error message.
1335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			goto fail;
1337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else if (status == 0) {
1340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Non-fatal error; try old way */
1341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((status = activate_old(handle)) != 1) {
1342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Both methods to open the packet socket failed.
1344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Tidy up and report our failure (handle->errbuf
1345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * is expected to be set by the functions above).
1346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			goto fail;
1348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We set up the socket, but not with memory-mapped access.
1353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	status = 0;
1355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.buffer_size != 0) {
1356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Set the socket buffer size to the specified value.
1358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF,
1360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    &handle->opt.buffer_size,
1361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof(handle->opt.buffer_size)) == -1) {
1362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 "SO_RCVBUF: %s", pcap_strerror(errno));
1364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			status = PCAP_ERROR;
1365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			goto fail;
1366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Allocate the buffer */
1370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->buffer	 = malloc(handle->bufsize + handle->offset);
1372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handle->buffer) {
1373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "malloc: %s", pcap_strerror(errno));
1375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		status = PCAP_ERROR;
1376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		goto fail;
1377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "handle->fd" is a socket, so "select()" and "poll()"
1381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * should work on it.
1382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->selectable_fd = handle->fd;
1384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return status;
1386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallfail:
1388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_cleanup_linux(handle);
1389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return status;
1390478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1391478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1392478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Read at most max_packets from the capture stream and call the callback
1394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  for each of them. Returns the number of packets handled or -1 if an
1395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  error occured.
1396478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1397478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
1398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_linux(pcap_t *handle, int max_packets, pcap_handler callback, u_char *user)
1399478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1400478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
1401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Currently, on Linux only one packet is delivered per read,
1402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * so we don't loop.
1403478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
1404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return pcap_read_packet(handle, callback, user);
1405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
1408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_set_datalink_linux(pcap_t *handle, int dlt)
1409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->linktype = dlt;
1411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
1412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
1413478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1414478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
1415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * linux_check_direction()
1416478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *
1417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Do checks based on packet direction.
1418478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
1419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline int
1420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralllinux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll)
1421478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
1422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux	*handlep = handle->priv;
1423478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sll->sll_pkttype == PACKET_OUTGOING) {
1425478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Outgoing packet.
1427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If this is from the loopback device, reject it;
1428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * we'll see the packet as an incoming packet as well,
1429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * and we don't want to see it twice.
1430478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (sll->sll_ifindex == handlep->lo_ifindex)
1432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If the user only wants incoming packets, reject it.
1436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->direction == PCAP_D_IN)
1438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
1440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Incoming packet.
1442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If the user only wants outgoing packets, reject it.
1443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->direction == PCAP_D_OUT)
1445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
1448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Read a packet from the socket calling the handler provided by
1452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  the user. Returns the number of packets received or -1 if an
1453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  error occured.
1454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
1456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata)
1457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux	*handlep = handle->priv;
1459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	u_char			*bp;
1460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			offset;
1461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
1462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sockaddr_ll	from;
1463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sll_header	*hdrp;
1464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
1465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sockaddr		from;
1466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
1467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
1468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iovec		iov;
1469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct msghdr		msg;
1470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct cmsghdr		*cmsg;
1471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	union {
1472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct cmsghdr	cmsg;
1473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		char		buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
1474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} cmsg_buf;
1475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	socklen_t		fromlen;
1477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			packet_len, caplen;
1479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr	pcap_header;
1480478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
1482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If this is a cooked device, leave extra room for a
1484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * fake packet header.
1485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->cooked)
1487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		offset = SLL_HDR_LEN;
1488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else
1489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		offset = 0;
1490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
1491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * This system doesn't have PF_PACKET sockets, so it doesn't
1493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * support cooked devices.
1494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	offset = 0;
1496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
1497478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Receive a single packet from the kernel.
1500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We ignore EINTR, as that might just be due to a signal
1501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * being delivered - if the signal should interrupt the
1502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * loop, the signal handler should call pcap_breakloop()
1503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to set handle->break_loop (we ignore it on other
1504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * platforms as well).
1505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We also ignore ENETDOWN, so that we can continue to
1506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * capture traffic if the interface goes down and comes
1507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * back up again; comments in the kernel indicate that
1508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we'll just block waiting for packets if we try to
1509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * receive from a socket that delivered ENETDOWN, and,
1510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * if we're using a memory-mapped buffer, we won't even
1511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * get notified of "network down" events.
1512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	bp = handle->buffer + handle->offset;
1514478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
1516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_name		= &from;
1517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_namelen		= sizeof(from);
1518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_iov		= &iov;
1519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_iovlen		= 1;
1520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_control		= &cmsg_buf;
1521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_controllen	= sizeof(cmsg_buf);
1522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	msg.msg_flags		= 0;
1523478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	iov.iov_len		= handle->bufsize - offset;
1525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	iov.iov_base		= bp + offset;
1526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1527478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	do {
1529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Has "pcap_breakloop()" been called?
1531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop) {
1533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Yes - clear the flag that indicates that it has,
1535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * and return PCAP_ERROR_BREAK as an indication that
1536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we were told to break out of the loop.
1537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
1539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_BREAK;
1540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
1543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC);
1544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fromlen = sizeof(from);
1546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		packet_len = recvfrom(
1547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->fd, bp + offset,
1548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->bufsize - offset, MSG_TRUNC,
1549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(struct sockaddr *) &from, &fromlen);
1550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} while (packet_len == -1 && errno == EINTR);
1552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Check if an error occured */
1554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (packet_len == -1) {
1556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (errno) {
1557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case EAGAIN:
1559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;	/* no packet there */
1560478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case ENETDOWN:
1562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * The device on which we're capturing went away.
1564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
1565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - we should really return
1566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch()
1567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * etc. aren't defined to return that.
1568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				"The interface went down");
1571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
1572478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
1574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 "recvfrom: %s", pcap_strerror(errno));
1576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
1577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
1581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handlep->sock_packet) {
1582478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Unfortunately, there is a window between socket() and
1584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * bind() where the kernel may queue packets from any
1585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * interface.  If we're bound to a particular interface,
1586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * discard packets not from that interface.
1587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
1588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * (If socket filters are supported, we could do the
1589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * same thing we do when changing the filter; however,
1590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that won't handle packet sockets without socket
1591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * filter support, and it's a bit more complicated.
1592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * It would save some instructions per packet, however.)
1593478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->ifindex != -1 &&
1595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    from.sll_ifindex != handlep->ifindex)
1596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Do checks based on packet direction.
1600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We can only do this if we're using PF_PACKET; the
1601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * address returned for SOCK_PACKET is a "sockaddr_pkt"
1602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * which lacks the relevant packet type information.
1603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!linux_check_direction(handle, &from))
1605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1607478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
1608478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
1610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If this is a cooked device, fill in the fake packet header.
1612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->cooked) {
1614478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
1615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Add the length of the fake header to the length
1616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of packet data we read.
1617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
1618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		packet_len += SLL_HDR_LEN;
1619478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp = (struct sll_header *)bp;
1621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_pkttype = map_packet_type_to_sll_type(from.sll_pkttype);
1622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_hatype = htons(from.sll_hatype);
1623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_halen = htons(from.sll_halen);
1624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(hdrp->sll_addr, from.sll_addr,
1625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    (from.sll_halen > SLL_ADDRLEN) ?
1626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		      SLL_ADDRLEN :
1627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		      from.sll_halen);
1628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_protocol = from.sll_protocol;
1629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI)
1632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->vlan_offset != -1) {
1633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
1634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			struct tpacket_auxdata *aux;
1635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			unsigned int len;
1636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			struct vlan_tag *tag;
1637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) ||
1639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    cmsg->cmsg_level != SOL_PACKET ||
1640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    cmsg->cmsg_type != PACKET_AUXDATA)
1641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
1642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg);
1644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(TP_STATUS_VLAN_VALID)
1645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if ((aux->tp_vlan_tci == 0) && !(aux->tp_status & TP_STATUS_VLAN_VALID))
1646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
1647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (aux->tp_vlan_tci == 0) /* this is ambigious but without the
1648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						TP_STATUS_VLAN_VALID flag, there is
1649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						nothing that we can do */
1650478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
1651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
1652478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			len = packet_len > iov.iov_len ? iov.iov_len : packet_len;
1654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (len < (unsigned int) handlep->vlan_offset)
1655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
1656478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			bp -= VLAN_TAG_LEN;
1658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
1659478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
1661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			tag->vlan_tpid = htons(ETH_P_8021Q);
1662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			tag->vlan_tci = htons(aux->tp_vlan_tci);
1663478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
1664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			packet_len += VLAN_TAG_LEN;
1665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_LINUX_TPACKET_AUXDATA_TP_VLAN_TCI) */
1668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PF_PACKET_SOCKETS */
1669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX: According to the kernel source we should get the real
1672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packet len if calling recvfrom with MSG_TRUNC set. It does
1673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * not seem to work here :(, but it is supported by this code
1674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * anyway.
1675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * To be honest the code RELIES on that feature so this is really
1676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * broken with 2.2.x kernels.
1677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * I spend a day to figure out what's going on and I found out
1678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * that the following is happening:
1679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The packet comes from a random interface and the packet_rcv
1681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * hook is called with a clone of the packet. That code inserts
1682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the packet into the receive queue of the packet socket.
1683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If a filter is attached to that socket that filter is run
1684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * first - and there lies the problem. The default filter always
1685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * cuts the packet at the snaplen:
1686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * # tcpdump -d
1688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * (000) ret      #68
1689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * So the packet filter cuts down the packet. The recvfrom call
1691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * says "hey, it's only 68 bytes, it fits into the buffer" with
1692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the result that we don't get the real packet length. This
1693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * is valid at least until kernel 2.2.17pre6.
1694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We currently handle this by making a copy of the filter
1696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * program, fixing all "ret" instructions with non-zero
1697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * operands to have an operand of 65535 so that the filter
1698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * doesn't truncate the packet, and supplying that modified
1699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * filter to the kernel.
1700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	caplen = packet_len;
1703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (caplen > handle->snapshot)
1704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		caplen = handle->snapshot;
1705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Run the packet filter if not using kernel filter */
1707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->filter_in_userland && handle->fcode.bf_insns) {
1708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (bpf_filter(handle->fcode.bf_insns, bp,
1709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		                packet_len, caplen) == 0)
1710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
1711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* rejected by filter */
1712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
1713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Fill in our own header data */
1717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* get timestamp for this packet */
1719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
1720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
1721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) {
1722511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"SIOCGSTAMPNS: %s", pcap_strerror(errno));
1724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
1725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        } else
1727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
1728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
1729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) {
1730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"SIOCGSTAMP: %s", pcap_strerror(errno));
1732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
1733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall        }
1735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_header.caplen	= caplen;
1737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_header.len		= packet_len;
1738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Count the packet.
1741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Arguably, we should count them before we check the filter,
1743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * as on many other platforms "ps_recv" counts packets
1744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handed to the filter rather than packets that passed
1745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the filter, but if filtering is done in the kernel, we
1746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * can't get a count of packets that passed the filter,
1747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and that would mean the meaning of "ps_recv" wouldn't
1748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * be the same on all Linux systems.
1749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - it's not the same on all systems in any case;
1751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * ideally, we should have a "get the statistics" call
1752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * that supplies more counts and indicates which of them
1753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it supplies, so that we supply a count of packets
1754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handed to the filter only on platforms where that
1755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * information is available.
1756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We count them here even if we can get the packet count
1758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * from the kernel, as we can only determine at run time
1759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * whether we'll be able to get it from the kernel (if
1760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * HAVE_TPACKET_STATS isn't defined, we can't get it from
1761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the kernel, but if it is defined, the library might
1762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * have been built with a 2.4 or later kernel, but we
1763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * might be running on a 2.2[.x] kernel without Alexey
1764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Kuznetzov's turbopacket patches, and thus the kernel
1765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * might not be able to supply those statistics).  We
1766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * could, I guess, try, when opening the socket, to get
1767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the statistics, and if we can not increment the count
1768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * here, but it's not clear that always incrementing
1769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the count is more expensive than always testing a flag
1770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * in memory.
1771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We keep the count in "handlep->packets_read", and use that
1773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * for "ps_recv" if we can't get the statistics from the kernel.
1774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We do that because, if we *can* get the statistics from
1775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the kernel, we use "handlep->stat.ps_recv" and
1776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "handlep->stat.ps_drop" as running counts, as reading the
1777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * statistics from the kernel resets the kernel statistics,
1778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and if we directly increment "handlep->stat.ps_recv" here,
1779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * that means it will count packets *twice* on systems where
1780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we can get kernel statistics - once here, and once in
1781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * pcap_stats_linux().
1782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->packets_read++;
1784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Call the user supplied callback function */
1786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	callback(userdata, &pcap_header, bp);
1787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
1789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
1792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_inject_linux(pcap_t *handle, const void *buf, size_t size)
1793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
1795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
1796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
1798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handlep->sock_packet) {
1799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* PF_PACKET socket */
1800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->ifindex == -1) {
1801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We don't support sending on the "any" device.
1803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			strlcpy(handle->errbuf,
1805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Sending packets isn't supported on the \"any\" device",
1806511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    PCAP_ERRBUF_SIZE);
1807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (-1);
1808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->cooked) {
1811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
1812511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We don't support sending on the "any" device.
1813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
1814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - how do you send on a bound cooked-mode
1815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * socket?
1816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Is a "sendto()" required there?
1817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
1818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			strlcpy(handle->errbuf,
1819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Sending packets isn't supported in cooked mode",
1820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    PCAP_ERRBUF_SIZE);
1821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (-1);
1822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
1825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = send(handle->fd, buf, size, 0);
1827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1) {
1828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "send: %s",
1829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    pcap_strerror(errno));
1830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
1831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (ret);
1833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Get the statistics for the given packet capture handle.
1837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Reports the number of dropped packets iff the kernel supports
1838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  the PACKET_STATISTICS "getsockopt()" argument (2.4 and later
1839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket
1840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  patches); otherwise, that information isn't available, and we lie
1841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  and report 0 as the count of dropped packets.
1842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
1843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
1844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_stats_linux(pcap_t *handle, struct pcap_stat *stats)
1845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
1846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
1847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET_STATS
1848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
1849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * For sockets using TPACKET_V1 or TPACKET_V2, the extra
1851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * stuff at the end of a struct tpacket_stats_v3 will not
1852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * be filled in, and we don't look at it so this is OK even
1853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * for those sockets.  In addition, the PF_PACKET socket
1854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code in the kernel only uses the length parameter to
1855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * compute how much data to copy out and to indicate how
1856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * much data was copied out, so it's OK to base it on the
1857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * size of a struct tpacket_stats.
1858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - it's probably OK, in fact, to just use a
1860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * struct tpacket_stats for V3 sockets, as we don't
1861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * care about the tp_freeze_q_cnt stat.
1862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_stats_v3 kstats;
1864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* HAVE_TPACKET3 */
1865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_stats kstats;
1866511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET3 */
1867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	socklen_t len = sizeof (struct tpacket_stats);
1868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET_STATS */
1869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	long if_dropped = 0;
1871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1872511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	To fill in ps_ifdrop, we parse /proc/net/dev for the number
1874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.promisc)
1876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
1877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if_dropped = handlep->proc_dropped;
1878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->proc_dropped = linux_if_drops(handlep->device);
1879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped);
1880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET_STATS
1883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Try to get the packet counts from the kernel.
1885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS,
1887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			&kstats, &len) > -1) {
1888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * On systems where the PACKET_STATISTICS "getsockopt()"
1890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * argument is supported on PF_PACKET sockets:
1891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	"ps_recv" counts only packets that *passed* the
1893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	filter, not packets that didn't pass the filter.
1894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	This includes packets later dropped because we
1895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	ran out of buffer space.
1896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	"ps_drop" counts packets dropped because we ran
1898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	out of buffer space.  It doesn't count packets
1899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	dropped by the interface driver.  It counts only
1900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	packets that passed the filter.
1901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	See above for ps_ifdrop.
1903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	Both statistics include packets not yet read from
1905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	the kernel by libpcap, and thus not yet seen by
1906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	the application.
1907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * In "linux/net/packet/af_packet.c", at least in the
1909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * 2.4.9 kernel, "tp_packets" is incremented for every
1910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packet that passes the packet filter *and* is
1911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * successfully queued on the socket; "tp_drops" is
1912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * incremented for every packet dropped because there's
1913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * not enough free space in the socket buffer.
1914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * When the statistics are returned for a PACKET_STATISTICS
1916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "getsockopt()" call, "tp_drops" is added to "tp_packets",
1917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * so that "tp_packets" counts all packets handed to
1918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the PF_PACKET socket, including packets dropped because
1919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * there wasn't room on the socket buffer - but not
1920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * including packets that didn't pass the filter.
1921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * In the BSD BPF, the count of received packets is
1923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * incremented for every packet handed to BPF, regardless
1924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of whether it passed the filter.
1925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We can't make "pcap_stats()" work the same on both
1927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * platforms, but the best approximation is to return
1928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "tp_packets" as the count of packets and "tp_drops"
1929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * as the count of drops.
1930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
1931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Keep a running total because each call to
1932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *    getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, ....
1933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * resets the counters to zero.
1934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->stat.ps_recv += kstats.tp_packets;
1936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->stat.ps_drop += kstats.tp_drops;
1937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*stats = handlep->stat;
1938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
1939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1940511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else
1941511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
1942511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
1943511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If the error was EOPNOTSUPP, fall through, so that
1944511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * if you build the library on a system with
1945511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "struct tpacket_stats" and run it on a system
1946511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that doesn't, it works as it does if the library
1947511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * is built on a system without "struct tpacket_stats".
1948511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
1949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno != EOPNOTSUPP) {
1950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
1951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "pcap_stats: %s", pcap_strerror(errno));
1952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
1953511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
1954511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
1955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
1956511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
1957511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * On systems where the PACKET_STATISTICS "getsockopt()" argument
1958511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * is not supported on PF_PACKET sockets:
1959511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1960511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	"ps_recv" counts only packets that *passed* the filter,
1961511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	not packets that didn't pass the filter.  It does not
1962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	count packets dropped because we ran out of buffer
1963511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	space.
1964511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1965511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	"ps_drop" is not supported.
1966511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1967511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	"ps_ifdrop" is supported. It will return the number
1968511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	of drops the interface reports in /proc/net/dev,
1969511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	if that is available.
1970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1971511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	"ps_recv" doesn't include packets not yet read from
1972511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	the kernel by libpcap.
1973511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
1974511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We maintain the count of packets processed by libpcap in
1975511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "handlep->packets_read", for reasons described in the comment
1976511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * at the end of pcap_read_packet().  We have no idea how many
1977511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets were dropped by the kernel buffers -- but we know
1978511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * how many the interface dropped, so we can return that.
1979511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
1980511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_recv = handlep->packets_read;
1982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_drop = 0;
1983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	stats->ps_ifdrop = handlep->stat.ps_ifdrop;
1984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
1985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
1986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
1987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
1988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Get from "/sys/class/net" all interfaces listed there; if they're
1989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * already in the list of interfaces we have, that won't add another
1990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * instance, but if they're not, that'll add them.
1991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
1992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * We don't bother getting any addresses for them; it appears you can't
1993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and,
1994511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * although some other types of addresses can be fetched with SIOCGIFADDR,
1995511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * we don't bother with them for now.
1996511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
1997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * We also don't fail if we couldn't open "/sys/class/net"; we just leave
1998511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the list of interfaces as is, and return 0, so that we can try
1999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * scanning /proc/net/dev.
2000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallscan_sys_class_net(pcap_if_t **devlistp, char *errbuf)
2003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	DIR *sys_class_net_d;
2005511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int fd;
2006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct dirent *ent;
2007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char subsystem_path[PATH_MAX+1];
2008511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct stat statb;
2009511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *p;
2010511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char name[512];	/* XXX - pick a size */
2011511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *q, *saveq;
2012511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq ifrflags;
2013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret = 1;
2014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sys_class_net_d = opendir("/sys/class/net");
2016511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sys_class_net_d == NULL) {
2017511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2018511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Don't fail if it doesn't exist at all.
2019511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOENT)
2021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (0);
2022511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2023511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2024511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Fail if we got some other error.
2025511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "Can't open /sys/class/net: %s", pcap_strerror(errno));
2028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
2029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2030511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Create a socket from which to fetch interface information.
2033511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2034511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	fd = socket(AF_INET, SOCK_DGRAM, 0);
2035511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (fd < 0) {
2036511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "socket: %s", pcap_strerror(errno));
2038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)closedir(sys_class_net_d);
2039511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
2040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (;;) {
2043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		errno = 0;
2044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ent = readdir(sys_class_net_d);
2045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ent == NULL) {
2046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2047511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Error or EOF; if errno != 0, it's an error.
2048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2049511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ignore "." and "..".
2054511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (strcmp(ent->d_name, ".") == 0 ||
2056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    strcmp(ent->d_name, "..") == 0)
2057511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ignore plain files; they do not have subdirectories
2061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * and thus have no attributes.
2062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2063511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ent->d_type == DT_REG)
2064511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2067511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Is there an "ifindex" file under that name?
2068511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * (We don't care whether it's a directory or
2069511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * a symlink; older kernels have directories
2070511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * for devices, newer kernels have symlinks to
2071511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * directories.)
2072511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2073511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(subsystem_path, sizeof subsystem_path,
2074511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "/sys/class/net/%s/ifindex", ent->d_name);
2075511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (lstat(subsystem_path, &statb) != 0) {
2076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Stat failed.  Either there was an error
2078511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * other than ENOENT, and we don't know if
2079511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * this is an interface, or it's ENOENT,
2080511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * and either some part of "/sys/class/net/{if}"
2081511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * disappeared, in which case it probably means
2082511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the interface disappeared, or there's no
2083511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "ifindex" file, which means it's not a
2084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * network interface.
2085511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2086511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2087511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2088511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2089511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2090511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Get the interface name.
2091511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2092511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p = &ent->d_name[0];
2093511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		q = &name[0];
2094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while (*p != '\0' && isascii(*p) && !isspace(*p)) {
2095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (*p == ':') {
2096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
2097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * This could be the separator between a
2098511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * name and an alias number, or it could be
2099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the separator between a name with no
2100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * alias number and the next field.
2101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 *
2102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * If there's a colon after digits, it
2103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * separates the name and the alias number,
2104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * otherwise it separates the name and the
2105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * next field.
2106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
2107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				saveq = q;
2108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				while (isascii(*p) && isdigit(*p))
2109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					*q++ = *p++;
2110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (*p != ':') {
2111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
2112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * That was the next field,
2113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * not the alias number.
2114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
2115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					q = saveq;
2116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
2117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
2118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else
2119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*q++ = *p++;
2120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*q = '\0';
2122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Get the flags for this interface, and skip it if
2125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it's not up.
2126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
2128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
2129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno == ENXIO || errno == ENODEV)
2130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
2131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "SIOCGIFFLAGS: %.*s: %s",
2133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    (int)sizeof(ifrflags.ifr_name),
2134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    ifrflags.ifr_name,
2135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
2136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!(ifrflags.ifr_flags & IFF_UP))
2140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Add an entry for this interface, with no addresses.
2144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
2146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    errbuf) == -1) {
2147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Failure.
2149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret != -1) {
2155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Well, we didn't fail for any other reason; did we
2157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * fail due to an error reading the directory?
2158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno != 0) {
2160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Error reading /sys/class/net: %s",
2162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
2163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	(void)close(fd);
2168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	(void)closedir(sys_class_net_d);
2169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (ret);
2170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Get from "/proc/net/dev" all interfaces listed there; if they're
2174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * already in the list of interfaces we have, that won't add another
2175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * instance, but if they're not, that'll add them.
2176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
2177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * See comments from scan_sys_class_net().
2178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallscan_proc_net_dev(pcap_if_t **devlistp, char *errbuf)
2181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	FILE *proc_net_f;
2183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int fd;
2184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char linebuf[512];
2185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int linenum;
2186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *p;
2187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char name[512];	/* XXX - pick a size */
2188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	char *q, *saveq;
2189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq ifrflags;
2190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret = 0;
2191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	proc_net_f = fopen("/proc/net/dev", "r");
2193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (proc_net_f == NULL) {
2194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Don't fail if it doesn't exist at all.
2196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOENT)
2198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (0);
2199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Fail if we got some other error.
2202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "Can't open /proc/net/dev: %s", pcap_strerror(errno));
2205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
2206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Create a socket from which to fetch interface information.
2210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	fd = socket(AF_INET, SOCK_DGRAM, 0);
2212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (fd < 0) {
2213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "socket: %s", pcap_strerror(errno));
2215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		(void)fclose(proc_net_f);
2216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
2217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (linenum = 1;
2220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) {
2221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Skip the first two lines - they're headers.
2223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (linenum <= 2)
2225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p = &linebuf[0];
2228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Skip leading white space.
2231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while (*p != '\0' && isascii(*p) && isspace(*p))
2233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			p++;
2234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (*p == '\0' || *p == '\n')
2235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;	/* blank line */
2236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Get the interface name.
2239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		q = &name[0];
2241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while (*p != '\0' && isascii(*p) && !isspace(*p)) {
2242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (*p == ':') {
2243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
2244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * This could be the separator between a
2245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * name and an alias number, or it could be
2246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the separator between a name with no
2247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * alias number and the next field.
2248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 *
2249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * If there's a colon after digits, it
2250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * separates the name and the alias number,
2251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * otherwise it separates the name and the
2252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * next field.
2253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
2254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				saveq = q;
2255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				while (isascii(*p) && isdigit(*p))
2256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					*q++ = *p++;
2257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (*p != ':') {
2258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
2259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * That was the next field,
2260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * not the alias number.
2261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
2262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					q = saveq;
2263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
2264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
2265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else
2266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*q++ = *p++;
2267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*q = '\0';
2269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Get the flags for this interface, and skip it if
2272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it's not up.
2273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name));
2275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {
2276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno == ENXIO)
2277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				continue;
2278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "SIOCGIFFLAGS: %.*s: %s",
2280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    (int)sizeof(ifrflags.ifr_name),
2281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    ifrflags.ifr_name,
2282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
2283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!(ifrflags.ifr_flags & IFF_UP))
2287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			continue;
2288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Add an entry for this interface, with no addresses.
2291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (pcap_add_if(devlistp, name, ifrflags.ifr_flags, NULL,
2293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    errbuf) == -1) {
2294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Failure.
2296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret != -1) {
2302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Well, we didn't fail for any other reason; did we
2304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * fail due to an error reading the file?
2305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ferror(proc_net_f)) {
2307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(void)snprintf(errbuf, PCAP_ERRBUF_SIZE,
2308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "Error reading /proc/net/dev: %s",
2309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
2310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = -1;
2311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	(void)close(fd);
2315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	(void)fclose(proc_net_f);
2316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (ret);
2317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Description string for the "any" device.
2321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic const char any_descr[] = "Pseudo-device that captures on all interfaces";
2323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallint
2325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf)
2326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
2328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Read "/sys/class/net", and add to the list of interfaces all
2331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * interfaces listed there that we don't already have, because,
2332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses,
2333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and even getifaddrs() won't return information about
2334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * interfaces with no addresses, so you need to read "/sys/class/net"
2335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to get the names of the rest of the interfaces.
2336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = scan_sys_class_net(alldevsp, errbuf);
2338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
2339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);	/* failed */
2340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 0) {
2341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * No /sys/class/net; try reading /proc/net/dev instead.
2343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (scan_proc_net_dev(alldevsp, errbuf) == -1)
2345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return (-1);
2346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Add the "any" device.
2350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pcap_add_if(alldevsp, "any", 0, any_descr, errbuf) < 0)
2352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return (-1);
2353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (0);
2355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Attach the given BPF code to the packet capture device.
2359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter,
2362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    int is_mmapped)
2363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep;
2365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef SO_ATTACH_FILTER
2366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sock_fprog	fcode;
2367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			can_filter_in_kernel;
2368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			err = 0;
2369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handle)
2372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
2373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!filter) {
2374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	        strncpy(handle->errbuf, "setfilter: No filter specified",
2375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			PCAP_ERRBUF_SIZE);
2376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
2377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep = handle->priv;
2380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Make our private copy of the filter */
2382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (install_bpf_program(handle, filter) < 0)
2384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* install_bpf_program() filled in errbuf */
2385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
2386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Run user level packet filter by default. Will be overriden if
2389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * installing a kernel filter succeeds.
2390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->filter_in_userland = 1;
2392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Install kernel level filter if possible */
2394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef SO_ATTACH_FILTER
2396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef USHRT_MAX
2397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->fcode.bf_len > USHRT_MAX) {
2398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * fcode.len is an unsigned short for current kernel.
2400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * I have yet to see BPF-Code with that much
2401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * instructions but still it is possible. So for the
2402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * sake of correctness I added this check.
2403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fprintf(stderr, "Warning: Filter too complex for kernel\n");
2405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fcode.len = 0;
2406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		fcode.filter = NULL;
2407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		can_filter_in_kernel = 0;
2408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else
2409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* USHRT_MAX */
2410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
2411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Oh joy, the Linux kernel uses struct sock_fprog instead
2413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of struct bpf_program and of course the length field is
2414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of different size. Pointed out by Sebastian
2415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Oh, and we also need to fix it up so that all "ret"
2417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * instructions with non-zero operands have 65535 as the
2418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * operand if we're not capturing in memory-mapped modee,
2419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * and so that, if we're in cooked mode, all memory-reference
2420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * instructions use special magic offsets in references to
2421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the link-layer header and assume that the link-layer
2422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * payload begins at 0; "fix_program()" will do that.
2423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		switch (fix_program(handle, &fcode, is_mmapped)) {
2425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case -1:
2427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		default:
2428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Fatal error; just quit.
2430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * (The "default" case shouldn't happen; we
2431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * return -1 for that reason.)
2432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
2434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case 0:
2436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * The program performed checks that we can't make
2438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * work in the kernel.
2439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			can_filter_in_kernel = 0;
2441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		case 1:
2444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We have a filter that'll work in the kernel.
2446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			can_filter_in_kernel = 1;
2448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
2449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * NOTE: at this point, we've set both the "len" and "filter"
2454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * fields of "fcode".  As of the 2.6.32.4 kernel, at least,
2455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * those are the only members of the "sock_fprog" structure,
2456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * so we initialize every member of that structure.
2457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If there is anything in "fcode" that is not initialized,
2459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it is either a field added in a later kernel, or it's
2460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * padding.
2461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If a new field is added, this code needs to be updated
2463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to set it correctly.
2464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If there are no other fields, then:
2466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	if the Linux kernel looks at the padding, it's
2468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	buggy;
2469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
2470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	if the Linux kernel doesn't look at the padding,
2471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	then if some tool complains that we're passing
2472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	uninitialized data to the kernel, then the tool
2473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	is buggy and needs to understand that it's just
2474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *	padding.
2475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (can_filter_in_kernel) {
2477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((err = set_kernel_filter(handle, &fcode)) == 0)
2478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
2479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Installation succeded - using kernel filter,
2481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * so userland filtering not needed.
2482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->filter_in_userland = 0;
2484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else if (err == -1)	/* Non-fatal error */
2486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		{
2487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Print a warning if we weren't able to install
2489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the filter for a reason other than "this kernel
2490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * isn't configured to support socket filters.
2491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) {
2493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				fprintf(stderr,
2494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Warning: Kernel filter failed: %s\n",
2495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					pcap_strerror(errno));
2496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
2497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we're not using the kernel filter, get rid of any kernel
2502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * filter that might've been there before, e.g. because the
2503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * previous filter could work in the kernel, or because some other
2504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * code attached a filter to the socket by some means other than
2505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * calling "pcap_setfilter()".  Otherwise, the kernel filter may
2506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * filter out packets that would pass the new userland filter.
2507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->filter_in_userland)
2509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		reset_kernel_filter(handle);
2510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Free up the copy of the filter that was made by "fix_program()".
2513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (fcode.filter != NULL)
2515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(fcode.filter);
2516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err == -2)
2518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Fatal error */
2519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
2520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* SO_ATTACH_FILTER */
2521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
2523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter)
2527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return pcap_setfilter_linux_common(handle, filter, 0);
2529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Set direction flag: Which packets do we accept on a forwarding
2534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * single device? IN, OUT or both?
2535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_setdirection_linux(pcap_t *handle, pcap_direction_t d)
2538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
2540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
2541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handlep->sock_packet) {
2543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->direction = d;
2544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
2545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
2548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We're not using PF_PACKET sockets, so we can't determine
2549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the direction of the packet.
2550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
2551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
2552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    "Setting direction is not supported on SOCK_PACKET sockets");
2553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return -1;
2554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
2557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Map the PACKET_ value to a LINUX_SLL_ value; we
2559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * want the same numerical value to be used in
2560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the link-layer header even if the numerical values
2561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * for the PACKET_ #defines change, so that programs
2562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * that look at the packet type field will always be
2563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * able to handle DLT_LINUX_SLL captures.
2564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic short int
2566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallmap_packet_type_to_sll_type(short int sll_pkttype)
2567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (sll_pkttype) {
2569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case PACKET_HOST:
2571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return htons(LINUX_SLL_HOST);
2572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case PACKET_BROADCAST:
2574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return htons(LINUX_SLL_BROADCAST);
2575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case PACKET_MULTICAST:
2577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return  htons(LINUX_SLL_MULTICAST);
2578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case PACKET_OTHERHOST:
2580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return htons(LINUX_SLL_OTHERHOST);
2581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case PACKET_OUTGOING:
2583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return htons(LINUX_SLL_OUTGOING);
2584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
2586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
2587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Linux uses the ARP hardware type to identify the type of an
2593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  interface. pcap uses the DLT_xxx constants for this. This
2594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  function takes a pointer to a "pcap_t", and an ARPHRD_xxx
2595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  constant, as arguments, and sets "handle->linktype" to the
2596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  appropriate DLT_XXX constant and sets "handle->offset" to
2597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  the appropriate value (to make "handle->offset" plus link-layer
2598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  header length be a multiple of 4, so that the link-layer payload
2599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  will be aligned on a 4-byte boundary when capturing packets).
2600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  (If the offset isn't set here, it'll be 0; add code as appropriate
2601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  for cases where it shouldn't be 0.)
2602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
2603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture
2604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  in cooked mode; otherwise, we can't use cooked mode, so we have
2605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  to pick some type that works in raw mode, or fail.
2606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
2607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Sets the link type to -1 if unable to map the type.
2608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void map_arphrd_to_dlt(pcap_t *handle, int arptype, int cooked_ok)
2610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (arptype) {
2612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_ETHER:
2614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This is (presumably) a real Ethernet capture; give it a
2616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so
2617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that an application can let you choose it, in case you're
2618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * capturing DOCSIS traffic that a Cisco Cable Modem
2619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Termination System is putting out onto an Ethernet (it
2620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * doesn't put an Ethernet header onto the wire, it puts raw
2621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * DOCSIS frames out on the wire inside the low-level
2622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ethernet framing).
2623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * XXX - are there any sorts of "fake Ethernet" that have
2625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * ARPHRD_ETHER but that *shouldn't offer DLT_DOCSIS as
2626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * a Cisco CMTS won't put traffic onto it or get traffic
2627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * bridged onto it?  ISDN is handled in "activate_new()",
2628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * as we fall back on cooked mode there; are there any
2629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * others?
2630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
2632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If that fails, just leave the list empty.
2634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->dlt_list != NULL) {
2636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_list[0] = DLT_EN10MB;
2637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_list[1] = DLT_DOCSIS;
2638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_count = 2;
2639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* FALLTHROUGH */
2641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_METRICOM:
2643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_LOOPBACK:
2644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_EN10MB;
2645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->offset = 2;
2646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_EETHER:
2649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_EN3MB;
2650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_AX25:
2653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_AX25_KISS;
2654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_PRONET:
2657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_PRONET;
2658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_CHAOS:
2661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_CHAOS;
2662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_CAN
2664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_CAN 280
2665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_CAN:
2667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_CAN_SOCKETCAN;
2668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IEEE802_TR
2671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IEEE802_TR 800	/* From Linux 2.4 */
2672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IEEE802_TR:
2674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IEEE802:
2675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_IEEE802;
2676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->offset = 2;
2677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_ARCNET:
2680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_ARCNET_LINUX;
2681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FDDI	/* From Linux 2.2.13 */
2684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FDDI	774
2685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FDDI:
2687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_FDDI;
2688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->offset = 3;
2689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_ATM  /* FIXME: How to #include this? */
2692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_ATM 19
2693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_ATM:
2695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The Classical IP implementation in ATM for Linux
2697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * supports both what RFC 1483 calls "LLC Encapsulation",
2698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in which each packet has an LLC header, possibly
2699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * with a SNAP header as well, prepended to it, and
2700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * what RFC 1483 calls "VC Based Multiplexing", in which
2701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * different virtual circuits carry different network
2702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * layer protocols, and no header is prepended to packets.
2703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * They both have an ARPHRD_ type of ARPHRD_ATM, so
2705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * you can't use the ARPHRD_ type to find out whether
2706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * captured packets will have an LLC header, and,
2707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * while there's a socket ioctl to *set* the encapsulation
2708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * type, there's no ioctl to *get* the encapsulation type.
2709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This means that
2711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	programs that dissect Linux Classical IP frames
2713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	would have to check for an LLC header and,
2714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	depending on whether they see one or not, dissect
2715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	the frame as LLC-encapsulated or as raw IP (I
2716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	don't know whether there's any traffic other than
2717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	IP that would show up on the socket, or whether
2718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	there's any support for IPv6 in the Linux
2719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	Classical IP code);
2720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	filter expressions would have to compile into
2722511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	code that checks for an LLC header and does
2723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	the right thing.
2724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Both of those are a nuisance - and, at least on systems
2726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that support PF_PACKET sockets, we don't have to put
2727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * up with those nuisances; instead, we can just capture
2728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in cooked mode.  That's what we'll do, if we can.
2729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Otherwise, we'll just fail.
2730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (cooked_ok)
2732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->linktype = DLT_LINUX_SLL;
2733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else
2734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->linktype = -1;
2735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IEEE80211  /* From Linux 2.4.6 */
2738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IEEE80211 801
2739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IEEE80211:
2741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_IEEE802_11;
2742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IEEE80211_PRISM  /* From Linux 2.4.18 */
2745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IEEE80211_PRISM 802
2746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IEEE80211_PRISM:
2748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_PRISM_HEADER;
2749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IEEE80211_RADIOTAP /* new */
2752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IEEE80211_RADIOTAP 803
2753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IEEE80211_RADIOTAP:
2755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_IEEE802_11_RADIO;
2756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_PPP:
2759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Some PPP code in the kernel supplies no link-layer
2761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * header whatsoever to PF_PACKET sockets; other PPP
2762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * code supplies PPP link-layer headers ("syncppp.c");
2763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * some PPP code might supply random link-layer
2764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * headers (PPP over ISDN - there's code in Ethereal,
2765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * for example, to cope with PPP-over-ISDN captures
2766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * with which the Ethereal developers have had to cope,
2767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * heuristically trying to determine which of the
2768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * oddball link-layer headers particular packets have).
2769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * As such, we just punt, and run all PPP interfaces
2771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in cooked mode, if we can; otherwise, we just treat
2772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it as DLT_RAW, for now - if somebody needs to capture,
2773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * on a 2.0[.x] kernel, on PPP devices that supply a
2774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * link-layer header, they'll have to add code here to
2775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * map to the appropriate DLT_ type (possibly adding a
2776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * new DLT_ type, if necessary).
2777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (cooked_ok)
2779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->linktype = DLT_LINUX_SLL;
2780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else {
2781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
2782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - handle ISDN types here?  We can't fall
2783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * back on cooked sockets, so we'd have to
2784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * figure out from the device name what type of
2785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * link-layer encapsulation it's using, and map
2786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * that to an appropriate DLT_ value, meaning
2787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we'd map "isdnN" devices to DLT_RAW (they
2788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * supply raw IP packets with no link-layer
2789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * header) and "isdY" devices to a new DLT_I4L_IP
2790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * type that has only an Ethernet packet type as
2791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * a link-layer header.
2792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
2793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * But sometimes we seem to get random crap
2794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * in the link-layer header when capturing on
2795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * ISDN devices....
2796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
2797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->linktype = DLT_RAW;
2798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_CISCO
2802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */
2803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_CISCO:
2805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_C_HDLC;
2806511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Not sure if this is correct for all tunnels, but it
2809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * works for CIPE */
2810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_TUNNEL:
2811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_SIT
2812511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_SIT 776	/* From Linux 2.2.13 */
2813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_SIT:
2815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_CSLIP:
2816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_SLIP6:
2817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_CSLIP6:
2818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_ADAPT:
2819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_SLIP:
2820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_RAWHDLC
2821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_RAWHDLC 518
2822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_RAWHDLC:
2824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_DLCI
2825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_DLCI 15
2826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_DLCI:
2828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * XXX - should some of those be mapped to DLT_LINUX_SLL
2830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * instead?  Should we just map all of them to DLT_LINUX_SLL?
2831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_RAW;
2833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FRAD
2836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FRAD 770
2837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FRAD:
2839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_FRELAY;
2840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_LOCALTLK:
2843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_LTALK;
2844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case 18:
2847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * RFC 4338 defines an encapsulation for IP and ARP
2849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packets that's compatible with the RFC 2625
2850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * encapsulation, but that uses a different ARP
2851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * hardware type and hardware addresses.  That
2852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * ARP hardware type is 18; Linux doesn't define
2853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * any ARPHRD_ value as 18, but if it ever officially
2854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * supports RFC 4338-style IP-over-FC, it should define
2855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * one.
2856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * For now, we map it to DLT_IP_OVER_FC, in the hopes
2858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that this will encourage its use in the future,
2859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * should Linux ever officially support RFC 4338-style
2860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * IP-over-FC.
2861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_IP_OVER_FC;
2863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FCPP
2866511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FCPP	784
2867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FCPP:
2869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FCAL
2870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FCAL	785
2871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2872511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FCAL:
2873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FCPL
2874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FCPL	786
2875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FCPL:
2877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_FCFABRIC
2878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_FCFABRIC	787
2879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_FCFABRIC:
2881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Back in 2002, Donald Lee at Cray wanted a DLT_ for
2883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * IP-over-FC:
2884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	http://www.mail-archive.com/tcpdump-workers@sandelman.ottawa.on.ca/msg01043.html
2886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * and one was assigned.
2888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * In a later private discussion (spun off from a message
2890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * on the ethereal-users list) on how to get that DLT_
2891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * value in libpcap on Linux, I ended up deciding that
2892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the best thing to do would be to have him tweak the
2893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * driver to set the ARPHRD_ value to some ARPHRD_FCxx
2894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * type, and map all those types to DLT_IP_OVER_FC:
2895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	I've checked into the libpcap and tcpdump CVS tree
2897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	support for DLT_IP_OVER_FC.  In order to use that,
2898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	you'd have to modify your modified driver to return
2899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	one of the ARPHRD_FCxxx types, in "fcLINUXfcp.c" -
2900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	change it to set "dev->type" to ARPHRD_FCFABRIC, for
2901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	example (the exact value doesn't matter, it can be
2902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	any of ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, or
2903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	ARPHRD_FCFABRIC).
2904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * 11 years later, Christian Svensson wanted to map
2906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * various ARPHRD_ values to DLT_FC_2 and
2907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * DLT_FC_2_WITH_FRAME_DELIMS for raw Fibre Channel
2908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * frames:
2909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *	https://github.com/mcr/libpcap/pull/29
2911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * There doesn't seem to be any network drivers that uses
2913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * any of the ARPHRD_FC* values for IP-over-FC, and
2914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * it's not exactly clear what the "Dummy types for non
2915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * ARP hardware" are supposed to mean (link-layer
2916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * header type?  Physical network type?), so it's
2917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * not exactly clear why the ARPHRD_FC* types exist
2918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in the first place.
2919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
2920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * For now, we map them to DLT_FC_2, and provide an
2921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * option of DLT_FC_2_WITH_FRAME_DELIMS, as well as
2922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * DLT_IP_OVER_FC just in case there's some old
2923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * driver out there that uses one of those types for
2924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * IP-over-FC on which somebody wants to capture
2925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packets.
2926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2);
2928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If that fails, just leave the list empty.
2930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->dlt_list != NULL) {
2932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_list[0] = DLT_FC_2;
2933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_list[1] = DLT_FC_2_WITH_FRAME_DELIMS;
2934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_list[2] = DLT_IP_OVER_FC;
2935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->dlt_count = 3;
2936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
2937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_FC_2;
2938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2940511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IRDA
2941511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IRDA	783
2942511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2943511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_IRDA:
2944511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Don't expect IP packet out of this interfaces... */
2945511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_LINUX_IRDA;
2946511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* We need to save packet direction for IrDA decoding,
2947511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * so let's use "Linux-cooked" mode. Jean II */
2948511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		//handlep->cooked = 1;
2949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation
2952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * is needed, please report it to <daniele@orlandi.com> */
2953511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_LAPD
2954511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_LAPD	8445
2955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2956511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_LAPD:
2957511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Don't expect IP packet out of this interfaces... */
2958511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_LINUX_LAPD;
2959511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2960511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2961511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_NONE
2962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_NONE	0xFFFE
2963511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2964511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case ARPHRD_NONE:
2965511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
2966511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * No link-layer header; packets are just IP
2967511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packets, so use DLT_RAW.
2968511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
2969511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_RAW;
2970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2971511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2972511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef ARPHRD_IEEE802154
2973511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define ARPHRD_IEEE802154      804
2974511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
2975511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall       case ARPHRD_IEEE802154:
2976511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall               handle->linktype =  DLT_IEEE802_15_4_NOFCS;
2977511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall               break;
2978511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2979511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
2980511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = -1;
2981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
2982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
2983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
2984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* ===== Functions to interface to the newer kernels ================== */
2986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
2987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
2988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Try to open a packet socket using the new kernel PF_PACKET interface.
2989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Returns 1 on success, 0 on an error that means the new interface isn't
2990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * present (so the old SOCK_PACKET interface should be tried), and a
2991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * PCAP_ERROR_ value on an error that means that the old mechanism won't
2992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * work either (so it shouldn't be tried).
2993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
2994511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
2995511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallactivate_new(pcap_t *handle)
2996511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
2997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
2998511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
2999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	const char		*device = handle->opt.source;
3000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			is_any_device = (strcmp(device, "any") == 0);
3001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			sock_fd = -1, arptype;
3002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PACKET_AUXDATA
3003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			val;
3004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3005511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			err = 0;
3006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct packet_mreq	mr;
3007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3008511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3009511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Open a socket with protocol family packet. If the
3010511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "any" device was specified, we open a SOCK_DGRAM
3011511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * socket for the cooked interface, otherwise we first
3012511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * try a SOCK_RAW socket for the raw interface.
3013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sock_fd = is_any_device ?
3015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		socket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_ALL)) :
3016511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
3017511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3018511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (sock_fd == -1) {
3019511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EINVAL || errno == EAFNOSUPPORT) {
3020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We don't support PF_PACKET/SOCK_whatever
3022511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * sockets; try the old mechanism.
3023511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3024511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
3025511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "socket: %s",
3028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 pcap_strerror(errno) );
3029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EPERM || errno == EACCES) {
3030511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * You don't have permission to open the
3032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * socket.
3033511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3034511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_PERM_DENIED;
3035511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
3036511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Other error.
3038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3039511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
3040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* It seems the kernel supports the new interface. */
3044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->sock_packet = 0;
3045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3047511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Get the interface index of the loopback device.
3048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If the attempt fails, don't fail, just set the
3049511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "handlep->lo_ifindex" to -1.
3050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - can there be more than one device that loops
3052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets back, i.e. devices other than "lo"?  If so,
3053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we'd need to find them all, and have an array of
3054511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * indices for them, and check all of them in
3055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "pcap_read_packet()".
3056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3057511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf);
3058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Default value for offset to align link-layer payload
3061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * on a 4-byte boundary.
3062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3063511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset	 = 0;
3064511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * What kind of frames do we have to deal with? Fall back
3067511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to cooked mode if we have an unknown interface type
3068511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * or a type we know doesn't work well in raw mode.
3069511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3070511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!is_any_device) {
3071511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Assume for now we don't need cooked mode. */
3072511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->cooked = 0;
3073511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3074511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->opt.rfmon) {
3075511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We were asked to turn on monitor mode.
3077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Do so before we get the link-layer type,
3078511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * because entering monitor mode could change
3079511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the link-layer type.
3080511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3081511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			err = enter_rfmon_mode(handle, sock_fd, device);
3082511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (err < 0) {
3083511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/* Hard failure */
3084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				close(sock_fd);
3085511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return err;
3086511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3087511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (err == 0) {
3088511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3089511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Nothing worked for turning monitor mode
3090511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * on.
3091511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3092511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				close(sock_fd);
3093511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR_RFMON_NOTSUP;
3094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Either monitor mode has been turned on for
3098511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the device, or we've been given a different
3099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * device to open for monitor mode.  If we've
3100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * been given a different device, use it.
3101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handlep->mondevice != NULL)
3103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				device = handlep->mondevice;
3104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		arptype	= iface_get_arptype(sock_fd, device, handle->errbuf);
3106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (arptype < 0) {
3107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			close(sock_fd);
3108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return arptype;
3109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		map_arphrd_to_dlt(handle, arptype, 1);
3111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->linktype == -1 ||
3112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handle->linktype == DLT_LINUX_SLL ||
3113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handle->linktype == DLT_LINUX_IRDA ||
3114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handle->linktype == DLT_LINUX_LAPD ||
3115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    (handle->linktype == DLT_EN10MB &&
3116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		     (strncmp("isdn", device, 4) == 0 ||
3117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		      strncmp("isdY", device, 4) == 0))) {
3118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Unknown interface type (-1), or a
3120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * device we explicitly chose to run
3121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * in cooked mode (e.g., PPP devices),
3122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * or an ISDN device (whose link-layer
3123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * type we can only determine by using
3124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * APIs that may be different on different
3125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * kernels) - reopen in cooked mode.
3126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (close(sock_fd) == -1) {
3128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 "close: %s", pcap_strerror(errno));
3130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR;
3131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			sock_fd = socket(PF_PACKET, SOCK_DGRAM,
3133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    htons(ETH_P_ALL));
3134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (sock_fd == -1) {
3135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "socket: %s", pcap_strerror(errno));
3137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (errno == EPERM || errno == EACCES) {
3138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
3139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * You don't have permission to
3140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * open the socket.
3141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
3142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return PCAP_ERROR_PERM_DENIED;
3143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				} else {
3144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
3145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * Other error.
3146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
3147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return PCAP_ERROR;
3148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
3149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->cooked = 1;
3151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Get rid of any link-layer type list
3154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we allocated - this only supports cooked
3155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * capture.
3156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->dlt_list != NULL) {
3158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				free(handle->dlt_list);
3159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->dlt_list = NULL;
3160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->dlt_count = 0;
3161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->linktype == -1) {
3164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Warn that we're falling back on
3166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * cooked mode; we may want to
3167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * update "map_arphrd_to_dlt()"
3168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * to handle the new type.
3169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"arptype %d not "
3172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"supported by libpcap - "
3173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"falling back to cooked "
3174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"socket",
3175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					arptype);
3176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * IrDA capture is not a real "cooked" capture,
3180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * it's IrLAP frames, not IP packets.  The
3181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * same applies to LAPD capture.
3182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->linktype != DLT_LINUX_IRDA &&
3184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    handle->linktype != DLT_LINUX_LAPD)
3185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->linktype = DLT_LINUX_SLL;
3186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->ifindex = iface_get_id(sock_fd, device,
3189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handle->errbuf);
3190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->ifindex == -1) {
3191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			close(sock_fd);
3192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
3193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((err = iface_bind(sock_fd, handlep->ifindex,
3196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    handle->errbuf)) != 1) {
3197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    	close(sock_fd);
3198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (err < 0)
3199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return err;
3200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			else
3201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return 0;	/* try old mechanism */
3202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
3204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The "any" device.
3206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->opt.rfmon) {
3208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * It doesn't support monitor mode.
3210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_RFMON_NOTSUP;
3212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * It uses cooked mode.
3216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->cooked = 1;
3218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->linktype = DLT_LINUX_SLL;
3219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We're not bound to a device.
3222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * For now, we're using this as an indication
3223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that we can't transmit; stop doing that only
3224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * if we figure out how to transmit in cooked
3225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * mode.
3226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->ifindex = -1;
3228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Select promiscuous mode on if "promisc" is set.
3232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Do not turn allmulti mode on if we don't select
3234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * promiscuous mode - on some devices (e.g., Orinoco
3235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * wireless interfaces), allmulti mode isn't supported
3236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and the driver implements it by turning promiscuous
3237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mode on, and that screws up the operation of the
3238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * card as a normal networking interface, and on no
3239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * other platform I know of does starting a non-
3240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * promiscuous capture affect which multicast packets
3241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * are received by the interface.
3242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Hmm, how can we set promiscuous mode on all interfaces?
3246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * I am not sure if that is possible at all.  For now, we
3247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * silently ignore attempts to turn promiscuous mode on
3248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * for the "any" device (so you don't have to explicitly
3249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * disable it in programs such as tcpdump).
3250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!is_any_device && handle->opt.promisc) {
3253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&mr, 0, sizeof(mr));
3254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		mr.mr_ifindex = handlep->ifindex;
3255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		mr.mr_type    = PACKET_MR_PROMISC;
3256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP,
3257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    &mr, sizeof(mr)) == -1) {
3258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				"setsockopt: %s", pcap_strerror(errno));
3260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			close(sock_fd);
3261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
3262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Enable auxillary data if supported and reserve room for
3266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * reconstructing VLAN headers. */
3267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PACKET_AUXDATA
3268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	val = 1;
3269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val,
3270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		       sizeof(val)) == -1 && errno != ENOPROTOOPT) {
3271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "setsockopt: %s", pcap_strerror(errno));
3273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		close(sock_fd);
3274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
3275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset += VLAN_TAG_LEN;
3277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PACKET_AUXDATA */
3278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * This is a 2.2[.x] or later kernel (we know that
3281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * because we're not using a SOCK_PACKET socket -
3282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * PF_PACKET is supported only in 2.2 and later
3283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * kernels).
3284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We can safely pass "recvfrom()" a byte count
3286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * based on the snapshot length.
3287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we're in cooked mode, make the snapshot length
3289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * large enough to hold a "cooked mode" header plus
3290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * 1 byte of packet data (so we don't pass a byte
3291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * count of 0 to "recvfrom()").
3292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->cooked) {
3294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->snapshot < SLL_HDR_LEN + 1)
3295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->snapshot = SLL_HDR_LEN + 1;
3296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->bufsize = handle->snapshot;
3298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Set the offset at which to insert VLAN tags.
3301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (handle->linktype) {
3303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_EN10MB:
3305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->vlan_offset = 2 * ETH_ALEN;
3306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case DLT_LINUX_SLL:
3309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->vlan_offset = 14;
3310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	default:
3313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->vlan_offset = -1; /* unknown */
3314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Save the socket FD in the pcap structure */
3318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->fd = sock_fd;
3319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS)
3321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) {
3322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int nsec_tstamps = 1;
3323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (setsockopt(handle->fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) {
3325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS");
3326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
3327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */
3330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
3332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* HAVE_PF_PACKET_SOCKETS */
3333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ebuf,
3334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		"New packet capturing interface not supported by build "
3335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		"environment", PCAP_ERRBUF_SIZE);
3336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
3337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PF_PACKET_SOCKETS */
3338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PACKET_RING
3341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
3342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Attempt to activate with memory-mapped access.
3343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On success, returns 1, and sets *status to 0 if there are no warnings
3345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * or to a PCAP_WARNING_ code if there is a warning.
3346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On failure due to lack of support for memory-mapped capture, returns
3348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 0.
3349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On error, returns -1, and sets *status to the appropriate error code;
3351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
3352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
3353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallactivate_mmap(pcap_t *handle, int *status)
3355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
3358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Attempt to allocate a buffer to hold the contents of one
3361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packet, for use by the oneshot callback.
3362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->oneshot_buffer = malloc(handle->snapshot);
3364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->oneshot_buffer == NULL) {
3365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "can't allocate oneshot buffer: %s",
3367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 pcap_strerror(errno));
3368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*status = PCAP_ERROR;
3369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.buffer_size == 0) {
3373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* by default request 2M for the ring buffer */
3374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->opt.buffer_size = 2*1024*1024;
3375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = prepare_tpacket_socket(handle);
3377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1) {
3378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->oneshot_buffer);
3379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*status = PCAP_ERROR;
3380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
3381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = create_ring(handle, status);
3383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 0) {
3384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We don't support memory-mapped capture; our caller
3386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * will fall back on reading from the socket.
3387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->oneshot_buffer);
3389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
3390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1) {
3392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Error attempting to enable memory-mapped capture;
3394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * fail.  create_ring() has set *status.
3395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->oneshot_buffer);
3397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Success.  *status has been set either to 0 if there are no
3402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * warnings or to a PCAP_WARNING_ value if there is a warning.
3403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Override some defaults and inherit the other fields from
3405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * activate_new.
3406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handle->offset is used to get the current position into the rx ring.
3407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handle->cc is used to store the ring size.
3408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (handlep->tp_version) {
3411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V1:
3412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->read_op = pcap_read_linux_mmap_v1;
3413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
3415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V2:
3416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->read_op = pcap_read_linux_mmap_v2;
3417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V3:
3421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->read_op = pcap_read_linux_mmap_v3;
3422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->cleanup_op = pcap_cleanup_linux_mmap;
3426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setfilter_op = pcap_setfilter_linux_mmap;
3427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->setnonblock_op = pcap_setnonblock_mmap;
3428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->getnonblock_op = pcap_getnonblock_mmap;
3429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->oneshot_callback = pcap_oneshot_mmap;
3430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->selectable_fd = handle->fd;
3431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
3432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* HAVE_PACKET_RING */
3434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallactivate_mmap(pcap_t *handle _U_, int *status _U_)
3436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
3438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PACKET_RING */
3440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PACKET_RING
3442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
3444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
3445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Attempt to set the socket to the specified version of the memory-mapped
3446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * header.
3447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Return 0 if we succeed; return 1 if we fail because that version isn't
3449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * supported; return -1 on any other error, and set handle->errbuf.
3450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
3451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallinit_tpacket(pcap_t *handle, int version, const char *version_str)
3453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int val = version;
3456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	socklen_t len = sizeof(val);
3457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Probe whether kernel supports the specified TPACKET version */
3459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) {
3460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOPROTOOPT || errno == EINVAL)
3461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 1;	/* no */
3462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Failed to even find out; this is a fatal error. */
3464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"can't get %s header len on packet socket: %s",
3466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			version_str,
3467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_strerror(errno));
3468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->tp_hdrlen = val;
3471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	val = version;
3473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val,
3474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			   sizeof(val)) < 0) {
3475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"can't activate %s on packet socket: %s",
3477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			version_str,
3478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_strerror(errno));
3479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->tp_version = version;
3482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Reserve space for VLAN tag reconstruction */
3484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	val = VLAN_TAG_LEN;
3485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val,
3486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			   sizeof(val)) < 0) {
3487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"can't set up reserve on packet socket: %s",
3489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_strerror(errno));
3490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
3494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */
3496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
3498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Attempt to set the socket to version 3 of the memory-mapped header and,
3499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * if that fails because version 3 isn't supported, attempt to fall
3500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * back to version 2.  If version 2 isn't supported, just leave it at
3501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * version 1.
3502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Return 1 if we succeed or if we fail because neither version 2 nor 3 is
3504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * supported; return -1 on any other error, and set handle->errbuf.
3505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
3506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallprepare_tpacket_socket(pcap_t *handle)
3508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
3511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
3512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->tp_version = TPACKET_V1;
3515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->tp_hdrlen = sizeof(struct tpacket_hdr);
3516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The only mode in which buffering is done on PF_PACKET
3520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * sockets, so that packets might not be delivered
3521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * immediately, is TPACKET_V3 mode.
3522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The buffering cannot be disabled in that mode, so
3524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * if the user has requested immediate mode, we don't
3525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * use TPACKET_V3.
3526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.immediate)
3528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = 1; /* pretend TPACKET_V3 couldn't be set */
3529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	else
3530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = init_tpacket(handle, TPACKET_V3, "TPACKET_V3");
3531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (-1 == ret) {
3532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Error during setting up TPACKET_V3. */
3533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else if (1 == ret) {
3535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* TPACKET_V3 not supported - fall back to TPACKET_V2. */
3536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET3 */
3537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
3539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2");
3540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (-1 == ret) {
3541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* Error during setting up TPACKET_V2. */
3542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
3543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET2 */
3545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET3 */
3549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
3551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
3554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Attempt to set up memory-mapped access.
3555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On success, returns 1, and sets *status to 0 if there are no warnings
3557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * or to a PCAP_WARNING_ code if there is a warning.
3558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On failure due to lack of support for memory-mapped capture, returns
3560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * 0.
3561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * On error, returns -1, and sets *status to the appropriate error code;
3563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message.
3564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
3565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallcreate_ring(pcap_t *handle, int *status)
3567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned i, j, frames_per_block;
3570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * For sockets using TPACKET_V1 or TPACKET_V2, the extra
3573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * stuff at the end of a struct tpacket_req3 will be
3574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * ignored, so this is OK even for those sockets.
3575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_req3 req;
3577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
3578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_req req;
3579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	socklen_t len;
3581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff;
3582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned int frame_size;
3583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Start out assuming no warnings or errors.
3586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*status = 0;
3588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (handlep->tp_version) {
3590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V1:
3592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
3593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V2:
3594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* Note that with large snapshot length (say 64K, which is
3596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the default for recent versions of tcpdump, the value that
3597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "-s 0" has given for a long time with tcpdump, and the
3598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * default in Wireshark/TShark/dumpcap), if we use the snapshot
3599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * length to calculate the frame length, only a few frames
3600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * will be available in the ring even with pretty
3601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * large ring size (and a lot of memory will be unused).
3602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
3603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ideally, we should choose a frame length based on the
3604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * minimum of the specified snapshot length and the maximum
3605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * packet size.  That's not as easy as it sounds; consider,
3606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * for example, an 802.11 interface in monitor mode, where
3607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the frame would include a radiotap header, where the
3608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * maximum radiotap header length is device-dependent.
3609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
3610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * So, for now, we just do this for Ethernet devices, where
3611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * there's no metadata header, and the link-layer header is
3612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * fixed length.  We can get the maximum packet size by
3613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * adding 18, the Ethernet header length plus the CRC length
3614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * (just in case we happen to get the CRC in the packet), to
3615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the MTU of the interface; we fetch the MTU in the hopes
3616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * that it reflects support for jumbo frames.  (Even if the
3617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * interface is just being used for passive snooping, the
3618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * driver might set the size of buffers in the receive ring
3619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * based on the MTU, so that the MTU limits the maximum size
3620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of packets that we can receive.)
3621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
3622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We don't do that if segmentation/fragmentation or receive
3623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * offload are enabled, so we don't get rudely surprised by
3624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "packets" bigger than the MTU. */
3625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		frame_size = handle->snapshot;
3626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->linktype == DLT_EN10MB) {
3627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			int mtu;
3628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			int offload;
3629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			offload = iface_get_offload(handle);
3631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (offload == -1) {
3632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_ERROR;
3633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -1;
3634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (!offload) {
3636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				mtu = iface_get_mtu(handle->fd, handle->opt.source,
3637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    handle->errbuf);
3638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (mtu == -1) {
3639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					*status = PCAP_ERROR;
3640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return -1;
3641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
3642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (frame_size > mtu + 18)
3643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					frame_size = mtu + 18;
3644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* NOTE: calculus matching those in tpacket_rcv()
3648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in linux-2.6/net/packet/af_packet.c
3649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		len = sizeof(sk_type);
3651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type,
3652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    &len) < 0) {
3653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "getsockopt: %s", pcap_strerror(errno));
3655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			*status = PCAP_ERROR;
3656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
3657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef PACKET_RESERVE
3659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		len = sizeof(tp_reserve);
3660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE,
3661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    &tp_reserve, &len) < 0) {
3662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (errno != ENOPROTOOPT) {
3663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * ENOPROTOOPT means "kernel doesn't support
3665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * PACKET_RESERVE", in which case we fall back
3666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * as best we can.
3667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "getsockopt: %s", pcap_strerror(errno));
3670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_ERROR;
3671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -1;
3672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			tp_reserve = 0;	/* older kernel, reserve not supported */
3674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
3676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tp_reserve = 0;	/* older kernel, reserve not supported */
3677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE;
3679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* XXX: in the kernel maclen is calculated from
3680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len
3681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * in:  packet_snd()           in linux-2.6/net/packet/af_packet.c
3682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * then packet_alloc_skb()     in linux-2.6/net/packet/af_packet.c
3683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c
3684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * but I see no way to get those sizes in userspace,
3685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * like for instance with an ifreq ioctl();
3686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the best thing I've found so far is MAX_HEADER in
3687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the kernel part of linux-2.6/include/linux/netdevice.h
3688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * which goes up to 128+48=176; since pcap-linux.c
3689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * defines a MAX_LINKHEADER_SIZE of 256 which is
3690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * greater than that, let's use it.. maybe is it even
3691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * large enough to directly replace macoff..
3692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tp_hdrlen = TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll) ;
3694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve;
3695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN
3696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * of netoff, which contradicts
3697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * linux-2.6/Documentation/networking/packet_mmap.txt
3698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * documenting that:
3699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "- Gap, chosen so that packet data (Start+tp_net)
3700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * aligns to TPACKET_ALIGNMENT=16"
3701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* NOTE: in linux-2.6/include/linux/skbuff.h:
3703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * "CPUs often take a performance hit
3704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *  when accessing unaligned memory locations"
3705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		macoff = netoff - maclen;
3707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size);
3708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
3709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V3:
3713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* The "frames" for this are actually buffers that
3714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * contain multiple variable-sized frames.
3715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
3716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We pick a "frame" size of 128K to leave enough
3717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * room for at least one reasonably-sized packet
3718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in the "frame". */
3719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		req.tp_frame_size = 131072;
3720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		req.tp_frame_nr = handle->opt.buffer_size/req.tp_frame_size;
3721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
3722511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* compute the minumum block size that will handle this frame.
3726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The block has to be page size aligned.
3727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The max block size allowed by the kernel is arch-dependent and
3728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it's not explicitly checked here. */
3729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_block_size = getpagesize();
3730511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while (req.tp_block_size < req.tp_frame_size)
3731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		req.tp_block_size <<= 1;
3732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	frames_per_block = req.tp_block_size/req.tp_frame_size;
3734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * PACKET_TIMESTAMP was added after linux/net_tstamp.h was,
3737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * so we check for PACKET_TIMESTAMP.  We check for
3738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * linux/net_tstamp.h just in case a system somehow has
3739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * PACKET_TIMESTAMP but not linux/net_tstamp.h; that might
3740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * be unnecessary.
3741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * SIOCSHWTSTAMP was introduced in the patch that introduced
3743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * linux/net_tstamp.h, so we don't bother checking whether
3744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * SIOCSHWTSTAMP is defined (if your Linux system has
3745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * linux/net_tstamp.h but doesn't define SIOCSHWTSTAMP, your
3746511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Linux system is badly broken).
3747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP)
3749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
3750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we were told to do so, ask the kernel and the driver
3751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to use hardware timestamps.
3752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
3753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Hardware timestamps are only supported with mmapped
3754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * captures.
3755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
3756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER ||
3757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER_UNSYNCED) {
3758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct hwtstamp_config hwconfig;
3759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct ifreq ifr;
3760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int timesource;
3761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
3763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Ask for hardware time stamps on all packets,
3764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * including transmitted packets.
3765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
3766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&hwconfig, 0, sizeof(hwconfig));
3767511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hwconfig.tx_type = HWTSTAMP_TX_ON;
3768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hwconfig.rx_filter = HWTSTAMP_FILTER_ALL;
3769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ifr, 0, sizeof(ifr));
3771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strcpy(ifr.ifr_name, handle->opt.source);
3772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ifr.ifr_data = (void *)&hwconfig;
3773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) {
3775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			switch (errno) {
3776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			case EPERM:
3778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Treat this as an error, as the
3780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * user should try to run this
3781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * with the appropriate privileges -
3782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * and, if they can't, shouldn't
3783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * try requesting hardware time stamps.
3784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_ERROR_PERM_DENIED;
3786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -1;
3787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			case EOPNOTSUPP:
3789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Treat this as a warning, as the
3791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * only way to fix the warning is to
3792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * get an adapter that supports hardware
3793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * time stamps.  We'll just fall back
3794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * on the standard host time stamps.
3795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP;
3797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
3798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			default:
3800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"SIOCSHWTSTAMP failed: %s",
3802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					pcap_strerror(errno));
3803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_ERROR;
3804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -1;
3805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3806511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
3807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Well, that worked.  Now specify the type of
3809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * hardware time stamp we want for this
3810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * socket.
3811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3812511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) {
3813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Hardware timestamp, synchronized
3815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * with the system clock.
3816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				timesource = SOF_TIMESTAMPING_SYS_HARDWARE;
3818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else {
3819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
3820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware
3821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * timestamp, not synchronized with the
3822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * system clock.
3823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
3824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				timesource = SOF_TIMESTAMPING_RAW_HARDWARE;
3825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP,
3827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				(void *)&timesource, sizeof(timesource))) {
3828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"can't set PACKET_TIMESTAMP: %s",
3830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					pcap_strerror(errno));
3831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				*status = PCAP_ERROR;
3832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return -1;
3833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
3834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */
3837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ask the kernel to create the ring */
3839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallretry:
3840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_block_nr = req.tp_frame_nr / frames_per_block;
3841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */
3843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_frame_nr = req.tp_block_nr * frames_per_block;
3844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
3846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* timeout value to retire block - use the configured buffering timeout, or default if <0. */
3847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_retire_blk_tov = (handlep->timeout>=0)?handlep->timeout:0;
3848511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* private data not used */
3849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_sizeof_priv = 0;
3850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Rx ring - feature request bits - none (rxhash will not be filled) */
3851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	req.tp_feature_req_word = 0;
3852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
3853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
3855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					(void *) &req, sizeof(req))) {
3856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((errno == ENOMEM) && (req.tp_block_nr > 1)) {
3857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Memory failure; try to reduce the requested ring
3859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * size.
3860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
3861511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We used to reduce this by half -- do 5% instead.
3862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * That may result in more iterations and a longer
3863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * startup, but the user will be much happier with
3864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the resulting buffer size.
3865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3866511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (req.tp_frame_nr < 20)
3867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				req.tp_frame_nr -= 1;
3868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			else
3869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				req.tp_frame_nr -= req.tp_frame_nr/20;
3870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			goto retry;
3871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3872511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENOPROTOOPT) {
3873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
3874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * We don't have ring buffer support in this kernel.
3875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
3876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
3877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "can't create rx ring on packet socket: %s",
3880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    pcap_strerror(errno));
3881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*status = PCAP_ERROR;
3882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* memory map the rx ring */
3886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size;
3887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->mmapbuf = mmap(0, handlep->mmapbuflen,
3888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0);
3889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->mmapbuf == MAP_FAILED) {
3890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "can't mmap rx ring: %s", pcap_strerror(errno));
3892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* clear the allocated ring on error*/
3894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		destroy_ring(handle);
3895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*status = PCAP_ERROR;
3896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3898511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3899511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* allocate a ring for each frame header pointer*/
3900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->cc = req.tp_frame_nr;
3901511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->buffer = malloc(handle->cc * sizeof(union thdr *));
3902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!handle->buffer) {
3903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
3904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "can't allocate ring of frame headers: %s",
3905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    pcap_strerror(errno));
3906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		destroy_ring(handle);
3908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		*status = PCAP_ERROR;
3909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
3910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* fill the header ring with proper frame ptr*/
3913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset = 0;
3914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (i=0; i<req.tp_block_nr; ++i) {
3915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		void *base = &handlep->mmapbuf[i*req.tp_block_size];
3916511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		for (j=0; j<frames_per_block; ++j, ++handle->offset) {
3917511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			RING_GET_FRAME(handle) = base;
3918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			base += req.tp_frame_size;
3919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
3920511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->bufsize = req.tp_frame_size;
3923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset = 0;
3924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
3925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* free all ring related resources*/
3928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
3929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralldestroy_ring(pcap_t *handle)
3930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* tell the kernel to destroy the ring*/
3934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct tpacket_req req;
3935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&req, 0, sizeof(req));
3936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING,
3937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				(void *) &req, sizeof(req));
3938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* if ring is mapped, unmap it*/
3940511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->mmapbuf) {
3941511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* do not test for mmap failure, as we can't recover from any error */
3942511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		munmap(handlep->mmapbuf, handlep->mmapbuflen);
3943511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->mmapbuf = NULL;
3944511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3945511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3946511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3947511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
3948511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Special one-shot callback, used for pcap_next() and pcap_next_ex(),
3949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * for Linux mmapped capture.
3950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * The problem is that pcap_next() and pcap_next_ex() expect the packet
3952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * data handed to the callback to be valid after the callback returns,
3953511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * but pcap_read_linux_mmap() has to release that packet as soon as
3954511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * the callback returns (otherwise, the kernel thinks there's still
3955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * at least one unprocessed packet available in the ring, so a select()
3956511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * will immediately return indicating that there's data to process), so,
3957511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * in the callback, we have to make a copy of the packet.
3958511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
3959511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Yes, this means that, if the capture is using the ring buffer, using
3960511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * pcap_next() or pcap_next_ex() requires more copies than using
3961511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * pcap_loop() or pcap_dispatch().  If that bothers you, don't use
3962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * pcap_next() or pcap_next_ex().
3963511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
3964511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
3965511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h,
3966511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall    const u_char *bytes)
3967511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3968511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct oneshot_userdata *sp = (struct oneshot_userdata *)user;
3969511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_t *handle = sp->pd;
3970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3971511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3972511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*sp->hdr = *h;
3973511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memcpy(handlep->oneshot_buffer, bytes, h->caplen);
3974511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	*sp->pkt = handlep->oneshot_buffer;
3975511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3976511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3977511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic void
3978511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_cleanup_linux_mmap( pcap_t *handle )
3979511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3980511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
3981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	destroy_ring(handle);
3983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->oneshot_buffer != NULL) {
3984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(handlep->oneshot_buffer);
3985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->oneshot_buffer = NULL;
3986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
3987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_cleanup_linux(handle);
3988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
3992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_getnonblock_mmap(pcap_t *p, char *errbuf)
3993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
3994511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = p->priv;
3995511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
3996511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* use negative value of timeout to indicate non blocking ops */
3997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return (handlep->timeout<0);
3998511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
3999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_setnonblock_mmap(pcap_t *p, int nonblock, char *errbuf)
4002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = p->priv;
4004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4005511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Map each value to their corresponding negation to
4007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * preserve the timeout value provided with pcap_set_timeout.
4008511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4009511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (nonblock) {
4010511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->timeout >= 0) {
4011511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
4012511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Indicate that we're switching to
4013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * non-blocking mode.
4014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
4015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->timeout = ~handlep->timeout;
4016511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4017511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
4018511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->timeout < 0) {
4019511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->timeout = ~handlep->timeout;
4020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4022511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
4023511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4024511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4025511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic inline union thdr *
4026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_get_ring_frame(pcap_t *handle, int status)
4027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	union thdr h;
4030511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	h.raw = RING_GET_FRAME(handle);
4032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (handlep->tp_version) {
4033511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V1:
4034511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (status != (h.h1->tp_status ? TP_STATUS_USER :
4035511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						TP_STATUS_KERNEL))
4036511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return NULL;
4037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
4039511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V2:
4040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (status != (h.h2->tp_status ? TP_STATUS_USER :
4041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						TP_STATUS_KERNEL))
4042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return NULL;
4043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
4046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case TPACKET_V3:
4047511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (status != (h.h3->hdr.bh1.block_status ? TP_STATUS_USER :
4048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						TP_STATUS_KERNEL))
4049511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return NULL;
4050511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
4051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return h.raw;
4054511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifndef POLLRDHUP
4057511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#define POLLRDHUP 0
4058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* wait for frames availability.*/
4061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_wait_for_frames_mmap(pcap_t *handle)
4062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4063511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!pcap_get_ring_frame(handle, TP_STATUS_USER)) {
4064511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct pcap_linux *handlep = handle->priv;
4065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int timeout;
4066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		char c;
4067511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct pollfd pollinfo;
4068511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int ret;
4069511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4070511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pollinfo.fd = handle->fd;
4071511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pollinfo.events = POLLIN;
4072511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4073511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->timeout == 0) {
4074511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
4075511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
4076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * XXX - due to a set of (mis)features in the
4077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * TPACKET_V3 kernel code, blocking forever with
4078511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * a TPACKET_V3 socket can, if few packets
4079511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * are arriving and passing the socket filter,
4080511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * cause most packets to be dropped.  See
4081511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * libpcap issue #335 for the full painful
4082511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * story.  The workaround is to have poll()
4083511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * time out very quickly, so we grab the
4084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * frames handed to us, and return them to
4085511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the kernel, ASAP.
4086511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 *
4087511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If those issues are ever fixed, we might
4088511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * want to check the kernel version and block
4089511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * forever with TPACKET_V3 if we're running
4090511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * with a kernel that has the fix.
4091511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
4092511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handlep->tp_version == TPACKET_V3)
4093511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				timeout = 1;	/* don't block for very long */
4094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			else
4095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				timeout = -1;	/* block forever */
4097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else if (handlep->timeout > 0)
4098511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			timeout = handlep->timeout;	/* block for that amount of time */
4099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		else
4100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			timeout = 0;	/* non-blocking mode - poll to pick up errors */
4101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		do {
4102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = poll(&pollinfo, 1, timeout);
4103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ret < 0 && errno != EINTR) {
4104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					"can't poll on packet socket: %s",
4106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					pcap_strerror(errno));
4107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR;
4108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else if (ret > 0 &&
4109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				(pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) {
4110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * There's some indication other than
4112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * "you can read on this descriptor" on
4113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the descriptor.
4114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (pollinfo.revents & (POLLHUP | POLLRDHUP)) {
4116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					snprintf(handle->errbuf,
4117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						PCAP_ERRBUF_SIZE,
4118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						"Hangup on packet socket");
4119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return PCAP_ERROR;
4120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
4121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (pollinfo.revents & POLLERR) {
4122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
4123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * A recv() will give us the
4124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * actual error code.
4125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 *
4126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * XXX - make the socket non-blocking?
4127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
4128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					if (recv(handle->fd, &c, sizeof c,
4129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						MSG_PEEK) != -1)
4130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						continue;	/* what, no error? */
4131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					if (errno == ENETDOWN) {
4132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						/*
4133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * The device on which we're
4134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * capturing went away.
4135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 *
4136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * XXX - we should really return
4137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * PCAP_ERROR_IFACE_NOT_UP,
4138511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * but pcap_dispatch() etc.
4139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * aren't defined to return
4140511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 * that.
4141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						 */
4142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						snprintf(handle->errbuf,
4143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall							PCAP_ERRBUF_SIZE,
4144511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall							"The interface went down");
4145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					} else {
4146511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						snprintf(handle->errbuf,
4147511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall							PCAP_ERRBUF_SIZE,
4148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall							"Error condition on packet socket: %s",
4149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall							strerror(errno));
4150511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					}
4151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return PCAP_ERROR;
4152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
4153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (pollinfo.revents & POLLNVAL) {
4154511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					snprintf(handle->errbuf,
4155511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						PCAP_ERRBUF_SIZE,
4156511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						"Invalid polling request on packet socket");
4157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					return PCAP_ERROR;
4158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
4159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* check for break loop condition on interrupted syscall*/
4161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handle->break_loop) {
4162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->break_loop = 0;
4163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR_BREAK;
4164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} while (ret < 0);
4166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
4168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* handle a single memory mapped packet */
4171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int pcap_handle_packet_mmap(
4172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_t *handle,
4173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcap_handler callback,
4174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		u_char *user,
4175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned char *frame,
4176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned int tp_len,
4177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned int tp_mac,
4178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned int tp_snaplen,
4179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned int tp_sec,
4180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		unsigned int tp_usec,
4181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int tp_vlan_tci_valid,
4182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		__u16 tp_vlan_tci)
4183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	unsigned char *bp;
4186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sockaddr_ll *sll;
4187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_pkthdr pcaphdr;
4188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* perform sanity check on internal offset. */
4190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (tp_mac + tp_snaplen > handle->bufsize) {
4191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"corrupted frame on kernel ring mac "
4193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"offset %d + caplen %d > frame len %d",
4194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			tp_mac, tp_snaplen, handle->bufsize);
4195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
4196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* run filter on received packet
4199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If the kernel filtering is enabled we need to run the
4200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * filter until all the frames present into the ring
4201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * at filter creation time are processed.
4202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * In this case, blocks_to_filter_in_userland is used
4203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * as a counter for the packet we need to filter.
4204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Note: alternatively it could be possible to stop applying
4205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the filter when the ring became empty, but it can possibly
4206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * happen a lot later... */
4207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	bp = frame + tp_mac;
4208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->filter_in_userland && handle->fcode.bf_insns &&
4209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			(bpf_filter(handle->fcode.bf_insns, bp,
4210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				tp_len, tp_snaplen) == 0))
4211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
4212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen);
4214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!linux_check_direction(handle, sll))
4215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
4216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* get required packet info from ring header */
4218511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcaphdr.ts.tv_sec = tp_sec;
4219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcaphdr.ts.tv_usec = tp_usec;
4220511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcaphdr.caplen = tp_snaplen;
4221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcaphdr.len = tp_len;
4222511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* if required build in place the sll header*/
4224511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->cooked) {
4225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct sll_header *hdrp;
4226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The kernel should have left us with enough
4229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * space for an sll header; back up the packet
4230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * data pointer into that space, as that'll be
4231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the beginning of the packet we pass to the
4232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * callback.
4233511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bp -= SLL_HDR_LEN;
4235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*/*
4237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Let's make sure that's past the end of
4238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the tpacket header, i.e. >=
4239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * ((u_char *)thdr + TPACKET_HDRLEN), so we
4240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * don't step on the header when we construct
4241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the sll header.
4242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (bp < (u_char *)frame +
4244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				   TPACKET_ALIGN(handlep->tp_hdrlen) +
4245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				   sizeof(struct sockaddr_ll)) {
4246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				"cooked-mode frame doesn't have room for sll header");
4248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return -1;
4249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * OK, that worked; construct the sll header.
4253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp = (struct sll_header *)bp;
4255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_pkttype = map_packet_type_to_sll_type(
4256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						sll->sll_pkttype);
4257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_hatype = htons(sll->sll_hatype);
4258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_halen = htons(sll->sll_halen);
4259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN);
4260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		hdrp->sll_protocol = sll->sll_protocol;
4261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* update packet len */
4263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcaphdr.caplen += SLL_HDR_LEN;
4264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcaphdr.len += SLL_HDR_LEN;
4265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3)
4268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (tp_vlan_tci_valid &&
4269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handlep->vlan_offset != -1 &&
4270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tp_snaplen >= (unsigned int) handlep->vlan_offset)
4271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	{
4272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		struct vlan_tag *tag;
4273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		bp -= VLAN_TAG_LEN;
4275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset);
4276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tag = (struct vlan_tag *)(bp + handlep->vlan_offset);
4278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tag->vlan_tpid = htons(ETH_P_8021Q);
4279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		tag->vlan_tci = htons(tp_vlan_tci);
4280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcaphdr.caplen += VLAN_TAG_LEN;
4282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcaphdr.len += VLAN_TAG_LEN;
4283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * The only way to tell the kernel to cut off the
4288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packet at a snapshot length is with a filter program;
4289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * if there's no filter program, the kernel won't cut
4290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the packet off.
4291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Trim the snapshot length to be no longer than the
4293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * specified snapshot length.
4294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (pcaphdr.caplen > handle->snapshot)
4296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		pcaphdr.caplen = handle->snapshot;
4297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* pass the packet to the user */
4299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	callback(user, &pcaphdr, bp);
4300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
4302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback,
4306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		u_char *user)
4307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int pkts = 0;
4310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
4311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* wait for frames availability.*/
4313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = pcap_wait_for_frames_mmap(handle);
4314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret) {
4315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
4316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* non-positive values of max_packets are used to require all
4319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets currently available in the ring */
4320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
4321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		union thdr h;
4322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
4324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!h.raw)
4325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = pcap_handle_packet_mmap(
4328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle,
4329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				callback,
4330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				user,
4331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.raw,
4332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h1->tp_len,
4333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h1->tp_mac,
4334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h1->tp_snaplen,
4335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h1->tp_sec,
4336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h1->tp_usec,
4337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				0,
4338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				0);
4339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret == 1) {
4340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkts++;
4341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->packets_read++;
4342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else if (ret < 0) {
4343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return ret;
4344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Hand this block back to the kernel, and, if we're
4348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * counting blocks that need to be filtered in userland
4349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * after having been filtered by the kernel, count
4350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the one we've just processed.
4351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		h.h1->tp_status = TP_STATUS_KERNEL;
4353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->blocks_to_filter_in_userland > 0) {
4354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->blocks_to_filter_in_userland--;
4355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handlep->blocks_to_filter_in_userland == 0) {
4356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * No more blocks need to be filtered
4358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * in userland.
4359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->filter_in_userland = 0;
4361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* next block */
4365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (++handle->offset >= handle->cc)
4366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->offset = 0;
4367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* check for break loop condition*/
4369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop) {
4370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
4371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_BREAK;
4372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return pkts;
4375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET2
4378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback,
4380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		u_char *user)
4381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4383511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int pkts = 0;
4384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
4385511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* wait for frames availability.*/
4387511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = pcap_wait_for_frames_mmap(handle);
4388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret) {
4389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
4390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* non-positive values of max_packets are used to require all
4393511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets currently available in the ring */
4394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
4395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		union thdr h;
4396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
4398511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!h.raw)
4399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = pcap_handle_packet_mmap(
4402511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle,
4403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				callback,
4404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				user,
4405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.raw,
4406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_len,
4407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_mac,
4408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_snaplen,
4409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_sec,
4410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? h.h2->tp_nsec : h.h2->tp_nsec / 1000,
4411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(TP_STATUS_VLAN_VALID)
4412511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				(h.h2->tp_vlan_tci || (h.h2->tp_status & TP_STATUS_VLAN_VALID)),
4413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
4414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_vlan_tci != 0,
4415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				h.h2->tp_vlan_tci);
4417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret == 1) {
4418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pkts++;
4419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->packets_read++;
4420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else if (ret < 0) {
4421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return ret;
4422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Hand this block back to the kernel, and, if we're
4426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * counting blocks that need to be filtered in userland
4427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * after having been filtered by the kernel, count
4428511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the one we've just processed.
4429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		h.h2->tp_status = TP_STATUS_KERNEL;
4431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->blocks_to_filter_in_userland > 0) {
4432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->blocks_to_filter_in_userland--;
4433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handlep->blocks_to_filter_in_userland == 0) {
4434511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4435511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * No more blocks need to be filtered
4436511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * in userland.
4437511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->filter_in_userland = 0;
4439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* next block */
4443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (++handle->offset >= handle->cc)
4444511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->offset = 0;
4445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4446511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* check for break loop condition*/
4447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop) {
4448511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
4449511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_BREAK;
4450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4451511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4452511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return pkts;
4453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET2 */
4455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_TPACKET3
4457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback,
4459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		u_char *user)
4460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	union thdr h;
4463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int pkts = 0;
4464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
4465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->current_packet == NULL) {
4467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* wait for frames availability.*/
4468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ret = pcap_wait_for_frames_mmap(handle);
4469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ret) {
4470511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return ret;
4471511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4473511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
4474511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!h.raw)
4475511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return pkts;
4476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4477511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* non-positive values of max_packets are used to require all
4478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * packets currently available in the ring */
4479511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) {
4480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->current_packet == NULL) {
4481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			h.raw = pcap_get_ring_frame(handle, TP_STATUS_USER);
4482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (!h.raw)
4483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
4484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt;
4486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->packets_left = h.h3->hdr.bh1.num_pkts;
4487511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		int packets_to_read = handlep->packets_left;
4489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!PACKET_COUNT_IS_UNLIMITED(max_packets) && packets_to_read > max_packets) {
4491511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			packets_to_read = max_packets;
4492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		while(packets_to_read--) {
4495511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			struct tpacket3_hdr* tp3_hdr = (struct tpacket3_hdr*) handlep->current_packet;
4496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ret = pcap_handle_packet_mmap(
4497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					handle,
4498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					callback,
4499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					user,
4500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					handlep->current_packet,
4501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->tp_len,
4502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->tp_mac,
4503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->tp_snaplen,
4504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->tp_sec,
4505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? tp3_hdr->tp_nsec : tp3_hdr->tp_nsec / 1000,
4506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(TP_STATUS_VLAN_VALID)
4507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					(tp3_hdr->hv1.tp_vlan_tci || (tp3_hdr->tp_status & TP_STATUS_VLAN_VALID)),
4508511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else
4509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->hv1.tp_vlan_tci != 0,
4510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
4511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					tp3_hdr->hv1.tp_vlan_tci);
4512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ret == 1) {
4513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				pkts++;
4514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->packets_read++;
4515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			} else if (ret < 0) {
4516511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->current_packet = NULL;
4517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return ret;
4518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->current_packet += tp3_hdr->tp_next_offset;
4520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->packets_left--;
4521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handlep->packets_left <= 0) {
4524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
4525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Hand this block back to the kernel, and, if
4526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we're counting blocks that need to be
4527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * filtered in userland after having been
4528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * filtered by the kernel, count the one we've
4529511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * just processed.
4530511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
4531511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			h.h3->hdr.bh1.block_status = TP_STATUS_KERNEL;
4532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (handlep->blocks_to_filter_in_userland > 0) {
4533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handlep->blocks_to_filter_in_userland--;
4534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (handlep->blocks_to_filter_in_userland == 0) {
4535511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
4536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * No more blocks need to be filtered
4537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * in userland.
4538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
4539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					handlep->filter_in_userland = 0;
4540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
4541511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4543511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/* next block */
4544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (++handle->offset >= handle->cc)
4545511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				handle->offset = 0;
4546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4547511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->current_packet = NULL;
4548511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/* check for break loop condition*/
4551511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->break_loop) {
4552511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->break_loop = 0;
4553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_BREAK;
4554511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4556511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return pkts;
4557511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_TPACKET3 */
4559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4561511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallpcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter)
4562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4563511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int n, offset;
4565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
4566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Don't rewrite "ret" instructions; we don't need to, as
4569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we're not reading packets with recvmsg(), and we don't
4570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * want to, as, by not rewriting them, the kernel can avoid
4571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * copying extra data.
4572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = pcap_setfilter_linux_common(handle, filter, 1);
4574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
4575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
4576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we're filtering in userland, there's nothing to do;
4579511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the new filter will be used for the next packet.
4580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4581511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handlep->filter_in_userland)
4582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;
4583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4584511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We're filtering in the kernel; the packets present in
4586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * all blocks currently in the ring were already filtered
4587511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * by the old filter, and so will need to be filtered in
4588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * userland by the new filter.
4589511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Get an upper bound for the number of such blocks; first,
4591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * walk the ring backward and count the free blocks.
4592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	offset = handle->offset;
4594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (--handle->offset < 0)
4595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->offset = handle->cc - 1;
4596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	for (n=0; n < handle->cc; ++n) {
4597511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (--handle->offset < 0)
4598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->offset = handle->cc - 1;
4599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (!pcap_get_ring_frame(handle, TP_STATUS_KERNEL))
4600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;
4601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4604511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we found free blocks, decrement the count of free
4605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * blocks by 1, just in case we lost a race with another
4606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * thread of control that was adding a packet while
4607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we were counting and that had run the filter before
4608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * we changed it.
4609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - could there be more than one block added in
4611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * this fashion?
4612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - is there a way to avoid that race, e.g. somehow
4614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * wait for all packets that passed the old filter to
4615511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * be added to the ring?
4616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4617511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (n != 0)
4618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		n--;
4619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* be careful to not change current ring position */
4621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset = offset;
4622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Set the count of blocks worth of packets to filter
4625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * in userland to the total number of blocks in the
4626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * ring minus the number of free blocks we found, and
4627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * turn on userland filtering.  (The count of blocks
4628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * worth of packets to filter in userland is guaranteed
4629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * not to be zero - n, above, couldn't be set to a
4630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * value > handle->cc, and if it were equal to
4631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handle->cc, it wouldn't be zero, and thus would
4632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * be decremented to handle->cc - 1.)
4633511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->blocks_to_filter_in_userland = handle->cc - n;
4635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->filter_in_userland = 1;
4636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return ret;
4637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PACKET_RING */
4640511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_PF_PACKET_SOCKETS
4643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
4644511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Return the index of the given device name. Fill ebuf and return
4645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  -1 on failure.
4646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
4647511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralliface_get_id(int fd, const char *device, char *ebuf)
4649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq	ifr;
4651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&ifr, 0, sizeof(ifr));
4653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
4654511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) {
4656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(ebuf, PCAP_ERRBUF_SIZE,
4657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "SIOCGIFINDEX: %s", pcap_strerror(errno));
4658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
4659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return ifr.ifr_ifindex;
4662511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4664511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
4665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Bind the socket associated with FD to the given device.
4666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  Return 1 on success, 0 if we should try a SOCK_PACKET socket,
4667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *  or a PCAP_ERROR_ value on a hard error.
4668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
4669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralliface_bind(int fd, int ifindex, char *ebuf)
4671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct sockaddr_ll	sll;
4673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int			err;
4674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	socklen_t		errlen = sizeof(err);
4675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&sll, 0, sizeof(sll));
4677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sll.sll_family		= AF_PACKET;
4678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sll.sll_ifindex		= ifindex;
4679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	sll.sll_protocol	= htons(ETH_P_ALL);
4680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) {
4682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENETDOWN) {
4683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
4684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Return a "network down" indication, so that
4685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * the application can report that rather than
4686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * saying we had a mysterious failure and
4687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * suggest that they report a problem to the
4688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * libpcap developers.
4689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
4690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_IFACE_NOT_UP;
4691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
4692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(ebuf, PCAP_ERRBUF_SIZE,
4693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 "bind: %s", pcap_strerror(errno));
4694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
4695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4697478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Any pending errors, e.g., network is down? */
4699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
4701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(ebuf, PCAP_ERRBUF_SIZE,
4702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"getsockopt: %s", pcap_strerror(errno));
4703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
4704478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
4705478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err == ENETDOWN) {
4707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
4708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Return a "network down" indication, so that
4709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the application can report that rather than
4710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * saying we had a mysterious failure and
4711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * suggest that they report a problem to the
4712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * libpcap developers.
4713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
4714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_IFACE_NOT_UP;
4715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else if (err > 0) {
4716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(ebuf, PCAP_ERRBUF_SIZE,
4717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			"bind: %s", pcap_strerror(err));
4718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 0;
4719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
4722511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4723478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
4725478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
4726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Check whether the device supports the Wireless Extensions.
4727511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE
4728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * if the device doesn't even exist.
4729478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
4730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
4731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallhas_wext(int sock_fd, const char *device, char *ebuf)
4732478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
4733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iwreq ireq;
4734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
4735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ireq.ifr_ifrn.ifrn_name, device,
4736511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    sizeof ireq.ifr_ifrn.ifrn_name);
4737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
4738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0)
4739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* yes */
4740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	snprintf(ebuf, PCAP_ERRBUF_SIZE,
4741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    "%s: SIOCGIWPRIV: %s", device, pcap_strerror(errno));
4742511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (errno == ENODEV)
4743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_NO_SUCH_DEVICE;
4744511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
4745511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
4746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4747511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
4748511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Per me si va ne la citta dolente,
4749511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Per me si va ne l'etterno dolore,
4750511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *	...
4751511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Lasciate ogne speranza, voi ch'intrate.
4752511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
4753511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * XXX - airmon-ng does special stuff with the Orinoco driver and the
4754511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * wlan-ng driver.
4755511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
4756511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralltypedef enum {
4757511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_WEXT,
4758511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_HOSTAP,
4759511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_PRISM,
4760511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_PRISM54,
4761511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_ACX100,
4762511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_RT2500,
4763511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_RT2570,
4764511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_RT73,
4765511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	MONITOR_RTL8XXX
4766511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall} monitor_type;
4767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4768511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
4769511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Use the Wireless Extensions, if we have them, to try to turn monitor mode
4770511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * on if it's not already on.
4771511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
4772511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Returns 1 on success, 0 if we don't support the Wireless Extensions
4773511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * on this device, or a PCAP_ERROR_ value if we do support them but
4774511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * we weren't able to turn monitor mode on.
4775511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
4776511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
4777511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallenter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device)
4778511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
4779511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4780511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - at least some adapters require non-Wireless Extensions
4781511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mechanisms to turn monitor mode on.
4782511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4783511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Atheros cards might require that a separate "monitor virtual access
4784511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * point" be created, with later versions of the madwifi driver.
4785511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode
4786511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * monitor -bssid", which apparently spits out a line "athN"
4787511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * where "athN" is the monitor mode device.  To leave monitor
4788511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mode, it destroys the monitor mode device.
4789511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4790511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Some Intel Centrino adapters might require private ioctls to get
4791511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * radio headers; the ipw2200 and ipw3945 drivers allow you to
4792511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * configure a separate "rtapN" interface to capture in monitor
4793511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mode without preventing the adapter from operating normally.
4794511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * (airmon-ng doesn't appear to use that, though.)
4795511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4796511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * It would be Truly Wonderful if mac80211 and nl80211 cleaned this
4797511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * up, and if all drivers were converted to mac80211 drivers.
4798511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4799511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If interface {if} is a mac80211 driver, the file
4800511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * /sys/class/net/{if}/phy80211 is a symlink to
4801511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * /sys/class/ieee80211/{phydev}, for some {phydev}.
4802511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4803511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at
4804511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * least, has a "wmaster0" device and a "wlan0" device; the
4805511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * latter is the one with the IP address.  Both show up in
4806511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "tcpdump -D" output.  Capturing on the wmaster0 device
4807511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * captures with 802.11 headers.
4808511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4809511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * airmon-ng searches through /sys/class/net for devices named
4810511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * monN, starting with mon0; as soon as one *doesn't* exist,
4811511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * it chooses that as the monitor device name.  If the "iw"
4812511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * command exists, it does "iw dev {if} interface add {monif}
4813511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * type monitor", where {monif} is the monitor device.  It
4814511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * then (sigh) sleeps .1 second, and then configures the
4815511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * device up.  Otherwise, if /sys/class/ieee80211/{phydev}/add_iface
4816511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * is a file, it writes {mondev}, without a newline, to that file,
4817511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * and again (sigh) sleeps .1 second, and then iwconfig's that
4818511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * device into monitor mode and configures it up.  Otherwise,
4819511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * you can't do monitor mode.
4820511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4821511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * All these devices are "glued" together by having the
4822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * /sys/class/net/{device}/phy80211 links pointing to the same
4823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * place, so, given a wmaster, wlan, or mon device, you can
4824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * find the other devices by looking for devices with
4825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the same phy80211 link.
4826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * To turn monitor mode off, delete the monitor interface,
4828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * either with "iw dev {monif} interface del" or by sending
4829511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface
4830511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4831511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Note: if you try to create a monitor device named "monN", and
4832511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * there's already a "monN" device, it fails, as least with
4833511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * the netlink interface (which is what iw uses), with a return
4834511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * value of -ENFILE.  (Return values are negative errnos.)  We
4835511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * could probably use that to find an unused device.
4836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4837511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
4838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int err;
4839511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iwreq ireq;
4840511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct iw_priv_args *priv;
4841511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	monitor_type montype;
4842511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int i;
4843511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	__u32 cmd;
4844511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ifreq ifr;
4845511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int oldflags;
4846511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int args[2];
4847511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int channel;
4848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4849511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4850511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Does this device *support* the Wireless Extensions?
4851511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4852511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	err = has_wext(sock_fd, device, handle->errbuf);
4853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (err <= 0)
4854511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return err;	/* either it doesn't or the device doesn't even exist */
4855511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4856511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Start out assuming we have no private extensions to control
4857511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * radio metadata.
4858511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4859511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	montype = MONITOR_WEXT;
4860511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	cmd = 0;
4861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4862511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
4863511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Try to get all the Wireless Extensions private ioctls
4864511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * supported by this device.
4865511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
4866511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * First, get the size of the buffer we need, by supplying no
4867511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * buffer and a length of 0.  If the device supports private
4868511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * ioctls, it should return E2BIG, with ireq.u.data.length set
4869511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * to the length we need.  If it doesn't support them, it should
4870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * return EOPNOTSUPP.
4871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
4872511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&ireq, 0, sizeof ireq);
4873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ireq.ifr_ifrn.ifrn_name, device,
4874511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    sizeof ireq.ifr_ifrn.ifrn_name);
4875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
4876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.u.data.pointer = (void *)args;
4877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.u.data.length = 0;
4878511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.u.data.flags = 0;
4879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) {
4880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!",
4882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    device);
4883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
4884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
4885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (errno != EOPNOTSUPP) {
4886478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * OK, it's not as if there are no private ioctls.
4888478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno != E2BIG) {
4890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
4891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Failed.
4892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
4893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: SIOCGIWPRIV: %s", device,
4895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
4896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
4897511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4900511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * OK, try to get the list of private ioctls.
4901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4902511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args));
4903511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (priv == NULL) {
4904511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4905511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "malloc: %s", pcap_strerror(errno));
4906511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
4907511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4908511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.u.data.pointer = (void *)priv;
4909511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) {
4910511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
4911511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: SIOCGIWPRIV: %s", device,
4912511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
4913511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			free(priv);
4914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
4915511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
4916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
4917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
4918511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Look for private ioctls to turn monitor mode on or, if
4919511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * monitor mode is on, to set the header type.
4920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
4921511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		for (i = 0; i < ireq.u.data.length; i++) {
4922511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "monitor_type") == 0) {
4923511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4924511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Hostap driver, use this one.
4925511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Set monitor mode first.
4926511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * You can set it to 0 to get DLT_IEEE80211,
4927511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * 1 to get DLT_PRISM, 2 to get
4928511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * DLT_IEEE80211_RADIO_AVS, and, with more
4929511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * recent versions of the driver, 3 to get
4930511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * DLT_IEEE80211_RADIO.
4931511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4932511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
4933511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4934511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
4935511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4936511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
4937511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4938511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_HOSTAP;
4939511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
4940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				break;
4941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
4942511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "set_prismhdr") == 0) {
4943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/*
4944511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Prism54 driver, use this one.
4945511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Set monitor mode first.
4946511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * You can set it to 2 to get DLT_IEEE80211
4947511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * or 3 or get DLT_PRISM.
4948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 */
4949511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
4950478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					break;
4951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
4952478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					break;
4953511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
4954511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_PRISM54;
4956511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
4957511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
4958511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4959511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "forceprismheader") == 0) {
4960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/*
4961511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * RT2570 driver, use this one.
4962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Do this after turning monitor mode on.
4963511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * You can set it to 1 to get DLT_PRISM or 2
4964511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * to get DLT_IEEE80211.
4965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 */
4966511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
4967511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4968511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
4969511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4970511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
4971511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4972511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_RT2570;
4973511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
4974511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
4975511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4976511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "forceprism") == 0) {
4977511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4978511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * RT73 driver, use this one.
4979511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Do this after turning monitor mode on.
4980511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Its argument is a *string*; you can
4981511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * set it to "1" to get DLT_PRISM or "2"
4982511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * to get DLT_IEEE80211.
4983511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4984511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR)
4985511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4986511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (priv[i].set_args & IW_PRIV_SIZE_FIXED)
4987511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
4988511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_RT73;
4989511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
4990511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
4991511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
4992511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "prismhdr") == 0) {
4993511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
4994511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * One of the RTL8xxx drivers, use this one.
4995511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * It can only be done after monitor mode
4996511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * has been turned on.  You can set it to 1
4997511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * to get DLT_PRISM or 0 to get DLT_IEEE80211.
4998511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
4999511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
5000511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5001511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
5002511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5003511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1)
5004511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5005511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_RTL8XXX;
5006511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
5007511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
5008511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
5009511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "rfmontx") == 0) {
5010511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
5011511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * RT2500 or RT61 driver, use this one.
5012511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * It has one one-byte parameter; set
5013511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * u.data.length to 1 and u.data.pointer to
5014511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * point to the parameter.
5015511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * It doesn't itself turn monitor mode on.
5016511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * You can set it to 1 to allow transmitting
5017511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * in monitor mode(?) and get DLT_IEEE80211,
5018511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * or set it to 0 to disallow transmitting in
5019511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * monitor mode(?) and get DLT_PRISM.
5020511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
5021511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
5022511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5023511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2)
5024511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5025511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				montype = MONITOR_RT2500;
5026511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				cmd = priv[i].cmd;
5027511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				break;
5028511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
5029511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (strcmp(priv[i].name, "monitor") == 0) {
5030511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
5031511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Either ACX100 or hostap, use this one.
5032511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * It turns monitor mode on.
5033511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * If it takes two arguments, it's ACX100;
5034511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the first argument is 1 for DLT_PRISM
5035511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * or 2 for DLT_IEEE80211, and the second
5036511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * argument is the channel on which to
5037511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * run.  If it takes one argument, it's
5038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * HostAP, and the argument is 2 for
5039511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * DLT_IEEE80211 and 3 for DLT_PRISM.
5040511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 *
5041511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * If we see this, we don't quit, as this
5042511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * might be a version of the hostap driver
5043511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * that also supports "monitor_type".
5044511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
5045511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT)
5046511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5047511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED))
5048511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5049511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				switch (priv[i].set_args & IW_PRIV_SIZE_MASK) {
5050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5051511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				case 1:
5052511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					montype = MONITOR_PRISM;
5053511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					cmd = priv[i].cmd;
5054511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5055511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5056511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				case 2:
5057511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					montype = MONITOR_ACX100;
5058511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					cmd = priv[i].cmd;
5059511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5060511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5061511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				default:
5062511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					break;
5063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				}
5064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
5065511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5066511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		free(priv);
5067511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5069511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5070511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - ipw3945?  islism?
5071511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5073511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5074511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Get the old mode.
5075511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5076511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ireq.ifr_ifrn.ifrn_name, device,
5077511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    sizeof ireq.ifr_ifrn.ifrn_name);
5078511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5079511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) {
5080511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5081511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We probably won't be able to set the mode, either.
5082511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5083511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_RFMON_NOTSUP;
5084511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5085511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5086511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5087511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Is it currently in monitor mode?
5088511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5089511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ireq.u.mode == IW_MODE_MONITOR) {
5090511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5091511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Yes.  Just leave things as they are.
5092511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We don't offer multiple link-layer types, as
5093511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * changing the link-layer type out from under
5094511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * somebody else capturing in monitor mode would
5095511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * be considered rude.
5096511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5097511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;
5098511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5099511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5100511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * No.  We have to put the adapter into rfmon mode.
5101511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5102511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5103511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5104511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * If we haven't already done so, arrange to have
5105511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "pcap_close_all()" called when we exit.
5106511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5107511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (!pcap_do_addexit(handle)) {
5108511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5109511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * "atexit()" failed; don't put the interface
5110511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in rfmon mode, just give up.
5111511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5112511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_RFMON_NOTSUP;
5113511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5114511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5115511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5116511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Save the old mode.
5117511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5118511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->oldmode = ireq.u.mode;
5119511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5120511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5121511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Put the adapter in rfmon mode.  How we do this depends
5122511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * on whether we have a special private ioctl or not.
5123511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5124511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (montype == MONITOR_PRISM) {
5125511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5126511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We have the "monitor" private ioctl, but none of
5127511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the other private ioctls.  Use this, and select
5128511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the Prism header.
5129511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5130511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * If it fails, just fall back on SIOCSIWMODE.
5131511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5132511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5133511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5134511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5135511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5136511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.u.data.length = 1;	/* 1 argument */
5137511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 3;	/* request Prism header */
5138aa5c5f3dbf05e6ceb406a8cb52b4da481fcaa1fdJP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5139511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, cmd, &ireq) != -1) {
5140478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5141511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Success.
5142511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Note that we have to put the old mode back
5143511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * when we close the device.
5144478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5145511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->must_do_on_close |= MUST_CLEAR_RFMON;
5146478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5147478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5148511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Add this to the list of pcaps to close
5149511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * when we exit.
5150478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5151511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_add_to_pcaps_to_close(handle);
5152511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5153511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 1;
5154478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5155478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5156478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5157511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Failure.  Fall back on SIOCSIWMODE.
5158511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5159511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5160511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5161511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5162511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * First, take the interface down if it's up; otherwise, we
5163511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * might get EBUSY.
5164511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5165511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	memset(&ifr, 0, sizeof(ifr));
5166511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
5167511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) {
5168511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5169511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: Can't get flags: %s", device, strerror(errno));
5170511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5171511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5172511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	oldflags = 0;
5173511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ifr.ifr_flags & IFF_UP) {
5174511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		oldflags = ifr.ifr_flags;
5175511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ifr.ifr_flags &= ~IFF_UP;
5176511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
5177511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5178511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: Can't set flags: %s", device, strerror(errno));
5179511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5180511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5181511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5182511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5183511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5184511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Then turn monitor mode on.
5185511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5186511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ireq.ifr_ifrn.ifrn_name, device,
5187511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    sizeof ireq.ifr_ifrn.ifrn_name);
5188511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5189511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ireq.u.mode = IW_MODE_MONITOR;
5190511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) {
5191511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5192511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Scientist, you've failed.
5193511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Bring the interface back up if we shut it down.
5194511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5195511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ifr.ifr_flags = oldflags;
5196511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
5197511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5198511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: Can't set flags: %s", device, strerror(errno));
5199511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5200511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5201511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR_RFMON_NOTSUP;
5202511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5203511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5204511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5205511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - airmon-ng does "iwconfig {if} key off" after setting
5206511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * monitor mode and setting the channel, and then does
5207511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * "iwconfig up".
5208511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5209511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5210511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5211511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Now select the appropriate radio header.
5212511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5213511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	switch (montype) {
5214511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5215511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_WEXT:
5216511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5217511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We don't have any private ioctl to set the header.
5218478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5219511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5220478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5221511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_HOSTAP:
5222478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5223511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Try to select the radiotap header.
5224478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5225511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5226511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5227511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5228511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5229511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 3;	/* request radiotap header */
5230511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5231511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, cmd, &ireq) != -1)
5232511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;	/* success */
5233478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5234511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5235511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * That failed.  Try to select the AVS header.
5236511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5237511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5238511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5239511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5240511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5241511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 2;	/* request AVS header */
5242511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5243511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, cmd, &ireq) != -1)
5244511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			break;	/* success */
5245511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5246511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5247511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * That failed.  Try to select the Prism header.
5248511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5249511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5250511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5251511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5252511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5253511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 1;	/* request Prism header */
5254511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5255511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5256511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5257511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5258511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_PRISM:
5259511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5260511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The private ioctl failed.
5261511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5262511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5263511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5264511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_PRISM54:
5265511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5266511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Select the Prism header.
5267511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5268511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5269511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5270511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5271511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5272511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 3;	/* request Prism header */
5273511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5274511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5275511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5276511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5277511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_ACX100:
5278511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5279511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Get the current channel.
5280511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5281511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5282511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5283511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5284511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5285511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) {
5286511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5287511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: SIOCGIWFREQ: %s", device,
5288511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    pcap_strerror(errno));
5289511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5290511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5291511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		channel = ireq.u.freq.m;
5292511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5293511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5294511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Select the Prism header, and set the channel to the
5295511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * current value.
5296511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5297511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5298511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5299511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5300511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5301511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 1;		/* request Prism header */
5302511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[1] = channel;	/* set channel */
5303511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, 2*sizeof (int));
5304511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5305511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5306511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5307511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_RT2500:
5308511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5309511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Disallow transmission - that turns on the
5310511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Prism header.
5311511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5312511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5313511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5314511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5315511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5316511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 0;	/* disallow transmitting */
5317511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5318511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5319511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5320511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5321511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_RT2570:
5322511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5323511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Force the Prism header.
5324511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5325511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5326511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5327511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5328511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5329511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 1;	/* request Prism header */
5330511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5331511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5332511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5333511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5334511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_RT73:
5335511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5336511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Force the Prism header.
5337511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5338511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5339511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5340511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5341511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5342511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.u.data.length = 1;	/* 1 argument */
5343511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.u.data.pointer = "1";
5344511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.u.data.flags = 0;
5345511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5346511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5347511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5348511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	case MONITOR_RTL8XXX:
5349511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5350511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Force the Prism header.
5351511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5352511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ireq, 0, sizeof ireq);
5353511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ireq.ifr_ifrn.ifrn_name, device,
5354511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    sizeof ireq.ifr_ifrn.ifrn_name);
5355511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ireq.ifr_ifrn.ifrn_name[sizeof ireq.ifr_ifrn.ifrn_name - 1] = 0;
5356511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		args[0] = 1;	/* request Prism header */
5357511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memcpy(ireq.u.name, args, sizeof (int));
5358511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ioctl(sock_fd, cmd, &ireq);
5359511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		break;
5360511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5361511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5362511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5363511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Now bring the interface back up if we brought it down.
5364511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5365511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (oldflags != 0) {
5366511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		ifr.ifr_flags = oldflags;
5367511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) {
5368511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5369511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			    "%s: Can't set flags: %s", device, strerror(errno));
5370511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5371511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5372511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * At least try to restore the old mode on the
5373511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * interface.
5374511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5375511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) {
5376511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				/*
5377511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * Scientist, you've failed.
5378511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 */
5379511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				fprintf(stderr,
5380511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n"
5381511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    "Please adjust manually.\n",
5382511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				    strerror(errno));
5383478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
5384511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5385478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5386511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5387478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5388511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5389511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Note that we have to put the old mode back when we
5390511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * close the device.
5391511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5392511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->must_do_on_close |= MUST_CLEAR_RFMON;
5393478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5394511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5395511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Add this to the list of pcaps to close when we exit.
5396511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5397511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	pcap_add_to_pcaps_to_close(handle);
5398478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5399511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
5400511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall}
5401511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* IW_MODE_MONITOR */
5402478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5403511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/*
5404511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Try various mechanisms to enter monitor mode.
5405511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall */
5406511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
5407511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallenter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device)
5408511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall{
5409511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR)
5410511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
5411511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5412478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5413511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef HAVE_LIBNL
5414511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = enter_rfmon_mode_mac80211(handle, sock_fd, device);
5415511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
5416511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;	/* error attempting to do so */
5417511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 1)
5418511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* success */
5419511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_LIBNL */
5420511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5421511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef IW_MODE_MONITOR
5422511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = enter_rfmon_mode_wext(handle, sock_fd, device);
5423511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret < 0)
5424511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return ret;	/* error attempting to do so */
5425511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == 1)
5426511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* success */
5427511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* IW_MODE_MONITOR */
5428478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5429511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5430511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Either none of the mechanisms we know about work or none
5431511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * of those mechanisms are available, so we can't do monitor
5432511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * mode.
5433511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5434478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
5435478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5436478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5437478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5438511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Find out if we have any form of fragmentation/reassembly offloading.
5439511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall *
5440511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * We do so using SIOCETHTOOL checking for various types of offloading;
5441511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * if SIOCETHTOOL isn't defined, or we don't have any #defines for any
5442511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * of the types of offloading, there's nothing we can do to check, so
5443511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * we just say "no, we don't".
5444478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5445511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO))
5446478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5447511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralliface_ethtool_ioctl(pcap_t *handle, int cmd, const char *cmdname)
5448478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5449478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct ifreq	ifr;
5450511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct ethtool_value eval;
5451478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5452478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
5453511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	strncpy(ifr.ifr_name, handle->opt.source, sizeof(ifr.ifr_name));
5454511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	eval.cmd = cmd;
5455511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	eval.data = 0;
5456511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ifr.ifr_data = (caddr_t)&eval;
5457511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) {
5458511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EOPNOTSUPP || errno == EINVAL) {
5459511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5460511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * OK, let's just return 0, which, in our
5461511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * case, either means "no, what we're asking
5462511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * about is not enabled" or "all the flags
5463511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * are clear (i.e., nothing is enabled)".
5464511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5465511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return 0;
5466511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5467511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5468511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    "%s: SIOETHTOOL(%s) ioctl failed: %s", handle->opt.source,
5469511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		    cmdname, strerror(errno));
5470478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5471478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5472511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return eval.data;
5473478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5474478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5475478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5476511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralliface_get_offload(pcap_t *handle)
5477478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5478511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int ret;
5479478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5480511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ETHTOOL_GTSO
5481511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = iface_ethtool_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO");
5482511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
5483511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
5484511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret)
5485511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* TCP segmentation offloading on */
5486511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5487478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5488511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ETHTOOL_GUFO
5489511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = iface_ethtool_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO");
5490511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
5491478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5492511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret)
5493511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* UDP fragmentation offloading on */
5494511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5495478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5496511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ETHTOOL_GGSO
5497511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5498511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - will this cause large unsegmented packets to be
5499511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handed to PF_PACKET sockets on transmission?  If not,
5500511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * this need not be checked.
5501511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5502511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = iface_ethtool_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO");
5503511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
5504511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
5505511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret)
5506511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* generic segmentation offloading on */
5507511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5508478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5509511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ETHTOOL_GFLAGS
5510511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = iface_ethtool_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS");
5511511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
5512511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
5513511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret & ETH_FLAG_LRO)
5514511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* large receive offloading on */
5515511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5516478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5517511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#ifdef ETHTOOL_GGRO
5518511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5519511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - will this cause large reassembled packets to be
5520511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * handed to PF_PACKET sockets on receipt?  If not,
5521511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * this need not be checked.
5522511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5523511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	ret = iface_ethtool_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO");
5524511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret == -1)
5525511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return -1;
5526511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (ret)
5527511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return 1;	/* generic (large) receive offloading on */
5528511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif
5529478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5530478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
5531478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5532511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#else /* SIOCETHTOOL */
5533511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallstatic int
5534511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgralliface_get_offload(pcap_t *handle _U_)
5535478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5536511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5537511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * XXX - do we need to get this information if we don't
5538511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * have the ethtool ioctls?  If so, how do we do that?
5539511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5540511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 0;
5541478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5542511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* SIOCETHTOOL */
5543478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5544511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall#endif /* HAVE_PF_PACKET_SOCKETS */
5545478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5546511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall/* ===== Functions to interface to the older kernels ================== */
5547478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5548478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5549511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Try to open a packet socket using the old kernel interface.
5550511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall * Returns 1 on success and a PCAP_ERROR_ value on an error.
5551478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5552478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5553511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallactivate_old(pcap_t *handle)
5554478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5555511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
5556478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int		arptype;
5557478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct ifreq	ifr;
5558511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	const char	*device = handle->opt.source;
5559511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct utsname	utsname;
5560511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	int		mtu;
5561478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5562511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Open the socket */
5563478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5564511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL));
5565511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->fd == -1) {
5566511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5567511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "socket: %s", pcap_strerror(errno));
5568511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == EPERM || errno == EACCES) {
5569511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5570511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * You don't have permission to open the
5571511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * socket.
5572511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5573511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_PERM_DENIED;
5574511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		} else {
5575511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5576511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Other error.
5577511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5578511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5579478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5580511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5581478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5582511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* It worked - we are using the old interface */
5583511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->sock_packet = 1;
5584478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5585511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* ...which means we get the link-layer header. */
5586511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->cooked = 0;
5587478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5588511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Bind to the given device */
5589478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5590511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (strcmp(device, "any") == 0) {
5591511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems",
5592511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			PCAP_ERRBUF_SIZE);
5593511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5594511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5595511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (iface_bind_old(handle->fd, device, handle->errbuf) == -1)
5596511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5597478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5598511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5599511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Try to get the link-layer type.
5600511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5601511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	arptype = iface_get_arptype(handle->fd, device, handle->errbuf);
5602511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (arptype < 0)
5603511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5604478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5605511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5606511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Try to find the DLT_ type corresponding to that
5607511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * link-layer type.
5608511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5609511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	map_arphrd_to_dlt(handle, arptype, 0);
5610511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->linktype == -1) {
5611511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5612511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 "unknown arptype %d", arptype);
5613511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5614511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5615478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5616511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/* Go to promisc mode if requested */
5617478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5618511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (handle->opt.promisc) {
5619511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		memset(&ifr, 0, sizeof(ifr));
5620511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
5621511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) {
5622511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5623511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 "SIOCGIFFLAGS: %s", pcap_strerror(errno));
5624511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5625511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5626511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if ((ifr.ifr_flags & IFF_PROMISC) == 0) {
5627511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5628511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Promiscuous mode isn't currently on,
5629511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * so turn it on, and remember that
5630511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we should turn it off when the
5631511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * pcap_t is closed.
5632511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5633478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5634511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5635511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * If we haven't already done so, arrange
5636511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * to have "pcap_close_all()" called when
5637511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * we exit.
5638511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5639511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (!pcap_do_addexit(handle)) {
5640478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/*
5641511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * "atexit()" failed; don't put
5642511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * the interface in promiscuous
5643511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * mode, just give up.
5644478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 */
5645511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR;
5646511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			}
5647478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5648511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			ifr.ifr_flags |= IFF_PROMISC;
5649511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) {
5650511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			        snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5651511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 "SIOCSIFFLAGS: %s",
5652511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 pcap_strerror(errno));
5653511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				return PCAP_ERROR;
5654478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
5655511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handlep->must_do_on_close |= MUST_CLEAR_PROMISC;
5656511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall
5657511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5658511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * Add this to the list of pcaps
5659511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * to close when we exit.
5660511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5661511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			pcap_add_to_pcaps_to_close(handle);
5662478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5663511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5664478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5665511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5666511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Compute the buffer size.
5667511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 *
5668511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * We're using SOCK_PACKET, so this might be a 2.0[.x]
5669511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * kernel, and might require special handling - check.
5670511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5671511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	if (uname(&utsname) < 0 ||
5672511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	    strncmp(utsname.release, "2.0", 3) == 0) {
5673511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5674511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * Either we couldn't find out what kernel release
5675511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * this is, or it's a 2.0[.x] kernel.
5676511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5677511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * In the 2.0[.x] kernel, a "recvfrom()" on
5678511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * a SOCK_PACKET socket, with MSG_TRUNC set, will
5679511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * return the number of bytes read, so if we pass
5680511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * a length based on the snapshot length, it'll
5681511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * return the number of bytes from the packet
5682511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * copied to userland, not the actual length
5683511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of the packet.
5684511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5685511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This means that, for example, the IP dissector
5686511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * in tcpdump will get handed a packet length less
5687511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * than the length in the IP header, and will
5688511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * complain about "truncated-ip".
5689511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5690511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * So we don't bother trying to copy from the
5691511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * kernel only the bytes in which we're interested,
5692511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * but instead copy them all, just as the older
5693511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * versions of libpcap for Linux did.
5694511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5695511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * The buffer therefore needs to be big enough to
5696511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * hold the largest packet we can get from this
5697511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * device.  Unfortunately, we can't get the MRU
5698511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * of the network; we can only get the MTU.  The
5699511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * MTU may be too small, in which case a packet larger
5700511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * than the buffer size will be truncated *and* we
5701511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * won't get the actual packet size.
5702511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5703511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * However, if the snapshot length is larger than
5704511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * the buffer size based on the MTU, we use the
5705511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * snapshot length as the buffer size, instead;
5706511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * this means that with a sufficiently large snapshot
5707511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * length we won't artificially truncate packets
5708511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * to the MTU-based size.
5709511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5710511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This mess just one of many problems with packet
5711511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * capture on 2.0[.x] kernels; you really want a
5712511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * 2.2[.x] or later kernel if you want packet capture
5713511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * to work well.
5714511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5715511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		mtu = iface_get_mtu(handle->fd, device, handle->errbuf);
5716511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (mtu == -1)
5717511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR;
5718511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->bufsize = MAX_LINKHEADER_SIZE + mtu;
5719511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (handle->bufsize < handle->snapshot)
5720511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			handle->bufsize = handle->snapshot;
5721511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else {
5722478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5723511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * This is a 2.2[.x] or later kernel.
5724511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 *
5725511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * We can safely pass "recvfrom()" a byte count
5726511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * based on the snapshot length.
5727478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5728511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		handle->bufsize = handle->snapshot;
5729511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	}
5730478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5731511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5732511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * Default value for offset to align link-layer payload
5733511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * on a 4-byte boundary.
5734511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5735511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handle->offset	 = 0;
5736478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5737511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	/*
5738511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * SOCK_PACKET sockets don't supply information from
5739511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 * stripped VLAN tags.
5740511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	 */
5741511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	handlep->vlan_offset = -1; /* unknown */
5742478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5743511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	return 1;
5744478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5745478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5746478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5747478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  Bind the socket associated with FD to the given device using the
5748478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  interface of the old kernels.
5749478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5750478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5751478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectiface_bind_old(int fd, const char *device, char *ebuf)
5752478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5753478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct sockaddr	saddr;
5754478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int		err;
5755478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	socklen_t	errlen = sizeof(err);
5756478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5757478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&saddr, 0, sizeof(saddr));
5758478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	strncpy(saddr.sa_data, device, sizeof(saddr.sa_data));
5759478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (bind(fd, &saddr, sizeof(saddr)) == -1) {
5760478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(ebuf, PCAP_ERRBUF_SIZE,
5761478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 "bind: %s", pcap_strerror(errno));
5762478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5763478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5764478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5765478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/* Any pending errors, e.g., network is down? */
5766478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5767478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) {
5768478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(ebuf, PCAP_ERRBUF_SIZE,
5769478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			"getsockopt: %s", pcap_strerror(errno));
5770478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5771478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5772478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5773478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (err > 0) {
5774478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(ebuf, PCAP_ERRBUF_SIZE,
5775478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			"bind: %s", pcap_strerror(err));
5776478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5777478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5778478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5779478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
5780478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5781478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5782478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5783478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/* ===== System calls available on all supported kernels ============== */
5784478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5785478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5786478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  Query the kernel for the MTU of the given interface.
5787478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5788478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5789478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectiface_get_mtu(int fd, const char *device, char *ebuf)
5790478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5791478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct ifreq	ifr;
5792478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5793478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (!device)
5794478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return BIGGER_THAN_ALL_MTUS;
5795478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5796478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
5797478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
5798478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5799478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) {
5800478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(ebuf, PCAP_ERRBUF_SIZE,
5801478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 "SIOCGIFMTU: %s", pcap_strerror(errno));
5802478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5803478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5804478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5805478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return ifr.ifr_mtu;
5806478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5807478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5808478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project/*
5809478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project *  Get the hardware type of the given interface as ARPHRD_xxx constant.
5810478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project */
5811478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5812478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectiface_get_arptype(int fd, const char *device, char *ebuf)
5813478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5814478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct ifreq	ifr;
5815478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5816478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memset(&ifr, 0, sizeof(ifr));
5817478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name));
5818478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5819478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) {
5820478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		snprintf(ebuf, PCAP_ERRBUF_SIZE,
5821478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 "SIOCGIFHWADDR: %s", pcap_strerror(errno));
5822511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		if (errno == ENODEV) {
5823511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			/*
5824511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * No such device.
5825511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 */
5826511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			return PCAP_ERROR_NO_SUCH_DEVICE;
5827511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		}
5828511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		return PCAP_ERROR;
5829478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5830478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5831478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return ifr.ifr_hwaddr.sa_family;
5832478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5833478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5834478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#ifdef SO_ATTACH_FILTER
5835478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5836511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrallfix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped)
5837478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5838511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	struct pcap_linux *handlep = handle->priv;
5839478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	size_t prog_size;
5840478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register int i;
5841478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	register struct bpf_insn *p;
5842478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	struct bpf_insn *f;
5843478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int len;
5844478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5845478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5846478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Make a copy of the filter, and modify that copy if
5847478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * necessary.
5848478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5849478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len;
5850478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	len = handle->fcode.bf_len;
5851478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	f = (struct bpf_insn *)malloc(prog_size);
5852478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (f == NULL) {
5853511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
5854478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 "malloc: %s", pcap_strerror(errno));
5855478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5856478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5857478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	memcpy(f, handle->fcode.bf_insns, prog_size);
5858478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fcode->len = len;
5859478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	fcode->filter = (struct sock_filter *) f;
5860478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5861478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	for (i = 0; i < len; ++i) {
5862478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p = &f[i];
5863478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5864478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * What type of instruction is this?
5865478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5866478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		switch (BPF_CLASS(p->code)) {
5867478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5868478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_RET:
5869478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5870511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * It's a return instruction; are we capturing
5871511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			 * in memory-mapped mode?
5872478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5873511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall			if (!is_mmapped) {
5874478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/*
5875511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * No; is the snapshot length a constant,
5876511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * rather than the contents of the
5877511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				 * accumulator?
5878478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 */
5879511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (BPF_MODE(p->code) == BPF_K) {
5880511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					/*
5881511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * Yes - if the value to be returned,
5882511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * i.e. the snapshot length, is
5883511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * anything other than 0, make it
5884511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * 65535, so that the packet is
5885511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * truncated by "recvfrom()",
5886511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * not by the filter.
5887511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 *
5888511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * XXX - there's nothing we can
5889511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * easily do if it's getting the
5890511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * value from the accumulator; we'd
5891511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * have to insert code to force
5892511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 * non-zero values to be 65535.
5893511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					 */
5894511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall					if (p->k != 0)
5895511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall						p->k = 65535;
5896511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				}
5897478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
5898478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
5899478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5900478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LD:
5901478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		case BPF_LDX:
5902478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			/*
5903478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * It's a load instruction; is it loading
5904478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 * from the packet?
5905478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 */
5906478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			switch (BPF_MODE(p->code)) {
5907478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5908478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case BPF_ABS:
5909478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case BPF_IND:
5910478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			case BPF_MSH:
5911478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/*
5912478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 * Yes; are we in cooked mode?
5913478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 */
5914511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				if (handlep->cooked) {
5915478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					/*
5916478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					 * Yes, so we need to fix this
5917478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					 * instruction.
5918478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					 */
5919478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					if (fix_offset(p) < 0) {
5920478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						/*
5921478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						 * We failed to do so.
5922478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						 * Return 0, so our caller
5923478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						 * knows to punt to userland.
5924478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						 */
5925478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project						return 0;
5926478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project					}
5927478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				}
5928478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				break;
5929478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
5930478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			break;
5931478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
5932478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5933478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 1;	/* we succeeded */
5934478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5935478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5936478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5937478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectfix_offset(struct bpf_insn *p)
5938478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5939478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5940478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * What's the offset?
5941478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
5942478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (p->k >= SLL_HDR_LEN) {
5943478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5944478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * It's within the link-layer payload; that starts at an
5945478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * offset of 0, as far as the kernel packet filter is
5946478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * concerned, so subtract the length of the link-layer
5947478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * header.
5948478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5949478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p->k -= SLL_HDR_LEN;
5950511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else if (p->k == 0) {
5951511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		/*
5952511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * It's the packet type field; map it to the special magic
5953511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 * kernel offset for that field.
5954511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		 */
5955511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall		p->k = SKF_AD_OFF + SKF_AD_PKTTYPE;
5956478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	} else if (p->k == 14) {
5957478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5958478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * It's the protocol field; map it to the special magic
5959478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * kernel offset for that field.
5960478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5961478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		p->k = SKF_AD_OFF + SKF_AD_PROTOCOL;
5962511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall	} else if ((bpf_int32)(p->k) > 0) {
5963478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
5964478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * It's within the header, but it's not one of those
5965478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * fields; we can't do that in the kernel, so punt
5966478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * to userland.
5967478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
5968478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		return -1;
5969478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
5970478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return 0;
5971478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
5972478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5973478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
5974478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectset_kernel_filter(pcap_t *handle, struct sock_fprog *fcode)
5975478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
5976478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int total_filter_on = 0;
5977478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int save_mode;
5978478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int ret;
5979478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int save_errno;
5980478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
5981478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
5982478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * The socket filter code doesn't discard all packets queued
5983478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * up on the socket when the filter is changed; this means
5984478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * that packets that don't match the new filter may show up
5985478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * after the new filter is put onto the socket, if those
5986478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * packets haven't yet been read.
5987478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5988478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * This means, for example, that if you do a tcpdump capture
5989478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * with a filter, the first few packets in the capture might
5990478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * be packets that wouldn't have passed the filter.
5991478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5992478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * We therefore discard all packets queued up on the socket
5993478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * when setting a kernel filter.  (This isn't an issue for
5994478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * userland filters, as the userland filtering is done after
5995478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * packets are queued up.)
5996478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
5997478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * To flush those packets, we put the socket in read-only mode,
5998478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * and read packets from the socket until there are no more to
5999478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * read.
6000478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
6001478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * In order to keep that from being an infinite loop - i.e.,
6002478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * to keep more packets from arriving while we're draining
6003478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * the queue - we put the "total filter", which is a filter
6004478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * that rejects all packets, onto the socket before draining
6005478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * the queue.
6006478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 *
6007478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * This code deliberately ignores any errors, so that you may
6008478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * get bogus packets if an error occurs, rather than having
6009478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * the filtering done in userland even if it could have been
6010478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * done in the kernel.
6011478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
6012478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
6013478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		       &total_fcode, sizeof(total_fcode)) == 0) {
6014478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		char drain[1];
6015478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6016478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6017478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Note that we've put the total filter onto the socket.
6018478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6019478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		total_filter_on = 1;
6020478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6021478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6022478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Save the socket's current mode, and put it in
6023478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * non-blocking mode; we drain it by reading packets
6024478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * until we get an error (which is normally a
6025478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * "nothing more to be read" error).
6026478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6027478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		save_mode = fcntl(handle->fd, F_GETFL, 0);
6028478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		if (save_mode != -1 &&
6029478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		    fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) >= 0) {
6030478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			while (recv(handle->fd, &drain, sizeof drain,
6031478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			       MSG_TRUNC) >= 0)
6032478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				;
6033478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			save_errno = errno;
6034478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			fcntl(handle->fd, F_SETFL, save_mode);
6035478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			if (save_errno != EAGAIN) {
6036478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				/* Fatal error */
6037478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				reset_kernel_filter(handle);
6038511eca30a483e912c274e1d8ba3a0f8f081e2227JP Abgrall				snprintf(handle->errbuf, PCAP_ERRBUF_SIZE,
6039478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				 "recv: %s", pcap_strerror(save_errno));
6040478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				return -2;
6041478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			}
6042478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		}
6043478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6044478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6045478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
6046478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * Now attach the new filter.
6047478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
6048478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER,
6049478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project			 fcode, sizeof(*fcode));
6050478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	if (ret == -1 && total_filter_on) {
6051478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6052478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * Well, we couldn't set that filter on the socket,
6053478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * but we could set the total filter on the socket.
6054478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 *
6055478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * This could, for example, mean that the filter was
6056478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * too big to put into the kernel, so we'll have to
6057478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * filter in userland; in any case, we'll be doing
6058478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * filtering in userland, so we need to remove the
6059478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * total filter so we see packets.
6060478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6061478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		save_errno = errno;
6062478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6063478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		/*
6064478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * XXX - if this fails, we're really screwed;
6065478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * we have the total filter on the socket,
6066478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 * and it won't come off.  What do we do then?
6067478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		 */
6068478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		reset_kernel_filter(handle);
6069478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6070478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project		errno = save_errno;
6071478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	}
6072478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return ret;
6073478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6074478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6075478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectstatic int
6076478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Projectreset_kernel_filter(pcap_t *handle)
6077478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project{
6078478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	/*
6079478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * setsockopt() barfs unless it get a dummy parameter.
6080478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * valgrind whines unless the value is initialized,
6081478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * as it has no idea that setsockopt() ignores its
6082478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 * parameter.
6083478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	 */
6084478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	int dummy = 0;
6085478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project
6086478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project	return setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER,
6087478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project				   &dummy, sizeof(dummy));
6088478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project}
6089478ab6c8b5bc982589be32eae1e5736efe721b58The Android Open Source Project#endif
6090