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 *)×ource, 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