1335640Shselasky/* 2335640Shselasky * pcap-linux.c: Packet capture interface to the Linux kernel 3335640Shselasky * 4335640Shselasky * Copyright (c) 2000 Torsten Landschoff <torsten@debian.org> 5335640Shselasky * Sebastian Krahmer <krahmer@cs.uni-potsdam.de> 6335640Shselasky * 7335640Shselasky * License: BSD 8335640Shselasky * 9335640Shselasky * Redistribution and use in source and binary forms, with or without 10335640Shselasky * modification, are permitted provided that the following conditions 11335640Shselasky * are met: 12335640Shselasky * 13335640Shselasky * 1. Redistributions of source code must retain the above copyright 14335640Shselasky * notice, this list of conditions and the following disclaimer. 15335640Shselasky * 2. Redistributions in binary form must reproduce the above copyright 16335640Shselasky * notice, this list of conditions and the following disclaimer in 17335640Shselasky * the documentation and/or other materials provided with the 18335640Shselasky * distribution. 19335640Shselasky * 3. The names of the authors may not be used to endorse or promote 20335640Shselasky * products derived from this software without specific prior 21335640Shselasky * written permission. 22335640Shselasky * 23335640Shselasky * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 24335640Shselasky * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 25335640Shselasky * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 26335640Shselasky * 27335640Shselasky * Modifications: Added PACKET_MMAP support 28335640Shselasky * Paolo Abeni <paolo.abeni@email.it> 29335640Shselasky * Added TPACKET_V3 support 30335640Shselasky * Gabor Tatarka <gabor.tatarka@ericsson.com> 31335640Shselasky * 32335640Shselasky * based on previous works of: 33335640Shselasky * Simon Patarin <patarin@cs.unibo.it> 34335640Shselasky * Phil Wood <cpw@lanl.gov> 35335640Shselasky * 36335640Shselasky * Monitor-mode support for mac80211 includes code taken from the iw 37335640Shselasky * command; the copyright notice for that code is 38335640Shselasky * 39335640Shselasky * Copyright (c) 2007, 2008 Johannes Berg 40335640Shselasky * Copyright (c) 2007 Andy Lutomirski 41335640Shselasky * Copyright (c) 2007 Mike Kershaw 42335640Shselasky * Copyright (c) 2008 G��bor Stefanik 43335640Shselasky * 44335640Shselasky * All rights reserved. 45335640Shselasky * 46335640Shselasky * Redistribution and use in source and binary forms, with or without 47335640Shselasky * modification, are permitted provided that the following conditions 48335640Shselasky * are met: 49335640Shselasky * 1. Redistributions of source code must retain the above copyright 50335640Shselasky * notice, this list of conditions and the following disclaimer. 51335640Shselasky * 2. Redistributions in binary form must reproduce the above copyright 52335640Shselasky * notice, this list of conditions and the following disclaimer in the 53335640Shselasky * documentation and/or other materials provided with the distribution. 54335640Shselasky * 3. The name of the author may not be used to endorse or promote products 55335640Shselasky * derived from this software without specific prior written permission. 56335640Shselasky * 57335640Shselasky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 58335640Shselasky * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 59335640Shselasky * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 60335640Shselasky * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 61335640Shselasky * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 62335640Shselasky * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 63335640Shselasky * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 64335640Shselasky * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 65335640Shselasky * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 66335640Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 67335640Shselasky * SUCH DAMAGE. 68335640Shselasky */ 69335640Shselasky 70335640Shselasky/* 71335640Shselasky * Known problems with 2.0[.x] kernels: 72335640Shselasky * 73335640Shselasky * - The loopback device gives every packet twice; on 2.2[.x] kernels, 74335640Shselasky * if we use PF_PACKET, we can filter out the transmitted version 75335640Shselasky * of the packet by using data in the "sockaddr_ll" returned by 76335640Shselasky * "recvfrom()", but, on 2.0[.x] kernels, we have to use 77335640Shselasky * PF_INET/SOCK_PACKET, which means "recvfrom()" supplies a 78335640Shselasky * "sockaddr_pkt" which doesn't give us enough information to let 79335640Shselasky * us do that. 80335640Shselasky * 81335640Shselasky * - We have to set the interface's IFF_PROMISC flag ourselves, if 82335640Shselasky * we're to run in promiscuous mode, which means we have to turn 83335640Shselasky * it off ourselves when we're done; the kernel doesn't keep track 84335640Shselasky * of how many sockets are listening promiscuously, which means 85335640Shselasky * it won't get turned off automatically when no sockets are 86335640Shselasky * listening promiscuously. We catch "pcap_close()" and, for 87335640Shselasky * interfaces we put into promiscuous mode, take them out of 88335640Shselasky * promiscuous mode - which isn't necessarily the right thing to 89335640Shselasky * do, if another socket also requested promiscuous mode between 90335640Shselasky * the time when we opened the socket and the time when we close 91335640Shselasky * the socket. 92335640Shselasky * 93335640Shselasky * - MSG_TRUNC isn't supported, so you can't specify that "recvfrom()" 94335640Shselasky * return the amount of data that you could have read, rather than 95335640Shselasky * the amount that was returned, so we can't just allocate a buffer 96335640Shselasky * whose size is the snapshot length and pass the snapshot length 97335640Shselasky * as the byte count, and also pass MSG_TRUNC, so that the return 98335640Shselasky * value tells us how long the packet was on the wire. 99335640Shselasky * 100335640Shselasky * This means that, if we want to get the actual size of the packet, 101335640Shselasky * so we can return it in the "len" field of the packet header, 102335640Shselasky * we have to read the entire packet, not just the part that fits 103335640Shselasky * within the snapshot length, and thus waste CPU time copying data 104335640Shselasky * from the kernel that our caller won't see. 105335640Shselasky * 106335640Shselasky * We have to get the actual size, and supply it in "len", because 107335640Shselasky * otherwise, the IP dissector in tcpdump, for example, will complain 108335640Shselasky * about "truncated-ip", as the packet will appear to have been 109335640Shselasky * shorter, on the wire, than the IP header said it should have been. 110335640Shselasky */ 111335640Shselasky 112335640Shselasky 113335640Shselasky#define _GNU_SOURCE 114335640Shselasky 115335640Shselasky#ifdef HAVE_CONFIG_H 116335640Shselasky#include <config.h> 117335640Shselasky#endif 118335640Shselasky 119335640Shselasky#include <errno.h> 120335640Shselasky#include <stdio.h> 121335640Shselasky#include <stdlib.h> 122335640Shselasky#include <ctype.h> 123335640Shselasky#include <unistd.h> 124335640Shselasky#include <fcntl.h> 125335640Shselasky#include <string.h> 126335640Shselasky#include <limits.h> 127335640Shselasky#include <sys/stat.h> 128335640Shselasky#include <sys/socket.h> 129335640Shselasky#include <sys/ioctl.h> 130335640Shselasky#include <sys/utsname.h> 131335640Shselasky#include <sys/mman.h> 132335640Shselasky#include <linux/if.h> 133335640Shselasky#include <linux/if_packet.h> 134335640Shselasky#include <linux/sockios.h> 135335640Shselasky#include <netinet/in.h> 136335640Shselasky#include <linux/if_ether.h> 137335640Shselasky#include <net/if_arp.h> 138335640Shselasky#include <poll.h> 139335640Shselasky#include <dirent.h> 140335640Shselasky 141335640Shselasky#include "pcap-int.h" 142335640Shselasky#include "pcap/sll.h" 143335640Shselasky#include "pcap/vlan.h" 144335640Shselasky 145335640Shselasky/* 146335640Shselasky * If PF_PACKET is defined, we can use {SOCK_RAW,SOCK_DGRAM}/PF_PACKET 147335640Shselasky * sockets rather than SOCK_PACKET sockets. 148335640Shselasky * 149335640Shselasky * To use them, we include <linux/if_packet.h> rather than 150335640Shselasky * <netpacket/packet.h>; we do so because 151335640Shselasky * 152335640Shselasky * some Linux distributions (e.g., Slackware 4.0) have 2.2 or 153335640Shselasky * later kernels and libc5, and don't provide a <netpacket/packet.h> 154335640Shselasky * file; 155335640Shselasky * 156335640Shselasky * not all versions of glibc2 have a <netpacket/packet.h> file 157335640Shselasky * that defines stuff needed for some of the 2.4-or-later-kernel 158335640Shselasky * features, so if the system has a 2.4 or later kernel, we 159335640Shselasky * still can't use those features. 160335640Shselasky * 161335640Shselasky * We're already including a number of other <linux/XXX.h> headers, and 162335640Shselasky * this code is Linux-specific (no other OS has PF_PACKET sockets as 163335640Shselasky * a raw packet capture mechanism), so it's not as if you gain any 164335640Shselasky * useful portability by using <netpacket/packet.h> 165335640Shselasky * 166335640Shselasky * XXX - should we just include <linux/if_packet.h> even if PF_PACKET 167335640Shselasky * isn't defined? It only defines one data structure in 2.0.x, so 168335640Shselasky * it shouldn't cause any problems. 169335640Shselasky */ 170335640Shselasky#ifdef PF_PACKET 171335640Shselasky# include <linux/if_packet.h> 172335640Shselasky 173335640Shselasky /* 174335640Shselasky * On at least some Linux distributions (for example, Red Hat 5.2), 175335640Shselasky * there's no <netpacket/packet.h> file, but PF_PACKET is defined if 176335640Shselasky * you include <sys/socket.h>, but <linux/if_packet.h> doesn't define 177335640Shselasky * any of the PF_PACKET stuff such as "struct sockaddr_ll" or any of 178335640Shselasky * the PACKET_xxx stuff. 179335640Shselasky * 180335640Shselasky * So we check whether PACKET_HOST is defined, and assume that we have 181335640Shselasky * PF_PACKET sockets only if it is defined. 182335640Shselasky */ 183335640Shselasky# ifdef PACKET_HOST 184335640Shselasky# define HAVE_PF_PACKET_SOCKETS 185335640Shselasky# ifdef PACKET_AUXDATA 186335640Shselasky# define HAVE_PACKET_AUXDATA 187335640Shselasky# endif /* PACKET_AUXDATA */ 188335640Shselasky# endif /* PACKET_HOST */ 189335640Shselasky 190335640Shselasky 191335640Shselasky /* check for memory mapped access avaibility. We assume every needed 192335640Shselasky * struct is defined if the macro TPACKET_HDRLEN is defined, because it 193335640Shselasky * uses many ring related structs and macros */ 194335640Shselasky# ifdef PCAP_SUPPORT_PACKET_RING 195335640Shselasky# ifdef TPACKET_HDRLEN 196335640Shselasky# define HAVE_PACKET_RING 197335640Shselasky# ifdef TPACKET3_HDRLEN 198335640Shselasky# define HAVE_TPACKET3 199335640Shselasky# endif /* TPACKET3_HDRLEN */ 200335640Shselasky# ifdef TPACKET2_HDRLEN 201335640Shselasky# define HAVE_TPACKET2 202335640Shselasky# else /* TPACKET2_HDRLEN */ 203335640Shselasky# define TPACKET_V1 0 /* Old kernel with only V1, so no TPACKET_Vn defined */ 204335640Shselasky# endif /* TPACKET2_HDRLEN */ 205335640Shselasky# endif /* TPACKET_HDRLEN */ 206335640Shselasky# endif /* PCAP_SUPPORT_PACKET_RING */ 207335640Shselasky#endif /* PF_PACKET */ 208335640Shselasky 209335640Shselasky#ifdef SO_ATTACH_FILTER 210335640Shselasky#include <linux/types.h> 211335640Shselasky#include <linux/filter.h> 212335640Shselasky#endif 213335640Shselasky 214335640Shselasky#ifdef HAVE_LINUX_NET_TSTAMP_H 215335640Shselasky#include <linux/net_tstamp.h> 216335640Shselasky#endif 217335640Shselasky 218335640Shselasky#ifdef HAVE_LINUX_SOCKIOS_H 219335640Shselasky#include <linux/sockios.h> 220335640Shselasky#endif 221335640Shselasky 222335640Shselasky#ifdef HAVE_LINUX_IF_BONDING_H 223335640Shselasky#include <linux/if_bonding.h> 224335640Shselasky 225335640Shselasky/* 226335640Shselasky * The ioctl code to use to check whether a device is a bonding device. 227335640Shselasky */ 228335640Shselasky#if defined(SIOCBONDINFOQUERY) 229335640Shselasky #define BOND_INFO_QUERY_IOCTL SIOCBONDINFOQUERY 230335640Shselasky#elif defined(BOND_INFO_QUERY_OLD) 231335640Shselasky #define BOND_INFO_QUERY_IOCTL BOND_INFO_QUERY_OLD 232335640Shselasky#endif 233335640Shselasky#endif /* HAVE_LINUX_IF_BONDING_H */ 234335640Shselasky 235335640Shselasky/* 236335640Shselasky * Got Wireless Extensions? 237335640Shselasky */ 238335640Shselasky#ifdef HAVE_LINUX_WIRELESS_H 239335640Shselasky#include <linux/wireless.h> 240335640Shselasky#endif /* HAVE_LINUX_WIRELESS_H */ 241335640Shselasky 242335640Shselasky/* 243335640Shselasky * Got libnl? 244335640Shselasky */ 245335640Shselasky#ifdef HAVE_LIBNL 246335640Shselasky#include <linux/nl80211.h> 247335640Shselasky 248335640Shselasky#include <netlink/genl/genl.h> 249335640Shselasky#include <netlink/genl/family.h> 250335640Shselasky#include <netlink/genl/ctrl.h> 251335640Shselasky#include <netlink/msg.h> 252335640Shselasky#include <netlink/attr.h> 253335640Shselasky#endif /* HAVE_LIBNL */ 254335640Shselasky 255335640Shselasky/* 256335640Shselasky * Got ethtool support? 257335640Shselasky */ 258335640Shselasky#ifdef HAVE_LINUX_ETHTOOL_H 259335640Shselasky#include <linux/ethtool.h> 260335640Shselasky#endif 261335640Shselasky 262335640Shselasky#ifndef HAVE_SOCKLEN_T 263335640Shselaskytypedef int socklen_t; 264335640Shselasky#endif 265335640Shselasky 266335640Shselasky#ifndef MSG_TRUNC 267335640Shselasky/* 268335640Shselasky * This is being compiled on a system that lacks MSG_TRUNC; define it 269335640Shselasky * with the value it has in the 2.2 and later kernels, so that, on 270335640Shselasky * those kernels, when we pass it in the flags argument to "recvfrom()" 271335640Shselasky * we're passing the right value and thus get the MSG_TRUNC behavior 272335640Shselasky * we want. (We don't get that behavior on 2.0[.x] kernels, because 273335640Shselasky * they didn't support MSG_TRUNC.) 274335640Shselasky */ 275335640Shselasky#define MSG_TRUNC 0x20 276335640Shselasky#endif 277335640Shselasky 278335640Shselasky#ifndef SOL_PACKET 279335640Shselasky/* 280335640Shselasky * This is being compiled on a system that lacks SOL_PACKET; define it 281335640Shselasky * with the value it has in the 2.2 and later kernels, so that we can 282335640Shselasky * set promiscuous mode in the good modern way rather than the old 283335640Shselasky * 2.0-kernel crappy way. 284335640Shselasky */ 285335640Shselasky#define SOL_PACKET 263 286335640Shselasky#endif 287335640Shselasky 288335640Shselasky#define MAX_LINKHEADER_SIZE 256 289335640Shselasky 290335640Shselasky/* 291335640Shselasky * When capturing on all interfaces we use this as the buffer size. 292335640Shselasky * Should be bigger then all MTUs that occur in real life. 293335640Shselasky * 64kB should be enough for now. 294335640Shselasky */ 295335640Shselasky#define BIGGER_THAN_ALL_MTUS (64*1024) 296335640Shselasky 297335640Shselasky/* 298335640Shselasky * Private data for capturing on Linux SOCK_PACKET or PF_PACKET sockets. 299335640Shselasky */ 300335640Shselaskystruct pcap_linux { 301335640Shselasky u_int packets_read; /* count of packets read with recvfrom() */ 302335640Shselasky long proc_dropped; /* packets reported dropped by /proc/net/dev */ 303335640Shselasky struct pcap_stat stat; 304335640Shselasky 305335640Shselasky char *device; /* device name */ 306335640Shselasky int filter_in_userland; /* must filter in userland */ 307335640Shselasky int blocks_to_filter_in_userland; 308335640Shselasky int must_do_on_close; /* stuff we must do when we close */ 309335640Shselasky int timeout; /* timeout for buffering */ 310335640Shselasky int sock_packet; /* using Linux 2.0 compatible interface */ 311335640Shselasky int cooked; /* using SOCK_DGRAM rather than SOCK_RAW */ 312335640Shselasky int ifindex; /* interface index of device we're bound to */ 313335640Shselasky int lo_ifindex; /* interface index of the loopback device */ 314335640Shselasky bpf_u_int32 oldmode; /* mode to restore when turning monitor mode off */ 315335640Shselasky char *mondevice; /* mac80211 monitor device we created */ 316335640Shselasky u_char *mmapbuf; /* memory-mapped region pointer */ 317335640Shselasky size_t mmapbuflen; /* size of region */ 318335640Shselasky int vlan_offset; /* offset at which to insert vlan tags; if -1, don't insert */ 319335640Shselasky u_int tp_version; /* version of tpacket_hdr for mmaped ring */ 320335640Shselasky u_int tp_hdrlen; /* hdrlen of tpacket_hdr for mmaped ring */ 321335640Shselasky u_char *oneshot_buffer; /* buffer for copy of packet */ 322335640Shselasky int poll_timeout; /* timeout to use in poll() */ 323335640Shselasky#ifdef HAVE_TPACKET3 324335640Shselasky unsigned char *current_packet; /* Current packet within the TPACKET_V3 block. Move to next block if NULL. */ 325335640Shselasky int packets_left; /* Unhandled packets left within the block from previous call to pcap_read_linux_mmap_v3 in case of TPACKET_V3. */ 326335640Shselasky#endif 327335640Shselasky}; 328335640Shselasky 329335640Shselasky/* 330335640Shselasky * Stuff to do when we close. 331335640Shselasky */ 332335640Shselasky#define MUST_CLEAR_PROMISC 0x00000001 /* clear promiscuous mode */ 333335640Shselasky#define MUST_CLEAR_RFMON 0x00000002 /* clear rfmon (monitor) mode */ 334335640Shselasky#define MUST_DELETE_MONIF 0x00000004 /* delete monitor-mode interface */ 335335640Shselasky 336335640Shselasky/* 337335640Shselasky * Prototypes for internal functions and methods. 338335640Shselasky */ 339335640Shselaskystatic int get_if_flags(const char *, bpf_u_int32 *, char *); 340335640Shselaskystatic int is_wifi(int, const char *); 341335640Shselaskystatic void map_arphrd_to_dlt(pcap_t *, int, int, const char *, int); 342335640Shselaskystatic int pcap_activate_linux(pcap_t *); 343335640Shselaskystatic int activate_old(pcap_t *); 344335640Shselaskystatic int activate_new(pcap_t *); 345335640Shselaskystatic int activate_mmap(pcap_t *, int *); 346335640Shselaskystatic int pcap_can_set_rfmon_linux(pcap_t *); 347335640Shselaskystatic int pcap_read_linux(pcap_t *, int, pcap_handler, u_char *); 348335640Shselaskystatic int pcap_read_packet(pcap_t *, pcap_handler, u_char *); 349335640Shselaskystatic int pcap_inject_linux(pcap_t *, const void *, size_t); 350335640Shselaskystatic int pcap_stats_linux(pcap_t *, struct pcap_stat *); 351335640Shselaskystatic int pcap_setfilter_linux(pcap_t *, struct bpf_program *); 352335640Shselaskystatic int pcap_setdirection_linux(pcap_t *, pcap_direction_t); 353335640Shselaskystatic int pcap_set_datalink_linux(pcap_t *, int); 354335640Shselaskystatic void pcap_cleanup_linux(pcap_t *); 355335640Shselasky 356335640Shselasky/* 357335640Shselasky * This is what the header structure looks like in a 64-bit kernel; 358335640Shselasky * we use this, rather than struct tpacket_hdr, if we're using 359335640Shselasky * TPACKET_V1 in 32-bit code running on a 64-bit kernel. 360335640Shselasky */ 361335640Shselaskystruct tpacket_hdr_64 { 362335640Shselasky uint64_t tp_status; 363335640Shselasky unsigned int tp_len; 364335640Shselasky unsigned int tp_snaplen; 365335640Shselasky unsigned short tp_mac; 366335640Shselasky unsigned short tp_net; 367335640Shselasky unsigned int tp_sec; 368335640Shselasky unsigned int tp_usec; 369335640Shselasky}; 370335640Shselasky 371335640Shselasky/* 372335640Shselasky * We use this internally as the tpacket version for TPACKET_V1 in 373335640Shselasky * 32-bit code on a 64-bit kernel. 374335640Shselasky */ 375335640Shselasky#define TPACKET_V1_64 99 376335640Shselasky 377335640Shselaskyunion thdr { 378335640Shselasky struct tpacket_hdr *h1; 379335640Shselasky struct tpacket_hdr_64 *h1_64; 380335640Shselasky#ifdef HAVE_TPACKET2 381335640Shselasky struct tpacket2_hdr *h2; 382335640Shselasky#endif 383335640Shselasky#ifdef HAVE_TPACKET3 384335640Shselasky struct tpacket_block_desc *h3; 385335640Shselasky#endif 386335640Shselasky void *raw; 387335640Shselasky}; 388335640Shselasky 389335640Shselasky#ifdef HAVE_PACKET_RING 390335640Shselasky#define RING_GET_FRAME_AT(h, offset) (((union thdr **)h->buffer)[(offset)]) 391335640Shselasky#define RING_GET_CURRENT_FRAME(h) RING_GET_FRAME_AT(h, h->offset) 392335640Shselasky 393335640Shselaskystatic void destroy_ring(pcap_t *handle); 394335640Shselaskystatic int create_ring(pcap_t *handle, int *status); 395335640Shselaskystatic int prepare_tpacket_socket(pcap_t *handle); 396335640Shselaskystatic void pcap_cleanup_linux_mmap(pcap_t *); 397335640Shselaskystatic int pcap_read_linux_mmap_v1(pcap_t *, int, pcap_handler , u_char *); 398335640Shselaskystatic int pcap_read_linux_mmap_v1_64(pcap_t *, int, pcap_handler , u_char *); 399335640Shselasky#ifdef HAVE_TPACKET2 400335640Shselaskystatic int pcap_read_linux_mmap_v2(pcap_t *, int, pcap_handler , u_char *); 401335640Shselasky#endif 402335640Shselasky#ifdef HAVE_TPACKET3 403335640Shselaskystatic int pcap_read_linux_mmap_v3(pcap_t *, int, pcap_handler , u_char *); 404335640Shselasky#endif 405335640Shselaskystatic int pcap_setfilter_linux_mmap(pcap_t *, struct bpf_program *); 406335640Shselaskystatic int pcap_setnonblock_mmap(pcap_t *p, int nonblock); 407335640Shselaskystatic int pcap_getnonblock_mmap(pcap_t *p); 408335640Shselaskystatic void pcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, 409335640Shselasky const u_char *bytes); 410335640Shselasky#endif 411335640Shselasky 412335640Shselasky/* 413335640Shselasky * In pre-3.0 kernels, the tp_vlan_tci field is set to whatever the 414335640Shselasky * vlan_tci field in the skbuff is. 0 can either mean "not on a VLAN" 415335640Shselasky * or "on VLAN 0". There is no flag set in the tp_status field to 416335640Shselasky * distinguish between them. 417335640Shselasky * 418335640Shselasky * In 3.0 and later kernels, if there's a VLAN tag present, the tp_vlan_tci 419335640Shselasky * field is set to the VLAN tag, and the TP_STATUS_VLAN_VALID flag is set 420335640Shselasky * in the tp_status field, otherwise the tp_vlan_tci field is set to 0 and 421335640Shselasky * the TP_STATUS_VLAN_VALID flag isn't set in the tp_status field. 422335640Shselasky * 423335640Shselasky * With a pre-3.0 kernel, we cannot distinguish between packets with no 424335640Shselasky * VLAN tag and packets on VLAN 0, so we will mishandle some packets, and 425335640Shselasky * there's nothing we can do about that. 426335640Shselasky * 427335640Shselasky * So, on those systems, which never set the TP_STATUS_VLAN_VALID flag, we 428335640Shselasky * continue the behavior of earlier libpcaps, wherein we treated packets 429335640Shselasky * with a VLAN tag of 0 as being packets without a VLAN tag rather than packets 430335640Shselasky * on VLAN 0. We do this by treating packets with a tp_vlan_tci of 0 and 431335640Shselasky * with the TP_STATUS_VLAN_VALID flag not set in tp_status as not having 432335640Shselasky * VLAN tags. This does the right thing on 3.0 and later kernels, and 433335640Shselasky * continues the old unfixably-imperfect behavior on pre-3.0 kernels. 434335640Shselasky * 435335640Shselasky * If TP_STATUS_VLAN_VALID isn't defined, we test it as the 0x10 bit; it 436335640Shselasky * has that value in 3.0 and later kernels. 437335640Shselasky */ 438335640Shselasky#ifdef TP_STATUS_VLAN_VALID 439335640Shselasky #define VLAN_VALID(hdr, hv) ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & TP_STATUS_VLAN_VALID)) 440335640Shselasky#else 441335640Shselasky /* 442335640Shselasky * This is being compiled on a system that lacks TP_STATUS_VLAN_VALID, 443335640Shselasky * so we testwith the value it has in the 3.0 and later kernels, so 444335640Shselasky * we can test it if we're running on a system that has it. (If we're 445335640Shselasky * running on a system that doesn't have it, it won't be set in the 446335640Shselasky * tp_status field, so the tests of it will always fail; that means 447335640Shselasky * we behave the way we did before we introduced this macro.) 448335640Shselasky */ 449335640Shselasky #define VLAN_VALID(hdr, hv) ((hv)->tp_vlan_tci != 0 || ((hdr)->tp_status & 0x10)) 450335640Shselasky#endif 451335640Shselasky 452335640Shselasky#ifdef TP_STATUS_VLAN_TPID_VALID 453335640Shselasky# define VLAN_TPID(hdr, hv) (((hv)->tp_vlan_tpid || ((hdr)->tp_status & TP_STATUS_VLAN_TPID_VALID)) ? (hv)->tp_vlan_tpid : ETH_P_8021Q) 454335640Shselasky#else 455335640Shselasky# define VLAN_TPID(hdr, hv) ETH_P_8021Q 456335640Shselasky#endif 457335640Shselasky 458335640Shselasky/* 459335640Shselasky * Wrap some ioctl calls 460335640Shselasky */ 461335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 462335640Shselaskystatic int iface_get_id(int fd, const char *device, char *ebuf); 463335640Shselasky#endif /* HAVE_PF_PACKET_SOCKETS */ 464335640Shselaskystatic int iface_get_mtu(int fd, const char *device, char *ebuf); 465335640Shselaskystatic int iface_get_arptype(int fd, const char *device, char *ebuf); 466335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 467335640Shselaskystatic int iface_bind(int fd, int ifindex, char *ebuf, int protocol); 468335640Shselasky#ifdef IW_MODE_MONITOR 469335640Shselaskystatic int has_wext(int sock_fd, const char *device, char *ebuf); 470335640Shselasky#endif /* IW_MODE_MONITOR */ 471335640Shselaskystatic int enter_rfmon_mode(pcap_t *handle, int sock_fd, 472335640Shselasky const char *device); 473335640Shselasky#endif /* HAVE_PF_PACKET_SOCKETS */ 474335640Shselasky#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) 475335640Shselaskystatic int iface_ethtool_get_ts_info(const char *device, pcap_t *handle, 476335640Shselasky char *ebuf); 477335640Shselasky#endif 478335640Shselasky#ifdef HAVE_PACKET_RING 479335640Shselaskystatic int iface_get_offload(pcap_t *handle); 480335640Shselasky#endif 481335640Shselaskystatic int iface_bind_old(int fd, const char *device, char *ebuf); 482335640Shselasky 483335640Shselasky#ifdef SO_ATTACH_FILTER 484335640Shselaskystatic int fix_program(pcap_t *handle, struct sock_fprog *fcode, 485335640Shselasky int is_mapped); 486356341Scystatic int fix_offset(pcap_t *handle, struct bpf_insn *p); 487335640Shselaskystatic int set_kernel_filter(pcap_t *handle, struct sock_fprog *fcode); 488335640Shselaskystatic int reset_kernel_filter(pcap_t *handle); 489335640Shselasky 490335640Shselaskystatic struct sock_filter total_insn 491335640Shselasky = BPF_STMT(BPF_RET | BPF_K, 0); 492335640Shselaskystatic struct sock_fprog total_fcode 493335640Shselasky = { 1, &total_insn }; 494335640Shselasky#endif /* SO_ATTACH_FILTER */ 495335640Shselasky 496335640Shselaskypcap_t * 497335640Shselaskypcap_create_interface(const char *device, char *ebuf) 498335640Shselasky{ 499335640Shselasky pcap_t *handle; 500335640Shselasky 501335640Shselasky handle = pcap_create_common(ebuf, sizeof (struct pcap_linux)); 502335640Shselasky if (handle == NULL) 503335640Shselasky return NULL; 504335640Shselasky 505335640Shselasky handle->activate_op = pcap_activate_linux; 506335640Shselasky handle->can_set_rfmon_op = pcap_can_set_rfmon_linux; 507335640Shselasky 508335640Shselasky#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) 509335640Shselasky /* 510335640Shselasky * See what time stamp types we support. 511335640Shselasky */ 512335640Shselasky if (iface_ethtool_get_ts_info(device, handle, ebuf) == -1) { 513335640Shselasky pcap_close(handle); 514335640Shselasky return NULL; 515335640Shselasky } 516335640Shselasky#endif 517335640Shselasky 518335640Shselasky#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) 519335640Shselasky /* 520335640Shselasky * We claim that we support microsecond and nanosecond time 521335640Shselasky * stamps. 522335640Shselasky * 523335640Shselasky * XXX - with adapter-supplied time stamps, can we choose 524335640Shselasky * microsecond or nanosecond time stamps on arbitrary 525335640Shselasky * adapters? 526335640Shselasky */ 527335640Shselasky handle->tstamp_precision_count = 2; 528335640Shselasky handle->tstamp_precision_list = malloc(2 * sizeof(u_int)); 529335640Shselasky if (handle->tstamp_precision_list == NULL) { 530335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 531335640Shselasky errno, "malloc"); 532335640Shselasky pcap_close(handle); 533335640Shselasky return NULL; 534335640Shselasky } 535335640Shselasky handle->tstamp_precision_list[0] = PCAP_TSTAMP_PRECISION_MICRO; 536335640Shselasky handle->tstamp_precision_list[1] = PCAP_TSTAMP_PRECISION_NANO; 537335640Shselasky#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */ 538335640Shselasky 539335640Shselasky return handle; 540335640Shselasky} 541335640Shselasky 542335640Shselasky#ifdef HAVE_LIBNL 543335640Shselasky/* 544335640Shselasky * If interface {if} is a mac80211 driver, the file 545335640Shselasky * /sys/class/net/{if}/phy80211 is a symlink to 546335640Shselasky * /sys/class/ieee80211/{phydev}, for some {phydev}. 547335640Shselasky * 548335640Shselasky * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at 549335640Shselasky * least, has a "wmaster0" device and a "wlan0" device; the 550335640Shselasky * latter is the one with the IP address. Both show up in 551335640Shselasky * "tcpdump -D" output. Capturing on the wmaster0 device 552335640Shselasky * captures with 802.11 headers. 553335640Shselasky * 554335640Shselasky * airmon-ng searches through /sys/class/net for devices named 555335640Shselasky * monN, starting with mon0; as soon as one *doesn't* exist, 556335640Shselasky * it chooses that as the monitor device name. If the "iw" 557335640Shselasky * command exists, it does "iw dev {if} interface add {monif} 558335640Shselasky * type monitor", where {monif} is the monitor device. It 559335640Shselasky * then (sigh) sleeps .1 second, and then configures the 560335640Shselasky * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface 561335640Shselasky * is a file, it writes {mondev}, without a newline, to that file, 562335640Shselasky * and again (sigh) sleeps .1 second, and then iwconfig's that 563335640Shselasky * device into monitor mode and configures it up. Otherwise, 564335640Shselasky * you can't do monitor mode. 565335640Shselasky * 566335640Shselasky * All these devices are "glued" together by having the 567335640Shselasky * /sys/class/net/{device}/phy80211 links pointing to the same 568335640Shselasky * place, so, given a wmaster, wlan, or mon device, you can 569335640Shselasky * find the other devices by looking for devices with 570335640Shselasky * the same phy80211 link. 571335640Shselasky * 572335640Shselasky * To turn monitor mode off, delete the monitor interface, 573335640Shselasky * either with "iw dev {monif} interface del" or by sending 574335640Shselasky * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface 575335640Shselasky * 576335640Shselasky * Note: if you try to create a monitor device named "monN", and 577335640Shselasky * there's already a "monN" device, it fails, as least with 578335640Shselasky * the netlink interface (which is what iw uses), with a return 579335640Shselasky * value of -ENFILE. (Return values are negative errnos.) We 580335640Shselasky * could probably use that to find an unused device. 581335640Shselasky * 582335640Shselasky * Yes, you can have multiple monitor devices for a given 583335640Shselasky * physical device. 584335640Shselasky */ 585335640Shselasky 586335640Shselasky/* 587335640Shselasky * Is this a mac80211 device? If so, fill in the physical device path and 588335640Shselasky * return 1; if not, return 0. On an error, fill in handle->errbuf and 589335640Shselasky * return PCAP_ERROR. 590335640Shselasky */ 591335640Shselaskystatic int 592335640Shselaskyget_mac80211_phydev(pcap_t *handle, const char *device, char *phydev_path, 593335640Shselasky size_t phydev_max_pathlen) 594335640Shselasky{ 595335640Shselasky char *pathstr; 596335640Shselasky ssize_t bytes_read; 597335640Shselasky 598335640Shselasky /* 599335640Shselasky * Generate the path string for the symlink to the physical device. 600335640Shselasky */ 601335640Shselasky if (asprintf(&pathstr, "/sys/class/net/%s/phy80211", device) == -1) { 602335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 603335640Shselasky "%s: Can't generate path name string for /sys/class/net device", 604335640Shselasky device); 605335640Shselasky return PCAP_ERROR; 606335640Shselasky } 607335640Shselasky bytes_read = readlink(pathstr, phydev_path, phydev_max_pathlen); 608335640Shselasky if (bytes_read == -1) { 609335640Shselasky if (errno == ENOENT || errno == EINVAL) { 610335640Shselasky /* 611335640Shselasky * Doesn't exist, or not a symlink; assume that 612335640Shselasky * means it's not a mac80211 device. 613335640Shselasky */ 614335640Shselasky free(pathstr); 615335640Shselasky return 0; 616335640Shselasky } 617335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 618335640Shselasky errno, "%s: Can't readlink %s", device, pathstr); 619335640Shselasky free(pathstr); 620335640Shselasky return PCAP_ERROR; 621335640Shselasky } 622335640Shselasky free(pathstr); 623335640Shselasky phydev_path[bytes_read] = '\0'; 624335640Shselasky return 1; 625335640Shselasky} 626335640Shselasky 627335640Shselasky#ifdef HAVE_LIBNL_SOCKETS 628335640Shselasky#define get_nl_errmsg nl_geterror 629335640Shselasky#else 630335640Shselasky/* libnl 2.x compatibility code */ 631335640Shselasky 632335640Shselasky#define nl_sock nl_handle 633335640Shselasky 634335640Shselaskystatic inline struct nl_handle * 635335640Shselaskynl_socket_alloc(void) 636335640Shselasky{ 637335640Shselasky return nl_handle_alloc(); 638335640Shselasky} 639335640Shselasky 640335640Shselaskystatic inline void 641335640Shselaskynl_socket_free(struct nl_handle *h) 642335640Shselasky{ 643335640Shselasky nl_handle_destroy(h); 644335640Shselasky} 645335640Shselasky 646335640Shselasky#define get_nl_errmsg strerror 647335640Shselasky 648335640Shselaskystatic inline int 649335640Shselasky__genl_ctrl_alloc_cache(struct nl_handle *h, struct nl_cache **cache) 650335640Shselasky{ 651335640Shselasky struct nl_cache *tmp = genl_ctrl_alloc_cache(h); 652335640Shselasky if (!tmp) 653335640Shselasky return -ENOMEM; 654335640Shselasky *cache = tmp; 655335640Shselasky return 0; 656335640Shselasky} 657335640Shselasky#define genl_ctrl_alloc_cache __genl_ctrl_alloc_cache 658335640Shselasky#endif /* !HAVE_LIBNL_SOCKETS */ 659335640Shselasky 660335640Shselaskystruct nl80211_state { 661335640Shselasky struct nl_sock *nl_sock; 662335640Shselasky struct nl_cache *nl_cache; 663335640Shselasky struct genl_family *nl80211; 664335640Shselasky}; 665335640Shselasky 666335640Shselaskystatic int 667335640Shselaskynl80211_init(pcap_t *handle, struct nl80211_state *state, const char *device) 668335640Shselasky{ 669335640Shselasky int err; 670335640Shselasky 671335640Shselasky state->nl_sock = nl_socket_alloc(); 672335640Shselasky if (!state->nl_sock) { 673335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 674335640Shselasky "%s: failed to allocate netlink handle", device); 675335640Shselasky return PCAP_ERROR; 676335640Shselasky } 677335640Shselasky 678335640Shselasky if (genl_connect(state->nl_sock)) { 679335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 680335640Shselasky "%s: failed to connect to generic netlink", device); 681335640Shselasky goto out_handle_destroy; 682335640Shselasky } 683335640Shselasky 684335640Shselasky err = genl_ctrl_alloc_cache(state->nl_sock, &state->nl_cache); 685335640Shselasky if (err < 0) { 686335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 687335640Shselasky "%s: failed to allocate generic netlink cache: %s", 688335640Shselasky device, get_nl_errmsg(-err)); 689335640Shselasky goto out_handle_destroy; 690335640Shselasky } 691335640Shselasky 692335640Shselasky state->nl80211 = genl_ctrl_search_by_name(state->nl_cache, "nl80211"); 693335640Shselasky if (!state->nl80211) { 694335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 695335640Shselasky "%s: nl80211 not found", device); 696335640Shselasky goto out_cache_free; 697335640Shselasky } 698335640Shselasky 699335640Shselasky return 0; 700335640Shselasky 701335640Shselaskyout_cache_free: 702335640Shselasky nl_cache_free(state->nl_cache); 703335640Shselaskyout_handle_destroy: 704335640Shselasky nl_socket_free(state->nl_sock); 705335640Shselasky return PCAP_ERROR; 706335640Shselasky} 707335640Shselasky 708335640Shselaskystatic void 709335640Shselaskynl80211_cleanup(struct nl80211_state *state) 710335640Shselasky{ 711335640Shselasky genl_family_put(state->nl80211); 712335640Shselasky nl_cache_free(state->nl_cache); 713335640Shselasky nl_socket_free(state->nl_sock); 714335640Shselasky} 715335640Shselasky 716335640Shselaskystatic int 717335640Shselaskydel_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, 718335640Shselasky const char *device, const char *mondevice); 719335640Shselasky 720335640Shselaskystatic int 721335640Shselaskyadd_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, 722335640Shselasky const char *device, const char *mondevice) 723335640Shselasky{ 724335640Shselasky struct pcap_linux *handlep = handle->priv; 725335640Shselasky int ifindex; 726335640Shselasky struct nl_msg *msg; 727335640Shselasky int err; 728335640Shselasky 729335640Shselasky ifindex = iface_get_id(sock_fd, device, handle->errbuf); 730335640Shselasky if (ifindex == -1) 731335640Shselasky return PCAP_ERROR; 732335640Shselasky 733335640Shselasky msg = nlmsg_alloc(); 734335640Shselasky if (!msg) { 735335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 736335640Shselasky "%s: failed to allocate netlink msg", device); 737335640Shselasky return PCAP_ERROR; 738335640Shselasky } 739335640Shselasky 740335640Shselasky genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 741335640Shselasky 0, NL80211_CMD_NEW_INTERFACE, 0); 742335640Shselasky NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 743335640Shselasky NLA_PUT_STRING(msg, NL80211_ATTR_IFNAME, mondevice); 744335640Shselasky NLA_PUT_U32(msg, NL80211_ATTR_IFTYPE, NL80211_IFTYPE_MONITOR); 745335640Shselasky 746335640Shselasky err = nl_send_auto_complete(state->nl_sock, msg); 747335640Shselasky if (err < 0) { 748335640Shselasky#if defined HAVE_LIBNL_NLE 749335640Shselasky if (err == -NLE_FAILURE) { 750335640Shselasky#else 751335640Shselasky if (err == -ENFILE) { 752335640Shselasky#endif 753335640Shselasky /* 754335640Shselasky * Device not available; our caller should just 755335640Shselasky * keep trying. (libnl 2.x maps ENFILE to 756335640Shselasky * NLE_FAILURE; it can also map other errors 757335640Shselasky * to that, but there's not much we can do 758335640Shselasky * about that.) 759335640Shselasky */ 760335640Shselasky nlmsg_free(msg); 761335640Shselasky return 0; 762335640Shselasky } else { 763335640Shselasky /* 764335640Shselasky * Real failure, not just "that device is not 765335640Shselasky * available. 766335640Shselasky */ 767335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 768335640Shselasky "%s: nl_send_auto_complete failed adding %s interface: %s", 769335640Shselasky device, mondevice, get_nl_errmsg(-err)); 770335640Shselasky nlmsg_free(msg); 771335640Shselasky return PCAP_ERROR; 772335640Shselasky } 773335640Shselasky } 774335640Shselasky err = nl_wait_for_ack(state->nl_sock); 775335640Shselasky if (err < 0) { 776335640Shselasky#if defined HAVE_LIBNL_NLE 777335640Shselasky if (err == -NLE_FAILURE) { 778335640Shselasky#else 779335640Shselasky if (err == -ENFILE) { 780335640Shselasky#endif 781335640Shselasky /* 782335640Shselasky * Device not available; our caller should just 783335640Shselasky * keep trying. (libnl 2.x maps ENFILE to 784335640Shselasky * NLE_FAILURE; it can also map other errors 785335640Shselasky * to that, but there's not much we can do 786335640Shselasky * about that.) 787335640Shselasky */ 788335640Shselasky nlmsg_free(msg); 789335640Shselasky return 0; 790335640Shselasky } else { 791335640Shselasky /* 792335640Shselasky * Real failure, not just "that device is not 793335640Shselasky * available. 794335640Shselasky */ 795335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 796335640Shselasky "%s: nl_wait_for_ack failed adding %s interface: %s", 797335640Shselasky device, mondevice, get_nl_errmsg(-err)); 798335640Shselasky nlmsg_free(msg); 799335640Shselasky return PCAP_ERROR; 800335640Shselasky } 801335640Shselasky } 802335640Shselasky 803335640Shselasky /* 804335640Shselasky * Success. 805335640Shselasky */ 806335640Shselasky nlmsg_free(msg); 807335640Shselasky 808335640Shselasky /* 809335640Shselasky * Try to remember the monitor device. 810335640Shselasky */ 811335640Shselasky handlep->mondevice = strdup(mondevice); 812335640Shselasky if (handlep->mondevice == NULL) { 813335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 814335640Shselasky errno, "strdup"); 815335640Shselasky /* 816335640Shselasky * Get rid of the monitor device. 817335640Shselasky */ 818335640Shselasky del_mon_if(handle, sock_fd, state, device, mondevice); 819335640Shselasky return PCAP_ERROR; 820335640Shselasky } 821335640Shselasky return 1; 822335640Shselasky 823335640Shselaskynla_put_failure: 824335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 825335640Shselasky "%s: nl_put failed adding %s interface", 826335640Shselasky device, mondevice); 827335640Shselasky nlmsg_free(msg); 828335640Shselasky return PCAP_ERROR; 829335640Shselasky} 830335640Shselasky 831335640Shselaskystatic int 832335640Shselaskydel_mon_if(pcap_t *handle, int sock_fd, struct nl80211_state *state, 833335640Shselasky const char *device, const char *mondevice) 834335640Shselasky{ 835335640Shselasky int ifindex; 836335640Shselasky struct nl_msg *msg; 837335640Shselasky int err; 838335640Shselasky 839335640Shselasky ifindex = iface_get_id(sock_fd, mondevice, handle->errbuf); 840335640Shselasky if (ifindex == -1) 841335640Shselasky return PCAP_ERROR; 842335640Shselasky 843335640Shselasky msg = nlmsg_alloc(); 844335640Shselasky if (!msg) { 845335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 846335640Shselasky "%s: failed to allocate netlink msg", device); 847335640Shselasky return PCAP_ERROR; 848335640Shselasky } 849335640Shselasky 850335640Shselasky genlmsg_put(msg, 0, 0, genl_family_get_id(state->nl80211), 0, 851335640Shselasky 0, NL80211_CMD_DEL_INTERFACE, 0); 852335640Shselasky NLA_PUT_U32(msg, NL80211_ATTR_IFINDEX, ifindex); 853335640Shselasky 854335640Shselasky err = nl_send_auto_complete(state->nl_sock, msg); 855335640Shselasky if (err < 0) { 856335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 857335640Shselasky "%s: nl_send_auto_complete failed deleting %s interface: %s", 858335640Shselasky device, mondevice, get_nl_errmsg(-err)); 859335640Shselasky nlmsg_free(msg); 860335640Shselasky return PCAP_ERROR; 861335640Shselasky } 862335640Shselasky err = nl_wait_for_ack(state->nl_sock); 863335640Shselasky if (err < 0) { 864335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 865335640Shselasky "%s: nl_wait_for_ack failed adding %s interface: %s", 866335640Shselasky device, mondevice, get_nl_errmsg(-err)); 867335640Shselasky nlmsg_free(msg); 868335640Shselasky return PCAP_ERROR; 869335640Shselasky } 870335640Shselasky 871335640Shselasky /* 872335640Shselasky * Success. 873335640Shselasky */ 874335640Shselasky nlmsg_free(msg); 875335640Shselasky return 1; 876335640Shselasky 877335640Shselaskynla_put_failure: 878335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 879335640Shselasky "%s: nl_put failed deleting %s interface", 880335640Shselasky device, mondevice); 881335640Shselasky nlmsg_free(msg); 882335640Shselasky return PCAP_ERROR; 883335640Shselasky} 884335640Shselasky 885335640Shselaskystatic int 886335640Shselaskyenter_rfmon_mode_mac80211(pcap_t *handle, int sock_fd, const char *device) 887335640Shselasky{ 888335640Shselasky struct pcap_linux *handlep = handle->priv; 889335640Shselasky int ret; 890335640Shselasky char phydev_path[PATH_MAX+1]; 891335640Shselasky struct nl80211_state nlstate; 892335640Shselasky struct ifreq ifr; 893335640Shselasky u_int n; 894335640Shselasky 895335640Shselasky /* 896335640Shselasky * Is this a mac80211 device? 897335640Shselasky */ 898335640Shselasky ret = get_mac80211_phydev(handle, device, phydev_path, PATH_MAX); 899335640Shselasky if (ret < 0) 900335640Shselasky return ret; /* error */ 901335640Shselasky if (ret == 0) 902335640Shselasky return 0; /* no error, but not mac80211 device */ 903335640Shselasky 904335640Shselasky /* 905335640Shselasky * XXX - is this already a monN device? 906335640Shselasky * If so, we're done. 907335640Shselasky * Is that determined by old Wireless Extensions ioctls? 908335640Shselasky */ 909335640Shselasky 910335640Shselasky /* 911335640Shselasky * OK, it's apparently a mac80211 device. 912335640Shselasky * Try to find an unused monN device for it. 913335640Shselasky */ 914335640Shselasky ret = nl80211_init(handle, &nlstate, device); 915335640Shselasky if (ret != 0) 916335640Shselasky return ret; 917335640Shselasky for (n = 0; n < UINT_MAX; n++) { 918335640Shselasky /* 919335640Shselasky * Try mon{n}. 920335640Shselasky */ 921335640Shselasky char mondevice[3+10+1]; /* mon{UINT_MAX}\0 */ 922335640Shselasky 923335640Shselasky pcap_snprintf(mondevice, sizeof mondevice, "mon%u", n); 924335640Shselasky ret = add_mon_if(handle, sock_fd, &nlstate, device, mondevice); 925335640Shselasky if (ret == 1) { 926335640Shselasky /* 927335640Shselasky * Success. We don't clean up the libnl state 928335640Shselasky * yet, as we'll be using it later. 929335640Shselasky */ 930335640Shselasky goto added; 931335640Shselasky } 932335640Shselasky if (ret < 0) { 933335640Shselasky /* 934335640Shselasky * Hard failure. Just return ret; handle->errbuf 935335640Shselasky * has already been set. 936335640Shselasky */ 937335640Shselasky nl80211_cleanup(&nlstate); 938335640Shselasky return ret; 939335640Shselasky } 940335640Shselasky } 941335640Shselasky 942335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 943335640Shselasky "%s: No free monN interfaces", device); 944335640Shselasky nl80211_cleanup(&nlstate); 945335640Shselasky return PCAP_ERROR; 946335640Shselasky 947335640Shselaskyadded: 948335640Shselasky 949335640Shselasky#if 0 950335640Shselasky /* 951335640Shselasky * Sleep for .1 seconds. 952335640Shselasky */ 953335640Shselasky delay.tv_sec = 0; 954335640Shselasky delay.tv_nsec = 500000000; 955335640Shselasky nanosleep(&delay, NULL); 956335640Shselasky#endif 957335640Shselasky 958335640Shselasky /* 959335640Shselasky * If we haven't already done so, arrange to have 960335640Shselasky * "pcap_close_all()" called when we exit. 961335640Shselasky */ 962335640Shselasky if (!pcap_do_addexit(handle)) { 963335640Shselasky /* 964335640Shselasky * "atexit()" failed; don't put the interface 965335640Shselasky * in rfmon mode, just give up. 966335640Shselasky */ 967335640Shselasky del_mon_if(handle, sock_fd, &nlstate, device, 968335640Shselasky handlep->mondevice); 969335640Shselasky nl80211_cleanup(&nlstate); 970335640Shselasky return PCAP_ERROR; 971335640Shselasky } 972335640Shselasky 973335640Shselasky /* 974335640Shselasky * Now configure the monitor interface up. 975335640Shselasky */ 976335640Shselasky memset(&ifr, 0, sizeof(ifr)); 977356341Scy pcap_strlcpy(ifr.ifr_name, handlep->mondevice, sizeof(ifr.ifr_name)); 978335640Shselasky if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { 979335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 980335640Shselasky errno, "%s: Can't get flags for %s", device, 981335640Shselasky handlep->mondevice); 982335640Shselasky del_mon_if(handle, sock_fd, &nlstate, device, 983335640Shselasky handlep->mondevice); 984335640Shselasky nl80211_cleanup(&nlstate); 985335640Shselasky return PCAP_ERROR; 986335640Shselasky } 987335640Shselasky ifr.ifr_flags |= IFF_UP|IFF_RUNNING; 988335640Shselasky if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { 989335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 990335640Shselasky errno, "%s: Can't set flags for %s", device, 991335640Shselasky handlep->mondevice); 992335640Shselasky del_mon_if(handle, sock_fd, &nlstate, device, 993335640Shselasky handlep->mondevice); 994335640Shselasky nl80211_cleanup(&nlstate); 995335640Shselasky return PCAP_ERROR; 996335640Shselasky } 997335640Shselasky 998335640Shselasky /* 999335640Shselasky * Success. Clean up the libnl state. 1000335640Shselasky */ 1001335640Shselasky nl80211_cleanup(&nlstate); 1002335640Shselasky 1003335640Shselasky /* 1004335640Shselasky * Note that we have to delete the monitor device when we close 1005335640Shselasky * the handle. 1006335640Shselasky */ 1007335640Shselasky handlep->must_do_on_close |= MUST_DELETE_MONIF; 1008335640Shselasky 1009335640Shselasky /* 1010335640Shselasky * Add this to the list of pcaps to close when we exit. 1011335640Shselasky */ 1012335640Shselasky pcap_add_to_pcaps_to_close(handle); 1013335640Shselasky 1014335640Shselasky return 1; 1015335640Shselasky} 1016335640Shselasky#endif /* HAVE_LIBNL */ 1017335640Shselasky 1018335640Shselasky#ifdef IW_MODE_MONITOR 1019335640Shselasky/* 1020335640Shselasky * Bonding devices mishandle unknown ioctls; they fail with ENODEV 1021335640Shselasky * rather than ENOTSUP, EOPNOTSUPP, or ENOTTY, so Wireless Extensions 1022335640Shselasky * will fail with ENODEV if we try to do them on a bonding device, 1023335640Shselasky * making us return a "no such device" indication rather than just 1024335640Shselasky * saying "no Wireless Extensions". 1025335640Shselasky * 1026335640Shselasky * So we check for bonding devices, if we can, before trying those 1027335640Shselasky * ioctls, by trying a bonding device information query ioctl to see 1028335640Shselasky * whether it succeeds. 1029335640Shselasky */ 1030335640Shselaskystatic int 1031335640Shselaskyis_bonding_device(int fd, const char *device) 1032335640Shselasky{ 1033335640Shselasky#ifdef BOND_INFO_QUERY_IOCTL 1034335640Shselasky struct ifreq ifr; 1035335640Shselasky ifbond ifb; 1036335640Shselasky 1037335640Shselasky memset(&ifr, 0, sizeof ifr); 1038356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof ifr.ifr_name); 1039335640Shselasky memset(&ifb, 0, sizeof ifb); 1040335640Shselasky ifr.ifr_data = (caddr_t)&ifb; 1041335640Shselasky if (ioctl(fd, BOND_INFO_QUERY_IOCTL, &ifr) == 0) 1042335640Shselasky return 1; /* success, so it's a bonding device */ 1043335640Shselasky#endif /* BOND_INFO_QUERY_IOCTL */ 1044335640Shselasky 1045335640Shselasky return 0; /* no, it's not a bonding device */ 1046335640Shselasky} 1047335640Shselasky#endif /* IW_MODE_MONITOR */ 1048335640Shselasky 1049335640Shselaskystatic int pcap_protocol(pcap_t *handle) 1050335640Shselasky{ 1051335640Shselasky int protocol; 1052335640Shselasky 1053335640Shselasky protocol = handle->opt.protocol; 1054335640Shselasky if (protocol == 0) 1055335640Shselasky protocol = ETH_P_ALL; 1056335640Shselasky 1057335640Shselasky return htons(protocol); 1058335640Shselasky} 1059335640Shselasky 1060335640Shselaskystatic int 1061335640Shselaskypcap_can_set_rfmon_linux(pcap_t *handle) 1062335640Shselasky{ 1063335640Shselasky#ifdef HAVE_LIBNL 1064335640Shselasky char phydev_path[PATH_MAX+1]; 1065335640Shselasky int ret; 1066335640Shselasky#endif 1067335640Shselasky#ifdef IW_MODE_MONITOR 1068335640Shselasky int sock_fd; 1069335640Shselasky struct iwreq ireq; 1070335640Shselasky#endif 1071335640Shselasky 1072335640Shselasky if (strcmp(handle->opt.device, "any") == 0) { 1073335640Shselasky /* 1074335640Shselasky * Monitor mode makes no sense on the "any" device. 1075335640Shselasky */ 1076335640Shselasky return 0; 1077335640Shselasky } 1078335640Shselasky 1079335640Shselasky#ifdef HAVE_LIBNL 1080335640Shselasky /* 1081335640Shselasky * Bleah. There doesn't seem to be a way to ask a mac80211 1082335640Shselasky * device, through libnl, whether it supports monitor mode; 1083335640Shselasky * we'll just check whether the device appears to be a 1084335640Shselasky * mac80211 device and, if so, assume the device supports 1085335640Shselasky * monitor mode. 1086335640Shselasky * 1087335640Shselasky * wmaster devices don't appear to support the Wireless 1088335640Shselasky * Extensions, but we can create a mon device for a 1089335640Shselasky * wmaster device, so we don't bother checking whether 1090335640Shselasky * a mac80211 device supports the Wireless Extensions. 1091335640Shselasky */ 1092335640Shselasky ret = get_mac80211_phydev(handle, handle->opt.device, phydev_path, 1093335640Shselasky PATH_MAX); 1094335640Shselasky if (ret < 0) 1095335640Shselasky return ret; /* error */ 1096335640Shselasky if (ret == 1) 1097335640Shselasky return 1; /* mac80211 device */ 1098335640Shselasky#endif 1099335640Shselasky 1100335640Shselasky#ifdef IW_MODE_MONITOR 1101335640Shselasky /* 1102335640Shselasky * Bleah. There doesn't appear to be an ioctl to use to ask 1103335640Shselasky * whether a device supports monitor mode; we'll just do 1104335640Shselasky * SIOCGIWMODE and, if it succeeds, assume the device supports 1105335640Shselasky * monitor mode. 1106335640Shselasky * 1107335640Shselasky * Open a socket on which to attempt to get the mode. 1108335640Shselasky * (We assume that if we have Wireless Extensions support 1109335640Shselasky * we also have PF_PACKET support.) 1110335640Shselasky */ 1111335640Shselasky sock_fd = socket(PF_PACKET, SOCK_RAW, pcap_protocol(handle)); 1112335640Shselasky if (sock_fd == -1) { 1113335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 1114335640Shselasky errno, "socket"); 1115335640Shselasky return PCAP_ERROR; 1116335640Shselasky } 1117335640Shselasky 1118335640Shselasky if (is_bonding_device(sock_fd, handle->opt.device)) { 1119335640Shselasky /* It's a bonding device, so don't even try. */ 1120335640Shselasky close(sock_fd); 1121335640Shselasky return 0; 1122335640Shselasky } 1123335640Shselasky 1124335640Shselasky /* 1125335640Shselasky * Attempt to get the current mode. 1126335640Shselasky */ 1127356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handle->opt.device, 1128335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 1129335640Shselasky if (ioctl(sock_fd, SIOCGIWMODE, &ireq) != -1) { 1130335640Shselasky /* 1131335640Shselasky * Well, we got the mode; assume we can set it. 1132335640Shselasky */ 1133335640Shselasky close(sock_fd); 1134335640Shselasky return 1; 1135335640Shselasky } 1136335640Shselasky if (errno == ENODEV) { 1137335640Shselasky /* The device doesn't even exist. */ 1138335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 1139335640Shselasky errno, "SIOCGIWMODE failed"); 1140335640Shselasky close(sock_fd); 1141335640Shselasky return PCAP_ERROR_NO_SUCH_DEVICE; 1142335640Shselasky } 1143335640Shselasky close(sock_fd); 1144335640Shselasky#endif 1145335640Shselasky return 0; 1146335640Shselasky} 1147335640Shselasky 1148335640Shselasky/* 1149335640Shselasky * Grabs the number of dropped packets by the interface from /proc/net/dev. 1150335640Shselasky * 1151335640Shselasky * XXX - what about /sys/class/net/{interface name}/rx_*? There are 1152335640Shselasky * individual devices giving, in ASCII, various rx_ and tx_ statistics. 1153335640Shselasky * 1154335640Shselasky * Or can we get them in binary form from netlink? 1155335640Shselasky */ 1156335640Shselaskystatic long int 1157335640Shselaskylinux_if_drops(const char * if_name) 1158335640Shselasky{ 1159335640Shselasky char buffer[512]; 1160356341Scy FILE *file; 1161356341Scy char *bufptr, *nameptr, *colonptr; 1162356341Scy int field_to_convert = 3; 1163335640Shselasky long int dropped_pkts = 0; 1164335640Shselasky 1165335640Shselasky file = fopen("/proc/net/dev", "r"); 1166335640Shselasky if (!file) 1167335640Shselasky return 0; 1168335640Shselasky 1169356341Scy while (fgets(buffer, sizeof(buffer), file) != NULL) 1170335640Shselasky { 1171335640Shselasky /* search for 'bytes' -- if its in there, then 1172335640Shselasky that means we need to grab the fourth field. otherwise 1173335640Shselasky grab the third field. */ 1174335640Shselasky if (field_to_convert != 4 && strstr(buffer, "bytes")) 1175335640Shselasky { 1176335640Shselasky field_to_convert = 4; 1177335640Shselasky continue; 1178335640Shselasky } 1179335640Shselasky 1180356341Scy /* 1181356341Scy * See whether this line corresponds to this device. 1182356341Scy * The line should have zero or more leading blanks, 1183356341Scy * followed by a device name, followed by a colon, 1184356341Scy * followed by the statistics. 1185356341Scy */ 1186356341Scy bufptr = buffer; 1187356341Scy /* Skip leading blanks */ 1188356341Scy while (*bufptr == ' ') 1189356341Scy bufptr++; 1190356341Scy nameptr = bufptr; 1191356341Scy /* Look for the colon */ 1192356341Scy colonptr = strchr(nameptr, ':'); 1193356341Scy if (colonptr == NULL) 1194335640Shselasky { 1195356341Scy /* 1196356341Scy * Not found; this could, for example, be the 1197356341Scy * header line. 1198356341Scy */ 1199356341Scy continue; 1200356341Scy } 1201356341Scy /* Null-terminate the interface name. */ 1202356341Scy *colonptr = '\0'; 1203356341Scy if (strcmp(if_name, nameptr) == 0) 1204356341Scy { 1205356341Scy /* 1206356341Scy * OK, this line has the statistics for the interface. 1207356341Scy * Skip past the interface name. 1208356341Scy */ 1209356341Scy bufptr = colonptr + 1; 1210335640Shselasky 1211335640Shselasky /* grab the nth field from it */ 1212356341Scy while (--field_to_convert && *bufptr != '\0') 1213335640Shselasky { 1214356341Scy /* 1215356341Scy * This isn't the field we want. 1216356341Scy * First, skip any leading blanks before 1217356341Scy * the field. 1218356341Scy */ 1219356341Scy while (*bufptr == ' ') 1220356341Scy bufptr++; 1221356341Scy 1222356341Scy /* 1223356341Scy * Now skip the non-blank characters of 1224356341Scy * the field. 1225356341Scy */ 1226356341Scy while (*bufptr != '\0' && *bufptr != ' ') 1227356341Scy bufptr++; 1228335640Shselasky } 1229335640Shselasky 1230356341Scy if (field_to_convert == 0) 1231356341Scy { 1232356341Scy /* 1233356341Scy * We've found the field we want. 1234356341Scy * Skip any leading blanks before it. 1235356341Scy */ 1236356341Scy while (*bufptr == ' ') 1237356341Scy bufptr++; 1238335640Shselasky 1239356341Scy /* 1240356341Scy * Now extract the value, if we have one. 1241356341Scy */ 1242356341Scy if (*bufptr != '\0') 1243356341Scy dropped_pkts = strtol(bufptr, NULL, 10); 1244356341Scy } 1245335640Shselasky break; 1246335640Shselasky } 1247335640Shselasky } 1248335640Shselasky 1249335640Shselasky fclose(file); 1250335640Shselasky return dropped_pkts; 1251335640Shselasky} 1252335640Shselasky 1253335640Shselasky 1254335640Shselasky/* 1255335640Shselasky * With older kernels promiscuous mode is kind of interesting because we 1256335640Shselasky * have to reset the interface before exiting. The problem can't really 1257335640Shselasky * be solved without some daemon taking care of managing usage counts. 1258335640Shselasky * If we put the interface into promiscuous mode, we set a flag indicating 1259335640Shselasky * that we must take it out of that mode when the interface is closed, 1260335640Shselasky * and, when closing the interface, if that flag is set we take it out 1261335640Shselasky * of promiscuous mode. 1262335640Shselasky * 1263335640Shselasky * Even with newer kernels, we have the same issue with rfmon mode. 1264335640Shselasky */ 1265335640Shselasky 1266335640Shselaskystatic void pcap_cleanup_linux( pcap_t *handle ) 1267335640Shselasky{ 1268335640Shselasky struct pcap_linux *handlep = handle->priv; 1269335640Shselasky struct ifreq ifr; 1270335640Shselasky#ifdef HAVE_LIBNL 1271335640Shselasky struct nl80211_state nlstate; 1272335640Shselasky int ret; 1273335640Shselasky#endif /* HAVE_LIBNL */ 1274335640Shselasky#ifdef IW_MODE_MONITOR 1275335640Shselasky int oldflags; 1276335640Shselasky struct iwreq ireq; 1277335640Shselasky#endif /* IW_MODE_MONITOR */ 1278335640Shselasky 1279335640Shselasky if (handlep->must_do_on_close != 0) { 1280335640Shselasky /* 1281335640Shselasky * There's something we have to do when closing this 1282335640Shselasky * pcap_t. 1283335640Shselasky */ 1284335640Shselasky if (handlep->must_do_on_close & MUST_CLEAR_PROMISC) { 1285335640Shselasky /* 1286335640Shselasky * We put the interface into promiscuous mode; 1287335640Shselasky * take it out of promiscuous mode. 1288335640Shselasky * 1289335640Shselasky * XXX - if somebody else wants it in promiscuous 1290335640Shselasky * mode, this code cannot know that, so it'll take 1291335640Shselasky * it out of promiscuous mode. That's not fixable 1292335640Shselasky * in 2.0[.x] kernels. 1293335640Shselasky */ 1294335640Shselasky memset(&ifr, 0, sizeof(ifr)); 1295356341Scy pcap_strlcpy(ifr.ifr_name, handlep->device, 1296335640Shselasky sizeof(ifr.ifr_name)); 1297335640Shselasky if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { 1298335640Shselasky fprintf(stderr, 1299335640Shselasky "Can't restore interface %s flags (SIOCGIFFLAGS failed: %s).\n" 1300335640Shselasky "Please adjust manually.\n" 1301335640Shselasky "Hint: This can't happen with Linux >= 2.2.0.\n", 1302335640Shselasky handlep->device, strerror(errno)); 1303335640Shselasky } else { 1304335640Shselasky if (ifr.ifr_flags & IFF_PROMISC) { 1305335640Shselasky /* 1306335640Shselasky * Promiscuous mode is currently on; 1307335640Shselasky * turn it off. 1308335640Shselasky */ 1309335640Shselasky ifr.ifr_flags &= ~IFF_PROMISC; 1310335640Shselasky if (ioctl(handle->fd, SIOCSIFFLAGS, 1311335640Shselasky &ifr) == -1) { 1312335640Shselasky fprintf(stderr, 1313335640Shselasky "Can't restore interface %s flags (SIOCSIFFLAGS failed: %s).\n" 1314335640Shselasky "Please adjust manually.\n" 1315335640Shselasky "Hint: This can't happen with Linux >= 2.2.0.\n", 1316335640Shselasky handlep->device, 1317335640Shselasky strerror(errno)); 1318335640Shselasky } 1319335640Shselasky } 1320335640Shselasky } 1321335640Shselasky } 1322335640Shselasky 1323335640Shselasky#ifdef HAVE_LIBNL 1324335640Shselasky if (handlep->must_do_on_close & MUST_DELETE_MONIF) { 1325335640Shselasky ret = nl80211_init(handle, &nlstate, handlep->device); 1326335640Shselasky if (ret >= 0) { 1327335640Shselasky ret = del_mon_if(handle, handle->fd, &nlstate, 1328335640Shselasky handlep->device, handlep->mondevice); 1329335640Shselasky nl80211_cleanup(&nlstate); 1330335640Shselasky } 1331335640Shselasky if (ret < 0) { 1332335640Shselasky fprintf(stderr, 1333335640Shselasky "Can't delete monitor interface %s (%s).\n" 1334335640Shselasky "Please delete manually.\n", 1335335640Shselasky handlep->mondevice, handle->errbuf); 1336335640Shselasky } 1337335640Shselasky } 1338335640Shselasky#endif /* HAVE_LIBNL */ 1339335640Shselasky 1340335640Shselasky#ifdef IW_MODE_MONITOR 1341335640Shselasky if (handlep->must_do_on_close & MUST_CLEAR_RFMON) { 1342335640Shselasky /* 1343335640Shselasky * We put the interface into rfmon mode; 1344335640Shselasky * take it out of rfmon mode. 1345335640Shselasky * 1346335640Shselasky * XXX - if somebody else wants it in rfmon 1347335640Shselasky * mode, this code cannot know that, so it'll take 1348335640Shselasky * it out of rfmon mode. 1349335640Shselasky */ 1350335640Shselasky 1351335640Shselasky /* 1352335640Shselasky * First, take the interface down if it's up; 1353335640Shselasky * otherwise, we might get EBUSY. 1354335640Shselasky * If we get errors, just drive on and print 1355335640Shselasky * a warning if we can't restore the mode. 1356335640Shselasky */ 1357335640Shselasky oldflags = 0; 1358335640Shselasky memset(&ifr, 0, sizeof(ifr)); 1359356341Scy pcap_strlcpy(ifr.ifr_name, handlep->device, 1360335640Shselasky sizeof(ifr.ifr_name)); 1361335640Shselasky if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) != -1) { 1362335640Shselasky if (ifr.ifr_flags & IFF_UP) { 1363335640Shselasky oldflags = ifr.ifr_flags; 1364335640Shselasky ifr.ifr_flags &= ~IFF_UP; 1365335640Shselasky if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) 1366335640Shselasky oldflags = 0; /* didn't set, don't restore */ 1367335640Shselasky } 1368335640Shselasky } 1369335640Shselasky 1370335640Shselasky /* 1371335640Shselasky * Now restore the mode. 1372335640Shselasky */ 1373356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, handlep->device, 1374335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 1375335640Shselasky ireq.u.mode = handlep->oldmode; 1376335640Shselasky if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) { 1377335640Shselasky /* 1378335640Shselasky * Scientist, you've failed. 1379335640Shselasky */ 1380335640Shselasky fprintf(stderr, 1381335640Shselasky "Can't restore interface %s wireless mode (SIOCSIWMODE failed: %s).\n" 1382335640Shselasky "Please adjust manually.\n", 1383335640Shselasky handlep->device, strerror(errno)); 1384335640Shselasky } 1385335640Shselasky 1386335640Shselasky /* 1387335640Shselasky * Now bring the interface back up if we brought 1388335640Shselasky * it down. 1389335640Shselasky */ 1390335640Shselasky if (oldflags != 0) { 1391335640Shselasky ifr.ifr_flags = oldflags; 1392335640Shselasky if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { 1393335640Shselasky fprintf(stderr, 1394335640Shselasky "Can't bring interface %s back up (SIOCSIFFLAGS failed: %s).\n" 1395335640Shselasky "Please adjust manually.\n", 1396335640Shselasky handlep->device, strerror(errno)); 1397335640Shselasky } 1398335640Shselasky } 1399335640Shselasky } 1400335640Shselasky#endif /* IW_MODE_MONITOR */ 1401335640Shselasky 1402335640Shselasky /* 1403335640Shselasky * Take this pcap out of the list of pcaps for which we 1404335640Shselasky * have to take the interface out of some mode. 1405335640Shselasky */ 1406335640Shselasky pcap_remove_from_pcaps_to_close(handle); 1407335640Shselasky } 1408335640Shselasky 1409335640Shselasky if (handlep->mondevice != NULL) { 1410335640Shselasky free(handlep->mondevice); 1411335640Shselasky handlep->mondevice = NULL; 1412335640Shselasky } 1413335640Shselasky if (handlep->device != NULL) { 1414335640Shselasky free(handlep->device); 1415335640Shselasky handlep->device = NULL; 1416335640Shselasky } 1417335640Shselasky pcap_cleanup_live_common(handle); 1418335640Shselasky} 1419335640Shselasky 1420335640Shselasky/* 1421335640Shselasky * Set the timeout to be used in poll() with memory-mapped packet capture. 1422335640Shselasky */ 1423335640Shselaskystatic void 1424335640Shselaskyset_poll_timeout(struct pcap_linux *handlep) 1425335640Shselasky{ 1426335640Shselasky#ifdef HAVE_TPACKET3 1427335640Shselasky struct utsname utsname; 1428335640Shselasky char *version_component, *endp; 1429335640Shselasky int major, minor; 1430335640Shselasky int broken_tpacket_v3 = 1; 1431335640Shselasky 1432335640Shselasky /* 1433335640Shselasky * Some versions of TPACKET_V3 have annoying bugs/misfeatures 1434335640Shselasky * around which we have to work. Determine if we have those 1435335640Shselasky * problems or not. 1436335640Shselasky */ 1437335640Shselasky if (uname(&utsname) == 0) { 1438335640Shselasky /* 1439335640Shselasky * 3.19 is the first release with a fixed version of 1440335640Shselasky * TPACKET_V3. We treat anything before that as 1441335640Shselasky * not haveing a fixed version; that may really mean 1442335640Shselasky * it has *no* version. 1443335640Shselasky */ 1444335640Shselasky version_component = utsname.release; 1445335640Shselasky major = strtol(version_component, &endp, 10); 1446335640Shselasky if (endp != version_component && *endp == '.') { 1447335640Shselasky /* 1448335640Shselasky * OK, that was a valid major version. 1449335640Shselasky * Get the minor version. 1450335640Shselasky */ 1451335640Shselasky version_component = endp + 1; 1452335640Shselasky minor = strtol(version_component, &endp, 10); 1453335640Shselasky if (endp != version_component && 1454335640Shselasky (*endp == '.' || *endp == '\0')) { 1455335640Shselasky /* 1456335640Shselasky * OK, that was a valid minor version. 1457335640Shselasky * Is this 3.19 or newer? 1458335640Shselasky */ 1459335640Shselasky if (major >= 4 || (major == 3 && minor >= 19)) { 1460335640Shselasky /* Yes. TPACKET_V3 works correctly. */ 1461335640Shselasky broken_tpacket_v3 = 0; 1462335640Shselasky } 1463335640Shselasky } 1464335640Shselasky } 1465335640Shselasky } 1466335640Shselasky#endif 1467335640Shselasky if (handlep->timeout == 0) { 1468335640Shselasky#ifdef HAVE_TPACKET3 1469335640Shselasky /* 1470335640Shselasky * XXX - due to a set of (mis)features in the TPACKET_V3 1471335640Shselasky * kernel code prior to the 3.19 kernel, blocking forever 1472335640Shselasky * with a TPACKET_V3 socket can, if few packets are 1473335640Shselasky * arriving and passing the socket filter, cause most 1474335640Shselasky * packets to be dropped. See libpcap issue #335 for the 1475335640Shselasky * full painful story. 1476335640Shselasky * 1477335640Shselasky * The workaround is to have poll() time out very quickly, 1478335640Shselasky * so we grab the frames handed to us, and return them to 1479335640Shselasky * the kernel, ASAP. 1480335640Shselasky */ 1481335640Shselasky if (handlep->tp_version == TPACKET_V3 && broken_tpacket_v3) 1482335640Shselasky handlep->poll_timeout = 1; /* don't block for very long */ 1483335640Shselasky else 1484335640Shselasky#endif 1485335640Shselasky handlep->poll_timeout = -1; /* block forever */ 1486335640Shselasky } else if (handlep->timeout > 0) { 1487335640Shselasky#ifdef HAVE_TPACKET3 1488335640Shselasky /* 1489335640Shselasky * For TPACKET_V3, the timeout is handled by the kernel, 1490335640Shselasky * so block forever; that way, we don't get extra timeouts. 1491335640Shselasky * Don't do that if we have a broken TPACKET_V3, though. 1492335640Shselasky */ 1493335640Shselasky if (handlep->tp_version == TPACKET_V3 && !broken_tpacket_v3) 1494335640Shselasky handlep->poll_timeout = -1; /* block forever, let TPACKET_V3 wake us up */ 1495335640Shselasky else 1496335640Shselasky#endif 1497335640Shselasky handlep->poll_timeout = handlep->timeout; /* block for that amount of time */ 1498335640Shselasky } else { 1499335640Shselasky /* 1500335640Shselasky * Non-blocking mode; we call poll() to pick up error 1501335640Shselasky * indications, but we don't want it to wait for 1502335640Shselasky * anything. 1503335640Shselasky */ 1504335640Shselasky handlep->poll_timeout = 0; 1505335640Shselasky } 1506335640Shselasky} 1507335640Shselasky 1508335640Shselasky/* 1509335640Shselasky * Get a handle for a live capture from the given device. You can 1510335640Shselasky * pass NULL as device to get all packages (without link level 1511335640Shselasky * information of course). If you pass 1 as promisc the interface 1512335640Shselasky * will be set to promiscous mode (XXX: I think this usage should 1513335640Shselasky * be deprecated and functions be added to select that later allow 1514335640Shselasky * modification of that values -- Torsten). 1515335640Shselasky */ 1516335640Shselaskystatic int 1517335640Shselaskypcap_activate_linux(pcap_t *handle) 1518335640Shselasky{ 1519335640Shselasky struct pcap_linux *handlep = handle->priv; 1520335640Shselasky const char *device; 1521335640Shselasky struct ifreq ifr; 1522335640Shselasky int status = 0; 1523335640Shselasky int ret; 1524335640Shselasky 1525335640Shselasky device = handle->opt.device; 1526335640Shselasky 1527335640Shselasky /* 1528335640Shselasky * Make sure the name we were handed will fit into the ioctls we 1529335640Shselasky * might perform on the device; if not, return a "No such device" 1530335640Shselasky * indication, as the Linux kernel shouldn't support creating 1531335640Shselasky * a device whose name won't fit into those ioctls. 1532335640Shselasky * 1533335640Shselasky * "Will fit" means "will fit, complete with a null terminator", 1534335640Shselasky * so if the length, which does *not* include the null terminator, 1535335640Shselasky * is greater than *or equal to* the size of the field into which 1536335640Shselasky * we'll be copying it, that won't fit. 1537335640Shselasky */ 1538335640Shselasky if (strlen(device) >= sizeof(ifr.ifr_name)) { 1539335640Shselasky status = PCAP_ERROR_NO_SUCH_DEVICE; 1540335640Shselasky goto fail; 1541335640Shselasky } 1542335640Shselasky 1543335640Shselasky /* 1544335640Shselasky * Turn a negative snapshot value (invalid), a snapshot value of 1545335640Shselasky * 0 (unspecified), or a value bigger than the normal maximum 1546335640Shselasky * value, into the maximum allowed value. 1547335640Shselasky * 1548335640Shselasky * If some application really *needs* a bigger snapshot 1549335640Shselasky * length, we should just increase MAXIMUM_SNAPLEN. 1550335640Shselasky */ 1551335640Shselasky if (handle->snapshot <= 0 || handle->snapshot > MAXIMUM_SNAPLEN) 1552335640Shselasky handle->snapshot = MAXIMUM_SNAPLEN; 1553335640Shselasky 1554335640Shselasky handle->inject_op = pcap_inject_linux; 1555335640Shselasky handle->setfilter_op = pcap_setfilter_linux; 1556335640Shselasky handle->setdirection_op = pcap_setdirection_linux; 1557335640Shselasky handle->set_datalink_op = pcap_set_datalink_linux; 1558335640Shselasky handle->getnonblock_op = pcap_getnonblock_fd; 1559335640Shselasky handle->setnonblock_op = pcap_setnonblock_fd; 1560335640Shselasky handle->cleanup_op = pcap_cleanup_linux; 1561335640Shselasky handle->read_op = pcap_read_linux; 1562335640Shselasky handle->stats_op = pcap_stats_linux; 1563335640Shselasky 1564335640Shselasky /* 1565335640Shselasky * The "any" device is a special device which causes us not 1566335640Shselasky * to bind to a particular device and thus to look at all 1567335640Shselasky * devices. 1568335640Shselasky */ 1569335640Shselasky if (strcmp(device, "any") == 0) { 1570335640Shselasky if (handle->opt.promisc) { 1571335640Shselasky handle->opt.promisc = 0; 1572335640Shselasky /* Just a warning. */ 1573335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 1574335640Shselasky "Promiscuous mode not supported on the \"any\" device"); 1575335640Shselasky status = PCAP_WARNING_PROMISC_NOTSUP; 1576335640Shselasky } 1577335640Shselasky } 1578335640Shselasky 1579335640Shselasky handlep->device = strdup(device); 1580335640Shselasky if (handlep->device == NULL) { 1581335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 1582335640Shselasky errno, "strdup"); 1583356341Scy status = PCAP_ERROR; 1584356341Scy goto fail; 1585335640Shselasky } 1586335640Shselasky 1587335640Shselasky /* copy timeout value */ 1588335640Shselasky handlep->timeout = handle->opt.timeout; 1589335640Shselasky 1590335640Shselasky /* 1591335640Shselasky * If we're in promiscuous mode, then we probably want 1592335640Shselasky * to see when the interface drops packets too, so get an 1593335640Shselasky * initial count from /proc/net/dev 1594335640Shselasky */ 1595335640Shselasky if (handle->opt.promisc) 1596335640Shselasky handlep->proc_dropped = linux_if_drops(handlep->device); 1597335640Shselasky 1598335640Shselasky /* 1599335640Shselasky * Current Linux kernels use the protocol family PF_PACKET to 1600335640Shselasky * allow direct access to all packets on the network while 1601335640Shselasky * older kernels had a special socket type SOCK_PACKET to 1602335640Shselasky * implement this feature. 1603335640Shselasky * While this old implementation is kind of obsolete we need 1604335640Shselasky * to be compatible with older kernels for a while so we are 1605335640Shselasky * trying both methods with the newer method preferred. 1606335640Shselasky */ 1607335640Shselasky ret = activate_new(handle); 1608335640Shselasky if (ret < 0) { 1609335640Shselasky /* 1610335640Shselasky * Fatal error with the new way; just fail. 1611335640Shselasky * ret has the error return; if it's PCAP_ERROR, 1612335640Shselasky * handle->errbuf has been set appropriately. 1613335640Shselasky */ 1614335640Shselasky status = ret; 1615335640Shselasky goto fail; 1616335640Shselasky } 1617335640Shselasky if (ret == 1) { 1618335640Shselasky /* 1619335640Shselasky * Success. 1620335640Shselasky * Try to use memory-mapped access. 1621335640Shselasky */ 1622335640Shselasky switch (activate_mmap(handle, &status)) { 1623335640Shselasky 1624335640Shselasky case 1: 1625335640Shselasky /* 1626335640Shselasky * We succeeded. status has been 1627335640Shselasky * set to the status to return, 1628335640Shselasky * which might be 0, or might be 1629335640Shselasky * a PCAP_WARNING_ value. 1630335640Shselasky * 1631335640Shselasky * Set the timeout to use in poll() before 1632335640Shselasky * returning. 1633335640Shselasky */ 1634335640Shselasky set_poll_timeout(handlep); 1635335640Shselasky return status; 1636335640Shselasky 1637335640Shselasky case 0: 1638335640Shselasky /* 1639335640Shselasky * Kernel doesn't support it - just continue 1640335640Shselasky * with non-memory-mapped access. 1641335640Shselasky */ 1642335640Shselasky break; 1643335640Shselasky 1644335640Shselasky case -1: 1645335640Shselasky /* 1646335640Shselasky * We failed to set up to use it, or the kernel 1647335640Shselasky * supports it, but we failed to enable it. 1648356341Scy * status has been set to the error status to 1649335640Shselasky * return and, if it's PCAP_ERROR, handle->errbuf 1650335640Shselasky * contains the error message. 1651335640Shselasky */ 1652335640Shselasky goto fail; 1653335640Shselasky } 1654335640Shselasky } 1655335640Shselasky else if (ret == 0) { 1656335640Shselasky /* Non-fatal error; try old way */ 1657335640Shselasky if ((ret = activate_old(handle)) != 1) { 1658335640Shselasky /* 1659335640Shselasky * Both methods to open the packet socket failed. 1660335640Shselasky * Tidy up and report our failure (handle->errbuf 1661335640Shselasky * is expected to be set by the functions above). 1662335640Shselasky */ 1663335640Shselasky status = ret; 1664335640Shselasky goto fail; 1665335640Shselasky } 1666335640Shselasky } 1667335640Shselasky 1668335640Shselasky /* 1669335640Shselasky * We set up the socket, but not with memory-mapped access. 1670335640Shselasky */ 1671335640Shselasky if (handle->opt.buffer_size != 0) { 1672335640Shselasky /* 1673335640Shselasky * Set the socket buffer size to the specified value. 1674335640Shselasky */ 1675335640Shselasky if (setsockopt(handle->fd, SOL_SOCKET, SO_RCVBUF, 1676335640Shselasky &handle->opt.buffer_size, 1677335640Shselasky sizeof(handle->opt.buffer_size)) == -1) { 1678335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 1679335640Shselasky PCAP_ERRBUF_SIZE, errno, "SO_RCVBUF"); 1680335640Shselasky status = PCAP_ERROR; 1681335640Shselasky goto fail; 1682335640Shselasky } 1683335640Shselasky } 1684335640Shselasky 1685335640Shselasky /* Allocate the buffer */ 1686335640Shselasky 1687335640Shselasky handle->buffer = malloc(handle->bufsize + handle->offset); 1688335640Shselasky if (!handle->buffer) { 1689335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 1690335640Shselasky errno, "malloc"); 1691335640Shselasky status = PCAP_ERROR; 1692335640Shselasky goto fail; 1693335640Shselasky } 1694335640Shselasky 1695335640Shselasky /* 1696335640Shselasky * "handle->fd" is a socket, so "select()" and "poll()" 1697335640Shselasky * should work on it. 1698335640Shselasky */ 1699335640Shselasky handle->selectable_fd = handle->fd; 1700335640Shselasky 1701335640Shselasky return status; 1702335640Shselasky 1703335640Shselaskyfail: 1704335640Shselasky pcap_cleanup_linux(handle); 1705335640Shselasky return status; 1706335640Shselasky} 1707335640Shselasky 1708335640Shselasky/* 1709335640Shselasky * Read at most max_packets from the capture stream and call the callback 1710335640Shselasky * for each of them. Returns the number of packets handled or -1 if an 1711335640Shselasky * error occured. 1712335640Shselasky */ 1713335640Shselaskystatic int 1714335640Shselaskypcap_read_linux(pcap_t *handle, int max_packets _U_, pcap_handler callback, u_char *user) 1715335640Shselasky{ 1716335640Shselasky /* 1717335640Shselasky * Currently, on Linux only one packet is delivered per read, 1718335640Shselasky * so we don't loop. 1719335640Shselasky */ 1720335640Shselasky return pcap_read_packet(handle, callback, user); 1721335640Shselasky} 1722335640Shselasky 1723335640Shselaskystatic int 1724335640Shselaskypcap_set_datalink_linux(pcap_t *handle, int dlt) 1725335640Shselasky{ 1726335640Shselasky handle->linktype = dlt; 1727335640Shselasky return 0; 1728335640Shselasky} 1729335640Shselasky 1730335640Shselasky/* 1731335640Shselasky * linux_check_direction() 1732335640Shselasky * 1733335640Shselasky * Do checks based on packet direction. 1734335640Shselasky */ 1735335640Shselaskystatic inline int 1736335640Shselaskylinux_check_direction(const pcap_t *handle, const struct sockaddr_ll *sll) 1737335640Shselasky{ 1738335640Shselasky struct pcap_linux *handlep = handle->priv; 1739335640Shselasky 1740335640Shselasky if (sll->sll_pkttype == PACKET_OUTGOING) { 1741335640Shselasky /* 1742335640Shselasky * Outgoing packet. 1743335640Shselasky * If this is from the loopback device, reject it; 1744335640Shselasky * we'll see the packet as an incoming packet as well, 1745335640Shselasky * and we don't want to see it twice. 1746335640Shselasky */ 1747335640Shselasky if (sll->sll_ifindex == handlep->lo_ifindex) 1748335640Shselasky return 0; 1749335640Shselasky 1750335640Shselasky /* 1751335640Shselasky * If this is an outgoing CAN or CAN FD frame, and 1752335640Shselasky * the user doesn't only want outgoing packets, 1753335640Shselasky * reject it; CAN devices and drivers, and the CAN 1754335640Shselasky * stack, always arrange to loop back transmitted 1755335640Shselasky * packets, so they also appear as incoming packets. 1756335640Shselasky * We don't want duplicate packets, and we can't 1757335640Shselasky * easily distinguish packets looped back by the CAN 1758335640Shselasky * layer than those received by the CAN layer, so we 1759335640Shselasky * eliminate this packet instead. 1760335640Shselasky */ 1761335640Shselasky if ((sll->sll_protocol == LINUX_SLL_P_CAN || 1762335640Shselasky sll->sll_protocol == LINUX_SLL_P_CANFD) && 1763335640Shselasky handle->direction != PCAP_D_OUT) 1764335640Shselasky return 0; 1765335640Shselasky 1766335640Shselasky /* 1767335640Shselasky * If the user only wants incoming packets, reject it. 1768335640Shselasky */ 1769335640Shselasky if (handle->direction == PCAP_D_IN) 1770335640Shselasky return 0; 1771335640Shselasky } else { 1772335640Shselasky /* 1773335640Shselasky * Incoming packet. 1774335640Shselasky * If the user only wants outgoing packets, reject it. 1775335640Shselasky */ 1776335640Shselasky if (handle->direction == PCAP_D_OUT) 1777335640Shselasky return 0; 1778335640Shselasky } 1779335640Shselasky return 1; 1780335640Shselasky} 1781335640Shselasky 1782335640Shselasky/* 1783335640Shselasky * Read a packet from the socket calling the handler provided by 1784335640Shselasky * the user. Returns the number of packets received or -1 if an 1785335640Shselasky * error occured. 1786335640Shselasky */ 1787335640Shselaskystatic int 1788335640Shselaskypcap_read_packet(pcap_t *handle, pcap_handler callback, u_char *userdata) 1789335640Shselasky{ 1790335640Shselasky struct pcap_linux *handlep = handle->priv; 1791335640Shselasky u_char *bp; 1792335640Shselasky int offset; 1793335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 1794335640Shselasky struct sockaddr_ll from; 1795335640Shselasky#else 1796335640Shselasky struct sockaddr from; 1797335640Shselasky#endif 1798335640Shselasky#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) 1799335640Shselasky struct iovec iov; 1800335640Shselasky struct msghdr msg; 1801335640Shselasky struct cmsghdr *cmsg; 1802335640Shselasky union { 1803335640Shselasky struct cmsghdr cmsg; 1804335640Shselasky char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata))]; 1805335640Shselasky } cmsg_buf; 1806335640Shselasky#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 1807335640Shselasky socklen_t fromlen; 1808335640Shselasky#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 1809335640Shselasky int packet_len, caplen; 1810335640Shselasky struct pcap_pkthdr pcap_header; 1811335640Shselasky 1812335640Shselasky struct bpf_aux_data aux_data; 1813335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 1814335640Shselasky /* 1815335640Shselasky * If this is a cooked device, leave extra room for a 1816335640Shselasky * fake packet header. 1817335640Shselasky */ 1818356341Scy if (handlep->cooked) { 1819356341Scy if (handle->linktype == DLT_LINUX_SLL2) 1820356341Scy offset = SLL2_HDR_LEN; 1821356341Scy else 1822356341Scy offset = SLL_HDR_LEN; 1823356341Scy } else 1824335640Shselasky offset = 0; 1825335640Shselasky#else 1826335640Shselasky /* 1827335640Shselasky * This system doesn't have PF_PACKET sockets, so it doesn't 1828335640Shselasky * support cooked devices. 1829335640Shselasky */ 1830335640Shselasky offset = 0; 1831335640Shselasky#endif 1832335640Shselasky 1833335640Shselasky /* 1834335640Shselasky * Receive a single packet from the kernel. 1835335640Shselasky * We ignore EINTR, as that might just be due to a signal 1836335640Shselasky * being delivered - if the signal should interrupt the 1837335640Shselasky * loop, the signal handler should call pcap_breakloop() 1838335640Shselasky * to set handle->break_loop (we ignore it on other 1839335640Shselasky * platforms as well). 1840335640Shselasky * We also ignore ENETDOWN, so that we can continue to 1841335640Shselasky * capture traffic if the interface goes down and comes 1842335640Shselasky * back up again; comments in the kernel indicate that 1843335640Shselasky * we'll just block waiting for packets if we try to 1844335640Shselasky * receive from a socket that delivered ENETDOWN, and, 1845335640Shselasky * if we're using a memory-mapped buffer, we won't even 1846335640Shselasky * get notified of "network down" events. 1847335640Shselasky */ 1848335640Shselasky bp = (u_char *)handle->buffer + handle->offset; 1849335640Shselasky 1850335640Shselasky#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) 1851335640Shselasky msg.msg_name = &from; 1852335640Shselasky msg.msg_namelen = sizeof(from); 1853335640Shselasky msg.msg_iov = &iov; 1854335640Shselasky msg.msg_iovlen = 1; 1855335640Shselasky msg.msg_control = &cmsg_buf; 1856335640Shselasky msg.msg_controllen = sizeof(cmsg_buf); 1857335640Shselasky msg.msg_flags = 0; 1858335640Shselasky 1859335640Shselasky iov.iov_len = handle->bufsize - offset; 1860335640Shselasky iov.iov_base = bp + offset; 1861335640Shselasky#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 1862335640Shselasky 1863335640Shselasky do { 1864335640Shselasky /* 1865335640Shselasky * Has "pcap_breakloop()" been called? 1866335640Shselasky */ 1867335640Shselasky if (handle->break_loop) { 1868335640Shselasky /* 1869335640Shselasky * Yes - clear the flag that indicates that it has, 1870335640Shselasky * and return PCAP_ERROR_BREAK as an indication that 1871335640Shselasky * we were told to break out of the loop. 1872335640Shselasky */ 1873335640Shselasky handle->break_loop = 0; 1874335640Shselasky return PCAP_ERROR_BREAK; 1875335640Shselasky } 1876335640Shselasky 1877335640Shselasky#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) 1878335640Shselasky packet_len = recvmsg(handle->fd, &msg, MSG_TRUNC); 1879335640Shselasky#else /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 1880335640Shselasky fromlen = sizeof(from); 1881335640Shselasky packet_len = recvfrom( 1882335640Shselasky handle->fd, bp + offset, 1883335640Shselasky handle->bufsize - offset, MSG_TRUNC, 1884335640Shselasky (struct sockaddr *) &from, &fromlen); 1885335640Shselasky#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 1886335640Shselasky } while (packet_len == -1 && errno == EINTR); 1887335640Shselasky 1888335640Shselasky /* Check if an error occured */ 1889335640Shselasky 1890335640Shselasky if (packet_len == -1) { 1891335640Shselasky switch (errno) { 1892335640Shselasky 1893335640Shselasky case EAGAIN: 1894335640Shselasky return 0; /* no packet there */ 1895335640Shselasky 1896335640Shselasky case ENETDOWN: 1897335640Shselasky /* 1898335640Shselasky * The device on which we're capturing went away. 1899335640Shselasky * 1900335640Shselasky * XXX - we should really return 1901335640Shselasky * PCAP_ERROR_IFACE_NOT_UP, but pcap_dispatch() 1902335640Shselasky * etc. aren't defined to return that. 1903335640Shselasky */ 1904335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 1905335640Shselasky "The interface went down"); 1906335640Shselasky return PCAP_ERROR; 1907335640Shselasky 1908335640Shselasky default: 1909335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 1910335640Shselasky PCAP_ERRBUF_SIZE, errno, "recvfrom"); 1911335640Shselasky return PCAP_ERROR; 1912335640Shselasky } 1913335640Shselasky } 1914335640Shselasky 1915335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 1916335640Shselasky if (!handlep->sock_packet) { 1917335640Shselasky /* 1918335640Shselasky * Unfortunately, there is a window between socket() and 1919335640Shselasky * bind() where the kernel may queue packets from any 1920335640Shselasky * interface. If we're bound to a particular interface, 1921335640Shselasky * discard packets not from that interface. 1922335640Shselasky * 1923335640Shselasky * (If socket filters are supported, we could do the 1924335640Shselasky * same thing we do when changing the filter; however, 1925335640Shselasky * that won't handle packet sockets without socket 1926335640Shselasky * filter support, and it's a bit more complicated. 1927335640Shselasky * It would save some instructions per packet, however.) 1928335640Shselasky */ 1929335640Shselasky if (handlep->ifindex != -1 && 1930335640Shselasky from.sll_ifindex != handlep->ifindex) 1931335640Shselasky return 0; 1932335640Shselasky 1933335640Shselasky /* 1934335640Shselasky * Do checks based on packet direction. 1935335640Shselasky * We can only do this if we're using PF_PACKET; the 1936335640Shselasky * address returned for SOCK_PACKET is a "sockaddr_pkt" 1937335640Shselasky * which lacks the relevant packet type information. 1938335640Shselasky */ 1939335640Shselasky if (!linux_check_direction(handle, &from)) 1940335640Shselasky return 0; 1941335640Shselasky } 1942335640Shselasky#endif 1943335640Shselasky 1944335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 1945335640Shselasky /* 1946335640Shselasky * If this is a cooked device, fill in the fake packet header. 1947335640Shselasky */ 1948335640Shselasky if (handlep->cooked) { 1949335640Shselasky /* 1950335640Shselasky * Add the length of the fake header to the length 1951335640Shselasky * of packet data we read. 1952335640Shselasky */ 1953356341Scy if (handle->linktype == DLT_LINUX_SLL2) { 1954356341Scy struct sll2_header *hdrp; 1955335640Shselasky 1956356341Scy packet_len += SLL2_HDR_LEN; 1957356341Scy 1958356341Scy hdrp = (struct sll2_header *)bp; 1959356341Scy hdrp->sll2_protocol = from.sll_protocol; 1960356341Scy hdrp->sll2_reserved_mbz = 0; 1961356341Scy hdrp->sll2_if_index = htonl(from.sll_ifindex); 1962356341Scy hdrp->sll2_hatype = htons(from.sll_hatype); 1963356341Scy hdrp->sll2_pkttype = from.sll_pkttype; 1964356341Scy hdrp->sll2_halen = from.sll_halen; 1965356341Scy memcpy(hdrp->sll2_addr, from.sll_addr, 1966356341Scy (from.sll_halen > SLL_ADDRLEN) ? 1967356341Scy SLL_ADDRLEN : 1968356341Scy from.sll_halen); 1969356341Scy } else { 1970356341Scy struct sll_header *hdrp; 1971356341Scy 1972356341Scy packet_len += SLL_HDR_LEN; 1973356341Scy 1974356341Scy hdrp = (struct sll_header *)bp; 1975356341Scy hdrp->sll_pkttype = htons(from.sll_pkttype); 1976356341Scy hdrp->sll_hatype = htons(from.sll_hatype); 1977356341Scy hdrp->sll_halen = htons(from.sll_halen); 1978356341Scy memcpy(hdrp->sll_addr, from.sll_addr, 1979356341Scy (from.sll_halen > SLL_ADDRLEN) ? 1980356341Scy SLL_ADDRLEN : 1981356341Scy from.sll_halen); 1982356341Scy hdrp->sll_protocol = from.sll_protocol; 1983356341Scy } 1984335640Shselasky } 1985335640Shselasky 1986335640Shselasky /* 1987335640Shselasky * Start out with no VLAN information. 1988335640Shselasky */ 1989335640Shselasky aux_data.vlan_tag_present = 0; 1990335640Shselasky aux_data.vlan_tag = 0; 1991335640Shselasky#if defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) 1992335640Shselasky if (handlep->vlan_offset != -1) { 1993335640Shselasky for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { 1994335640Shselasky struct tpacket_auxdata *aux; 1995335640Shselasky unsigned int len; 1996335640Shselasky struct vlan_tag *tag; 1997335640Shselasky 1998335640Shselasky if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata)) || 1999335640Shselasky cmsg->cmsg_level != SOL_PACKET || 2000335640Shselasky cmsg->cmsg_type != PACKET_AUXDATA) { 2001335640Shselasky /* 2002335640Shselasky * This isn't a PACKET_AUXDATA auxiliary 2003335640Shselasky * data item. 2004335640Shselasky */ 2005335640Shselasky continue; 2006335640Shselasky } 2007335640Shselasky 2008335640Shselasky aux = (struct tpacket_auxdata *)CMSG_DATA(cmsg); 2009335640Shselasky if (!VLAN_VALID(aux, aux)) { 2010335640Shselasky /* 2011335640Shselasky * There is no VLAN information in the 2012335640Shselasky * auxiliary data. 2013335640Shselasky */ 2014335640Shselasky continue; 2015335640Shselasky } 2016335640Shselasky 2017335640Shselasky len = (u_int)packet_len > iov.iov_len ? iov.iov_len : (u_int)packet_len; 2018335640Shselasky if (len < (u_int)handlep->vlan_offset) 2019335640Shselasky break; 2020335640Shselasky 2021335640Shselasky /* 2022335640Shselasky * Move everything in the header, except the 2023335640Shselasky * type field, down VLAN_TAG_LEN bytes, to 2024335640Shselasky * allow us to insert the VLAN tag between 2025335640Shselasky * that stuff and the type field. 2026335640Shselasky */ 2027335640Shselasky bp -= VLAN_TAG_LEN; 2028335640Shselasky memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); 2029335640Shselasky 2030335640Shselasky /* 2031335640Shselasky * Now insert the tag. 2032335640Shselasky */ 2033335640Shselasky tag = (struct vlan_tag *)(bp + handlep->vlan_offset); 2034335640Shselasky tag->vlan_tpid = htons(VLAN_TPID(aux, aux)); 2035335640Shselasky tag->vlan_tci = htons(aux->tp_vlan_tci); 2036335640Shselasky 2037335640Shselasky /* 2038335640Shselasky * Save a flag indicating that we have a VLAN tag, 2039335640Shselasky * and the VLAN TCI, to bpf_aux_data struct for 2040335640Shselasky * use by the BPF filter if we're doing the 2041335640Shselasky * filtering in userland. 2042335640Shselasky */ 2043335640Shselasky aux_data.vlan_tag_present = 1; 2044335640Shselasky aux_data.vlan_tag = htons(aux->tp_vlan_tci) & 0x0fff; 2045335640Shselasky 2046335640Shselasky /* 2047335640Shselasky * Add the tag to the packet lengths. 2048335640Shselasky */ 2049335640Shselasky packet_len += VLAN_TAG_LEN; 2050335640Shselasky } 2051335640Shselasky } 2052335640Shselasky#endif /* defined(HAVE_PACKET_AUXDATA) && defined(HAVE_STRUCT_TPACKET_AUXDATA_TP_VLAN_TCI) */ 2053335640Shselasky#endif /* HAVE_PF_PACKET_SOCKETS */ 2054335640Shselasky 2055335640Shselasky /* 2056335640Shselasky * XXX: According to the kernel source we should get the real 2057335640Shselasky * packet len if calling recvfrom with MSG_TRUNC set. It does 2058335640Shselasky * not seem to work here :(, but it is supported by this code 2059335640Shselasky * anyway. 2060335640Shselasky * To be honest the code RELIES on that feature so this is really 2061335640Shselasky * broken with 2.2.x kernels. 2062335640Shselasky * I spend a day to figure out what's going on and I found out 2063335640Shselasky * that the following is happening: 2064335640Shselasky * 2065335640Shselasky * The packet comes from a random interface and the packet_rcv 2066335640Shselasky * hook is called with a clone of the packet. That code inserts 2067335640Shselasky * the packet into the receive queue of the packet socket. 2068335640Shselasky * If a filter is attached to that socket that filter is run 2069335640Shselasky * first - and there lies the problem. The default filter always 2070335640Shselasky * cuts the packet at the snaplen: 2071335640Shselasky * 2072335640Shselasky * # tcpdump -d 2073335640Shselasky * (000) ret #68 2074335640Shselasky * 2075335640Shselasky * So the packet filter cuts down the packet. The recvfrom call 2076335640Shselasky * says "hey, it's only 68 bytes, it fits into the buffer" with 2077335640Shselasky * the result that we don't get the real packet length. This 2078335640Shselasky * is valid at least until kernel 2.2.17pre6. 2079335640Shselasky * 2080335640Shselasky * We currently handle this by making a copy of the filter 2081335640Shselasky * program, fixing all "ret" instructions with non-zero 2082335640Shselasky * operands to have an operand of MAXIMUM_SNAPLEN so that the 2083335640Shselasky * filter doesn't truncate the packet, and supplying that modified 2084335640Shselasky * filter to the kernel. 2085335640Shselasky */ 2086335640Shselasky 2087335640Shselasky caplen = packet_len; 2088335640Shselasky if (caplen > handle->snapshot) 2089335640Shselasky caplen = handle->snapshot; 2090335640Shselasky 2091335640Shselasky /* Run the packet filter if not using kernel filter */ 2092335640Shselasky if (handlep->filter_in_userland && handle->fcode.bf_insns) { 2093335640Shselasky if (bpf_filter_with_aux_data(handle->fcode.bf_insns, bp, 2094335640Shselasky packet_len, caplen, &aux_data) == 0) { 2095335640Shselasky /* rejected by filter */ 2096335640Shselasky return 0; 2097335640Shselasky } 2098335640Shselasky } 2099335640Shselasky 2100335640Shselasky /* Fill in our own header data */ 2101335640Shselasky 2102335640Shselasky /* get timestamp for this packet */ 2103335640Shselasky#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) 2104335640Shselasky if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) { 2105335640Shselasky if (ioctl(handle->fd, SIOCGSTAMPNS, &pcap_header.ts) == -1) { 2106335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 2107335640Shselasky PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMPNS"); 2108335640Shselasky return PCAP_ERROR; 2109335640Shselasky } 2110335640Shselasky } else 2111335640Shselasky#endif 2112335640Shselasky { 2113335640Shselasky if (ioctl(handle->fd, SIOCGSTAMP, &pcap_header.ts) == -1) { 2114335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 2115335640Shselasky PCAP_ERRBUF_SIZE, errno, "SIOCGSTAMP"); 2116335640Shselasky return PCAP_ERROR; 2117335640Shselasky } 2118335640Shselasky } 2119335640Shselasky 2120335640Shselasky pcap_header.caplen = caplen; 2121335640Shselasky pcap_header.len = packet_len; 2122335640Shselasky 2123335640Shselasky /* 2124335640Shselasky * Count the packet. 2125335640Shselasky * 2126335640Shselasky * Arguably, we should count them before we check the filter, 2127335640Shselasky * as on many other platforms "ps_recv" counts packets 2128335640Shselasky * handed to the filter rather than packets that passed 2129335640Shselasky * the filter, but if filtering is done in the kernel, we 2130335640Shselasky * can't get a count of packets that passed the filter, 2131335640Shselasky * and that would mean the meaning of "ps_recv" wouldn't 2132335640Shselasky * be the same on all Linux systems. 2133335640Shselasky * 2134335640Shselasky * XXX - it's not the same on all systems in any case; 2135335640Shselasky * ideally, we should have a "get the statistics" call 2136335640Shselasky * that supplies more counts and indicates which of them 2137335640Shselasky * it supplies, so that we supply a count of packets 2138335640Shselasky * handed to the filter only on platforms where that 2139335640Shselasky * information is available. 2140335640Shselasky * 2141335640Shselasky * We count them here even if we can get the packet count 2142335640Shselasky * from the kernel, as we can only determine at run time 2143335640Shselasky * whether we'll be able to get it from the kernel (if 2144335640Shselasky * HAVE_STRUCT_TPACKET_STATS isn't defined, we can't get it from 2145335640Shselasky * the kernel, but if it is defined, the library might 2146335640Shselasky * have been built with a 2.4 or later kernel, but we 2147335640Shselasky * might be running on a 2.2[.x] kernel without Alexey 2148335640Shselasky * Kuznetzov's turbopacket patches, and thus the kernel 2149335640Shselasky * might not be able to supply those statistics). We 2150335640Shselasky * could, I guess, try, when opening the socket, to get 2151335640Shselasky * the statistics, and if we can not increment the count 2152335640Shselasky * here, but it's not clear that always incrementing 2153335640Shselasky * the count is more expensive than always testing a flag 2154335640Shselasky * in memory. 2155335640Shselasky * 2156335640Shselasky * We keep the count in "handlep->packets_read", and use that 2157335640Shselasky * for "ps_recv" if we can't get the statistics from the kernel. 2158335640Shselasky * We do that because, if we *can* get the statistics from 2159335640Shselasky * the kernel, we use "handlep->stat.ps_recv" and 2160335640Shselasky * "handlep->stat.ps_drop" as running counts, as reading the 2161335640Shselasky * statistics from the kernel resets the kernel statistics, 2162335640Shselasky * and if we directly increment "handlep->stat.ps_recv" here, 2163335640Shselasky * that means it will count packets *twice* on systems where 2164335640Shselasky * we can get kernel statistics - once here, and once in 2165335640Shselasky * pcap_stats_linux(). 2166335640Shselasky */ 2167335640Shselasky handlep->packets_read++; 2168335640Shselasky 2169335640Shselasky /* Call the user supplied callback function */ 2170335640Shselasky callback(userdata, &pcap_header, bp); 2171335640Shselasky 2172335640Shselasky return 1; 2173335640Shselasky} 2174335640Shselasky 2175335640Shselaskystatic int 2176335640Shselaskypcap_inject_linux(pcap_t *handle, const void *buf, size_t size) 2177335640Shselasky{ 2178335640Shselasky struct pcap_linux *handlep = handle->priv; 2179335640Shselasky int ret; 2180335640Shselasky 2181335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 2182335640Shselasky if (!handlep->sock_packet) { 2183335640Shselasky /* PF_PACKET socket */ 2184335640Shselasky if (handlep->ifindex == -1) { 2185335640Shselasky /* 2186335640Shselasky * We don't support sending on the "any" device. 2187335640Shselasky */ 2188356341Scy pcap_strlcpy(handle->errbuf, 2189335640Shselasky "Sending packets isn't supported on the \"any\" device", 2190335640Shselasky PCAP_ERRBUF_SIZE); 2191335640Shselasky return (-1); 2192335640Shselasky } 2193335640Shselasky 2194335640Shselasky if (handlep->cooked) { 2195335640Shselasky /* 2196356341Scy * We don't support sending on cooked-mode sockets. 2197335640Shselasky * 2198335640Shselasky * XXX - how do you send on a bound cooked-mode 2199335640Shselasky * socket? 2200335640Shselasky * Is a "sendto()" required there? 2201335640Shselasky */ 2202356341Scy pcap_strlcpy(handle->errbuf, 2203335640Shselasky "Sending packets isn't supported in cooked mode", 2204335640Shselasky PCAP_ERRBUF_SIZE); 2205335640Shselasky return (-1); 2206335640Shselasky } 2207335640Shselasky } 2208335640Shselasky#endif 2209335640Shselasky 2210335640Shselasky ret = send(handle->fd, buf, size, 0); 2211335640Shselasky if (ret == -1) { 2212335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 2213335640Shselasky errno, "send"); 2214335640Shselasky return (-1); 2215335640Shselasky } 2216335640Shselasky return (ret); 2217335640Shselasky} 2218335640Shselasky 2219335640Shselasky/* 2220335640Shselasky * Get the statistics for the given packet capture handle. 2221335640Shselasky * Reports the number of dropped packets iff the kernel supports 2222335640Shselasky * the PACKET_STATISTICS "getsockopt()" argument (2.4 and later 2223335640Shselasky * kernels, and 2.2[.x] kernels with Alexey Kuznetzov's turbopacket 2224335640Shselasky * patches); otherwise, that information isn't available, and we lie 2225335640Shselasky * and report 0 as the count of dropped packets. 2226335640Shselasky */ 2227335640Shselaskystatic int 2228335640Shselaskypcap_stats_linux(pcap_t *handle, struct pcap_stat *stats) 2229335640Shselasky{ 2230335640Shselasky struct pcap_linux *handlep = handle->priv; 2231335640Shselasky#ifdef HAVE_STRUCT_TPACKET_STATS 2232335640Shselasky#ifdef HAVE_TPACKET3 2233335640Shselasky /* 2234335640Shselasky * For sockets using TPACKET_V1 or TPACKET_V2, the extra 2235335640Shselasky * stuff at the end of a struct tpacket_stats_v3 will not 2236335640Shselasky * be filled in, and we don't look at it so this is OK even 2237335640Shselasky * for those sockets. In addition, the PF_PACKET socket 2238335640Shselasky * code in the kernel only uses the length parameter to 2239335640Shselasky * compute how much data to copy out and to indicate how 2240335640Shselasky * much data was copied out, so it's OK to base it on the 2241335640Shselasky * size of a struct tpacket_stats. 2242335640Shselasky * 2243335640Shselasky * XXX - it's probably OK, in fact, to just use a 2244335640Shselasky * struct tpacket_stats for V3 sockets, as we don't 2245335640Shselasky * care about the tp_freeze_q_cnt stat. 2246335640Shselasky */ 2247335640Shselasky struct tpacket_stats_v3 kstats; 2248335640Shselasky#else /* HAVE_TPACKET3 */ 2249335640Shselasky struct tpacket_stats kstats; 2250335640Shselasky#endif /* HAVE_TPACKET3 */ 2251335640Shselasky socklen_t len = sizeof (struct tpacket_stats); 2252335640Shselasky#endif /* HAVE_STRUCT_TPACKET_STATS */ 2253335640Shselasky 2254335640Shselasky long if_dropped = 0; 2255335640Shselasky 2256335640Shselasky /* 2257335640Shselasky * To fill in ps_ifdrop, we parse /proc/net/dev for the number 2258335640Shselasky */ 2259335640Shselasky if (handle->opt.promisc) 2260335640Shselasky { 2261335640Shselasky if_dropped = handlep->proc_dropped; 2262335640Shselasky handlep->proc_dropped = linux_if_drops(handlep->device); 2263335640Shselasky handlep->stat.ps_ifdrop += (handlep->proc_dropped - if_dropped); 2264335640Shselasky } 2265335640Shselasky 2266335640Shselasky#ifdef HAVE_STRUCT_TPACKET_STATS 2267335640Shselasky /* 2268335640Shselasky * Try to get the packet counts from the kernel. 2269335640Shselasky */ 2270335640Shselasky if (getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, 2271335640Shselasky &kstats, &len) > -1) { 2272335640Shselasky /* 2273335640Shselasky * On systems where the PACKET_STATISTICS "getsockopt()" 2274335640Shselasky * argument is supported on PF_PACKET sockets: 2275335640Shselasky * 2276335640Shselasky * "ps_recv" counts only packets that *passed* the 2277335640Shselasky * filter, not packets that didn't pass the filter. 2278335640Shselasky * This includes packets later dropped because we 2279335640Shselasky * ran out of buffer space. 2280335640Shselasky * 2281335640Shselasky * "ps_drop" counts packets dropped because we ran 2282335640Shselasky * out of buffer space. It doesn't count packets 2283335640Shselasky * dropped by the interface driver. It counts only 2284335640Shselasky * packets that passed the filter. 2285335640Shselasky * 2286335640Shselasky * See above for ps_ifdrop. 2287335640Shselasky * 2288335640Shselasky * Both statistics include packets not yet read from 2289335640Shselasky * the kernel by libpcap, and thus not yet seen by 2290335640Shselasky * the application. 2291335640Shselasky * 2292335640Shselasky * In "linux/net/packet/af_packet.c", at least in the 2293335640Shselasky * 2.4.9 kernel, "tp_packets" is incremented for every 2294335640Shselasky * packet that passes the packet filter *and* is 2295335640Shselasky * successfully queued on the socket; "tp_drops" is 2296335640Shselasky * incremented for every packet dropped because there's 2297335640Shselasky * not enough free space in the socket buffer. 2298335640Shselasky * 2299335640Shselasky * When the statistics are returned for a PACKET_STATISTICS 2300335640Shselasky * "getsockopt()" call, "tp_drops" is added to "tp_packets", 2301335640Shselasky * so that "tp_packets" counts all packets handed to 2302335640Shselasky * the PF_PACKET socket, including packets dropped because 2303335640Shselasky * there wasn't room on the socket buffer - but not 2304335640Shselasky * including packets that didn't pass the filter. 2305335640Shselasky * 2306335640Shselasky * In the BSD BPF, the count of received packets is 2307335640Shselasky * incremented for every packet handed to BPF, regardless 2308335640Shselasky * of whether it passed the filter. 2309335640Shselasky * 2310335640Shselasky * We can't make "pcap_stats()" work the same on both 2311335640Shselasky * platforms, but the best approximation is to return 2312335640Shselasky * "tp_packets" as the count of packets and "tp_drops" 2313335640Shselasky * as the count of drops. 2314335640Shselasky * 2315335640Shselasky * Keep a running total because each call to 2316335640Shselasky * getsockopt(handle->fd, SOL_PACKET, PACKET_STATISTICS, .... 2317335640Shselasky * resets the counters to zero. 2318335640Shselasky */ 2319335640Shselasky handlep->stat.ps_recv += kstats.tp_packets; 2320335640Shselasky handlep->stat.ps_drop += kstats.tp_drops; 2321335640Shselasky *stats = handlep->stat; 2322335640Shselasky return 0; 2323335640Shselasky } 2324335640Shselasky else 2325335640Shselasky { 2326335640Shselasky /* 2327335640Shselasky * If the error was EOPNOTSUPP, fall through, so that 2328335640Shselasky * if you build the library on a system with 2329335640Shselasky * "struct tpacket_stats" and run it on a system 2330335640Shselasky * that doesn't, it works as it does if the library 2331335640Shselasky * is built on a system without "struct tpacket_stats". 2332335640Shselasky */ 2333335640Shselasky if (errno != EOPNOTSUPP) { 2334335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 2335335640Shselasky PCAP_ERRBUF_SIZE, errno, "pcap_stats"); 2336335640Shselasky return -1; 2337335640Shselasky } 2338335640Shselasky } 2339335640Shselasky#endif 2340335640Shselasky /* 2341335640Shselasky * On systems where the PACKET_STATISTICS "getsockopt()" argument 2342335640Shselasky * is not supported on PF_PACKET sockets: 2343335640Shselasky * 2344335640Shselasky * "ps_recv" counts only packets that *passed* the filter, 2345335640Shselasky * not packets that didn't pass the filter. It does not 2346335640Shselasky * count packets dropped because we ran out of buffer 2347335640Shselasky * space. 2348335640Shselasky * 2349335640Shselasky * "ps_drop" is not supported. 2350335640Shselasky * 2351335640Shselasky * "ps_ifdrop" is supported. It will return the number 2352335640Shselasky * of drops the interface reports in /proc/net/dev, 2353335640Shselasky * if that is available. 2354335640Shselasky * 2355335640Shselasky * "ps_recv" doesn't include packets not yet read from 2356335640Shselasky * the kernel by libpcap. 2357335640Shselasky * 2358335640Shselasky * We maintain the count of packets processed by libpcap in 2359335640Shselasky * "handlep->packets_read", for reasons described in the comment 2360335640Shselasky * at the end of pcap_read_packet(). We have no idea how many 2361335640Shselasky * packets were dropped by the kernel buffers -- but we know 2362335640Shselasky * how many the interface dropped, so we can return that. 2363335640Shselasky */ 2364335640Shselasky 2365335640Shselasky stats->ps_recv = handlep->packets_read; 2366335640Shselasky stats->ps_drop = 0; 2367335640Shselasky stats->ps_ifdrop = handlep->stat.ps_ifdrop; 2368335640Shselasky return 0; 2369335640Shselasky} 2370335640Shselasky 2371335640Shselaskystatic int 2372335640Shselaskyadd_linux_if(pcap_if_list_t *devlistp, const char *ifname, int fd, char *errbuf) 2373335640Shselasky{ 2374335640Shselasky const char *p; 2375335640Shselasky char name[512]; /* XXX - pick a size */ 2376335640Shselasky char *q, *saveq; 2377335640Shselasky struct ifreq ifrflags; 2378335640Shselasky 2379335640Shselasky /* 2380335640Shselasky * Get the interface name. 2381335640Shselasky */ 2382335640Shselasky p = ifname; 2383335640Shselasky q = &name[0]; 2384335640Shselasky while (*p != '\0' && isascii(*p) && !isspace(*p)) { 2385335640Shselasky if (*p == ':') { 2386335640Shselasky /* 2387335640Shselasky * This could be the separator between a 2388335640Shselasky * name and an alias number, or it could be 2389335640Shselasky * the separator between a name with no 2390335640Shselasky * alias number and the next field. 2391335640Shselasky * 2392335640Shselasky * If there's a colon after digits, it 2393335640Shselasky * separates the name and the alias number, 2394335640Shselasky * otherwise it separates the name and the 2395335640Shselasky * next field. 2396335640Shselasky */ 2397335640Shselasky saveq = q; 2398335640Shselasky while (isascii(*p) && isdigit(*p)) 2399335640Shselasky *q++ = *p++; 2400335640Shselasky if (*p != ':') { 2401335640Shselasky /* 2402335640Shselasky * That was the next field, 2403335640Shselasky * not the alias number. 2404335640Shselasky */ 2405335640Shselasky q = saveq; 2406335640Shselasky } 2407335640Shselasky break; 2408335640Shselasky } else 2409335640Shselasky *q++ = *p++; 2410335640Shselasky } 2411335640Shselasky *q = '\0'; 2412335640Shselasky 2413335640Shselasky /* 2414335640Shselasky * Get the flags for this interface. 2415335640Shselasky */ 2416356341Scy pcap_strlcpy(ifrflags.ifr_name, name, sizeof(ifrflags.ifr_name)); 2417335640Shselasky if (ioctl(fd, SIOCGIFFLAGS, (char *)&ifrflags) < 0) { 2418335640Shselasky if (errno == ENXIO || errno == ENODEV) 2419335640Shselasky return (0); /* device doesn't actually exist - ignore it */ 2420335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2421335640Shselasky errno, "SIOCGIFFLAGS: %.*s", 2422335640Shselasky (int)sizeof(ifrflags.ifr_name), 2423335640Shselasky ifrflags.ifr_name); 2424335640Shselasky return (-1); 2425335640Shselasky } 2426335640Shselasky 2427335640Shselasky /* 2428335640Shselasky * Add an entry for this interface, with no addresses, if it's 2429335640Shselasky * not already in the list. 2430335640Shselasky */ 2431335640Shselasky if (find_or_add_if(devlistp, name, ifrflags.ifr_flags, 2432335640Shselasky get_if_flags, errbuf) == NULL) { 2433335640Shselasky /* 2434335640Shselasky * Failure. 2435335640Shselasky */ 2436335640Shselasky return (-1); 2437335640Shselasky } 2438335640Shselasky 2439335640Shselasky return (0); 2440335640Shselasky} 2441335640Shselasky 2442335640Shselasky/* 2443335640Shselasky * Get from "/sys/class/net" all interfaces listed there; if they're 2444335640Shselasky * already in the list of interfaces we have, that won't add another 2445335640Shselasky * instance, but if they're not, that'll add them. 2446335640Shselasky * 2447335640Shselasky * We don't bother getting any addresses for them; it appears you can't 2448335640Shselasky * use SIOCGIFADDR on Linux to get IPv6 addresses for interfaces, and, 2449335640Shselasky * although some other types of addresses can be fetched with SIOCGIFADDR, 2450335640Shselasky * we don't bother with them for now. 2451335640Shselasky * 2452335640Shselasky * We also don't fail if we couldn't open "/sys/class/net"; we just leave 2453335640Shselasky * the list of interfaces as is, and return 0, so that we can try 2454335640Shselasky * scanning /proc/net/dev. 2455335640Shselasky * 2456335640Shselasky * Otherwise, we return 1 if we don't get an error and -1 if we do. 2457335640Shselasky */ 2458335640Shselaskystatic int 2459335640Shselaskyscan_sys_class_net(pcap_if_list_t *devlistp, char *errbuf) 2460335640Shselasky{ 2461335640Shselasky DIR *sys_class_net_d; 2462335640Shselasky int fd; 2463335640Shselasky struct dirent *ent; 2464335640Shselasky char subsystem_path[PATH_MAX+1]; 2465335640Shselasky struct stat statb; 2466335640Shselasky int ret = 1; 2467335640Shselasky 2468335640Shselasky sys_class_net_d = opendir("/sys/class/net"); 2469335640Shselasky if (sys_class_net_d == NULL) { 2470335640Shselasky /* 2471335640Shselasky * Don't fail if it doesn't exist at all. 2472335640Shselasky */ 2473335640Shselasky if (errno == ENOENT) 2474335640Shselasky return (0); 2475335640Shselasky 2476335640Shselasky /* 2477335640Shselasky * Fail if we got some other error. 2478335640Shselasky */ 2479335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2480335640Shselasky errno, "Can't open /sys/class/net"); 2481335640Shselasky return (-1); 2482335640Shselasky } 2483335640Shselasky 2484335640Shselasky /* 2485335640Shselasky * Create a socket from which to fetch interface information. 2486335640Shselasky */ 2487335640Shselasky fd = socket(PF_UNIX, SOCK_RAW, 0); 2488335640Shselasky if (fd < 0) { 2489335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2490335640Shselasky errno, "socket"); 2491335640Shselasky (void)closedir(sys_class_net_d); 2492335640Shselasky return (-1); 2493335640Shselasky } 2494335640Shselasky 2495335640Shselasky for (;;) { 2496335640Shselasky errno = 0; 2497335640Shselasky ent = readdir(sys_class_net_d); 2498335640Shselasky if (ent == NULL) { 2499335640Shselasky /* 2500335640Shselasky * Error or EOF; if errno != 0, it's an error. 2501335640Shselasky */ 2502335640Shselasky break; 2503335640Shselasky } 2504335640Shselasky 2505335640Shselasky /* 2506335640Shselasky * Ignore "." and "..". 2507335640Shselasky */ 2508335640Shselasky if (strcmp(ent->d_name, ".") == 0 || 2509335640Shselasky strcmp(ent->d_name, "..") == 0) 2510335640Shselasky continue; 2511335640Shselasky 2512335640Shselasky /* 2513335640Shselasky * Ignore plain files; they do not have subdirectories 2514335640Shselasky * and thus have no attributes. 2515335640Shselasky */ 2516335640Shselasky if (ent->d_type == DT_REG) 2517335640Shselasky continue; 2518335640Shselasky 2519335640Shselasky /* 2520335640Shselasky * Is there an "ifindex" file under that name? 2521335640Shselasky * (We don't care whether it's a directory or 2522335640Shselasky * a symlink; older kernels have directories 2523335640Shselasky * for devices, newer kernels have symlinks to 2524335640Shselasky * directories.) 2525335640Shselasky */ 2526335640Shselasky pcap_snprintf(subsystem_path, sizeof subsystem_path, 2527335640Shselasky "/sys/class/net/%s/ifindex", ent->d_name); 2528335640Shselasky if (lstat(subsystem_path, &statb) != 0) { 2529335640Shselasky /* 2530335640Shselasky * Stat failed. Either there was an error 2531335640Shselasky * other than ENOENT, and we don't know if 2532335640Shselasky * this is an interface, or it's ENOENT, 2533335640Shselasky * and either some part of "/sys/class/net/{if}" 2534335640Shselasky * disappeared, in which case it probably means 2535335640Shselasky * the interface disappeared, or there's no 2536335640Shselasky * "ifindex" file, which means it's not a 2537335640Shselasky * network interface. 2538335640Shselasky */ 2539335640Shselasky continue; 2540335640Shselasky } 2541335640Shselasky 2542335640Shselasky /* 2543335640Shselasky * Attempt to add the interface. 2544335640Shselasky */ 2545335640Shselasky if (add_linux_if(devlistp, &ent->d_name[0], fd, errbuf) == -1) { 2546335640Shselasky /* Fail. */ 2547335640Shselasky ret = -1; 2548335640Shselasky break; 2549335640Shselasky } 2550335640Shselasky } 2551335640Shselasky if (ret != -1) { 2552335640Shselasky /* 2553335640Shselasky * Well, we didn't fail for any other reason; did we 2554335640Shselasky * fail due to an error reading the directory? 2555335640Shselasky */ 2556335640Shselasky if (errno != 0) { 2557335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2558335640Shselasky errno, "Error reading /sys/class/net"); 2559335640Shselasky ret = -1; 2560335640Shselasky } 2561335640Shselasky } 2562335640Shselasky 2563335640Shselasky (void)close(fd); 2564335640Shselasky (void)closedir(sys_class_net_d); 2565335640Shselasky return (ret); 2566335640Shselasky} 2567335640Shselasky 2568335640Shselasky/* 2569335640Shselasky * Get from "/proc/net/dev" all interfaces listed there; if they're 2570335640Shselasky * already in the list of interfaces we have, that won't add another 2571335640Shselasky * instance, but if they're not, that'll add them. 2572335640Shselasky * 2573335640Shselasky * See comments from scan_sys_class_net(). 2574335640Shselasky */ 2575335640Shselaskystatic int 2576335640Shselaskyscan_proc_net_dev(pcap_if_list_t *devlistp, char *errbuf) 2577335640Shselasky{ 2578335640Shselasky FILE *proc_net_f; 2579335640Shselasky int fd; 2580335640Shselasky char linebuf[512]; 2581335640Shselasky int linenum; 2582335640Shselasky char *p; 2583335640Shselasky int ret = 0; 2584335640Shselasky 2585335640Shselasky proc_net_f = fopen("/proc/net/dev", "r"); 2586335640Shselasky if (proc_net_f == NULL) { 2587335640Shselasky /* 2588335640Shselasky * Don't fail if it doesn't exist at all. 2589335640Shselasky */ 2590335640Shselasky if (errno == ENOENT) 2591335640Shselasky return (0); 2592335640Shselasky 2593335640Shselasky /* 2594335640Shselasky * Fail if we got some other error. 2595335640Shselasky */ 2596335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2597335640Shselasky errno, "Can't open /proc/net/dev"); 2598335640Shselasky return (-1); 2599335640Shselasky } 2600335640Shselasky 2601335640Shselasky /* 2602335640Shselasky * Create a socket from which to fetch interface information. 2603335640Shselasky */ 2604335640Shselasky fd = socket(PF_UNIX, SOCK_RAW, 0); 2605335640Shselasky if (fd < 0) { 2606335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2607335640Shselasky errno, "socket"); 2608335640Shselasky (void)fclose(proc_net_f); 2609335640Shselasky return (-1); 2610335640Shselasky } 2611335640Shselasky 2612335640Shselasky for (linenum = 1; 2613335640Shselasky fgets(linebuf, sizeof linebuf, proc_net_f) != NULL; linenum++) { 2614335640Shselasky /* 2615335640Shselasky * Skip the first two lines - they're headers. 2616335640Shselasky */ 2617335640Shselasky if (linenum <= 2) 2618335640Shselasky continue; 2619335640Shselasky 2620335640Shselasky p = &linebuf[0]; 2621335640Shselasky 2622335640Shselasky /* 2623335640Shselasky * Skip leading white space. 2624335640Shselasky */ 2625335640Shselasky while (*p != '\0' && isascii(*p) && isspace(*p)) 2626335640Shselasky p++; 2627335640Shselasky if (*p == '\0' || *p == '\n') 2628335640Shselasky continue; /* blank line */ 2629335640Shselasky 2630335640Shselasky /* 2631335640Shselasky * Attempt to add the interface. 2632335640Shselasky */ 2633335640Shselasky if (add_linux_if(devlistp, p, fd, errbuf) == -1) { 2634335640Shselasky /* Fail. */ 2635335640Shselasky ret = -1; 2636335640Shselasky break; 2637335640Shselasky } 2638335640Shselasky } 2639335640Shselasky if (ret != -1) { 2640335640Shselasky /* 2641335640Shselasky * Well, we didn't fail for any other reason; did we 2642335640Shselasky * fail due to an error reading the file? 2643335640Shselasky */ 2644335640Shselasky if (ferror(proc_net_f)) { 2645335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2646335640Shselasky errno, "Error reading /proc/net/dev"); 2647335640Shselasky ret = -1; 2648335640Shselasky } 2649335640Shselasky } 2650335640Shselasky 2651335640Shselasky (void)close(fd); 2652335640Shselasky (void)fclose(proc_net_f); 2653335640Shselasky return (ret); 2654335640Shselasky} 2655335640Shselasky 2656335640Shselasky/* 2657335640Shselasky * Description string for the "any" device. 2658335640Shselasky */ 2659335640Shselaskystatic const char any_descr[] = "Pseudo-device that captures on all interfaces"; 2660335640Shselasky 2661335640Shselasky/* 2662335640Shselasky * A SOCK_PACKET or PF_PACKET socket can be bound to any network interface. 2663335640Shselasky */ 2664335640Shselaskystatic int 2665335640Shselaskycan_be_bound(const char *name _U_) 2666335640Shselasky{ 2667335640Shselasky return (1); 2668335640Shselasky} 2669335640Shselasky 2670335640Shselasky/* 2671335640Shselasky * Get additional flags for a device, using SIOCGIFMEDIA. 2672335640Shselasky */ 2673335640Shselaskystatic int 2674335640Shselaskyget_if_flags(const char *name, bpf_u_int32 *flags, char *errbuf) 2675335640Shselasky{ 2676335640Shselasky int sock; 2677335640Shselasky FILE *fh; 2678335640Shselasky unsigned int arptype; 2679335640Shselasky struct ifreq ifr; 2680335640Shselasky struct ethtool_value info; 2681335640Shselasky 2682335640Shselasky if (*flags & PCAP_IF_LOOPBACK) { 2683335640Shselasky /* 2684335640Shselasky * Loopback devices aren't wireless, and "connected"/ 2685335640Shselasky * "disconnected" doesn't apply to them. 2686335640Shselasky */ 2687335640Shselasky *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE; 2688335640Shselasky return 0; 2689335640Shselasky } 2690335640Shselasky 2691335640Shselasky sock = socket(AF_INET, SOCK_DGRAM, 0); 2692335640Shselasky if (sock == -1) { 2693335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, 2694335640Shselasky "Can't create socket to get ethtool information for %s", 2695335640Shselasky name); 2696335640Shselasky return -1; 2697335640Shselasky } 2698335640Shselasky 2699335640Shselasky /* 2700335640Shselasky * OK, what type of network is this? 2701335640Shselasky * In particular, is it wired or wireless? 2702335640Shselasky */ 2703335640Shselasky if (is_wifi(sock, name)) { 2704335640Shselasky /* 2705335640Shselasky * Wi-Fi, hence wireless. 2706335640Shselasky */ 2707335640Shselasky *flags |= PCAP_IF_WIRELESS; 2708335640Shselasky } else { 2709335640Shselasky /* 2710335640Shselasky * OK, what does /sys/class/net/{if}/type contain? 2711335640Shselasky * (We don't use that for Wi-Fi, as it'll report 2712335640Shselasky * "Ethernet", i.e. ARPHRD_ETHER, for non-monitor- 2713335640Shselasky * mode devices.) 2714335640Shselasky */ 2715335640Shselasky char *pathstr; 2716335640Shselasky 2717335640Shselasky if (asprintf(&pathstr, "/sys/class/net/%s/type", name) == -1) { 2718335640Shselasky pcap_snprintf(errbuf, PCAP_ERRBUF_SIZE, 2719335640Shselasky "%s: Can't generate path name string for /sys/class/net device", 2720335640Shselasky name); 2721335640Shselasky close(sock); 2722335640Shselasky return -1; 2723335640Shselasky } 2724335640Shselasky fh = fopen(pathstr, "r"); 2725335640Shselasky if (fh != NULL) { 2726335640Shselasky if (fscanf(fh, "%u", &arptype) == 1) { 2727335640Shselasky /* 2728335640Shselasky * OK, we got an ARPHRD_ type; what is it? 2729335640Shselasky */ 2730335640Shselasky switch (arptype) { 2731335640Shselasky 2732335640Shselasky#ifdef ARPHRD_LOOPBACK 2733335640Shselasky case ARPHRD_LOOPBACK: 2734335640Shselasky /* 2735335640Shselasky * These are types to which 2736335640Shselasky * "connected" and "disconnected" 2737335640Shselasky * don't apply, so don't bother 2738335640Shselasky * asking about it. 2739335640Shselasky * 2740335640Shselasky * XXX - add other types? 2741335640Shselasky */ 2742335640Shselasky close(sock); 2743335640Shselasky fclose(fh); 2744335640Shselasky free(pathstr); 2745335640Shselasky return 0; 2746335640Shselasky#endif 2747335640Shselasky 2748335640Shselasky case ARPHRD_IRDA: 2749335640Shselasky case ARPHRD_IEEE80211: 2750335640Shselasky case ARPHRD_IEEE80211_PRISM: 2751335640Shselasky case ARPHRD_IEEE80211_RADIOTAP: 2752335640Shselasky#ifdef ARPHRD_IEEE802154 2753335640Shselasky case ARPHRD_IEEE802154: 2754335640Shselasky#endif 2755335640Shselasky#ifdef ARPHRD_IEEE802154_MONITOR 2756335640Shselasky case ARPHRD_IEEE802154_MONITOR: 2757335640Shselasky#endif 2758335640Shselasky#ifdef ARPHRD_6LOWPAN 2759335640Shselasky case ARPHRD_6LOWPAN: 2760335640Shselasky#endif 2761335640Shselasky /* 2762335640Shselasky * Various wireless types. 2763335640Shselasky */ 2764335640Shselasky *flags |= PCAP_IF_WIRELESS; 2765335640Shselasky break; 2766335640Shselasky } 2767335640Shselasky } 2768335640Shselasky fclose(fh); 2769335640Shselasky free(pathstr); 2770335640Shselasky } 2771335640Shselasky } 2772335640Shselasky 2773335640Shselasky#ifdef ETHTOOL_GLINK 2774335640Shselasky memset(&ifr, 0, sizeof(ifr)); 2775356341Scy pcap_strlcpy(ifr.ifr_name, name, sizeof(ifr.ifr_name)); 2776335640Shselasky info.cmd = ETHTOOL_GLINK; 2777335640Shselasky ifr.ifr_data = (caddr_t)&info; 2778335640Shselasky if (ioctl(sock, SIOCETHTOOL, &ifr) == -1) { 2779335640Shselasky int save_errno = errno; 2780335640Shselasky 2781335640Shselasky switch (save_errno) { 2782335640Shselasky 2783335640Shselasky case EOPNOTSUPP: 2784335640Shselasky case EINVAL: 2785335640Shselasky /* 2786335640Shselasky * OK, this OS version or driver doesn't support 2787335640Shselasky * asking for this information. 2788335640Shselasky * XXX - distinguish between "this doesn't 2789335640Shselasky * support ethtool at all because it's not 2790335640Shselasky * that type of device" vs. "this doesn't 2791335640Shselasky * support ethtool even though it's that 2792335640Shselasky * type of device", and return "unknown". 2793335640Shselasky */ 2794335640Shselasky *flags |= PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE; 2795335640Shselasky close(sock); 2796335640Shselasky return 0; 2797335640Shselasky 2798335640Shselasky case ENODEV: 2799335640Shselasky /* 2800335640Shselasky * OK, no such device. 2801335640Shselasky * The user will find that out when they try to 2802335640Shselasky * activate the device; just say "OK" and 2803335640Shselasky * don't set anything. 2804335640Shselasky */ 2805335640Shselasky close(sock); 2806335640Shselasky return 0; 2807335640Shselasky 2808335640Shselasky default: 2809335640Shselasky /* 2810335640Shselasky * Other error. 2811335640Shselasky */ 2812335640Shselasky pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, 2813335640Shselasky save_errno, 2814335640Shselasky "%s: SIOCETHTOOL(ETHTOOL_GLINK) ioctl failed", 2815335640Shselasky name); 2816335640Shselasky close(sock); 2817335640Shselasky return -1; 2818335640Shselasky } 2819335640Shselasky } 2820335640Shselasky 2821335640Shselasky /* 2822335640Shselasky * Is it connected? 2823335640Shselasky */ 2824335640Shselasky if (info.data) { 2825335640Shselasky /* 2826335640Shselasky * It's connected. 2827335640Shselasky */ 2828335640Shselasky *flags |= PCAP_IF_CONNECTION_STATUS_CONNECTED; 2829335640Shselasky } else { 2830335640Shselasky /* 2831335640Shselasky * It's disconnected. 2832335640Shselasky */ 2833335640Shselasky *flags |= PCAP_IF_CONNECTION_STATUS_DISCONNECTED; 2834335640Shselasky } 2835335640Shselasky#endif 2836335640Shselasky 2837335640Shselasky close(sock); 2838335640Shselasky return 0; 2839335640Shselasky} 2840335640Shselasky 2841335640Shselaskyint 2842335640Shselaskypcap_platform_finddevs(pcap_if_list_t *devlistp, char *errbuf) 2843335640Shselasky{ 2844335640Shselasky int ret; 2845335640Shselasky 2846335640Shselasky /* 2847335640Shselasky * Get the list of regular interfaces first. 2848335640Shselasky */ 2849335640Shselasky if (pcap_findalldevs_interfaces(devlistp, errbuf, can_be_bound, 2850335640Shselasky get_if_flags) == -1) 2851335640Shselasky return (-1); /* failure */ 2852335640Shselasky 2853335640Shselasky /* 2854335640Shselasky * Read "/sys/class/net", and add to the list of interfaces all 2855335640Shselasky * interfaces listed there that we don't already have, because, 2856335640Shselasky * on Linux, SIOCGIFCONF reports only interfaces with IPv4 addresses, 2857335640Shselasky * and even getifaddrs() won't return information about 2858335640Shselasky * interfaces with no addresses, so you need to read "/sys/class/net" 2859335640Shselasky * to get the names of the rest of the interfaces. 2860335640Shselasky */ 2861335640Shselasky ret = scan_sys_class_net(devlistp, errbuf); 2862335640Shselasky if (ret == -1) 2863335640Shselasky return (-1); /* failed */ 2864335640Shselasky if (ret == 0) { 2865335640Shselasky /* 2866335640Shselasky * No /sys/class/net; try reading /proc/net/dev instead. 2867335640Shselasky */ 2868335640Shselasky if (scan_proc_net_dev(devlistp, errbuf) == -1) 2869335640Shselasky return (-1); 2870335640Shselasky } 2871335640Shselasky 2872335640Shselasky /* 2873335640Shselasky * Add the "any" device. 2874335640Shselasky * As it refers to all network devices, not to any particular 2875335640Shselasky * network device, the notion of "connected" vs. "disconnected" 2876335640Shselasky * doesn't apply. 2877335640Shselasky */ 2878335640Shselasky if (add_dev(devlistp, "any", 2879335640Shselasky PCAP_IF_UP|PCAP_IF_RUNNING|PCAP_IF_CONNECTION_STATUS_NOT_APPLICABLE, 2880335640Shselasky any_descr, errbuf) == NULL) 2881335640Shselasky return (-1); 2882335640Shselasky 2883335640Shselasky return (0); 2884335640Shselasky} 2885335640Shselasky 2886335640Shselasky/* 2887335640Shselasky * Attach the given BPF code to the packet capture device. 2888335640Shselasky */ 2889335640Shselaskystatic int 2890335640Shselaskypcap_setfilter_linux_common(pcap_t *handle, struct bpf_program *filter, 2891335640Shselasky int is_mmapped) 2892335640Shselasky{ 2893335640Shselasky struct pcap_linux *handlep; 2894335640Shselasky#ifdef SO_ATTACH_FILTER 2895335640Shselasky struct sock_fprog fcode; 2896335640Shselasky int can_filter_in_kernel; 2897335640Shselasky int err = 0; 2898335640Shselasky#endif 2899335640Shselasky 2900335640Shselasky if (!handle) 2901335640Shselasky return -1; 2902335640Shselasky if (!filter) { 2903356341Scy pcap_strlcpy(handle->errbuf, "setfilter: No filter specified", 2904335640Shselasky PCAP_ERRBUF_SIZE); 2905335640Shselasky return -1; 2906335640Shselasky } 2907335640Shselasky 2908335640Shselasky handlep = handle->priv; 2909335640Shselasky 2910335640Shselasky /* Make our private copy of the filter */ 2911335640Shselasky 2912335640Shselasky if (install_bpf_program(handle, filter) < 0) 2913335640Shselasky /* install_bpf_program() filled in errbuf */ 2914335640Shselasky return -1; 2915335640Shselasky 2916335640Shselasky /* 2917335640Shselasky * Run user level packet filter by default. Will be overriden if 2918335640Shselasky * installing a kernel filter succeeds. 2919335640Shselasky */ 2920335640Shselasky handlep->filter_in_userland = 1; 2921335640Shselasky 2922335640Shselasky /* Install kernel level filter if possible */ 2923335640Shselasky 2924335640Shselasky#ifdef SO_ATTACH_FILTER 2925335640Shselasky#ifdef USHRT_MAX 2926335640Shselasky if (handle->fcode.bf_len > USHRT_MAX) { 2927335640Shselasky /* 2928335640Shselasky * fcode.len is an unsigned short for current kernel. 2929335640Shselasky * I have yet to see BPF-Code with that much 2930335640Shselasky * instructions but still it is possible. So for the 2931335640Shselasky * sake of correctness I added this check. 2932335640Shselasky */ 2933335640Shselasky fprintf(stderr, "Warning: Filter too complex for kernel\n"); 2934335640Shselasky fcode.len = 0; 2935335640Shselasky fcode.filter = NULL; 2936335640Shselasky can_filter_in_kernel = 0; 2937335640Shselasky } else 2938335640Shselasky#endif /* USHRT_MAX */ 2939335640Shselasky { 2940335640Shselasky /* 2941335640Shselasky * Oh joy, the Linux kernel uses struct sock_fprog instead 2942335640Shselasky * of struct bpf_program and of course the length field is 2943335640Shselasky * of different size. Pointed out by Sebastian 2944335640Shselasky * 2945335640Shselasky * Oh, and we also need to fix it up so that all "ret" 2946335640Shselasky * instructions with non-zero operands have MAXIMUM_SNAPLEN 2947335640Shselasky * as the operand if we're not capturing in memory-mapped 2948335640Shselasky * mode, and so that, if we're in cooked mode, all memory- 2949335640Shselasky * reference instructions use special magic offsets in 2950335640Shselasky * references to the link-layer header and assume that the 2951335640Shselasky * link-layer payload begins at 0; "fix_program()" will do 2952335640Shselasky * that. 2953335640Shselasky */ 2954335640Shselasky switch (fix_program(handle, &fcode, is_mmapped)) { 2955335640Shselasky 2956335640Shselasky case -1: 2957335640Shselasky default: 2958335640Shselasky /* 2959335640Shselasky * Fatal error; just quit. 2960335640Shselasky * (The "default" case shouldn't happen; we 2961335640Shselasky * return -1 for that reason.) 2962335640Shselasky */ 2963335640Shselasky return -1; 2964335640Shselasky 2965335640Shselasky case 0: 2966335640Shselasky /* 2967335640Shselasky * The program performed checks that we can't make 2968335640Shselasky * work in the kernel. 2969335640Shselasky */ 2970335640Shselasky can_filter_in_kernel = 0; 2971335640Shselasky break; 2972335640Shselasky 2973335640Shselasky case 1: 2974335640Shselasky /* 2975335640Shselasky * We have a filter that'll work in the kernel. 2976335640Shselasky */ 2977335640Shselasky can_filter_in_kernel = 1; 2978335640Shselasky break; 2979335640Shselasky } 2980335640Shselasky } 2981335640Shselasky 2982335640Shselasky /* 2983335640Shselasky * NOTE: at this point, we've set both the "len" and "filter" 2984335640Shselasky * fields of "fcode". As of the 2.6.32.4 kernel, at least, 2985335640Shselasky * those are the only members of the "sock_fprog" structure, 2986335640Shselasky * so we initialize every member of that structure. 2987335640Shselasky * 2988335640Shselasky * If there is anything in "fcode" that is not initialized, 2989335640Shselasky * it is either a field added in a later kernel, or it's 2990335640Shselasky * padding. 2991335640Shselasky * 2992335640Shselasky * If a new field is added, this code needs to be updated 2993335640Shselasky * to set it correctly. 2994335640Shselasky * 2995335640Shselasky * If there are no other fields, then: 2996335640Shselasky * 2997335640Shselasky * if the Linux kernel looks at the padding, it's 2998335640Shselasky * buggy; 2999335640Shselasky * 3000335640Shselasky * if the Linux kernel doesn't look at the padding, 3001335640Shselasky * then if some tool complains that we're passing 3002335640Shselasky * uninitialized data to the kernel, then the tool 3003335640Shselasky * is buggy and needs to understand that it's just 3004335640Shselasky * padding. 3005335640Shselasky */ 3006335640Shselasky if (can_filter_in_kernel) { 3007335640Shselasky if ((err = set_kernel_filter(handle, &fcode)) == 0) 3008335640Shselasky { 3009335640Shselasky /* 3010335640Shselasky * Installation succeded - using kernel filter, 3011335640Shselasky * so userland filtering not needed. 3012335640Shselasky */ 3013335640Shselasky handlep->filter_in_userland = 0; 3014335640Shselasky } 3015335640Shselasky else if (err == -1) /* Non-fatal error */ 3016335640Shselasky { 3017335640Shselasky /* 3018335640Shselasky * Print a warning if we weren't able to install 3019335640Shselasky * the filter for a reason other than "this kernel 3020335640Shselasky * isn't configured to support socket filters. 3021335640Shselasky */ 3022335640Shselasky if (errno != ENOPROTOOPT && errno != EOPNOTSUPP) { 3023335640Shselasky fprintf(stderr, 3024335640Shselasky "Warning: Kernel filter failed: %s\n", 3025335640Shselasky pcap_strerror(errno)); 3026335640Shselasky } 3027335640Shselasky } 3028335640Shselasky } 3029335640Shselasky 3030335640Shselasky /* 3031335640Shselasky * If we're not using the kernel filter, get rid of any kernel 3032335640Shselasky * filter that might've been there before, e.g. because the 3033335640Shselasky * previous filter could work in the kernel, or because some other 3034335640Shselasky * code attached a filter to the socket by some means other than 3035335640Shselasky * calling "pcap_setfilter()". Otherwise, the kernel filter may 3036335640Shselasky * filter out packets that would pass the new userland filter. 3037335640Shselasky */ 3038335640Shselasky if (handlep->filter_in_userland) { 3039335640Shselasky if (reset_kernel_filter(handle) == -1) { 3040335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 3041335640Shselasky PCAP_ERRBUF_SIZE, errno, 3042335640Shselasky "can't remove kernel filter"); 3043335640Shselasky err = -2; /* fatal error */ 3044335640Shselasky } 3045335640Shselasky } 3046335640Shselasky 3047335640Shselasky /* 3048335640Shselasky * Free up the copy of the filter that was made by "fix_program()". 3049335640Shselasky */ 3050335640Shselasky if (fcode.filter != NULL) 3051335640Shselasky free(fcode.filter); 3052335640Shselasky 3053335640Shselasky if (err == -2) 3054335640Shselasky /* Fatal error */ 3055335640Shselasky return -1; 3056335640Shselasky#endif /* SO_ATTACH_FILTER */ 3057335640Shselasky 3058335640Shselasky return 0; 3059335640Shselasky} 3060335640Shselasky 3061335640Shselaskystatic int 3062335640Shselaskypcap_setfilter_linux(pcap_t *handle, struct bpf_program *filter) 3063335640Shselasky{ 3064335640Shselasky return pcap_setfilter_linux_common(handle, filter, 0); 3065335640Shselasky} 3066335640Shselasky 3067335640Shselasky 3068335640Shselasky/* 3069335640Shselasky * Set direction flag: Which packets do we accept on a forwarding 3070335640Shselasky * single device? IN, OUT or both? 3071335640Shselasky */ 3072335640Shselaskystatic int 3073335640Shselaskypcap_setdirection_linux(pcap_t *handle, pcap_direction_t d) 3074335640Shselasky{ 3075335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 3076335640Shselasky struct pcap_linux *handlep = handle->priv; 3077335640Shselasky 3078335640Shselasky if (!handlep->sock_packet) { 3079335640Shselasky handle->direction = d; 3080335640Shselasky return 0; 3081335640Shselasky } 3082335640Shselasky#endif 3083335640Shselasky /* 3084335640Shselasky * We're not using PF_PACKET sockets, so we can't determine 3085335640Shselasky * the direction of the packet. 3086335640Shselasky */ 3087335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 3088335640Shselasky "Setting direction is not supported on SOCK_PACKET sockets"); 3089335640Shselasky return -1; 3090335640Shselasky} 3091335640Shselasky 3092335640Shselaskystatic int 3093335640Shselaskyis_wifi(int sock_fd 3094335640Shselasky#ifndef IW_MODE_MONITOR 3095335640Shselasky_U_ 3096335640Shselasky#endif 3097335640Shselasky, const char *device) 3098335640Shselasky{ 3099335640Shselasky char *pathstr; 3100335640Shselasky struct stat statb; 3101335640Shselasky#ifdef IW_MODE_MONITOR 3102335640Shselasky char errbuf[PCAP_ERRBUF_SIZE]; 3103335640Shselasky#endif 3104335640Shselasky 3105335640Shselasky /* 3106335640Shselasky * See if there's a sysfs wireless directory for it. 3107335640Shselasky * If so, it's a wireless interface. 3108335640Shselasky */ 3109335640Shselasky if (asprintf(&pathstr, "/sys/class/net/%s/wireless", device) == -1) { 3110335640Shselasky /* 3111335640Shselasky * Just give up here. 3112335640Shselasky */ 3113335640Shselasky return 0; 3114335640Shselasky } 3115335640Shselasky if (stat(pathstr, &statb) == 0) { 3116335640Shselasky free(pathstr); 3117335640Shselasky return 1; 3118335640Shselasky } 3119335640Shselasky free(pathstr); 3120335640Shselasky 3121335640Shselasky#ifdef IW_MODE_MONITOR 3122335640Shselasky /* 3123335640Shselasky * OK, maybe it's not wireless, or maybe this kernel doesn't 3124335640Shselasky * support sysfs. Try the wireless extensions. 3125335640Shselasky */ 3126335640Shselasky if (has_wext(sock_fd, device, errbuf) == 1) { 3127335640Shselasky /* 3128335640Shselasky * It supports the wireless extensions, so it's a Wi-Fi 3129335640Shselasky * device. 3130335640Shselasky */ 3131335640Shselasky return 1; 3132335640Shselasky } 3133335640Shselasky#endif 3134335640Shselasky return 0; 3135335640Shselasky} 3136335640Shselasky 3137335640Shselasky/* 3138335640Shselasky * Linux uses the ARP hardware type to identify the type of an 3139335640Shselasky * interface. pcap uses the DLT_xxx constants for this. This 3140335640Shselasky * function takes a pointer to a "pcap_t", and an ARPHRD_xxx 3141335640Shselasky * constant, as arguments, and sets "handle->linktype" to the 3142335640Shselasky * appropriate DLT_XXX constant and sets "handle->offset" to 3143335640Shselasky * the appropriate value (to make "handle->offset" plus link-layer 3144335640Shselasky * header length be a multiple of 4, so that the link-layer payload 3145335640Shselasky * will be aligned on a 4-byte boundary when capturing packets). 3146335640Shselasky * (If the offset isn't set here, it'll be 0; add code as appropriate 3147335640Shselasky * for cases where it shouldn't be 0.) 3148335640Shselasky * 3149335640Shselasky * If "cooked_ok" is non-zero, we can use DLT_LINUX_SLL and capture 3150335640Shselasky * in cooked mode; otherwise, we can't use cooked mode, so we have 3151335640Shselasky * to pick some type that works in raw mode, or fail. 3152335640Shselasky * 3153335640Shselasky * Sets the link type to -1 if unable to map the type. 3154335640Shselasky */ 3155335640Shselaskystatic void map_arphrd_to_dlt(pcap_t *handle, int sock_fd, int arptype, 3156335640Shselasky const char *device, int cooked_ok) 3157335640Shselasky{ 3158335640Shselasky static const char cdma_rmnet[] = "cdma_rmnet"; 3159335640Shselasky 3160335640Shselasky switch (arptype) { 3161335640Shselasky 3162335640Shselasky case ARPHRD_ETHER: 3163335640Shselasky /* 3164335640Shselasky * For various annoying reasons having to do with DHCP 3165335640Shselasky * software, some versions of Android give the mobile- 3166335640Shselasky * phone-network interface an ARPHRD_ value of 3167335640Shselasky * ARPHRD_ETHER, even though the packets supplied by 3168335640Shselasky * that interface have no link-layer header, and begin 3169335640Shselasky * with an IP header, so that the ARPHRD_ value should 3170335640Shselasky * be ARPHRD_NONE. 3171335640Shselasky * 3172335640Shselasky * Detect those devices by checking the device name, and 3173335640Shselasky * use DLT_RAW for them. 3174335640Shselasky */ 3175335640Shselasky if (strncmp(device, cdma_rmnet, sizeof cdma_rmnet - 1) == 0) { 3176335640Shselasky handle->linktype = DLT_RAW; 3177335640Shselasky return; 3178335640Shselasky } 3179335640Shselasky 3180335640Shselasky /* 3181335640Shselasky * Is this a real Ethernet device? If so, give it a 3182335640Shselasky * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 3183335640Shselasky * that an application can let you choose it, in case you're 3184335640Shselasky * capturing DOCSIS traffic that a Cisco Cable Modem 3185335640Shselasky * Termination System is putting out onto an Ethernet (it 3186335640Shselasky * doesn't put an Ethernet header onto the wire, it puts raw 3187335640Shselasky * DOCSIS frames out on the wire inside the low-level 3188335640Shselasky * Ethernet framing). 3189335640Shselasky * 3190335640Shselasky * XXX - are there any other sorts of "fake Ethernet" that 3191335640Shselasky * have ARPHRD_ETHER but that shouldn't offer DLT_DOCSIS as 3192335640Shselasky * a Cisco CMTS won't put traffic onto it or get traffic 3193335640Shselasky * bridged onto it? ISDN is handled in "activate_new()", 3194335640Shselasky * as we fall back on cooked mode there, and we use 3195335640Shselasky * is_wifi() to check for 802.11 devices; are there any 3196335640Shselasky * others? 3197335640Shselasky */ 3198335640Shselasky if (!is_wifi(sock_fd, device)) { 3199335640Shselasky /* 3200335640Shselasky * It's not a Wi-Fi device; offer DOCSIS. 3201335640Shselasky */ 3202335640Shselasky handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 3203335640Shselasky /* 3204335640Shselasky * If that fails, just leave the list empty. 3205335640Shselasky */ 3206335640Shselasky if (handle->dlt_list != NULL) { 3207335640Shselasky handle->dlt_list[0] = DLT_EN10MB; 3208335640Shselasky handle->dlt_list[1] = DLT_DOCSIS; 3209335640Shselasky handle->dlt_count = 2; 3210335640Shselasky } 3211335640Shselasky } 3212335640Shselasky /* FALLTHROUGH */ 3213335640Shselasky 3214335640Shselasky case ARPHRD_METRICOM: 3215335640Shselasky case ARPHRD_LOOPBACK: 3216335640Shselasky handle->linktype = DLT_EN10MB; 3217335640Shselasky handle->offset = 2; 3218335640Shselasky break; 3219335640Shselasky 3220335640Shselasky case ARPHRD_EETHER: 3221335640Shselasky handle->linktype = DLT_EN3MB; 3222335640Shselasky break; 3223335640Shselasky 3224335640Shselasky case ARPHRD_AX25: 3225335640Shselasky handle->linktype = DLT_AX25_KISS; 3226335640Shselasky break; 3227335640Shselasky 3228335640Shselasky case ARPHRD_PRONET: 3229335640Shselasky handle->linktype = DLT_PRONET; 3230335640Shselasky break; 3231335640Shselasky 3232335640Shselasky case ARPHRD_CHAOS: 3233335640Shselasky handle->linktype = DLT_CHAOS; 3234335640Shselasky break; 3235335640Shselasky#ifndef ARPHRD_CAN 3236335640Shselasky#define ARPHRD_CAN 280 3237335640Shselasky#endif 3238335640Shselasky case ARPHRD_CAN: 3239335640Shselasky /* 3240335640Shselasky * Map this to DLT_LINUX_SLL; that way, CAN frames will 3241335640Shselasky * have ETH_P_CAN/LINUX_SLL_P_CAN as the protocol and 3242335640Shselasky * CAN FD frames will have ETH_P_CANFD/LINUX_SLL_P_CANFD 3243335640Shselasky * as the protocol, so they can be distinguished by the 3244335640Shselasky * protocol in the SLL header. 3245335640Shselasky */ 3246335640Shselasky handle->linktype = DLT_LINUX_SLL; 3247335640Shselasky break; 3248335640Shselasky 3249335640Shselasky#ifndef ARPHRD_IEEE802_TR 3250335640Shselasky#define ARPHRD_IEEE802_TR 800 /* From Linux 2.4 */ 3251335640Shselasky#endif 3252335640Shselasky case ARPHRD_IEEE802_TR: 3253335640Shselasky case ARPHRD_IEEE802: 3254335640Shselasky handle->linktype = DLT_IEEE802; 3255335640Shselasky handle->offset = 2; 3256335640Shselasky break; 3257335640Shselasky 3258335640Shselasky case ARPHRD_ARCNET: 3259335640Shselasky handle->linktype = DLT_ARCNET_LINUX; 3260335640Shselasky break; 3261335640Shselasky 3262335640Shselasky#ifndef ARPHRD_FDDI /* From Linux 2.2.13 */ 3263335640Shselasky#define ARPHRD_FDDI 774 3264335640Shselasky#endif 3265335640Shselasky case ARPHRD_FDDI: 3266335640Shselasky handle->linktype = DLT_FDDI; 3267335640Shselasky handle->offset = 3; 3268335640Shselasky break; 3269335640Shselasky 3270335640Shselasky#ifndef ARPHRD_ATM /* FIXME: How to #include this? */ 3271335640Shselasky#define ARPHRD_ATM 19 3272335640Shselasky#endif 3273335640Shselasky case ARPHRD_ATM: 3274335640Shselasky /* 3275335640Shselasky * The Classical IP implementation in ATM for Linux 3276335640Shselasky * supports both what RFC 1483 calls "LLC Encapsulation", 3277335640Shselasky * in which each packet has an LLC header, possibly 3278335640Shselasky * with a SNAP header as well, prepended to it, and 3279335640Shselasky * what RFC 1483 calls "VC Based Multiplexing", in which 3280335640Shselasky * different virtual circuits carry different network 3281335640Shselasky * layer protocols, and no header is prepended to packets. 3282335640Shselasky * 3283335640Shselasky * They both have an ARPHRD_ type of ARPHRD_ATM, so 3284335640Shselasky * you can't use the ARPHRD_ type to find out whether 3285335640Shselasky * captured packets will have an LLC header, and, 3286335640Shselasky * while there's a socket ioctl to *set* the encapsulation 3287335640Shselasky * type, there's no ioctl to *get* the encapsulation type. 3288335640Shselasky * 3289335640Shselasky * This means that 3290335640Shselasky * 3291335640Shselasky * programs that dissect Linux Classical IP frames 3292335640Shselasky * would have to check for an LLC header and, 3293335640Shselasky * depending on whether they see one or not, dissect 3294335640Shselasky * the frame as LLC-encapsulated or as raw IP (I 3295335640Shselasky * don't know whether there's any traffic other than 3296335640Shselasky * IP that would show up on the socket, or whether 3297335640Shselasky * there's any support for IPv6 in the Linux 3298335640Shselasky * Classical IP code); 3299335640Shselasky * 3300335640Shselasky * filter expressions would have to compile into 3301335640Shselasky * code that checks for an LLC header and does 3302335640Shselasky * the right thing. 3303335640Shselasky * 3304335640Shselasky * Both of those are a nuisance - and, at least on systems 3305335640Shselasky * that support PF_PACKET sockets, we don't have to put 3306335640Shselasky * up with those nuisances; instead, we can just capture 3307335640Shselasky * in cooked mode. That's what we'll do, if we can. 3308335640Shselasky * Otherwise, we'll just fail. 3309335640Shselasky */ 3310335640Shselasky if (cooked_ok) 3311335640Shselasky handle->linktype = DLT_LINUX_SLL; 3312335640Shselasky else 3313335640Shselasky handle->linktype = -1; 3314335640Shselasky break; 3315335640Shselasky 3316335640Shselasky#ifndef ARPHRD_IEEE80211 /* From Linux 2.4.6 */ 3317335640Shselasky#define ARPHRD_IEEE80211 801 3318335640Shselasky#endif 3319335640Shselasky case ARPHRD_IEEE80211: 3320335640Shselasky handle->linktype = DLT_IEEE802_11; 3321335640Shselasky break; 3322335640Shselasky 3323335640Shselasky#ifndef ARPHRD_IEEE80211_PRISM /* From Linux 2.4.18 */ 3324335640Shselasky#define ARPHRD_IEEE80211_PRISM 802 3325335640Shselasky#endif 3326335640Shselasky case ARPHRD_IEEE80211_PRISM: 3327335640Shselasky handle->linktype = DLT_PRISM_HEADER; 3328335640Shselasky break; 3329335640Shselasky 3330335640Shselasky#ifndef ARPHRD_IEEE80211_RADIOTAP /* new */ 3331335640Shselasky#define ARPHRD_IEEE80211_RADIOTAP 803 3332335640Shselasky#endif 3333335640Shselasky case ARPHRD_IEEE80211_RADIOTAP: 3334335640Shselasky handle->linktype = DLT_IEEE802_11_RADIO; 3335335640Shselasky break; 3336335640Shselasky 3337335640Shselasky case ARPHRD_PPP: 3338335640Shselasky /* 3339335640Shselasky * Some PPP code in the kernel supplies no link-layer 3340335640Shselasky * header whatsoever to PF_PACKET sockets; other PPP 3341335640Shselasky * code supplies PPP link-layer headers ("syncppp.c"); 3342335640Shselasky * some PPP code might supply random link-layer 3343335640Shselasky * headers (PPP over ISDN - there's code in Ethereal, 3344335640Shselasky * for example, to cope with PPP-over-ISDN captures 3345335640Shselasky * with which the Ethereal developers have had to cope, 3346335640Shselasky * heuristically trying to determine which of the 3347335640Shselasky * oddball link-layer headers particular packets have). 3348335640Shselasky * 3349335640Shselasky * As such, we just punt, and run all PPP interfaces 3350335640Shselasky * in cooked mode, if we can; otherwise, we just treat 3351335640Shselasky * it as DLT_RAW, for now - if somebody needs to capture, 3352335640Shselasky * on a 2.0[.x] kernel, on PPP devices that supply a 3353335640Shselasky * link-layer header, they'll have to add code here to 3354335640Shselasky * map to the appropriate DLT_ type (possibly adding a 3355335640Shselasky * new DLT_ type, if necessary). 3356335640Shselasky */ 3357335640Shselasky if (cooked_ok) 3358335640Shselasky handle->linktype = DLT_LINUX_SLL; 3359335640Shselasky else { 3360335640Shselasky /* 3361335640Shselasky * XXX - handle ISDN types here? We can't fall 3362335640Shselasky * back on cooked sockets, so we'd have to 3363335640Shselasky * figure out from the device name what type of 3364335640Shselasky * link-layer encapsulation it's using, and map 3365335640Shselasky * that to an appropriate DLT_ value, meaning 3366335640Shselasky * we'd map "isdnN" devices to DLT_RAW (they 3367335640Shselasky * supply raw IP packets with no link-layer 3368335640Shselasky * header) and "isdY" devices to a new DLT_I4L_IP 3369335640Shselasky * type that has only an Ethernet packet type as 3370335640Shselasky * a link-layer header. 3371335640Shselasky * 3372335640Shselasky * But sometimes we seem to get random crap 3373335640Shselasky * in the link-layer header when capturing on 3374335640Shselasky * ISDN devices.... 3375335640Shselasky */ 3376335640Shselasky handle->linktype = DLT_RAW; 3377335640Shselasky } 3378335640Shselasky break; 3379335640Shselasky 3380335640Shselasky#ifndef ARPHRD_CISCO 3381335640Shselasky#define ARPHRD_CISCO 513 /* previously ARPHRD_HDLC */ 3382335640Shselasky#endif 3383335640Shselasky case ARPHRD_CISCO: 3384335640Shselasky handle->linktype = DLT_C_HDLC; 3385335640Shselasky break; 3386335640Shselasky 3387335640Shselasky /* Not sure if this is correct for all tunnels, but it 3388335640Shselasky * works for CIPE */ 3389335640Shselasky case ARPHRD_TUNNEL: 3390335640Shselasky#ifndef ARPHRD_SIT 3391335640Shselasky#define ARPHRD_SIT 776 /* From Linux 2.2.13 */ 3392335640Shselasky#endif 3393335640Shselasky case ARPHRD_SIT: 3394335640Shselasky case ARPHRD_CSLIP: 3395335640Shselasky case ARPHRD_SLIP6: 3396335640Shselasky case ARPHRD_CSLIP6: 3397335640Shselasky case ARPHRD_ADAPT: 3398335640Shselasky case ARPHRD_SLIP: 3399335640Shselasky#ifndef ARPHRD_RAWHDLC 3400335640Shselasky#define ARPHRD_RAWHDLC 518 3401335640Shselasky#endif 3402335640Shselasky case ARPHRD_RAWHDLC: 3403335640Shselasky#ifndef ARPHRD_DLCI 3404335640Shselasky#define ARPHRD_DLCI 15 3405335640Shselasky#endif 3406335640Shselasky case ARPHRD_DLCI: 3407335640Shselasky /* 3408335640Shselasky * XXX - should some of those be mapped to DLT_LINUX_SLL 3409335640Shselasky * instead? Should we just map all of them to DLT_LINUX_SLL? 3410335640Shselasky */ 3411335640Shselasky handle->linktype = DLT_RAW; 3412335640Shselasky break; 3413335640Shselasky 3414335640Shselasky#ifndef ARPHRD_FRAD 3415335640Shselasky#define ARPHRD_FRAD 770 3416335640Shselasky#endif 3417335640Shselasky case ARPHRD_FRAD: 3418335640Shselasky handle->linktype = DLT_FRELAY; 3419335640Shselasky break; 3420335640Shselasky 3421335640Shselasky case ARPHRD_LOCALTLK: 3422335640Shselasky handle->linktype = DLT_LTALK; 3423335640Shselasky break; 3424335640Shselasky 3425335640Shselasky case 18: 3426335640Shselasky /* 3427335640Shselasky * RFC 4338 defines an encapsulation for IP and ARP 3428335640Shselasky * packets that's compatible with the RFC 2625 3429335640Shselasky * encapsulation, but that uses a different ARP 3430335640Shselasky * hardware type and hardware addresses. That 3431335640Shselasky * ARP hardware type is 18; Linux doesn't define 3432335640Shselasky * any ARPHRD_ value as 18, but if it ever officially 3433335640Shselasky * supports RFC 4338-style IP-over-FC, it should define 3434335640Shselasky * one. 3435335640Shselasky * 3436335640Shselasky * For now, we map it to DLT_IP_OVER_FC, in the hopes 3437335640Shselasky * that this will encourage its use in the future, 3438335640Shselasky * should Linux ever officially support RFC 4338-style 3439335640Shselasky * IP-over-FC. 3440335640Shselasky */ 3441335640Shselasky handle->linktype = DLT_IP_OVER_FC; 3442335640Shselasky break; 3443335640Shselasky 3444335640Shselasky#ifndef ARPHRD_FCPP 3445335640Shselasky#define ARPHRD_FCPP 784 3446335640Shselasky#endif 3447335640Shselasky case ARPHRD_FCPP: 3448335640Shselasky#ifndef ARPHRD_FCAL 3449335640Shselasky#define ARPHRD_FCAL 785 3450335640Shselasky#endif 3451335640Shselasky case ARPHRD_FCAL: 3452335640Shselasky#ifndef ARPHRD_FCPL 3453335640Shselasky#define ARPHRD_FCPL 786 3454335640Shselasky#endif 3455335640Shselasky case ARPHRD_FCPL: 3456335640Shselasky#ifndef ARPHRD_FCFABRIC 3457335640Shselasky#define ARPHRD_FCFABRIC 787 3458335640Shselasky#endif 3459335640Shselasky case ARPHRD_FCFABRIC: 3460335640Shselasky /* 3461335640Shselasky * Back in 2002, Donald Lee at Cray wanted a DLT_ for 3462335640Shselasky * IP-over-FC: 3463335640Shselasky * 3464335640Shselasky * http://www.mail-archive.com/tcpdump-workers@sandelman.ottawa.on.ca/msg01043.html 3465335640Shselasky * 3466335640Shselasky * and one was assigned. 3467335640Shselasky * 3468335640Shselasky * In a later private discussion (spun off from a message 3469335640Shselasky * on the ethereal-users list) on how to get that DLT_ 3470335640Shselasky * value in libpcap on Linux, I ended up deciding that 3471335640Shselasky * the best thing to do would be to have him tweak the 3472335640Shselasky * driver to set the ARPHRD_ value to some ARPHRD_FCxx 3473335640Shselasky * type, and map all those types to DLT_IP_OVER_FC: 3474335640Shselasky * 3475335640Shselasky * I've checked into the libpcap and tcpdump CVS tree 3476335640Shselasky * support for DLT_IP_OVER_FC. In order to use that, 3477335640Shselasky * you'd have to modify your modified driver to return 3478335640Shselasky * one of the ARPHRD_FCxxx types, in "fcLINUXfcp.c" - 3479335640Shselasky * change it to set "dev->type" to ARPHRD_FCFABRIC, for 3480335640Shselasky * example (the exact value doesn't matter, it can be 3481335640Shselasky * any of ARPHRD_FCPP, ARPHRD_FCAL, ARPHRD_FCPL, or 3482335640Shselasky * ARPHRD_FCFABRIC). 3483335640Shselasky * 3484335640Shselasky * 11 years later, Christian Svensson wanted to map 3485335640Shselasky * various ARPHRD_ values to DLT_FC_2 and 3486335640Shselasky * DLT_FC_2_WITH_FRAME_DELIMS for raw Fibre Channel 3487335640Shselasky * frames: 3488335640Shselasky * 3489335640Shselasky * https://github.com/mcr/libpcap/pull/29 3490335640Shselasky * 3491335640Shselasky * There doesn't seem to be any network drivers that uses 3492335640Shselasky * any of the ARPHRD_FC* values for IP-over-FC, and 3493335640Shselasky * it's not exactly clear what the "Dummy types for non 3494335640Shselasky * ARP hardware" are supposed to mean (link-layer 3495335640Shselasky * header type? Physical network type?), so it's 3496335640Shselasky * not exactly clear why the ARPHRD_FC* types exist 3497335640Shselasky * in the first place. 3498335640Shselasky * 3499335640Shselasky * For now, we map them to DLT_FC_2, and provide an 3500335640Shselasky * option of DLT_FC_2_WITH_FRAME_DELIMS, as well as 3501335640Shselasky * DLT_IP_OVER_FC just in case there's some old 3502335640Shselasky * driver out there that uses one of those types for 3503335640Shselasky * IP-over-FC on which somebody wants to capture 3504335640Shselasky * packets. 3505335640Shselasky */ 3506335640Shselasky handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 3); 3507335640Shselasky /* 3508335640Shselasky * If that fails, just leave the list empty. 3509335640Shselasky */ 3510335640Shselasky if (handle->dlt_list != NULL) { 3511335640Shselasky handle->dlt_list[0] = DLT_FC_2; 3512335640Shselasky handle->dlt_list[1] = DLT_FC_2_WITH_FRAME_DELIMS; 3513335640Shselasky handle->dlt_list[2] = DLT_IP_OVER_FC; 3514335640Shselasky handle->dlt_count = 3; 3515335640Shselasky } 3516335640Shselasky handle->linktype = DLT_FC_2; 3517335640Shselasky break; 3518335640Shselasky 3519335640Shselasky#ifndef ARPHRD_IRDA 3520335640Shselasky#define ARPHRD_IRDA 783 3521335640Shselasky#endif 3522335640Shselasky case ARPHRD_IRDA: 3523335640Shselasky /* Don't expect IP packet out of this interfaces... */ 3524335640Shselasky handle->linktype = DLT_LINUX_IRDA; 3525335640Shselasky /* We need to save packet direction for IrDA decoding, 3526335640Shselasky * so let's use "Linux-cooked" mode. Jean II 3527335640Shselasky * 3528335640Shselasky * XXX - this is handled in activate_new(). */ 3529335640Shselasky /* handlep->cooked = 1; */ 3530335640Shselasky break; 3531335640Shselasky 3532335640Shselasky /* ARPHRD_LAPD is unofficial and randomly allocated, if reallocation 3533335640Shselasky * is needed, please report it to <daniele@orlandi.com> */ 3534335640Shselasky#ifndef ARPHRD_LAPD 3535335640Shselasky#define ARPHRD_LAPD 8445 3536335640Shselasky#endif 3537335640Shselasky case ARPHRD_LAPD: 3538335640Shselasky /* Don't expect IP packet out of this interfaces... */ 3539335640Shselasky handle->linktype = DLT_LINUX_LAPD; 3540335640Shselasky break; 3541335640Shselasky 3542335640Shselasky#ifndef ARPHRD_NONE 3543335640Shselasky#define ARPHRD_NONE 0xFFFE 3544335640Shselasky#endif 3545335640Shselasky case ARPHRD_NONE: 3546335640Shselasky /* 3547335640Shselasky * No link-layer header; packets are just IP 3548335640Shselasky * packets, so use DLT_RAW. 3549335640Shselasky */ 3550335640Shselasky handle->linktype = DLT_RAW; 3551335640Shselasky break; 3552335640Shselasky 3553335640Shselasky#ifndef ARPHRD_IEEE802154 3554335640Shselasky#define ARPHRD_IEEE802154 804 3555335640Shselasky#endif 3556335640Shselasky case ARPHRD_IEEE802154: 3557335640Shselasky handle->linktype = DLT_IEEE802_15_4_NOFCS; 3558335640Shselasky break; 3559335640Shselasky 3560335640Shselasky#ifndef ARPHRD_NETLINK 3561335640Shselasky#define ARPHRD_NETLINK 824 3562335640Shselasky#endif 3563335640Shselasky case ARPHRD_NETLINK: 3564335640Shselasky handle->linktype = DLT_NETLINK; 3565335640Shselasky /* 3566335640Shselasky * We need to use cooked mode, so that in sll_protocol we 3567335640Shselasky * pick up the netlink protocol type such as NETLINK_ROUTE, 3568335640Shselasky * NETLINK_GENERIC, NETLINK_FIB_LOOKUP, etc. 3569335640Shselasky * 3570335640Shselasky * XXX - this is handled in activate_new(). 3571335640Shselasky */ 3572335640Shselasky /* handlep->cooked = 1; */ 3573335640Shselasky break; 3574335640Shselasky 3575335640Shselasky#ifndef ARPHRD_VSOCKMON 3576335640Shselasky#define ARPHRD_VSOCKMON 826 3577335640Shselasky#endif 3578335640Shselasky case ARPHRD_VSOCKMON: 3579335640Shselasky handle->linktype = DLT_VSOCK; 3580335640Shselasky break; 3581335640Shselasky 3582335640Shselasky default: 3583335640Shselasky handle->linktype = -1; 3584335640Shselasky break; 3585335640Shselasky } 3586335640Shselasky} 3587335640Shselasky 3588335640Shselasky/* ===== Functions to interface to the newer kernels ================== */ 3589335640Shselasky 3590356341Scy#ifdef PACKET_RESERVE 3591356341Scystatic void 3592356341Scyset_dlt_list_cooked(pcap_t *handle, int sock_fd) 3593356341Scy{ 3594356341Scy socklen_t len; 3595356341Scy unsigned int tp_reserve; 3596356341Scy 3597356341Scy /* 3598356341Scy * If we can't do PACKET_RESERVE, we can't reserve extra space 3599356341Scy * for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2. 3600356341Scy */ 3601356341Scy len = sizeof(tp_reserve); 3602356341Scy if (getsockopt(sock_fd, SOL_PACKET, PACKET_RESERVE, &tp_reserve, 3603356341Scy &len) == 0) { 3604356341Scy /* 3605356341Scy * Yes, we can do DLL_LINUX_SLL2. 3606356341Scy */ 3607356341Scy handle->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 3608356341Scy /* 3609356341Scy * If that fails, just leave the list empty. 3610356341Scy */ 3611356341Scy if (handle->dlt_list != NULL) { 3612356341Scy handle->dlt_list[0] = DLT_LINUX_SLL; 3613356341Scy handle->dlt_list[1] = DLT_LINUX_SLL2; 3614356341Scy handle->dlt_count = 2; 3615356341Scy } 3616356341Scy } 3617356341Scy} 3618356341Scy#else 3619335640Shselasky/* 3620356341Scy * The build environment doesn't define PACKET_RESERVE, so we can't reserve 3621356341Scy * extra space for a DLL_LINUX_SLL2 header, so we can't support DLT_LINUX_SLL2. 3622356341Scy */ 3623356341Scystatic void 3624356341Scyset_dlt_list_cooked(pcap_t *handle _U_, int sock_fd _U_) 3625356341Scy{ 3626356341Scy} 3627356341Scy#endif 3628356341Scy 3629356341Scy/* 3630335640Shselasky * Try to open a packet socket using the new kernel PF_PACKET interface. 3631335640Shselasky * Returns 1 on success, 0 on an error that means the new interface isn't 3632335640Shselasky * present (so the old SOCK_PACKET interface should be tried), and a 3633335640Shselasky * PCAP_ERROR_ value on an error that means that the old mechanism won't 3634335640Shselasky * work either (so it shouldn't be tried). 3635335640Shselasky */ 3636335640Shselaskystatic int 3637335640Shselaskyactivate_new(pcap_t *handle) 3638335640Shselasky{ 3639335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 3640335640Shselasky struct pcap_linux *handlep = handle->priv; 3641335640Shselasky const char *device = handle->opt.device; 3642335640Shselasky int is_any_device = (strcmp(device, "any") == 0); 3643335640Shselasky int protocol = pcap_protocol(handle); 3644356341Scy int sock_fd = -1, arptype, ret; 3645335640Shselasky#ifdef HAVE_PACKET_AUXDATA 3646335640Shselasky int val; 3647335640Shselasky#endif 3648335640Shselasky int err = 0; 3649335640Shselasky struct packet_mreq mr; 3650335640Shselasky#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) 3651335640Shselasky int bpf_extensions; 3652335640Shselasky socklen_t len = sizeof(bpf_extensions); 3653335640Shselasky#endif 3654335640Shselasky 3655335640Shselasky /* 3656335640Shselasky * Open a socket with protocol family packet. If the 3657335640Shselasky * "any" device was specified, we open a SOCK_DGRAM 3658335640Shselasky * socket for the cooked interface, otherwise we first 3659335640Shselasky * try a SOCK_RAW socket for the raw interface. 3660335640Shselasky */ 3661335640Shselasky sock_fd = is_any_device ? 3662335640Shselasky socket(PF_PACKET, SOCK_DGRAM, protocol) : 3663335640Shselasky socket(PF_PACKET, SOCK_RAW, protocol); 3664335640Shselasky 3665335640Shselasky if (sock_fd == -1) { 3666335640Shselasky if (errno == EINVAL || errno == EAFNOSUPPORT) { 3667335640Shselasky /* 3668335640Shselasky * We don't support PF_PACKET/SOCK_whatever 3669335640Shselasky * sockets; try the old mechanism. 3670335640Shselasky */ 3671335640Shselasky return 0; 3672335640Shselasky } 3673335640Shselasky if (errno == EPERM || errno == EACCES) { 3674335640Shselasky /* 3675335640Shselasky * You don't have permission to open the 3676335640Shselasky * socket. 3677335640Shselasky */ 3678356341Scy ret = PCAP_ERROR_PERM_DENIED; 3679335640Shselasky } else { 3680335640Shselasky /* 3681335640Shselasky * Other error. 3682335640Shselasky */ 3683356341Scy ret = PCAP_ERROR; 3684335640Shselasky } 3685356341Scy pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 3686356341Scy errno, "socket"); 3687356341Scy return ret; 3688335640Shselasky } 3689335640Shselasky 3690335640Shselasky /* It seems the kernel supports the new interface. */ 3691335640Shselasky handlep->sock_packet = 0; 3692335640Shselasky 3693335640Shselasky /* 3694335640Shselasky * Get the interface index of the loopback device. 3695335640Shselasky * If the attempt fails, don't fail, just set the 3696335640Shselasky * "handlep->lo_ifindex" to -1. 3697335640Shselasky * 3698335640Shselasky * XXX - can there be more than one device that loops 3699335640Shselasky * packets back, i.e. devices other than "lo"? If so, 3700335640Shselasky * we'd need to find them all, and have an array of 3701335640Shselasky * indices for them, and check all of them in 3702335640Shselasky * "pcap_read_packet()". 3703335640Shselasky */ 3704335640Shselasky handlep->lo_ifindex = iface_get_id(sock_fd, "lo", handle->errbuf); 3705335640Shselasky 3706335640Shselasky /* 3707335640Shselasky * Default value for offset to align link-layer payload 3708335640Shselasky * on a 4-byte boundary. 3709335640Shselasky */ 3710335640Shselasky handle->offset = 0; 3711335640Shselasky 3712335640Shselasky /* 3713335640Shselasky * What kind of frames do we have to deal with? Fall back 3714335640Shselasky * to cooked mode if we have an unknown interface type 3715335640Shselasky * or a type we know doesn't work well in raw mode. 3716335640Shselasky */ 3717335640Shselasky if (!is_any_device) { 3718335640Shselasky /* Assume for now we don't need cooked mode. */ 3719335640Shselasky handlep->cooked = 0; 3720335640Shselasky 3721335640Shselasky if (handle->opt.rfmon) { 3722335640Shselasky /* 3723335640Shselasky * We were asked to turn on monitor mode. 3724335640Shselasky * Do so before we get the link-layer type, 3725335640Shselasky * because entering monitor mode could change 3726335640Shselasky * the link-layer type. 3727335640Shselasky */ 3728335640Shselasky err = enter_rfmon_mode(handle, sock_fd, device); 3729335640Shselasky if (err < 0) { 3730335640Shselasky /* Hard failure */ 3731335640Shselasky close(sock_fd); 3732335640Shselasky return err; 3733335640Shselasky } 3734335640Shselasky if (err == 0) { 3735335640Shselasky /* 3736335640Shselasky * Nothing worked for turning monitor mode 3737335640Shselasky * on. 3738335640Shselasky */ 3739335640Shselasky close(sock_fd); 3740335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 3741335640Shselasky } 3742335640Shselasky 3743335640Shselasky /* 3744335640Shselasky * Either monitor mode has been turned on for 3745335640Shselasky * the device, or we've been given a different 3746335640Shselasky * device to open for monitor mode. If we've 3747335640Shselasky * been given a different device, use it. 3748335640Shselasky */ 3749335640Shselasky if (handlep->mondevice != NULL) 3750335640Shselasky device = handlep->mondevice; 3751335640Shselasky } 3752335640Shselasky arptype = iface_get_arptype(sock_fd, device, handle->errbuf); 3753335640Shselasky if (arptype < 0) { 3754335640Shselasky close(sock_fd); 3755335640Shselasky return arptype; 3756335640Shselasky } 3757335640Shselasky map_arphrd_to_dlt(handle, sock_fd, arptype, device, 1); 3758335640Shselasky if (handle->linktype == -1 || 3759335640Shselasky handle->linktype == DLT_LINUX_SLL || 3760335640Shselasky handle->linktype == DLT_LINUX_IRDA || 3761335640Shselasky handle->linktype == DLT_LINUX_LAPD || 3762335640Shselasky handle->linktype == DLT_NETLINK || 3763335640Shselasky (handle->linktype == DLT_EN10MB && 3764335640Shselasky (strncmp("isdn", device, 4) == 0 || 3765335640Shselasky strncmp("isdY", device, 4) == 0))) { 3766335640Shselasky /* 3767335640Shselasky * Unknown interface type (-1), or a 3768335640Shselasky * device we explicitly chose to run 3769335640Shselasky * in cooked mode (e.g., PPP devices), 3770335640Shselasky * or an ISDN device (whose link-layer 3771335640Shselasky * type we can only determine by using 3772335640Shselasky * APIs that may be different on different 3773335640Shselasky * kernels) - reopen in cooked mode. 3774335640Shselasky */ 3775335640Shselasky if (close(sock_fd) == -1) { 3776335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 3777335640Shselasky PCAP_ERRBUF_SIZE, errno, "close"); 3778335640Shselasky return PCAP_ERROR; 3779335640Shselasky } 3780335640Shselasky sock_fd = socket(PF_PACKET, SOCK_DGRAM, protocol); 3781335640Shselasky if (sock_fd == -1) { 3782335640Shselasky if (errno == EPERM || errno == EACCES) { 3783335640Shselasky /* 3784335640Shselasky * You don't have permission to 3785335640Shselasky * open the socket. 3786335640Shselasky */ 3787356341Scy ret = PCAP_ERROR_PERM_DENIED; 3788335640Shselasky } else { 3789335640Shselasky /* 3790335640Shselasky * Other error. 3791335640Shselasky */ 3792356341Scy ret = PCAP_ERROR; 3793335640Shselasky } 3794356341Scy pcap_fmt_errmsg_for_errno(handle->errbuf, 3795356341Scy PCAP_ERRBUF_SIZE, errno, "socket"); 3796356341Scy return ret; 3797335640Shselasky } 3798335640Shselasky handlep->cooked = 1; 3799335640Shselasky 3800335640Shselasky /* 3801335640Shselasky * Get rid of any link-layer type list 3802335640Shselasky * we allocated - this only supports cooked 3803335640Shselasky * capture. 3804335640Shselasky */ 3805335640Shselasky if (handle->dlt_list != NULL) { 3806335640Shselasky free(handle->dlt_list); 3807335640Shselasky handle->dlt_list = NULL; 3808335640Shselasky handle->dlt_count = 0; 3809356341Scy set_dlt_list_cooked(handle, sock_fd); 3810335640Shselasky } 3811335640Shselasky 3812335640Shselasky if (handle->linktype == -1) { 3813335640Shselasky /* 3814335640Shselasky * Warn that we're falling back on 3815335640Shselasky * cooked mode; we may want to 3816335640Shselasky * update "map_arphrd_to_dlt()" 3817335640Shselasky * to handle the new type. 3818335640Shselasky */ 3819335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 3820335640Shselasky "arptype %d not " 3821335640Shselasky "supported by libpcap - " 3822335640Shselasky "falling back to cooked " 3823335640Shselasky "socket", 3824335640Shselasky arptype); 3825335640Shselasky } 3826335640Shselasky 3827335640Shselasky /* 3828335640Shselasky * IrDA capture is not a real "cooked" capture, 3829335640Shselasky * it's IrLAP frames, not IP packets. The 3830335640Shselasky * same applies to LAPD capture. 3831335640Shselasky */ 3832335640Shselasky if (handle->linktype != DLT_LINUX_IRDA && 3833335640Shselasky handle->linktype != DLT_LINUX_LAPD && 3834335640Shselasky handle->linktype != DLT_NETLINK) 3835335640Shselasky handle->linktype = DLT_LINUX_SLL; 3836335640Shselasky } 3837335640Shselasky 3838335640Shselasky handlep->ifindex = iface_get_id(sock_fd, device, 3839335640Shselasky handle->errbuf); 3840335640Shselasky if (handlep->ifindex == -1) { 3841335640Shselasky close(sock_fd); 3842335640Shselasky return PCAP_ERROR; 3843335640Shselasky } 3844335640Shselasky 3845335640Shselasky if ((err = iface_bind(sock_fd, handlep->ifindex, 3846335640Shselasky handle->errbuf, protocol)) != 1) { 3847335640Shselasky close(sock_fd); 3848335640Shselasky if (err < 0) 3849335640Shselasky return err; 3850335640Shselasky else 3851335640Shselasky return 0; /* try old mechanism */ 3852335640Shselasky } 3853335640Shselasky } else { 3854335640Shselasky /* 3855335640Shselasky * The "any" device. 3856335640Shselasky */ 3857335640Shselasky if (handle->opt.rfmon) { 3858335640Shselasky /* 3859335640Shselasky * It doesn't support monitor mode. 3860335640Shselasky */ 3861335640Shselasky close(sock_fd); 3862335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 3863335640Shselasky } 3864335640Shselasky 3865335640Shselasky /* 3866335640Shselasky * It uses cooked mode. 3867335640Shselasky */ 3868335640Shselasky handlep->cooked = 1; 3869335640Shselasky handle->linktype = DLT_LINUX_SLL; 3870356341Scy handle->dlt_list = NULL; 3871356341Scy handle->dlt_count = 0; 3872356341Scy set_dlt_list_cooked(handle, sock_fd); 3873335640Shselasky 3874335640Shselasky /* 3875335640Shselasky * We're not bound to a device. 3876335640Shselasky * For now, we're using this as an indication 3877335640Shselasky * that we can't transmit; stop doing that only 3878335640Shselasky * if we figure out how to transmit in cooked 3879335640Shselasky * mode. 3880335640Shselasky */ 3881335640Shselasky handlep->ifindex = -1; 3882335640Shselasky } 3883335640Shselasky 3884335640Shselasky /* 3885335640Shselasky * Select promiscuous mode on if "promisc" is set. 3886335640Shselasky * 3887335640Shselasky * Do not turn allmulti mode on if we don't select 3888335640Shselasky * promiscuous mode - on some devices (e.g., Orinoco 3889335640Shselasky * wireless interfaces), allmulti mode isn't supported 3890335640Shselasky * and the driver implements it by turning promiscuous 3891335640Shselasky * mode on, and that screws up the operation of the 3892335640Shselasky * card as a normal networking interface, and on no 3893335640Shselasky * other platform I know of does starting a non- 3894335640Shselasky * promiscuous capture affect which multicast packets 3895335640Shselasky * are received by the interface. 3896335640Shselasky */ 3897335640Shselasky 3898335640Shselasky /* 3899335640Shselasky * Hmm, how can we set promiscuous mode on all interfaces? 3900335640Shselasky * I am not sure if that is possible at all. For now, we 3901335640Shselasky * silently ignore attempts to turn promiscuous mode on 3902335640Shselasky * for the "any" device (so you don't have to explicitly 3903335640Shselasky * disable it in programs such as tcpdump). 3904335640Shselasky */ 3905335640Shselasky 3906335640Shselasky if (!is_any_device && handle->opt.promisc) { 3907335640Shselasky memset(&mr, 0, sizeof(mr)); 3908335640Shselasky mr.mr_ifindex = handlep->ifindex; 3909335640Shselasky mr.mr_type = PACKET_MR_PROMISC; 3910335640Shselasky if (setsockopt(sock_fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, 3911335640Shselasky &mr, sizeof(mr)) == -1) { 3912335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 3913356341Scy PCAP_ERRBUF_SIZE, errno, "setsockopt (PACKET_ADD_MEMBERSHIP)"); 3914335640Shselasky close(sock_fd); 3915335640Shselasky return PCAP_ERROR; 3916335640Shselasky } 3917335640Shselasky } 3918335640Shselasky 3919335640Shselasky /* Enable auxillary data if supported and reserve room for 3920335640Shselasky * reconstructing VLAN headers. */ 3921335640Shselasky#ifdef HAVE_PACKET_AUXDATA 3922335640Shselasky val = 1; 3923335640Shselasky if (setsockopt(sock_fd, SOL_PACKET, PACKET_AUXDATA, &val, 3924335640Shselasky sizeof(val)) == -1 && errno != ENOPROTOOPT) { 3925335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 3926356341Scy errno, "setsockopt (PACKET_AUXDATA)"); 3927335640Shselasky close(sock_fd); 3928335640Shselasky return PCAP_ERROR; 3929335640Shselasky } 3930335640Shselasky handle->offset += VLAN_TAG_LEN; 3931335640Shselasky#endif /* HAVE_PACKET_AUXDATA */ 3932335640Shselasky 3933335640Shselasky /* 3934335640Shselasky * This is a 2.2[.x] or later kernel (we know that 3935335640Shselasky * because we're not using a SOCK_PACKET socket - 3936335640Shselasky * PF_PACKET is supported only in 2.2 and later 3937335640Shselasky * kernels). 3938335640Shselasky * 3939335640Shselasky * We can safely pass "recvfrom()" a byte count 3940335640Shselasky * based on the snapshot length. 3941335640Shselasky * 3942335640Shselasky * If we're in cooked mode, make the snapshot length 3943335640Shselasky * large enough to hold a "cooked mode" header plus 3944335640Shselasky * 1 byte of packet data (so we don't pass a byte 3945335640Shselasky * count of 0 to "recvfrom()"). 3946356341Scy * XXX - we don't know whether this will be DLT_LINUX_SLL 3947356341Scy * or DLT_LINUX_SLL2, so make sure it's big enough for 3948356341Scy * a DLT_LINUX_SLL2 "cooked mode" header; a snapshot length 3949356341Scy * that small is silly anyway. 3950335640Shselasky */ 3951335640Shselasky if (handlep->cooked) { 3952356341Scy if (handle->snapshot < SLL2_HDR_LEN + 1) 3953356341Scy handle->snapshot = SLL2_HDR_LEN + 1; 3954335640Shselasky } 3955335640Shselasky handle->bufsize = handle->snapshot; 3956335640Shselasky 3957335640Shselasky /* 3958335640Shselasky * Set the offset at which to insert VLAN tags. 3959335640Shselasky * That should be the offset of the type field. 3960335640Shselasky */ 3961335640Shselasky switch (handle->linktype) { 3962335640Shselasky 3963335640Shselasky case DLT_EN10MB: 3964335640Shselasky /* 3965335640Shselasky * The type field is after the destination and source 3966335640Shselasky * MAC address. 3967335640Shselasky */ 3968335640Shselasky handlep->vlan_offset = 2 * ETH_ALEN; 3969335640Shselasky break; 3970335640Shselasky 3971335640Shselasky case DLT_LINUX_SLL: 3972335640Shselasky /* 3973335640Shselasky * The type field is in the last 2 bytes of the 3974335640Shselasky * DLT_LINUX_SLL header. 3975335640Shselasky */ 3976335640Shselasky handlep->vlan_offset = SLL_HDR_LEN - 2; 3977335640Shselasky break; 3978335640Shselasky 3979335640Shselasky default: 3980335640Shselasky handlep->vlan_offset = -1; /* unknown */ 3981335640Shselasky break; 3982335640Shselasky } 3983335640Shselasky 3984335640Shselasky#if defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) 3985335640Shselasky if (handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO) { 3986335640Shselasky int nsec_tstamps = 1; 3987335640Shselasky 3988335640Shselasky if (setsockopt(sock_fd, SOL_SOCKET, SO_TIMESTAMPNS, &nsec_tstamps, sizeof(nsec_tstamps)) < 0) { 3989335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, "setsockopt: unable to set SO_TIMESTAMPNS"); 3990335640Shselasky close(sock_fd); 3991335640Shselasky return PCAP_ERROR; 3992335640Shselasky } 3993335640Shselasky } 3994335640Shselasky#endif /* defined(SIOCGSTAMPNS) && defined(SO_TIMESTAMPNS) */ 3995335640Shselasky 3996335640Shselasky /* 3997335640Shselasky * We've succeeded. Save the socket FD in the pcap structure. 3998335640Shselasky */ 3999335640Shselasky handle->fd = sock_fd; 4000335640Shselasky 4001335640Shselasky#if defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) 4002335640Shselasky /* 4003335640Shselasky * Can we generate special code for VLAN checks? 4004335640Shselasky * (XXX - what if we need the special code but it's not supported 4005335640Shselasky * by the OS? Is that possible?) 4006335640Shselasky */ 4007335640Shselasky if (getsockopt(sock_fd, SOL_SOCKET, SO_BPF_EXTENSIONS, 4008335640Shselasky &bpf_extensions, &len) == 0) { 4009335640Shselasky if (bpf_extensions >= SKF_AD_VLAN_TAG_PRESENT) { 4010335640Shselasky /* 4011335640Shselasky * Yes, we can. Request that we do so. 4012335640Shselasky */ 4013335640Shselasky handle->bpf_codegen_flags |= BPF_SPECIAL_VLAN_HANDLING; 4014335640Shselasky } 4015335640Shselasky } 4016335640Shselasky#endif /* defined(SO_BPF_EXTENSIONS) && defined(SKF_AD_VLAN_TAG_PRESENT) */ 4017335640Shselasky 4018335640Shselasky return 1; 4019335640Shselasky#else /* HAVE_PF_PACKET_SOCKETS */ 4020356341Scy pcap_strlcpy(ebuf, 4021335640Shselasky "New packet capturing interface not supported by build " 4022335640Shselasky "environment", PCAP_ERRBUF_SIZE); 4023335640Shselasky return 0; 4024335640Shselasky#endif /* HAVE_PF_PACKET_SOCKETS */ 4025335640Shselasky} 4026335640Shselasky 4027335640Shselasky#ifdef HAVE_PACKET_RING 4028335640Shselasky/* 4029335640Shselasky * Attempt to activate with memory-mapped access. 4030335640Shselasky * 4031335640Shselasky * On success, returns 1, and sets *status to 0 if there are no warnings 4032335640Shselasky * or to a PCAP_WARNING_ code if there is a warning. 4033335640Shselasky * 4034335640Shselasky * On failure due to lack of support for memory-mapped capture, returns 4035335640Shselasky * 0. 4036335640Shselasky * 4037335640Shselasky * On error, returns -1, and sets *status to the appropriate error code; 4038335640Shselasky * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. 4039335640Shselasky */ 4040335640Shselaskystatic int 4041335640Shselaskyactivate_mmap(pcap_t *handle, int *status) 4042335640Shselasky{ 4043335640Shselasky struct pcap_linux *handlep = handle->priv; 4044335640Shselasky int ret; 4045335640Shselasky 4046335640Shselasky /* 4047335640Shselasky * Attempt to allocate a buffer to hold the contents of one 4048335640Shselasky * packet, for use by the oneshot callback. 4049335640Shselasky */ 4050335640Shselasky handlep->oneshot_buffer = malloc(handle->snapshot); 4051335640Shselasky if (handlep->oneshot_buffer == NULL) { 4052335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4053335640Shselasky errno, "can't allocate oneshot buffer"); 4054335640Shselasky *status = PCAP_ERROR; 4055335640Shselasky return -1; 4056335640Shselasky } 4057335640Shselasky 4058335640Shselasky if (handle->opt.buffer_size == 0) { 4059335640Shselasky /* by default request 2M for the ring buffer */ 4060335640Shselasky handle->opt.buffer_size = 2*1024*1024; 4061335640Shselasky } 4062335640Shselasky ret = prepare_tpacket_socket(handle); 4063335640Shselasky if (ret == -1) { 4064335640Shselasky free(handlep->oneshot_buffer); 4065335640Shselasky *status = PCAP_ERROR; 4066335640Shselasky return ret; 4067335640Shselasky } 4068335640Shselasky ret = create_ring(handle, status); 4069335640Shselasky if (ret == 0) { 4070335640Shselasky /* 4071335640Shselasky * We don't support memory-mapped capture; our caller 4072335640Shselasky * will fall back on reading from the socket. 4073335640Shselasky */ 4074335640Shselasky free(handlep->oneshot_buffer); 4075335640Shselasky return 0; 4076335640Shselasky } 4077335640Shselasky if (ret == -1) { 4078335640Shselasky /* 4079335640Shselasky * Error attempting to enable memory-mapped capture; 4080335640Shselasky * fail. create_ring() has set *status. 4081335640Shselasky */ 4082335640Shselasky free(handlep->oneshot_buffer); 4083335640Shselasky return -1; 4084335640Shselasky } 4085335640Shselasky 4086335640Shselasky /* 4087335640Shselasky * Success. *status has been set either to 0 if there are no 4088335640Shselasky * warnings or to a PCAP_WARNING_ value if there is a warning. 4089335640Shselasky * 4090335640Shselasky * Override some defaults and inherit the other fields from 4091335640Shselasky * activate_new. 4092335640Shselasky * handle->offset is used to get the current position into the rx ring. 4093335640Shselasky * handle->cc is used to store the ring size. 4094335640Shselasky */ 4095335640Shselasky 4096335640Shselasky switch (handlep->tp_version) { 4097335640Shselasky case TPACKET_V1: 4098335640Shselasky handle->read_op = pcap_read_linux_mmap_v1; 4099335640Shselasky break; 4100335640Shselasky case TPACKET_V1_64: 4101335640Shselasky handle->read_op = pcap_read_linux_mmap_v1_64; 4102335640Shselasky break; 4103335640Shselasky#ifdef HAVE_TPACKET2 4104335640Shselasky case TPACKET_V2: 4105335640Shselasky handle->read_op = pcap_read_linux_mmap_v2; 4106335640Shselasky break; 4107335640Shselasky#endif 4108335640Shselasky#ifdef HAVE_TPACKET3 4109335640Shselasky case TPACKET_V3: 4110335640Shselasky handle->read_op = pcap_read_linux_mmap_v3; 4111335640Shselasky break; 4112335640Shselasky#endif 4113335640Shselasky } 4114335640Shselasky handle->cleanup_op = pcap_cleanup_linux_mmap; 4115335640Shselasky handle->setfilter_op = pcap_setfilter_linux_mmap; 4116335640Shselasky handle->setnonblock_op = pcap_setnonblock_mmap; 4117335640Shselasky handle->getnonblock_op = pcap_getnonblock_mmap; 4118335640Shselasky handle->oneshot_callback = pcap_oneshot_mmap; 4119335640Shselasky handle->selectable_fd = handle->fd; 4120335640Shselasky return 1; 4121335640Shselasky} 4122335640Shselasky#else /* HAVE_PACKET_RING */ 4123335640Shselaskystatic int 4124335640Shselaskyactivate_mmap(pcap_t *handle _U_, int *status _U_) 4125335640Shselasky{ 4126335640Shselasky return 0; 4127335640Shselasky} 4128335640Shselasky#endif /* HAVE_PACKET_RING */ 4129335640Shselasky 4130335640Shselasky#ifdef HAVE_PACKET_RING 4131335640Shselasky 4132335640Shselasky#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3) 4133335640Shselasky/* 4134335640Shselasky * Attempt to set the socket to the specified version of the memory-mapped 4135335640Shselasky * header. 4136335640Shselasky * 4137335640Shselasky * Return 0 if we succeed; return 1 if we fail because that version isn't 4138335640Shselasky * supported; return -1 on any other error, and set handle->errbuf. 4139335640Shselasky */ 4140335640Shselaskystatic int 4141335640Shselaskyinit_tpacket(pcap_t *handle, int version, const char *version_str) 4142335640Shselasky{ 4143335640Shselasky struct pcap_linux *handlep = handle->priv; 4144335640Shselasky int val = version; 4145335640Shselasky socklen_t len = sizeof(val); 4146335640Shselasky 4147335640Shselasky /* 4148335640Shselasky * Probe whether kernel supports the specified TPACKET version; 4149335640Shselasky * this also gets the length of the header for that version. 4150356341Scy * 4151356341Scy * This socket option was introduced in 2.6.27, which was 4152356341Scy * also the first release with TPACKET_V2 support. 4153335640Shselasky */ 4154335640Shselasky if (getsockopt(handle->fd, SOL_PACKET, PACKET_HDRLEN, &val, &len) < 0) { 4155356341Scy if (errno == ENOPROTOOPT || errno == EINVAL) { 4156356341Scy /* 4157356341Scy * ENOPROTOOPT means the kernel is too old to 4158356341Scy * support PACKET_HDRLEN at all, which means 4159356341Scy * it either doesn't support TPACKET at all 4160356341Scy * or supports only TPACKET_V1. 4161356341Scy */ 4162335640Shselasky return 1; /* no */ 4163356341Scy } 4164335640Shselasky 4165335640Shselasky /* Failed to even find out; this is a fatal error. */ 4166335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4167335640Shselasky errno, "can't get %s header len on packet socket", 4168335640Shselasky version_str); 4169335640Shselasky return -1; 4170335640Shselasky } 4171335640Shselasky handlep->tp_hdrlen = val; 4172335640Shselasky 4173335640Shselasky val = version; 4174335640Shselasky if (setsockopt(handle->fd, SOL_PACKET, PACKET_VERSION, &val, 4175335640Shselasky sizeof(val)) < 0) { 4176335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4177335640Shselasky errno, "can't activate %s on packet socket", version_str); 4178335640Shselasky return -1; 4179335640Shselasky } 4180335640Shselasky handlep->tp_version = version; 4181335640Shselasky 4182356341Scy /* 4183356341Scy * Reserve space for VLAN tag reconstruction. 4184356341Scy * This option was also introduced in 2.6.27. 4185356341Scy */ 4186335640Shselasky val = VLAN_TAG_LEN; 4187335640Shselasky if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, &val, 4188335640Shselasky sizeof(val)) < 0) { 4189335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4190335640Shselasky errno, "can't set up reserve on packet socket"); 4191335640Shselasky return -1; 4192335640Shselasky } 4193335640Shselasky 4194335640Shselasky return 0; 4195335640Shselasky} 4196335640Shselasky#endif /* defined HAVE_TPACKET2 || defined HAVE_TPACKET3 */ 4197335640Shselasky 4198335640Shselasky/* 4199335640Shselasky * If the instruction set for which we're compiling has both 32-bit 4200335640Shselasky * and 64-bit versions, and Linux support for the 64-bit version 4201335640Shselasky * predates TPACKET_V2, define ISA_64_BIT as the .machine value 4202335640Shselasky * you get from uname() for the 64-bit version. Otherwise, leave 4203335640Shselasky * it undefined. (This includes ARM, which has a 64-bit version, 4204335640Shselasky * but Linux support for it appeared well after TPACKET_V2 support 4205335640Shselasky * did, so there should never be a case where 32-bit ARM code is 4206335640Shselasky * running o a 64-bit kernel that only supports TPACKET_V1.) 4207335640Shselasky * 4208335640Shselasky * If we've omitted your favorite such architecture, please contribute 4209335640Shselasky * a patch. (No patch is needed for architectures that are 32-bit-only 4210335640Shselasky * or for which Linux has no support for 32-bit userland - or for which, 4211335640Shselasky * as noted, 64-bit support appeared in Linux after TPACKET_V2 support 4212335640Shselasky * did.) 4213335640Shselasky */ 4214335640Shselasky#if defined(__i386__) 4215335640Shselasky#define ISA_64_BIT "x86_64" 4216335640Shselasky#elif defined(__ppc__) 4217335640Shselasky#define ISA_64_BIT "ppc64" 4218335640Shselasky#elif defined(__sparc__) 4219335640Shselasky#define ISA_64_BIT "sparc64" 4220335640Shselasky#elif defined(__s390__) 4221335640Shselasky#define ISA_64_BIT "s390x" 4222335640Shselasky#elif defined(__mips__) 4223335640Shselasky#define ISA_64_BIT "mips64" 4224335640Shselasky#elif defined(__hppa__) 4225335640Shselasky#define ISA_64_BIT "parisc64" 4226335640Shselasky#endif 4227335640Shselasky 4228335640Shselasky/* 4229335640Shselasky * Attempt to set the socket to version 3 of the memory-mapped header and, 4230335640Shselasky * if that fails because version 3 isn't supported, attempt to fall 4231335640Shselasky * back to version 2. If version 2 isn't supported, just leave it at 4232335640Shselasky * version 1. 4233335640Shselasky * 4234335640Shselasky * Return 1 if we succeed or if we fail because neither version 2 nor 3 is 4235335640Shselasky * supported; return -1 on any other error, and set handle->errbuf. 4236335640Shselasky */ 4237335640Shselaskystatic int 4238335640Shselaskyprepare_tpacket_socket(pcap_t *handle) 4239335640Shselasky{ 4240335640Shselasky struct pcap_linux *handlep = handle->priv; 4241335640Shselasky#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3) 4242335640Shselasky int ret; 4243335640Shselasky#endif 4244335640Shselasky 4245335640Shselasky#ifdef HAVE_TPACKET3 4246335640Shselasky /* 4247335640Shselasky * Try setting the version to TPACKET_V3. 4248335640Shselasky * 4249335640Shselasky * The only mode in which buffering is done on PF_PACKET 4250335640Shselasky * sockets, so that packets might not be delivered 4251335640Shselasky * immediately, is TPACKET_V3 mode. 4252335640Shselasky * 4253335640Shselasky * The buffering cannot be disabled in that mode, so 4254335640Shselasky * if the user has requested immediate mode, we don't 4255335640Shselasky * use TPACKET_V3. 4256335640Shselasky */ 4257335640Shselasky if (!handle->opt.immediate) { 4258335640Shselasky ret = init_tpacket(handle, TPACKET_V3, "TPACKET_V3"); 4259335640Shselasky if (ret == 0) { 4260335640Shselasky /* 4261335640Shselasky * Success. 4262335640Shselasky */ 4263335640Shselasky return 1; 4264335640Shselasky } 4265335640Shselasky if (ret == -1) { 4266335640Shselasky /* 4267335640Shselasky * We failed for some reason other than "the 4268335640Shselasky * kernel doesn't support TPACKET_V3". 4269335640Shselasky */ 4270335640Shselasky return -1; 4271335640Shselasky } 4272335640Shselasky } 4273335640Shselasky#endif /* HAVE_TPACKET3 */ 4274335640Shselasky 4275335640Shselasky#ifdef HAVE_TPACKET2 4276335640Shselasky /* 4277335640Shselasky * Try setting the version to TPACKET_V2. 4278335640Shselasky */ 4279335640Shselasky ret = init_tpacket(handle, TPACKET_V2, "TPACKET_V2"); 4280335640Shselasky if (ret == 0) { 4281335640Shselasky /* 4282335640Shselasky * Success. 4283335640Shselasky */ 4284335640Shselasky return 1; 4285335640Shselasky } 4286335640Shselasky if (ret == -1) { 4287335640Shselasky /* 4288335640Shselasky * We failed for some reason other than "the 4289335640Shselasky * kernel doesn't support TPACKET_V2". 4290335640Shselasky */ 4291335640Shselasky return -1; 4292335640Shselasky } 4293335640Shselasky#endif /* HAVE_TPACKET2 */ 4294335640Shselasky 4295335640Shselasky /* 4296356341Scy * OK, we're using TPACKET_V1, as either that's all the kernel 4297356341Scy * supports or it doesn't support TPACKET at all. In the latter 4298356341Scy * case, create_ring() will fail, and we'll fall back on non- 4299356341Scy * memory-mapped capture. 4300335640Shselasky */ 4301335640Shselasky handlep->tp_version = TPACKET_V1; 4302335640Shselasky handlep->tp_hdrlen = sizeof(struct tpacket_hdr); 4303335640Shselasky 4304335640Shselasky#ifdef ISA_64_BIT 4305335640Shselasky /* 4306335640Shselasky * 32-bit userspace + 64-bit kernel + TPACKET_V1 are not compatible with 4307335640Shselasky * each other due to platform-dependent data type size differences. 4308335640Shselasky * 4309335640Shselasky * If we have a 32-bit userland and a 64-bit kernel, use an 4310335640Shselasky * internally-defined TPACKET_V1_64, with which we use a 64-bit 4311335640Shselasky * version of the data structures. 4312335640Shselasky */ 4313335640Shselasky if (sizeof(long) == 4) { 4314335640Shselasky /* 4315335640Shselasky * This is 32-bit code. 4316335640Shselasky */ 4317335640Shselasky struct utsname utsname; 4318335640Shselasky 4319335640Shselasky if (uname(&utsname) == -1) { 4320335640Shselasky /* 4321335640Shselasky * Failed. 4322335640Shselasky */ 4323335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 4324335640Shselasky PCAP_ERRBUF_SIZE, errno, "uname failed"); 4325335640Shselasky return -1; 4326335640Shselasky } 4327335640Shselasky if (strcmp(utsname.machine, ISA_64_BIT) == 0) { 4328335640Shselasky /* 4329335640Shselasky * uname() tells us the machine is 64-bit, 4330335640Shselasky * so we presumably have a 64-bit kernel. 4331335640Shselasky * 4332335640Shselasky * XXX - this presumes that uname() won't lie 4333335640Shselasky * in 32-bit code and claim that the machine 4334335640Shselasky * has the 32-bit version of the ISA. 4335335640Shselasky */ 4336335640Shselasky handlep->tp_version = TPACKET_V1_64; 4337335640Shselasky handlep->tp_hdrlen = sizeof(struct tpacket_hdr_64); 4338335640Shselasky } 4339335640Shselasky } 4340335640Shselasky#endif 4341335640Shselasky 4342335640Shselasky return 1; 4343335640Shselasky} 4344335640Shselasky 4345335640Shselasky#define MAX(a,b) ((a)>(b)?(a):(b)) 4346335640Shselasky 4347335640Shselasky/* 4348335640Shselasky * Attempt to set up memory-mapped access. 4349335640Shselasky * 4350335640Shselasky * On success, returns 1, and sets *status to 0 if there are no warnings 4351335640Shselasky * or to a PCAP_WARNING_ code if there is a warning. 4352335640Shselasky * 4353335640Shselasky * On failure due to lack of support for memory-mapped capture, returns 4354335640Shselasky * 0. 4355335640Shselasky * 4356335640Shselasky * On error, returns -1, and sets *status to the appropriate error code; 4357335640Shselasky * if that is PCAP_ERROR, sets handle->errbuf to the appropriate message. 4358335640Shselasky */ 4359335640Shselaskystatic int 4360335640Shselaskycreate_ring(pcap_t *handle, int *status) 4361335640Shselasky{ 4362335640Shselasky struct pcap_linux *handlep = handle->priv; 4363335640Shselasky unsigned i, j, frames_per_block; 4364335640Shselasky#ifdef HAVE_TPACKET3 4365335640Shselasky /* 4366335640Shselasky * For sockets using TPACKET_V1 or TPACKET_V2, the extra 4367335640Shselasky * stuff at the end of a struct tpacket_req3 will be 4368335640Shselasky * ignored, so this is OK even for those sockets. 4369335640Shselasky */ 4370335640Shselasky struct tpacket_req3 req; 4371335640Shselasky#else 4372335640Shselasky struct tpacket_req req; 4373335640Shselasky#endif 4374335640Shselasky socklen_t len; 4375335640Shselasky unsigned int sk_type, tp_reserve, maclen, tp_hdrlen, netoff, macoff; 4376335640Shselasky unsigned int frame_size; 4377335640Shselasky 4378335640Shselasky /* 4379335640Shselasky * Start out assuming no warnings or errors. 4380335640Shselasky */ 4381335640Shselasky *status = 0; 4382335640Shselasky 4383335640Shselasky switch (handlep->tp_version) { 4384335640Shselasky 4385335640Shselasky case TPACKET_V1: 4386335640Shselasky case TPACKET_V1_64: 4387335640Shselasky#ifdef HAVE_TPACKET2 4388335640Shselasky case TPACKET_V2: 4389335640Shselasky#endif 4390335640Shselasky /* Note that with large snapshot length (say 256K, which is 4391335640Shselasky * the default for recent versions of tcpdump, Wireshark, 4392335640Shselasky * TShark, dumpcap or 64K, the value that "-s 0" has given for 4393335640Shselasky * a long time with tcpdump), if we use the snapshot 4394335640Shselasky * length to calculate the frame length, only a few frames 4395335640Shselasky * will be available in the ring even with pretty 4396335640Shselasky * large ring size (and a lot of memory will be unused). 4397335640Shselasky * 4398335640Shselasky * Ideally, we should choose a frame length based on the 4399335640Shselasky * minimum of the specified snapshot length and the maximum 4400335640Shselasky * packet size. That's not as easy as it sounds; consider, 4401335640Shselasky * for example, an 802.11 interface in monitor mode, where 4402335640Shselasky * the frame would include a radiotap header, where the 4403335640Shselasky * maximum radiotap header length is device-dependent. 4404335640Shselasky * 4405335640Shselasky * So, for now, we just do this for Ethernet devices, where 4406335640Shselasky * there's no metadata header, and the link-layer header is 4407335640Shselasky * fixed length. We can get the maximum packet size by 4408335640Shselasky * adding 18, the Ethernet header length plus the CRC length 4409335640Shselasky * (just in case we happen to get the CRC in the packet), to 4410335640Shselasky * the MTU of the interface; we fetch the MTU in the hopes 4411335640Shselasky * that it reflects support for jumbo frames. (Even if the 4412335640Shselasky * interface is just being used for passive snooping, the 4413335640Shselasky * driver might set the size of buffers in the receive ring 4414335640Shselasky * based on the MTU, so that the MTU limits the maximum size 4415335640Shselasky * of packets that we can receive.) 4416335640Shselasky * 4417335640Shselasky * If segmentation/fragmentation or receive offload are 4418335640Shselasky * enabled, we can get reassembled/aggregated packets larger 4419335640Shselasky * than MTU, but bounded to 65535 plus the Ethernet overhead, 4420335640Shselasky * due to kernel and protocol constraints */ 4421335640Shselasky frame_size = handle->snapshot; 4422335640Shselasky if (handle->linktype == DLT_EN10MB) { 4423335640Shselasky unsigned int max_frame_len; 4424335640Shselasky int mtu; 4425335640Shselasky int offload; 4426335640Shselasky 4427335640Shselasky mtu = iface_get_mtu(handle->fd, handle->opt.device, 4428335640Shselasky handle->errbuf); 4429335640Shselasky if (mtu == -1) { 4430335640Shselasky *status = PCAP_ERROR; 4431335640Shselasky return -1; 4432335640Shselasky } 4433335640Shselasky offload = iface_get_offload(handle); 4434335640Shselasky if (offload == -1) { 4435335640Shselasky *status = PCAP_ERROR; 4436335640Shselasky return -1; 4437335640Shselasky } 4438335640Shselasky if (offload) 4439335640Shselasky max_frame_len = MAX(mtu, 65535); 4440335640Shselasky else 4441335640Shselasky max_frame_len = mtu; 4442335640Shselasky max_frame_len += 18; 4443335640Shselasky 4444335640Shselasky if (frame_size > max_frame_len) 4445335640Shselasky frame_size = max_frame_len; 4446335640Shselasky } 4447335640Shselasky 4448335640Shselasky /* NOTE: calculus matching those in tpacket_rcv() 4449335640Shselasky * in linux-2.6/net/packet/af_packet.c 4450335640Shselasky */ 4451335640Shselasky len = sizeof(sk_type); 4452335640Shselasky if (getsockopt(handle->fd, SOL_SOCKET, SO_TYPE, &sk_type, 4453335640Shselasky &len) < 0) { 4454335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 4455356341Scy PCAP_ERRBUF_SIZE, errno, "getsockopt (SO_TYPE)"); 4456335640Shselasky *status = PCAP_ERROR; 4457335640Shselasky return -1; 4458335640Shselasky } 4459335640Shselasky#ifdef PACKET_RESERVE 4460335640Shselasky len = sizeof(tp_reserve); 4461335640Shselasky if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, 4462335640Shselasky &tp_reserve, &len) < 0) { 4463335640Shselasky if (errno != ENOPROTOOPT) { 4464335640Shselasky /* 4465335640Shselasky * ENOPROTOOPT means "kernel doesn't support 4466335640Shselasky * PACKET_RESERVE", in which case we fall back 4467335640Shselasky * as best we can. 4468335640Shselasky */ 4469335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 4470356341Scy PCAP_ERRBUF_SIZE, errno, 4471356341Scy "getsockopt (PACKET_RESERVE)"); 4472335640Shselasky *status = PCAP_ERROR; 4473335640Shselasky return -1; 4474335640Shselasky } 4475356341Scy /* 4476356341Scy * Older kernel, so we can't use PACKET_RESERVE; 4477356341Scy * this means we can't reserver extra space 4478356341Scy * for a DLT_LINUX_SLL2 header. 4479356341Scy */ 4480356341Scy tp_reserve = 0; 4481356341Scy } else { 4482356341Scy /* 4483356341Scy * We can reserve extra space for a DLT_LINUX_SLL2 4484356341Scy * header. Do so. 4485356341Scy * 4486356341Scy * XXX - we assume that the kernel is still adding 4487356341Scy * 16 bytes of extra space; that happens to 4488356341Scy * correspond to SLL_HDR_LEN (whether intentionally 4489356341Scy * or not - the kernel code has a raw "16" in 4490356341Scy * the expression), so we subtract SLL_HDR_LEN 4491356341Scy * from SLL2_HDR_LEN to get the additional space 4492356341Scy * needed. 4493356341Scy * 4494356341Scy * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)? 4495356341Scy */ 4496356341Scy tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN; 4497356341Scy len = sizeof(tp_reserve); 4498356341Scy if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, 4499356341Scy &tp_reserve, len) < 0) { 4500356341Scy pcap_fmt_errmsg_for_errno(handle->errbuf, 4501356341Scy PCAP_ERRBUF_SIZE, errno, 4502356341Scy "setsockopt (PACKET_RESERVE)"); 4503356341Scy *status = PCAP_ERROR; 4504356341Scy return -1; 4505356341Scy } 4506335640Shselasky } 4507335640Shselasky#else 4508356341Scy /* 4509356341Scy * Build environment for an older kernel, so we can't 4510356341Scy * use PACKET_RESERVE; this means we can't reserve 4511356341Scy * extra space for a DLT_LINUX_SLL2 header. 4512356341Scy */ 4513356341Scy tp_reserve = 0; 4514335640Shselasky#endif 4515335640Shselasky maclen = (sk_type == SOCK_DGRAM) ? 0 : MAX_LINKHEADER_SIZE; 4516335640Shselasky /* XXX: in the kernel maclen is calculated from 4517335640Shselasky * LL_ALLOCATED_SPACE(dev) and vnet_hdr.hdr_len 4518335640Shselasky * in: packet_snd() in linux-2.6/net/packet/af_packet.c 4519335640Shselasky * then packet_alloc_skb() in linux-2.6/net/packet/af_packet.c 4520335640Shselasky * then sock_alloc_send_pskb() in linux-2.6/net/core/sock.c 4521335640Shselasky * but I see no way to get those sizes in userspace, 4522335640Shselasky * like for instance with an ifreq ioctl(); 4523335640Shselasky * the best thing I've found so far is MAX_HEADER in 4524335640Shselasky * the kernel part of linux-2.6/include/linux/netdevice.h 4525335640Shselasky * which goes up to 128+48=176; since pcap-linux.c 4526335640Shselasky * defines a MAX_LINKHEADER_SIZE of 256 which is 4527335640Shselasky * greater than that, let's use it.. maybe is it even 4528335640Shselasky * large enough to directly replace macoff.. 4529335640Shselasky */ 4530335640Shselasky tp_hdrlen = TPACKET_ALIGN(handlep->tp_hdrlen) + sizeof(struct sockaddr_ll) ; 4531335640Shselasky netoff = TPACKET_ALIGN(tp_hdrlen + (maclen < 16 ? 16 : maclen)) + tp_reserve; 4532335640Shselasky /* NOTE: AFAICS tp_reserve may break the TPACKET_ALIGN 4533335640Shselasky * of netoff, which contradicts 4534335640Shselasky * linux-2.6/Documentation/networking/packet_mmap.txt 4535335640Shselasky * documenting that: 4536335640Shselasky * "- Gap, chosen so that packet data (Start+tp_net) 4537335640Shselasky * aligns to TPACKET_ALIGNMENT=16" 4538335640Shselasky */ 4539335640Shselasky /* NOTE: in linux-2.6/include/linux/skbuff.h: 4540335640Shselasky * "CPUs often take a performance hit 4541335640Shselasky * when accessing unaligned memory locations" 4542335640Shselasky */ 4543335640Shselasky macoff = netoff - maclen; 4544335640Shselasky req.tp_frame_size = TPACKET_ALIGN(macoff + frame_size); 4545335640Shselasky /* 4546335640Shselasky * Round the buffer size up to a multiple of the 4547335640Shselasky * frame size (rather than rounding down, which 4548335640Shselasky * would give a buffer smaller than our caller asked 4549335640Shselasky * for, and possibly give zero frames if the requested 4550335640Shselasky * buffer size is too small for one frame). 4551335640Shselasky */ 4552335640Shselasky req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/req.tp_frame_size; 4553335640Shselasky break; 4554335640Shselasky 4555335640Shselasky#ifdef HAVE_TPACKET3 4556335640Shselasky case TPACKET_V3: 4557356341Scy /* 4558356341Scy * If we have TPACKET_V3, we have PACKET_RESERVE. 4559356341Scy */ 4560356341Scy len = sizeof(tp_reserve); 4561356341Scy if (getsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, 4562356341Scy &tp_reserve, &len) < 0) { 4563356341Scy /* 4564356341Scy * Even ENOPROTOOPT is an error - we wouldn't 4565356341Scy * be here if the kernel didn't support 4566356341Scy * TPACKET_V3, which means it supports 4567356341Scy * PACKET_RESERVE. 4568356341Scy */ 4569356341Scy pcap_fmt_errmsg_for_errno(handle->errbuf, 4570356341Scy PCAP_ERRBUF_SIZE, errno, 4571356341Scy "getsockopt (PACKET_RESERVE)"); 4572356341Scy *status = PCAP_ERROR; 4573356341Scy return -1; 4574356341Scy } 4575356341Scy /* 4576356341Scy * We can reserve extra space for a DLT_LINUX_SLL2 4577356341Scy * header. Do so. 4578356341Scy * 4579356341Scy * XXX - we assume that the kernel is still adding 4580356341Scy * 16 bytes of extra space; that happens to 4581356341Scy * correspond to SLL_HDR_LEN (whether intentionally 4582356341Scy * or not - the kernel code has a raw "16" in 4583356341Scy * the expression), so we subtract SLL_HDR_LEN 4584356341Scy * from SLL2_HDR_LEN to get the additional space 4585356341Scy * needed. 4586356341Scy * 4587356341Scy * XXX - should we use TPACKET_ALIGN(SLL2_HDR_LEN - SLL_HDR_LEN)? 4588356341Scy */ 4589356341Scy tp_reserve += SLL2_HDR_LEN - SLL_HDR_LEN; 4590356341Scy len = sizeof(tp_reserve); 4591356341Scy if (setsockopt(handle->fd, SOL_PACKET, PACKET_RESERVE, 4592356341Scy &tp_reserve, len) < 0) { 4593356341Scy pcap_fmt_errmsg_for_errno(handle->errbuf, 4594356341Scy PCAP_ERRBUF_SIZE, errno, 4595356341Scy "setsockopt (PACKET_RESERVE)"); 4596356341Scy *status = PCAP_ERROR; 4597356341Scy return -1; 4598356341Scy } 4599356341Scy 4600335640Shselasky /* The "frames" for this are actually buffers that 4601335640Shselasky * contain multiple variable-sized frames. 4602335640Shselasky * 4603335640Shselasky * We pick a "frame" size of MAXIMUM_SNAPLEN to leave 4604335640Shselasky * enough room for at least one reasonably-sized packet 4605335640Shselasky * in the "frame". */ 4606335640Shselasky req.tp_frame_size = MAXIMUM_SNAPLEN; 4607335640Shselasky /* 4608335640Shselasky * Round the buffer size up to a multiple of the 4609335640Shselasky * "frame" size (rather than rounding down, which 4610335640Shselasky * would give a buffer smaller than our caller asked 4611335640Shselasky * for, and possibly give zero "frames" if the requested 4612335640Shselasky * buffer size is too small for one "frame"). 4613335640Shselasky */ 4614335640Shselasky req.tp_frame_nr = (handle->opt.buffer_size + req.tp_frame_size - 1)/req.tp_frame_size; 4615335640Shselasky break; 4616335640Shselasky#endif 4617335640Shselasky default: 4618335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 4619335640Shselasky "Internal error: unknown TPACKET_ value %u", 4620335640Shselasky handlep->tp_version); 4621335640Shselasky *status = PCAP_ERROR; 4622335640Shselasky return -1; 4623335640Shselasky } 4624335640Shselasky 4625335640Shselasky /* compute the minumum block size that will handle this frame. 4626335640Shselasky * The block has to be page size aligned. 4627335640Shselasky * The max block size allowed by the kernel is arch-dependent and 4628335640Shselasky * it's not explicitly checked here. */ 4629335640Shselasky req.tp_block_size = getpagesize(); 4630335640Shselasky while (req.tp_block_size < req.tp_frame_size) 4631335640Shselasky req.tp_block_size <<= 1; 4632335640Shselasky 4633335640Shselasky frames_per_block = req.tp_block_size/req.tp_frame_size; 4634335640Shselasky 4635335640Shselasky /* 4636335640Shselasky * PACKET_TIMESTAMP was added after linux/net_tstamp.h was, 4637335640Shselasky * so we check for PACKET_TIMESTAMP. We check for 4638335640Shselasky * linux/net_tstamp.h just in case a system somehow has 4639335640Shselasky * PACKET_TIMESTAMP but not linux/net_tstamp.h; that might 4640335640Shselasky * be unnecessary. 4641335640Shselasky * 4642335640Shselasky * SIOCSHWTSTAMP was introduced in the patch that introduced 4643335640Shselasky * linux/net_tstamp.h, so we don't bother checking whether 4644335640Shselasky * SIOCSHWTSTAMP is defined (if your Linux system has 4645335640Shselasky * linux/net_tstamp.h but doesn't define SIOCSHWTSTAMP, your 4646335640Shselasky * Linux system is badly broken). 4647335640Shselasky */ 4648335640Shselasky#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) 4649335640Shselasky /* 4650335640Shselasky * If we were told to do so, ask the kernel and the driver 4651335640Shselasky * to use hardware timestamps. 4652335640Shselasky * 4653335640Shselasky * Hardware timestamps are only supported with mmapped 4654335640Shselasky * captures. 4655335640Shselasky */ 4656335640Shselasky if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER || 4657335640Shselasky handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER_UNSYNCED) { 4658335640Shselasky struct hwtstamp_config hwconfig; 4659335640Shselasky struct ifreq ifr; 4660335640Shselasky int timesource; 4661335640Shselasky 4662335640Shselasky /* 4663335640Shselasky * Ask for hardware time stamps on all packets, 4664335640Shselasky * including transmitted packets. 4665335640Shselasky */ 4666335640Shselasky memset(&hwconfig, 0, sizeof(hwconfig)); 4667335640Shselasky hwconfig.tx_type = HWTSTAMP_TX_ON; 4668335640Shselasky hwconfig.rx_filter = HWTSTAMP_FILTER_ALL; 4669335640Shselasky 4670335640Shselasky memset(&ifr, 0, sizeof(ifr)); 4671356341Scy pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); 4672335640Shselasky ifr.ifr_data = (void *)&hwconfig; 4673335640Shselasky 4674335640Shselasky if (ioctl(handle->fd, SIOCSHWTSTAMP, &ifr) < 0) { 4675335640Shselasky switch (errno) { 4676335640Shselasky 4677335640Shselasky case EPERM: 4678335640Shselasky /* 4679335640Shselasky * Treat this as an error, as the 4680335640Shselasky * user should try to run this 4681335640Shselasky * with the appropriate privileges - 4682335640Shselasky * and, if they can't, shouldn't 4683335640Shselasky * try requesting hardware time stamps. 4684335640Shselasky */ 4685335640Shselasky *status = PCAP_ERROR_PERM_DENIED; 4686335640Shselasky return -1; 4687335640Shselasky 4688335640Shselasky case EOPNOTSUPP: 4689335640Shselasky case ERANGE: 4690335640Shselasky /* 4691335640Shselasky * Treat this as a warning, as the 4692335640Shselasky * only way to fix the warning is to 4693335640Shselasky * get an adapter that supports hardware 4694335640Shselasky * time stamps for *all* packets. 4695335640Shselasky * (ERANGE means "we support hardware 4696335640Shselasky * time stamps, but for packets matching 4697335640Shselasky * that particular filter", so it means 4698335640Shselasky * "we don't support hardware time stamps 4699335640Shselasky * for all incoming packets" here.) 4700335640Shselasky * 4701335640Shselasky * We'll just fall back on the standard 4702335640Shselasky * host time stamps. 4703335640Shselasky */ 4704335640Shselasky *status = PCAP_WARNING_TSTAMP_TYPE_NOTSUP; 4705335640Shselasky break; 4706335640Shselasky 4707335640Shselasky default: 4708335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 4709335640Shselasky PCAP_ERRBUF_SIZE, errno, 4710335640Shselasky "SIOCSHWTSTAMP failed"); 4711335640Shselasky *status = PCAP_ERROR; 4712335640Shselasky return -1; 4713335640Shselasky } 4714335640Shselasky } else { 4715335640Shselasky /* 4716335640Shselasky * Well, that worked. Now specify the type of 4717335640Shselasky * hardware time stamp we want for this 4718335640Shselasky * socket. 4719335640Shselasky */ 4720335640Shselasky if (handle->opt.tstamp_type == PCAP_TSTAMP_ADAPTER) { 4721335640Shselasky /* 4722335640Shselasky * Hardware timestamp, synchronized 4723335640Shselasky * with the system clock. 4724335640Shselasky */ 4725335640Shselasky timesource = SOF_TIMESTAMPING_SYS_HARDWARE; 4726335640Shselasky } else { 4727335640Shselasky /* 4728335640Shselasky * PCAP_TSTAMP_ADAPTER_UNSYNCED - hardware 4729335640Shselasky * timestamp, not synchronized with the 4730335640Shselasky * system clock. 4731335640Shselasky */ 4732335640Shselasky timesource = SOF_TIMESTAMPING_RAW_HARDWARE; 4733335640Shselasky } 4734335640Shselasky if (setsockopt(handle->fd, SOL_PACKET, PACKET_TIMESTAMP, 4735335640Shselasky (void *)×ource, sizeof(timesource))) { 4736335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 4737335640Shselasky PCAP_ERRBUF_SIZE, errno, 4738335640Shselasky "can't set PACKET_TIMESTAMP"); 4739335640Shselasky *status = PCAP_ERROR; 4740335640Shselasky return -1; 4741335640Shselasky } 4742335640Shselasky } 4743335640Shselasky } 4744335640Shselasky#endif /* HAVE_LINUX_NET_TSTAMP_H && PACKET_TIMESTAMP */ 4745335640Shselasky 4746335640Shselasky /* ask the kernel to create the ring */ 4747335640Shselaskyretry: 4748335640Shselasky req.tp_block_nr = req.tp_frame_nr / frames_per_block; 4749335640Shselasky 4750335640Shselasky /* req.tp_frame_nr is requested to match frames_per_block*req.tp_block_nr */ 4751335640Shselasky req.tp_frame_nr = req.tp_block_nr * frames_per_block; 4752335640Shselasky 4753335640Shselasky#ifdef HAVE_TPACKET3 4754335640Shselasky /* timeout value to retire block - use the configured buffering timeout, or default if <0. */ 4755356341Scy if (handlep->timeout > 0) { 4756356341Scy /* Use the user specified timeout as the block timeout */ 4757356341Scy req.tp_retire_blk_tov = handlep->timeout; 4758356341Scy } else if (handlep->timeout == 0) { 4759356341Scy /* 4760356341Scy * In pcap, this means "infinite timeout"; TPACKET_V3 4761356341Scy * doesn't support that, so just set it to UINT_MAX 4762356341Scy * milliseconds. In the TPACKET_V3 loop, if the 4763356341Scy * timeout is 0, and we haven't yet seen any packets, 4764356341Scy * and we block and still don't have any packets, we 4765356341Scy * keep blocking until we do. 4766356341Scy */ 4767356341Scy req.tp_retire_blk_tov = UINT_MAX; 4768356341Scy } else { 4769356341Scy /* 4770356341Scy * XXX - this is not valid; use 0, meaning "have the 4771356341Scy * kernel pick a default", for now. 4772356341Scy */ 4773356341Scy req.tp_retire_blk_tov = 0; 4774356341Scy } 4775335640Shselasky /* private data not used */ 4776335640Shselasky req.tp_sizeof_priv = 0; 4777335640Shselasky /* Rx ring - feature request bits - none (rxhash will not be filled) */ 4778335640Shselasky req.tp_feature_req_word = 0; 4779335640Shselasky#endif 4780335640Shselasky 4781335640Shselasky if (setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, 4782335640Shselasky (void *) &req, sizeof(req))) { 4783335640Shselasky if ((errno == ENOMEM) && (req.tp_block_nr > 1)) { 4784335640Shselasky /* 4785335640Shselasky * Memory failure; try to reduce the requested ring 4786335640Shselasky * size. 4787335640Shselasky * 4788335640Shselasky * We used to reduce this by half -- do 5% instead. 4789335640Shselasky * That may result in more iterations and a longer 4790335640Shselasky * startup, but the user will be much happier with 4791335640Shselasky * the resulting buffer size. 4792335640Shselasky */ 4793335640Shselasky if (req.tp_frame_nr < 20) 4794335640Shselasky req.tp_frame_nr -= 1; 4795335640Shselasky else 4796335640Shselasky req.tp_frame_nr -= req.tp_frame_nr/20; 4797335640Shselasky goto retry; 4798335640Shselasky } 4799335640Shselasky if (errno == ENOPROTOOPT) { 4800335640Shselasky /* 4801335640Shselasky * We don't have ring buffer support in this kernel. 4802335640Shselasky */ 4803335640Shselasky return 0; 4804335640Shselasky } 4805335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4806335640Shselasky errno, "can't create rx ring on packet socket"); 4807335640Shselasky *status = PCAP_ERROR; 4808335640Shselasky return -1; 4809335640Shselasky } 4810335640Shselasky 4811335640Shselasky /* memory map the rx ring */ 4812335640Shselasky handlep->mmapbuflen = req.tp_block_nr * req.tp_block_size; 4813335640Shselasky handlep->mmapbuf = mmap(0, handlep->mmapbuflen, 4814335640Shselasky PROT_READ|PROT_WRITE, MAP_SHARED, handle->fd, 0); 4815335640Shselasky if (handlep->mmapbuf == MAP_FAILED) { 4816335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4817335640Shselasky errno, "can't mmap rx ring"); 4818335640Shselasky 4819335640Shselasky /* clear the allocated ring on error*/ 4820335640Shselasky destroy_ring(handle); 4821335640Shselasky *status = PCAP_ERROR; 4822335640Shselasky return -1; 4823335640Shselasky } 4824335640Shselasky 4825335640Shselasky /* allocate a ring for each frame header pointer*/ 4826335640Shselasky handle->cc = req.tp_frame_nr; 4827335640Shselasky handle->buffer = malloc(handle->cc * sizeof(union thdr *)); 4828335640Shselasky if (!handle->buffer) { 4829335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 4830335640Shselasky errno, "can't allocate ring of frame headers"); 4831335640Shselasky 4832335640Shselasky destroy_ring(handle); 4833335640Shselasky *status = PCAP_ERROR; 4834335640Shselasky return -1; 4835335640Shselasky } 4836335640Shselasky 4837335640Shselasky /* fill the header ring with proper frame ptr*/ 4838335640Shselasky handle->offset = 0; 4839335640Shselasky for (i=0; i<req.tp_block_nr; ++i) { 4840335640Shselasky void *base = &handlep->mmapbuf[i*req.tp_block_size]; 4841335640Shselasky for (j=0; j<frames_per_block; ++j, ++handle->offset) { 4842335640Shselasky RING_GET_CURRENT_FRAME(handle) = base; 4843335640Shselasky base += req.tp_frame_size; 4844335640Shselasky } 4845335640Shselasky } 4846335640Shselasky 4847335640Shselasky handle->bufsize = req.tp_frame_size; 4848335640Shselasky handle->offset = 0; 4849335640Shselasky return 1; 4850335640Shselasky} 4851335640Shselasky 4852335640Shselasky/* free all ring related resources*/ 4853335640Shselaskystatic void 4854335640Shselaskydestroy_ring(pcap_t *handle) 4855335640Shselasky{ 4856335640Shselasky struct pcap_linux *handlep = handle->priv; 4857335640Shselasky 4858335640Shselasky /* tell the kernel to destroy the ring*/ 4859335640Shselasky struct tpacket_req req; 4860335640Shselasky memset(&req, 0, sizeof(req)); 4861335640Shselasky /* do not test for setsockopt failure, as we can't recover from any error */ 4862335640Shselasky (void)setsockopt(handle->fd, SOL_PACKET, PACKET_RX_RING, 4863335640Shselasky (void *) &req, sizeof(req)); 4864335640Shselasky 4865335640Shselasky /* if ring is mapped, unmap it*/ 4866335640Shselasky if (handlep->mmapbuf) { 4867335640Shselasky /* do not test for mmap failure, as we can't recover from any error */ 4868335640Shselasky (void)munmap(handlep->mmapbuf, handlep->mmapbuflen); 4869335640Shselasky handlep->mmapbuf = NULL; 4870335640Shselasky } 4871335640Shselasky} 4872335640Shselasky 4873335640Shselasky/* 4874335640Shselasky * Special one-shot callback, used for pcap_next() and pcap_next_ex(), 4875335640Shselasky * for Linux mmapped capture. 4876335640Shselasky * 4877335640Shselasky * The problem is that pcap_next() and pcap_next_ex() expect the packet 4878335640Shselasky * data handed to the callback to be valid after the callback returns, 4879335640Shselasky * but pcap_read_linux_mmap() has to release that packet as soon as 4880335640Shselasky * the callback returns (otherwise, the kernel thinks there's still 4881335640Shselasky * at least one unprocessed packet available in the ring, so a select() 4882335640Shselasky * will immediately return indicating that there's data to process), so, 4883335640Shselasky * in the callback, we have to make a copy of the packet. 4884335640Shselasky * 4885335640Shselasky * Yes, this means that, if the capture is using the ring buffer, using 4886335640Shselasky * pcap_next() or pcap_next_ex() requires more copies than using 4887335640Shselasky * pcap_loop() or pcap_dispatch(). If that bothers you, don't use 4888335640Shselasky * pcap_next() or pcap_next_ex(). 4889335640Shselasky */ 4890335640Shselaskystatic void 4891335640Shselaskypcap_oneshot_mmap(u_char *user, const struct pcap_pkthdr *h, 4892335640Shselasky const u_char *bytes) 4893335640Shselasky{ 4894335640Shselasky struct oneshot_userdata *sp = (struct oneshot_userdata *)user; 4895335640Shselasky pcap_t *handle = sp->pd; 4896335640Shselasky struct pcap_linux *handlep = handle->priv; 4897335640Shselasky 4898335640Shselasky *sp->hdr = *h; 4899335640Shselasky memcpy(handlep->oneshot_buffer, bytes, h->caplen); 4900335640Shselasky *sp->pkt = handlep->oneshot_buffer; 4901335640Shselasky} 4902335640Shselasky 4903335640Shselaskystatic void 4904335640Shselaskypcap_cleanup_linux_mmap( pcap_t *handle ) 4905335640Shselasky{ 4906335640Shselasky struct pcap_linux *handlep = handle->priv; 4907335640Shselasky 4908335640Shselasky destroy_ring(handle); 4909335640Shselasky if (handlep->oneshot_buffer != NULL) { 4910335640Shselasky free(handlep->oneshot_buffer); 4911335640Shselasky handlep->oneshot_buffer = NULL; 4912335640Shselasky } 4913335640Shselasky pcap_cleanup_linux(handle); 4914335640Shselasky} 4915335640Shselasky 4916335640Shselasky 4917335640Shselaskystatic int 4918335640Shselaskypcap_getnonblock_mmap(pcap_t *handle) 4919335640Shselasky{ 4920335640Shselasky struct pcap_linux *handlep = handle->priv; 4921335640Shselasky 4922335640Shselasky /* use negative value of timeout to indicate non blocking ops */ 4923335640Shselasky return (handlep->timeout<0); 4924335640Shselasky} 4925335640Shselasky 4926335640Shselaskystatic int 4927335640Shselaskypcap_setnonblock_mmap(pcap_t *handle, int nonblock) 4928335640Shselasky{ 4929335640Shselasky struct pcap_linux *handlep = handle->priv; 4930335640Shselasky 4931335640Shselasky /* 4932335640Shselasky * Set the file descriptor to non-blocking mode, as we use 4933335640Shselasky * it for sending packets. 4934335640Shselasky */ 4935335640Shselasky if (pcap_setnonblock_fd(handle, nonblock) == -1) 4936335640Shselasky return -1; 4937335640Shselasky 4938335640Shselasky /* 4939335640Shselasky * Map each value to their corresponding negation to 4940335640Shselasky * preserve the timeout value provided with pcap_set_timeout. 4941335640Shselasky */ 4942335640Shselasky if (nonblock) { 4943335640Shselasky if (handlep->timeout >= 0) { 4944335640Shselasky /* 4945335640Shselasky * Indicate that we're switching to 4946335640Shselasky * non-blocking mode. 4947335640Shselasky */ 4948335640Shselasky handlep->timeout = ~handlep->timeout; 4949335640Shselasky } 4950335640Shselasky } else { 4951335640Shselasky if (handlep->timeout < 0) { 4952335640Shselasky handlep->timeout = ~handlep->timeout; 4953335640Shselasky } 4954335640Shselasky } 4955335640Shselasky /* Update the timeout to use in poll(). */ 4956335640Shselasky set_poll_timeout(handlep); 4957335640Shselasky return 0; 4958335640Shselasky} 4959335640Shselasky 4960335640Shselasky/* 4961335640Shselasky * Get the status field of the ring buffer frame at a specified offset. 4962335640Shselasky */ 4963335640Shselaskystatic inline int 4964335640Shselaskypcap_get_ring_frame_status(pcap_t *handle, int offset) 4965335640Shselasky{ 4966335640Shselasky struct pcap_linux *handlep = handle->priv; 4967335640Shselasky union thdr h; 4968335640Shselasky 4969335640Shselasky h.raw = RING_GET_FRAME_AT(handle, offset); 4970335640Shselasky switch (handlep->tp_version) { 4971335640Shselasky case TPACKET_V1: 4972335640Shselasky return (h.h1->tp_status); 4973335640Shselasky break; 4974335640Shselasky case TPACKET_V1_64: 4975335640Shselasky return (h.h1_64->tp_status); 4976335640Shselasky break; 4977335640Shselasky#ifdef HAVE_TPACKET2 4978335640Shselasky case TPACKET_V2: 4979335640Shselasky return (h.h2->tp_status); 4980335640Shselasky break; 4981335640Shselasky#endif 4982335640Shselasky#ifdef HAVE_TPACKET3 4983335640Shselasky case TPACKET_V3: 4984335640Shselasky return (h.h3->hdr.bh1.block_status); 4985335640Shselasky break; 4986335640Shselasky#endif 4987335640Shselasky } 4988335640Shselasky /* This should not happen. */ 4989335640Shselasky return 0; 4990335640Shselasky} 4991335640Shselasky 4992335640Shselasky#ifndef POLLRDHUP 4993335640Shselasky#define POLLRDHUP 0 4994335640Shselasky#endif 4995335640Shselasky 4996335640Shselasky/* 4997335640Shselasky * Block waiting for frames to be available. 4998335640Shselasky */ 4999335640Shselaskystatic int pcap_wait_for_frames_mmap(pcap_t *handle) 5000335640Shselasky{ 5001335640Shselasky struct pcap_linux *handlep = handle->priv; 5002335640Shselasky char c; 5003335640Shselasky struct pollfd pollinfo; 5004335640Shselasky int ret; 5005335640Shselasky 5006335640Shselasky pollinfo.fd = handle->fd; 5007335640Shselasky pollinfo.events = POLLIN; 5008335640Shselasky 5009335640Shselasky do { 5010335640Shselasky /* 5011335640Shselasky * Yes, we do this even in non-blocking mode, as it's 5012335640Shselasky * the only way to get error indications from a 5013335640Shselasky * tpacket socket. 5014335640Shselasky * 5015335640Shselasky * The timeout is 0 in non-blocking mode, so poll() 5016335640Shselasky * returns immediately. 5017335640Shselasky */ 5018335640Shselasky ret = poll(&pollinfo, 1, handlep->poll_timeout); 5019335640Shselasky if (ret < 0 && errno != EINTR) { 5020335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 5021335640Shselasky PCAP_ERRBUF_SIZE, errno, 5022335640Shselasky "can't poll on packet socket"); 5023335640Shselasky return PCAP_ERROR; 5024335640Shselasky } else if (ret > 0 && 5025335640Shselasky (pollinfo.revents & (POLLHUP|POLLRDHUP|POLLERR|POLLNVAL))) { 5026335640Shselasky /* 5027335640Shselasky * There's some indication other than 5028335640Shselasky * "you can read on this descriptor" on 5029335640Shselasky * the descriptor. 5030335640Shselasky */ 5031335640Shselasky if (pollinfo.revents & (POLLHUP | POLLRDHUP)) { 5032335640Shselasky pcap_snprintf(handle->errbuf, 5033335640Shselasky PCAP_ERRBUF_SIZE, 5034335640Shselasky "Hangup on packet socket"); 5035335640Shselasky return PCAP_ERROR; 5036335640Shselasky } 5037335640Shselasky if (pollinfo.revents & POLLERR) { 5038335640Shselasky /* 5039335640Shselasky * A recv() will give us the actual error code. 5040335640Shselasky * 5041335640Shselasky * XXX - make the socket non-blocking? 5042335640Shselasky */ 5043335640Shselasky if (recv(handle->fd, &c, sizeof c, 5044335640Shselasky MSG_PEEK) != -1) 5045335640Shselasky continue; /* what, no error? */ 5046335640Shselasky if (errno == ENETDOWN) { 5047335640Shselasky /* 5048335640Shselasky * The device on which we're 5049335640Shselasky * capturing went away. 5050335640Shselasky * 5051335640Shselasky * XXX - we should really return 5052335640Shselasky * PCAP_ERROR_IFACE_NOT_UP, but 5053335640Shselasky * pcap_dispatch() etc. aren't 5054335640Shselasky * defined to return that. 5055335640Shselasky */ 5056335640Shselasky pcap_snprintf(handle->errbuf, 5057335640Shselasky PCAP_ERRBUF_SIZE, 5058335640Shselasky "The interface went down"); 5059335640Shselasky } else { 5060335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 5061335640Shselasky PCAP_ERRBUF_SIZE, errno, 5062335640Shselasky "Error condition on packet socket"); 5063335640Shselasky } 5064335640Shselasky return PCAP_ERROR; 5065335640Shselasky } 5066335640Shselasky if (pollinfo.revents & POLLNVAL) { 5067335640Shselasky pcap_snprintf(handle->errbuf, 5068335640Shselasky PCAP_ERRBUF_SIZE, 5069335640Shselasky "Invalid polling request on packet socket"); 5070335640Shselasky return PCAP_ERROR; 5071335640Shselasky } 5072335640Shselasky } 5073335640Shselasky /* check for break loop condition on interrupted syscall*/ 5074335640Shselasky if (handle->break_loop) { 5075335640Shselasky handle->break_loop = 0; 5076335640Shselasky return PCAP_ERROR_BREAK; 5077335640Shselasky } 5078335640Shselasky } while (ret < 0); 5079335640Shselasky return 0; 5080335640Shselasky} 5081335640Shselasky 5082335640Shselasky/* handle a single memory mapped packet */ 5083335640Shselaskystatic int pcap_handle_packet_mmap( 5084335640Shselasky pcap_t *handle, 5085335640Shselasky pcap_handler callback, 5086335640Shselasky u_char *user, 5087335640Shselasky unsigned char *frame, 5088335640Shselasky unsigned int tp_len, 5089335640Shselasky unsigned int tp_mac, 5090335640Shselasky unsigned int tp_snaplen, 5091335640Shselasky unsigned int tp_sec, 5092335640Shselasky unsigned int tp_usec, 5093335640Shselasky int tp_vlan_tci_valid, 5094335640Shselasky __u16 tp_vlan_tci, 5095335640Shselasky __u16 tp_vlan_tpid) 5096335640Shselasky{ 5097335640Shselasky struct pcap_linux *handlep = handle->priv; 5098335640Shselasky unsigned char *bp; 5099335640Shselasky struct sockaddr_ll *sll; 5100335640Shselasky struct pcap_pkthdr pcaphdr; 5101335640Shselasky unsigned int snaplen = tp_snaplen; 5102356341Scy struct utsname utsname; 5103335640Shselasky 5104335640Shselasky /* perform sanity check on internal offset. */ 5105335640Shselasky if (tp_mac + tp_snaplen > handle->bufsize) { 5106356341Scy /* 5107356341Scy * Report some system information as a debugging aid. 5108356341Scy */ 5109356341Scy if (uname(&utsname) != -1) { 5110356341Scy pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 5111356341Scy "corrupted frame on kernel ring mac " 5112356341Scy "offset %u + caplen %u > frame len %d " 5113356341Scy "(kernel %.32s version %s, machine %.16s)", 5114356341Scy tp_mac, tp_snaplen, handle->bufsize, 5115356341Scy utsname.release, utsname.version, 5116356341Scy utsname.machine); 5117356341Scy } else { 5118356341Scy pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 5119356341Scy "corrupted frame on kernel ring mac " 5120356341Scy "offset %u + caplen %u > frame len %d", 5121356341Scy tp_mac, tp_snaplen, handle->bufsize); 5122356341Scy } 5123335640Shselasky return -1; 5124335640Shselasky } 5125335640Shselasky 5126335640Shselasky /* run filter on received packet 5127335640Shselasky * If the kernel filtering is enabled we need to run the 5128335640Shselasky * filter until all the frames present into the ring 5129335640Shselasky * at filter creation time are processed. 5130335640Shselasky * In this case, blocks_to_filter_in_userland is used 5131335640Shselasky * as a counter for the packet we need to filter. 5132335640Shselasky * Note: alternatively it could be possible to stop applying 5133335640Shselasky * the filter when the ring became empty, but it can possibly 5134335640Shselasky * happen a lot later... */ 5135335640Shselasky bp = frame + tp_mac; 5136335640Shselasky 5137335640Shselasky /* if required build in place the sll header*/ 5138335640Shselasky sll = (void *)frame + TPACKET_ALIGN(handlep->tp_hdrlen); 5139335640Shselasky if (handlep->cooked) { 5140356341Scy if (handle->linktype == DLT_LINUX_SLL2) { 5141356341Scy struct sll2_header *hdrp; 5142335640Shselasky 5143356341Scy /* 5144356341Scy * The kernel should have left us with enough 5145356341Scy * space for an sll header; back up the packet 5146356341Scy * data pointer into that space, as that'll be 5147356341Scy * the beginning of the packet we pass to the 5148356341Scy * callback. 5149356341Scy */ 5150356341Scy bp -= SLL2_HDR_LEN; 5151335640Shselasky 5152356341Scy /* 5153356341Scy * Let's make sure that's past the end of 5154356341Scy * the tpacket header, i.e. >= 5155356341Scy * ((u_char *)thdr + TPACKET_HDRLEN), so we 5156356341Scy * don't step on the header when we construct 5157356341Scy * the sll header. 5158356341Scy */ 5159356341Scy if (bp < (u_char *)frame + 5160356341Scy TPACKET_ALIGN(handlep->tp_hdrlen) + 5161356341Scy sizeof(struct sockaddr_ll)) { 5162356341Scy pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 5163356341Scy "cooked-mode frame doesn't have room for sll header"); 5164356341Scy return -1; 5165356341Scy } 5166335640Shselasky 5167356341Scy /* 5168356341Scy * OK, that worked; construct the sll header. 5169356341Scy */ 5170356341Scy hdrp = (struct sll2_header *)bp; 5171356341Scy hdrp->sll2_protocol = sll->sll_protocol; 5172356341Scy hdrp->sll2_reserved_mbz = 0; 5173356341Scy hdrp->sll2_if_index = htonl(sll->sll_ifindex); 5174356341Scy hdrp->sll2_hatype = htons(sll->sll_hatype); 5175356341Scy hdrp->sll2_pkttype = sll->sll_pkttype; 5176356341Scy hdrp->sll2_halen = sll->sll_halen; 5177356341Scy memcpy(hdrp->sll2_addr, sll->sll_addr, SLL_ADDRLEN); 5178335640Shselasky 5179356341Scy snaplen += sizeof(struct sll2_header); 5180356341Scy } else { 5181356341Scy struct sll_header *hdrp; 5182356341Scy 5183356341Scy /* 5184356341Scy * The kernel should have left us with enough 5185356341Scy * space for an sll header; back up the packet 5186356341Scy * data pointer into that space, as that'll be 5187356341Scy * the beginning of the packet we pass to the 5188356341Scy * callback. 5189356341Scy */ 5190356341Scy bp -= SLL_HDR_LEN; 5191356341Scy 5192356341Scy /* 5193356341Scy * Let's make sure that's past the end of 5194356341Scy * the tpacket header, i.e. >= 5195356341Scy * ((u_char *)thdr + TPACKET_HDRLEN), so we 5196356341Scy * don't step on the header when we construct 5197356341Scy * the sll header. 5198356341Scy */ 5199356341Scy if (bp < (u_char *)frame + 5200356341Scy TPACKET_ALIGN(handlep->tp_hdrlen) + 5201356341Scy sizeof(struct sockaddr_ll)) { 5202356341Scy pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 5203356341Scy "cooked-mode frame doesn't have room for sll header"); 5204356341Scy return -1; 5205356341Scy } 5206356341Scy 5207356341Scy /* 5208356341Scy * OK, that worked; construct the sll header. 5209356341Scy */ 5210356341Scy hdrp = (struct sll_header *)bp; 5211356341Scy hdrp->sll_pkttype = htons(sll->sll_pkttype); 5212356341Scy hdrp->sll_hatype = htons(sll->sll_hatype); 5213356341Scy hdrp->sll_halen = htons(sll->sll_halen); 5214356341Scy memcpy(hdrp->sll_addr, sll->sll_addr, SLL_ADDRLEN); 5215356341Scy hdrp->sll_protocol = sll->sll_protocol; 5216356341Scy 5217356341Scy snaplen += sizeof(struct sll_header); 5218356341Scy } 5219335640Shselasky } 5220335640Shselasky 5221335640Shselasky if (handlep->filter_in_userland && handle->fcode.bf_insns) { 5222335640Shselasky struct bpf_aux_data aux_data; 5223335640Shselasky 5224335640Shselasky aux_data.vlan_tag_present = tp_vlan_tci_valid; 5225335640Shselasky aux_data.vlan_tag = tp_vlan_tci & 0x0fff; 5226335640Shselasky 5227335640Shselasky if (bpf_filter_with_aux_data(handle->fcode.bf_insns, 5228335640Shselasky bp, 5229335640Shselasky tp_len, 5230335640Shselasky snaplen, 5231335640Shselasky &aux_data) == 0) 5232335640Shselasky return 0; 5233335640Shselasky } 5234335640Shselasky 5235335640Shselasky if (!linux_check_direction(handle, sll)) 5236335640Shselasky return 0; 5237335640Shselasky 5238335640Shselasky /* get required packet info from ring header */ 5239335640Shselasky pcaphdr.ts.tv_sec = tp_sec; 5240335640Shselasky pcaphdr.ts.tv_usec = tp_usec; 5241335640Shselasky pcaphdr.caplen = tp_snaplen; 5242335640Shselasky pcaphdr.len = tp_len; 5243335640Shselasky 5244335640Shselasky /* if required build in place the sll header*/ 5245335640Shselasky if (handlep->cooked) { 5246335640Shselasky /* update packet len */ 5247356341Scy if (handle->linktype == DLT_LINUX_SLL2) { 5248356341Scy pcaphdr.caplen += SLL2_HDR_LEN; 5249356341Scy pcaphdr.len += SLL2_HDR_LEN; 5250356341Scy } else { 5251356341Scy pcaphdr.caplen += SLL_HDR_LEN; 5252356341Scy pcaphdr.len += SLL_HDR_LEN; 5253356341Scy } 5254335640Shselasky } 5255335640Shselasky 5256335640Shselasky#if defined(HAVE_TPACKET2) || defined(HAVE_TPACKET3) 5257335640Shselasky if (tp_vlan_tci_valid && 5258335640Shselasky handlep->vlan_offset != -1 && 5259335640Shselasky tp_snaplen >= (unsigned int) handlep->vlan_offset) 5260335640Shselasky { 5261335640Shselasky struct vlan_tag *tag; 5262335640Shselasky 5263335640Shselasky /* 5264335640Shselasky * Move everything in the header, except the type field, 5265335640Shselasky * down VLAN_TAG_LEN bytes, to allow us to insert the 5266335640Shselasky * VLAN tag between that stuff and the type field. 5267335640Shselasky */ 5268335640Shselasky bp -= VLAN_TAG_LEN; 5269335640Shselasky memmove(bp, bp + VLAN_TAG_LEN, handlep->vlan_offset); 5270335640Shselasky 5271335640Shselasky /* 5272335640Shselasky * Now insert the tag. 5273335640Shselasky */ 5274335640Shselasky tag = (struct vlan_tag *)(bp + handlep->vlan_offset); 5275335640Shselasky tag->vlan_tpid = htons(tp_vlan_tpid); 5276335640Shselasky tag->vlan_tci = htons(tp_vlan_tci); 5277335640Shselasky 5278335640Shselasky /* 5279335640Shselasky * Add the tag to the packet lengths. 5280335640Shselasky */ 5281335640Shselasky pcaphdr.caplen += VLAN_TAG_LEN; 5282335640Shselasky pcaphdr.len += VLAN_TAG_LEN; 5283335640Shselasky } 5284335640Shselasky#endif 5285335640Shselasky 5286335640Shselasky /* 5287335640Shselasky * The only way to tell the kernel to cut off the 5288335640Shselasky * packet at a snapshot length is with a filter program; 5289335640Shselasky * if there's no filter program, the kernel won't cut 5290335640Shselasky * the packet off. 5291335640Shselasky * 5292335640Shselasky * Trim the snapshot length to be no longer than the 5293335640Shselasky * specified snapshot length. 5294335640Shselasky */ 5295335640Shselasky if (pcaphdr.caplen > (bpf_u_int32)handle->snapshot) 5296335640Shselasky pcaphdr.caplen = handle->snapshot; 5297335640Shselasky 5298335640Shselasky /* pass the packet to the user */ 5299335640Shselasky callback(user, &pcaphdr, bp); 5300335640Shselasky 5301335640Shselasky return 1; 5302335640Shselasky} 5303335640Shselasky 5304335640Shselaskystatic int 5305335640Shselaskypcap_read_linux_mmap_v1(pcap_t *handle, int max_packets, pcap_handler callback, 5306335640Shselasky u_char *user) 5307335640Shselasky{ 5308335640Shselasky struct pcap_linux *handlep = handle->priv; 5309335640Shselasky union thdr h; 5310335640Shselasky int pkts = 0; 5311335640Shselasky int ret; 5312335640Shselasky 5313335640Shselasky /* wait for frames availability.*/ 5314335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5315335640Shselasky if (h.h1->tp_status == TP_STATUS_KERNEL) { 5316335640Shselasky /* 5317335640Shselasky * The current frame is owned by the kernel; wait for 5318335640Shselasky * a frame to be handed to us. 5319335640Shselasky */ 5320335640Shselasky ret = pcap_wait_for_frames_mmap(handle); 5321335640Shselasky if (ret) { 5322335640Shselasky return ret; 5323335640Shselasky } 5324335640Shselasky } 5325335640Shselasky 5326335640Shselasky /* non-positive values of max_packets are used to require all 5327335640Shselasky * packets currently available in the ring */ 5328335640Shselasky while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) { 5329335640Shselasky /* 5330335640Shselasky * Get the current ring buffer frame, and break if 5331335640Shselasky * it's still owned by the kernel. 5332335640Shselasky */ 5333335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5334335640Shselasky if (h.h1->tp_status == TP_STATUS_KERNEL) 5335335640Shselasky break; 5336335640Shselasky 5337335640Shselasky ret = pcap_handle_packet_mmap( 5338335640Shselasky handle, 5339335640Shselasky callback, 5340335640Shselasky user, 5341335640Shselasky h.raw, 5342335640Shselasky h.h1->tp_len, 5343335640Shselasky h.h1->tp_mac, 5344335640Shselasky h.h1->tp_snaplen, 5345335640Shselasky h.h1->tp_sec, 5346335640Shselasky h.h1->tp_usec, 5347335640Shselasky 0, 5348335640Shselasky 0, 5349335640Shselasky 0); 5350335640Shselasky if (ret == 1) { 5351335640Shselasky pkts++; 5352335640Shselasky handlep->packets_read++; 5353335640Shselasky } else if (ret < 0) { 5354335640Shselasky return ret; 5355335640Shselasky } 5356335640Shselasky 5357335640Shselasky /* 5358335640Shselasky * Hand this block back to the kernel, and, if we're 5359335640Shselasky * counting blocks that need to be filtered in userland 5360335640Shselasky * after having been filtered by the kernel, count 5361335640Shselasky * the one we've just processed. 5362335640Shselasky */ 5363335640Shselasky h.h1->tp_status = TP_STATUS_KERNEL; 5364335640Shselasky if (handlep->blocks_to_filter_in_userland > 0) { 5365335640Shselasky handlep->blocks_to_filter_in_userland--; 5366335640Shselasky if (handlep->blocks_to_filter_in_userland == 0) { 5367335640Shselasky /* 5368335640Shselasky * No more blocks need to be filtered 5369335640Shselasky * in userland. 5370335640Shselasky */ 5371335640Shselasky handlep->filter_in_userland = 0; 5372335640Shselasky } 5373335640Shselasky } 5374335640Shselasky 5375335640Shselasky /* next block */ 5376335640Shselasky if (++handle->offset >= handle->cc) 5377335640Shselasky handle->offset = 0; 5378335640Shselasky 5379335640Shselasky /* check for break loop condition*/ 5380335640Shselasky if (handle->break_loop) { 5381335640Shselasky handle->break_loop = 0; 5382335640Shselasky return PCAP_ERROR_BREAK; 5383335640Shselasky } 5384335640Shselasky } 5385335640Shselasky return pkts; 5386335640Shselasky} 5387335640Shselasky 5388335640Shselaskystatic int 5389335640Shselaskypcap_read_linux_mmap_v1_64(pcap_t *handle, int max_packets, pcap_handler callback, 5390335640Shselasky u_char *user) 5391335640Shselasky{ 5392335640Shselasky struct pcap_linux *handlep = handle->priv; 5393335640Shselasky union thdr h; 5394335640Shselasky int pkts = 0; 5395335640Shselasky int ret; 5396335640Shselasky 5397335640Shselasky /* wait for frames availability.*/ 5398335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5399335640Shselasky if (h.h1_64->tp_status == TP_STATUS_KERNEL) { 5400335640Shselasky /* 5401335640Shselasky * The current frame is owned by the kernel; wait for 5402335640Shselasky * a frame to be handed to us. 5403335640Shselasky */ 5404335640Shselasky ret = pcap_wait_for_frames_mmap(handle); 5405335640Shselasky if (ret) { 5406335640Shselasky return ret; 5407335640Shselasky } 5408335640Shselasky } 5409335640Shselasky 5410335640Shselasky /* non-positive values of max_packets are used to require all 5411335640Shselasky * packets currently available in the ring */ 5412335640Shselasky while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) { 5413335640Shselasky /* 5414335640Shselasky * Get the current ring buffer frame, and break if 5415335640Shselasky * it's still owned by the kernel. 5416335640Shselasky */ 5417335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5418335640Shselasky if (h.h1_64->tp_status == TP_STATUS_KERNEL) 5419335640Shselasky break; 5420335640Shselasky 5421335640Shselasky ret = pcap_handle_packet_mmap( 5422335640Shselasky handle, 5423335640Shselasky callback, 5424335640Shselasky user, 5425335640Shselasky h.raw, 5426335640Shselasky h.h1_64->tp_len, 5427335640Shselasky h.h1_64->tp_mac, 5428335640Shselasky h.h1_64->tp_snaplen, 5429335640Shselasky h.h1_64->tp_sec, 5430335640Shselasky h.h1_64->tp_usec, 5431335640Shselasky 0, 5432335640Shselasky 0, 5433335640Shselasky 0); 5434335640Shselasky if (ret == 1) { 5435335640Shselasky pkts++; 5436335640Shselasky handlep->packets_read++; 5437335640Shselasky } else if (ret < 0) { 5438335640Shselasky return ret; 5439335640Shselasky } 5440335640Shselasky 5441335640Shselasky /* 5442335640Shselasky * Hand this block back to the kernel, and, if we're 5443335640Shselasky * counting blocks that need to be filtered in userland 5444335640Shselasky * after having been filtered by the kernel, count 5445335640Shselasky * the one we've just processed. 5446335640Shselasky */ 5447335640Shselasky h.h1_64->tp_status = TP_STATUS_KERNEL; 5448335640Shselasky if (handlep->blocks_to_filter_in_userland > 0) { 5449335640Shselasky handlep->blocks_to_filter_in_userland--; 5450335640Shselasky if (handlep->blocks_to_filter_in_userland == 0) { 5451335640Shselasky /* 5452335640Shselasky * No more blocks need to be filtered 5453335640Shselasky * in userland. 5454335640Shselasky */ 5455335640Shselasky handlep->filter_in_userland = 0; 5456335640Shselasky } 5457335640Shselasky } 5458335640Shselasky 5459335640Shselasky /* next block */ 5460335640Shselasky if (++handle->offset >= handle->cc) 5461335640Shselasky handle->offset = 0; 5462335640Shselasky 5463335640Shselasky /* check for break loop condition*/ 5464335640Shselasky if (handle->break_loop) { 5465335640Shselasky handle->break_loop = 0; 5466335640Shselasky return PCAP_ERROR_BREAK; 5467335640Shselasky } 5468335640Shselasky } 5469335640Shselasky return pkts; 5470335640Shselasky} 5471335640Shselasky 5472335640Shselasky#ifdef HAVE_TPACKET2 5473335640Shselaskystatic int 5474335640Shselaskypcap_read_linux_mmap_v2(pcap_t *handle, int max_packets, pcap_handler callback, 5475335640Shselasky u_char *user) 5476335640Shselasky{ 5477335640Shselasky struct pcap_linux *handlep = handle->priv; 5478335640Shselasky union thdr h; 5479335640Shselasky int pkts = 0; 5480335640Shselasky int ret; 5481335640Shselasky 5482335640Shselasky /* wait for frames availability.*/ 5483335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5484335640Shselasky if (h.h2->tp_status == TP_STATUS_KERNEL) { 5485335640Shselasky /* 5486335640Shselasky * The current frame is owned by the kernel; wait for 5487335640Shselasky * a frame to be handed to us. 5488335640Shselasky */ 5489335640Shselasky ret = pcap_wait_for_frames_mmap(handle); 5490335640Shselasky if (ret) { 5491335640Shselasky return ret; 5492335640Shselasky } 5493335640Shselasky } 5494335640Shselasky 5495335640Shselasky /* non-positive values of max_packets are used to require all 5496335640Shselasky * packets currently available in the ring */ 5497335640Shselasky while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) { 5498335640Shselasky /* 5499335640Shselasky * Get the current ring buffer frame, and break if 5500335640Shselasky * it's still owned by the kernel. 5501335640Shselasky */ 5502335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5503335640Shselasky if (h.h2->tp_status == TP_STATUS_KERNEL) 5504335640Shselasky break; 5505335640Shselasky 5506335640Shselasky ret = pcap_handle_packet_mmap( 5507335640Shselasky handle, 5508335640Shselasky callback, 5509335640Shselasky user, 5510335640Shselasky h.raw, 5511335640Shselasky h.h2->tp_len, 5512335640Shselasky h.h2->tp_mac, 5513335640Shselasky h.h2->tp_snaplen, 5514335640Shselasky h.h2->tp_sec, 5515335640Shselasky handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? h.h2->tp_nsec : h.h2->tp_nsec / 1000, 5516335640Shselasky VLAN_VALID(h.h2, h.h2), 5517335640Shselasky h.h2->tp_vlan_tci, 5518335640Shselasky VLAN_TPID(h.h2, h.h2)); 5519335640Shselasky if (ret == 1) { 5520335640Shselasky pkts++; 5521335640Shselasky handlep->packets_read++; 5522335640Shselasky } else if (ret < 0) { 5523335640Shselasky return ret; 5524335640Shselasky } 5525335640Shselasky 5526335640Shselasky /* 5527335640Shselasky * Hand this block back to the kernel, and, if we're 5528335640Shselasky * counting blocks that need to be filtered in userland 5529335640Shselasky * after having been filtered by the kernel, count 5530335640Shselasky * the one we've just processed. 5531335640Shselasky */ 5532335640Shselasky h.h2->tp_status = TP_STATUS_KERNEL; 5533335640Shselasky if (handlep->blocks_to_filter_in_userland > 0) { 5534335640Shselasky handlep->blocks_to_filter_in_userland--; 5535335640Shselasky if (handlep->blocks_to_filter_in_userland == 0) { 5536335640Shselasky /* 5537335640Shselasky * No more blocks need to be filtered 5538335640Shselasky * in userland. 5539335640Shselasky */ 5540335640Shselasky handlep->filter_in_userland = 0; 5541335640Shselasky } 5542335640Shselasky } 5543335640Shselasky 5544335640Shselasky /* next block */ 5545335640Shselasky if (++handle->offset >= handle->cc) 5546335640Shselasky handle->offset = 0; 5547335640Shselasky 5548335640Shselasky /* check for break loop condition*/ 5549335640Shselasky if (handle->break_loop) { 5550335640Shselasky handle->break_loop = 0; 5551335640Shselasky return PCAP_ERROR_BREAK; 5552335640Shselasky } 5553335640Shselasky } 5554335640Shselasky return pkts; 5555335640Shselasky} 5556335640Shselasky#endif /* HAVE_TPACKET2 */ 5557335640Shselasky 5558335640Shselasky#ifdef HAVE_TPACKET3 5559335640Shselaskystatic int 5560335640Shselaskypcap_read_linux_mmap_v3(pcap_t *handle, int max_packets, pcap_handler callback, 5561335640Shselasky u_char *user) 5562335640Shselasky{ 5563335640Shselasky struct pcap_linux *handlep = handle->priv; 5564335640Shselasky union thdr h; 5565335640Shselasky int pkts = 0; 5566335640Shselasky int ret; 5567335640Shselasky 5568335640Shselaskyagain: 5569335640Shselasky if (handlep->current_packet == NULL) { 5570335640Shselasky /* wait for frames availability.*/ 5571335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5572335640Shselasky if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) { 5573335640Shselasky /* 5574335640Shselasky * The current frame is owned by the kernel; wait 5575335640Shselasky * for a frame to be handed to us. 5576335640Shselasky */ 5577335640Shselasky ret = pcap_wait_for_frames_mmap(handle); 5578335640Shselasky if (ret) { 5579335640Shselasky return ret; 5580335640Shselasky } 5581335640Shselasky } 5582335640Shselasky } 5583335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5584335640Shselasky if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) { 5585335640Shselasky if (pkts == 0 && handlep->timeout == 0) { 5586335640Shselasky /* Block until we see a packet. */ 5587335640Shselasky goto again; 5588335640Shselasky } 5589335640Shselasky return pkts; 5590335640Shselasky } 5591335640Shselasky 5592335640Shselasky /* non-positive values of max_packets are used to require all 5593335640Shselasky * packets currently available in the ring */ 5594335640Shselasky while ((pkts < max_packets) || PACKET_COUNT_IS_UNLIMITED(max_packets)) { 5595335640Shselasky int packets_to_read; 5596335640Shselasky 5597335640Shselasky if (handlep->current_packet == NULL) { 5598335640Shselasky h.raw = RING_GET_CURRENT_FRAME(handle); 5599335640Shselasky if (h.h3->hdr.bh1.block_status == TP_STATUS_KERNEL) 5600335640Shselasky break; 5601335640Shselasky 5602335640Shselasky handlep->current_packet = h.raw + h.h3->hdr.bh1.offset_to_first_pkt; 5603335640Shselasky handlep->packets_left = h.h3->hdr.bh1.num_pkts; 5604335640Shselasky } 5605335640Shselasky packets_to_read = handlep->packets_left; 5606335640Shselasky 5607335640Shselasky if (!PACKET_COUNT_IS_UNLIMITED(max_packets) && 5608335640Shselasky packets_to_read > (max_packets - pkts)) { 5609335640Shselasky /* 5610335640Shselasky * We've been given a maximum number of packets 5611335640Shselasky * to process, and there are more packets in 5612335640Shselasky * this buffer than that. Only process enough 5613335640Shselasky * of them to get us up to that maximum. 5614335640Shselasky */ 5615335640Shselasky packets_to_read = max_packets - pkts; 5616335640Shselasky } 5617335640Shselasky 5618335640Shselasky while (packets_to_read-- && !handle->break_loop) { 5619335640Shselasky struct tpacket3_hdr* tp3_hdr = (struct tpacket3_hdr*) handlep->current_packet; 5620335640Shselasky ret = pcap_handle_packet_mmap( 5621335640Shselasky handle, 5622335640Shselasky callback, 5623335640Shselasky user, 5624335640Shselasky handlep->current_packet, 5625335640Shselasky tp3_hdr->tp_len, 5626335640Shselasky tp3_hdr->tp_mac, 5627335640Shselasky tp3_hdr->tp_snaplen, 5628335640Shselasky tp3_hdr->tp_sec, 5629335640Shselasky handle->opt.tstamp_precision == PCAP_TSTAMP_PRECISION_NANO ? tp3_hdr->tp_nsec : tp3_hdr->tp_nsec / 1000, 5630335640Shselasky VLAN_VALID(tp3_hdr, &tp3_hdr->hv1), 5631335640Shselasky tp3_hdr->hv1.tp_vlan_tci, 5632335640Shselasky VLAN_TPID(tp3_hdr, &tp3_hdr->hv1)); 5633335640Shselasky if (ret == 1) { 5634335640Shselasky pkts++; 5635335640Shselasky handlep->packets_read++; 5636335640Shselasky } else if (ret < 0) { 5637335640Shselasky handlep->current_packet = NULL; 5638335640Shselasky return ret; 5639335640Shselasky } 5640335640Shselasky handlep->current_packet += tp3_hdr->tp_next_offset; 5641335640Shselasky handlep->packets_left--; 5642335640Shselasky } 5643335640Shselasky 5644335640Shselasky if (handlep->packets_left <= 0) { 5645335640Shselasky /* 5646335640Shselasky * Hand this block back to the kernel, and, if 5647335640Shselasky * we're counting blocks that need to be 5648335640Shselasky * filtered in userland after having been 5649335640Shselasky * filtered by the kernel, count the one we've 5650335640Shselasky * just processed. 5651335640Shselasky */ 5652335640Shselasky h.h3->hdr.bh1.block_status = TP_STATUS_KERNEL; 5653335640Shselasky if (handlep->blocks_to_filter_in_userland > 0) { 5654335640Shselasky handlep->blocks_to_filter_in_userland--; 5655335640Shselasky if (handlep->blocks_to_filter_in_userland == 0) { 5656335640Shselasky /* 5657335640Shselasky * No more blocks need to be filtered 5658335640Shselasky * in userland. 5659335640Shselasky */ 5660335640Shselasky handlep->filter_in_userland = 0; 5661335640Shselasky } 5662335640Shselasky } 5663335640Shselasky 5664335640Shselasky /* next block */ 5665335640Shselasky if (++handle->offset >= handle->cc) 5666335640Shselasky handle->offset = 0; 5667335640Shselasky 5668335640Shselasky handlep->current_packet = NULL; 5669335640Shselasky } 5670335640Shselasky 5671335640Shselasky /* check for break loop condition*/ 5672335640Shselasky if (handle->break_loop) { 5673335640Shselasky handle->break_loop = 0; 5674335640Shselasky return PCAP_ERROR_BREAK; 5675335640Shselasky } 5676335640Shselasky } 5677335640Shselasky if (pkts == 0 && handlep->timeout == 0) { 5678335640Shselasky /* Block until we see a packet. */ 5679335640Shselasky goto again; 5680335640Shselasky } 5681335640Shselasky return pkts; 5682335640Shselasky} 5683335640Shselasky#endif /* HAVE_TPACKET3 */ 5684335640Shselasky 5685335640Shselaskystatic int 5686335640Shselaskypcap_setfilter_linux_mmap(pcap_t *handle, struct bpf_program *filter) 5687335640Shselasky{ 5688335640Shselasky struct pcap_linux *handlep = handle->priv; 5689335640Shselasky int n, offset; 5690335640Shselasky int ret; 5691335640Shselasky 5692335640Shselasky /* 5693335640Shselasky * Don't rewrite "ret" instructions; we don't need to, as 5694335640Shselasky * we're not reading packets with recvmsg(), and we don't 5695335640Shselasky * want to, as, by not rewriting them, the kernel can avoid 5696335640Shselasky * copying extra data. 5697335640Shselasky */ 5698335640Shselasky ret = pcap_setfilter_linux_common(handle, filter, 1); 5699335640Shselasky if (ret < 0) 5700335640Shselasky return ret; 5701335640Shselasky 5702335640Shselasky /* 5703335640Shselasky * If we're filtering in userland, there's nothing to do; 5704335640Shselasky * the new filter will be used for the next packet. 5705335640Shselasky */ 5706335640Shselasky if (handlep->filter_in_userland) 5707335640Shselasky return ret; 5708335640Shselasky 5709335640Shselasky /* 5710335640Shselasky * We're filtering in the kernel; the packets present in 5711335640Shselasky * all blocks currently in the ring were already filtered 5712335640Shselasky * by the old filter, and so will need to be filtered in 5713335640Shselasky * userland by the new filter. 5714335640Shselasky * 5715335640Shselasky * Get an upper bound for the number of such blocks; first, 5716335640Shselasky * walk the ring backward and count the free blocks. 5717335640Shselasky */ 5718335640Shselasky offset = handle->offset; 5719335640Shselasky if (--offset < 0) 5720335640Shselasky offset = handle->cc - 1; 5721335640Shselasky for (n=0; n < handle->cc; ++n) { 5722335640Shselasky if (--offset < 0) 5723335640Shselasky offset = handle->cc - 1; 5724335640Shselasky if (pcap_get_ring_frame_status(handle, offset) != TP_STATUS_KERNEL) 5725335640Shselasky break; 5726335640Shselasky } 5727335640Shselasky 5728335640Shselasky /* 5729335640Shselasky * If we found free blocks, decrement the count of free 5730335640Shselasky * blocks by 1, just in case we lost a race with another 5731335640Shselasky * thread of control that was adding a packet while 5732335640Shselasky * we were counting and that had run the filter before 5733335640Shselasky * we changed it. 5734335640Shselasky * 5735335640Shselasky * XXX - could there be more than one block added in 5736335640Shselasky * this fashion? 5737335640Shselasky * 5738335640Shselasky * XXX - is there a way to avoid that race, e.g. somehow 5739335640Shselasky * wait for all packets that passed the old filter to 5740335640Shselasky * be added to the ring? 5741335640Shselasky */ 5742335640Shselasky if (n != 0) 5743335640Shselasky n--; 5744335640Shselasky 5745335640Shselasky /* 5746335640Shselasky * Set the count of blocks worth of packets to filter 5747335640Shselasky * in userland to the total number of blocks in the 5748335640Shselasky * ring minus the number of free blocks we found, and 5749335640Shselasky * turn on userland filtering. (The count of blocks 5750335640Shselasky * worth of packets to filter in userland is guaranteed 5751335640Shselasky * not to be zero - n, above, couldn't be set to a 5752335640Shselasky * value > handle->cc, and if it were equal to 5753335640Shselasky * handle->cc, it wouldn't be zero, and thus would 5754335640Shselasky * be decremented to handle->cc - 1.) 5755335640Shselasky */ 5756335640Shselasky handlep->blocks_to_filter_in_userland = handle->cc - n; 5757335640Shselasky handlep->filter_in_userland = 1; 5758335640Shselasky return ret; 5759335640Shselasky} 5760335640Shselasky 5761335640Shselasky#endif /* HAVE_PACKET_RING */ 5762335640Shselasky 5763335640Shselasky 5764335640Shselasky#ifdef HAVE_PF_PACKET_SOCKETS 5765335640Shselasky/* 5766335640Shselasky * Return the index of the given device name. Fill ebuf and return 5767335640Shselasky * -1 on failure. 5768335640Shselasky */ 5769335640Shselaskystatic int 5770335640Shselaskyiface_get_id(int fd, const char *device, char *ebuf) 5771335640Shselasky{ 5772335640Shselasky struct ifreq ifr; 5773335640Shselasky 5774335640Shselasky memset(&ifr, 0, sizeof(ifr)); 5775356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 5776335640Shselasky 5777335640Shselasky if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1) { 5778335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 5779335640Shselasky errno, "SIOCGIFINDEX"); 5780335640Shselasky return -1; 5781335640Shselasky } 5782335640Shselasky 5783335640Shselasky return ifr.ifr_ifindex; 5784335640Shselasky} 5785335640Shselasky 5786335640Shselasky/* 5787335640Shselasky * Bind the socket associated with FD to the given device. 5788335640Shselasky * Return 1 on success, 0 if we should try a SOCK_PACKET socket, 5789335640Shselasky * or a PCAP_ERROR_ value on a hard error. 5790335640Shselasky */ 5791335640Shselaskystatic int 5792335640Shselaskyiface_bind(int fd, int ifindex, char *ebuf, int protocol) 5793335640Shselasky{ 5794335640Shselasky struct sockaddr_ll sll; 5795335640Shselasky int err; 5796335640Shselasky socklen_t errlen = sizeof(err); 5797335640Shselasky 5798335640Shselasky memset(&sll, 0, sizeof(sll)); 5799335640Shselasky sll.sll_family = AF_PACKET; 5800335640Shselasky sll.sll_ifindex = ifindex; 5801335640Shselasky sll.sll_protocol = protocol; 5802335640Shselasky 5803335640Shselasky if (bind(fd, (struct sockaddr *) &sll, sizeof(sll)) == -1) { 5804335640Shselasky if (errno == ENETDOWN) { 5805335640Shselasky /* 5806335640Shselasky * Return a "network down" indication, so that 5807335640Shselasky * the application can report that rather than 5808335640Shselasky * saying we had a mysterious failure and 5809335640Shselasky * suggest that they report a problem to the 5810335640Shselasky * libpcap developers. 5811335640Shselasky */ 5812335640Shselasky return PCAP_ERROR_IFACE_NOT_UP; 5813335640Shselasky } else { 5814335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 5815335640Shselasky errno, "bind"); 5816335640Shselasky return PCAP_ERROR; 5817335640Shselasky } 5818335640Shselasky } 5819335640Shselasky 5820335640Shselasky /* Any pending errors, e.g., network is down? */ 5821335640Shselasky 5822335640Shselasky if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { 5823335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 5824356341Scy errno, "getsockopt (SO_ERROR)"); 5825335640Shselasky return 0; 5826335640Shselasky } 5827335640Shselasky 5828335640Shselasky if (err == ENETDOWN) { 5829335640Shselasky /* 5830335640Shselasky * Return a "network down" indication, so that 5831335640Shselasky * the application can report that rather than 5832335640Shselasky * saying we had a mysterious failure and 5833335640Shselasky * suggest that they report a problem to the 5834335640Shselasky * libpcap developers. 5835335640Shselasky */ 5836335640Shselasky return PCAP_ERROR_IFACE_NOT_UP; 5837335640Shselasky } else if (err > 0) { 5838335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 5839335640Shselasky err, "bind"); 5840335640Shselasky return 0; 5841335640Shselasky } 5842335640Shselasky 5843335640Shselasky return 1; 5844335640Shselasky} 5845335640Shselasky 5846335640Shselasky#ifdef IW_MODE_MONITOR 5847335640Shselasky/* 5848335640Shselasky * Check whether the device supports the Wireless Extensions. 5849335640Shselasky * Returns 1 if it does, 0 if it doesn't, PCAP_ERROR_NO_SUCH_DEVICE 5850335640Shselasky * if the device doesn't even exist. 5851335640Shselasky */ 5852335640Shselaskystatic int 5853335640Shselaskyhas_wext(int sock_fd, const char *device, char *ebuf) 5854335640Shselasky{ 5855335640Shselasky struct iwreq ireq; 5856356341Scy int ret; 5857335640Shselasky 5858335640Shselasky if (is_bonding_device(sock_fd, device)) 5859335640Shselasky return 0; /* bonding device, so don't even try */ 5860335640Shselasky 5861356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 5862335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 5863335640Shselasky if (ioctl(sock_fd, SIOCGIWNAME, &ireq) >= 0) 5864335640Shselasky return 1; /* yes */ 5865356341Scy if (errno == ENODEV) 5866356341Scy ret = PCAP_ERROR_NO_SUCH_DEVICE; 5867356341Scy else 5868356341Scy ret = 0; 5869335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, errno, 5870335640Shselasky "%s: SIOCGIWNAME", device); 5871356341Scy return ret; 5872335640Shselasky} 5873335640Shselasky 5874335640Shselasky/* 5875335640Shselasky * Per me si va ne la citta dolente, 5876335640Shselasky * Per me si va ne l'etterno dolore, 5877335640Shselasky * ... 5878335640Shselasky * Lasciate ogne speranza, voi ch'intrate. 5879335640Shselasky * 5880335640Shselasky * XXX - airmon-ng does special stuff with the Orinoco driver and the 5881335640Shselasky * wlan-ng driver. 5882335640Shselasky */ 5883335640Shselaskytypedef enum { 5884335640Shselasky MONITOR_WEXT, 5885335640Shselasky MONITOR_HOSTAP, 5886335640Shselasky MONITOR_PRISM, 5887335640Shselasky MONITOR_PRISM54, 5888335640Shselasky MONITOR_ACX100, 5889335640Shselasky MONITOR_RT2500, 5890335640Shselasky MONITOR_RT2570, 5891335640Shselasky MONITOR_RT73, 5892335640Shselasky MONITOR_RTL8XXX 5893335640Shselasky} monitor_type; 5894335640Shselasky 5895335640Shselasky/* 5896335640Shselasky * Use the Wireless Extensions, if we have them, to try to turn monitor mode 5897335640Shselasky * on if it's not already on. 5898335640Shselasky * 5899335640Shselasky * Returns 1 on success, 0 if we don't support the Wireless Extensions 5900335640Shselasky * on this device, or a PCAP_ERROR_ value if we do support them but 5901335640Shselasky * we weren't able to turn monitor mode on. 5902335640Shselasky */ 5903335640Shselaskystatic int 5904335640Shselaskyenter_rfmon_mode_wext(pcap_t *handle, int sock_fd, const char *device) 5905335640Shselasky{ 5906335640Shselasky /* 5907335640Shselasky * XXX - at least some adapters require non-Wireless Extensions 5908335640Shselasky * mechanisms to turn monitor mode on. 5909335640Shselasky * 5910335640Shselasky * Atheros cards might require that a separate "monitor virtual access 5911335640Shselasky * point" be created, with later versions of the madwifi driver. 5912335640Shselasky * airmon-ng does "wlanconfig ath create wlandev {if} wlanmode 5913335640Shselasky * monitor -bssid", which apparently spits out a line "athN" 5914335640Shselasky * where "athN" is the monitor mode device. To leave monitor 5915335640Shselasky * mode, it destroys the monitor mode device. 5916335640Shselasky * 5917335640Shselasky * Some Intel Centrino adapters might require private ioctls to get 5918335640Shselasky * radio headers; the ipw2200 and ipw3945 drivers allow you to 5919335640Shselasky * configure a separate "rtapN" interface to capture in monitor 5920335640Shselasky * mode without preventing the adapter from operating normally. 5921335640Shselasky * (airmon-ng doesn't appear to use that, though.) 5922335640Shselasky * 5923335640Shselasky * It would be Truly Wonderful if mac80211 and nl80211 cleaned this 5924335640Shselasky * up, and if all drivers were converted to mac80211 drivers. 5925335640Shselasky * 5926335640Shselasky * If interface {if} is a mac80211 driver, the file 5927335640Shselasky * /sys/class/net/{if}/phy80211 is a symlink to 5928335640Shselasky * /sys/class/ieee80211/{phydev}, for some {phydev}. 5929335640Shselasky * 5930335640Shselasky * On Fedora 9, with a 2.6.26.3-29 kernel, my Zydas stick, at 5931335640Shselasky * least, has a "wmaster0" device and a "wlan0" device; the 5932335640Shselasky * latter is the one with the IP address. Both show up in 5933335640Shselasky * "tcpdump -D" output. Capturing on the wmaster0 device 5934335640Shselasky * captures with 802.11 headers. 5935335640Shselasky * 5936335640Shselasky * airmon-ng searches through /sys/class/net for devices named 5937335640Shselasky * monN, starting with mon0; as soon as one *doesn't* exist, 5938335640Shselasky * it chooses that as the monitor device name. If the "iw" 5939335640Shselasky * command exists, it does "iw dev {if} interface add {monif} 5940335640Shselasky * type monitor", where {monif} is the monitor device. It 5941335640Shselasky * then (sigh) sleeps .1 second, and then configures the 5942335640Shselasky * device up. Otherwise, if /sys/class/ieee80211/{phydev}/add_iface 5943335640Shselasky * is a file, it writes {mondev}, without a newline, to that file, 5944335640Shselasky * and again (sigh) sleeps .1 second, and then iwconfig's that 5945335640Shselasky * device into monitor mode and configures it up. Otherwise, 5946335640Shselasky * you can't do monitor mode. 5947335640Shselasky * 5948335640Shselasky * All these devices are "glued" together by having the 5949335640Shselasky * /sys/class/net/{device}/phy80211 links pointing to the same 5950335640Shselasky * place, so, given a wmaster, wlan, or mon device, you can 5951335640Shselasky * find the other devices by looking for devices with 5952335640Shselasky * the same phy80211 link. 5953335640Shselasky * 5954335640Shselasky * To turn monitor mode off, delete the monitor interface, 5955335640Shselasky * either with "iw dev {monif} interface del" or by sending 5956335640Shselasky * {monif}, with no NL, down /sys/class/ieee80211/{phydev}/remove_iface 5957335640Shselasky * 5958335640Shselasky * Note: if you try to create a monitor device named "monN", and 5959335640Shselasky * there's already a "monN" device, it fails, as least with 5960335640Shselasky * the netlink interface (which is what iw uses), with a return 5961335640Shselasky * value of -ENFILE. (Return values are negative errnos.) We 5962335640Shselasky * could probably use that to find an unused device. 5963335640Shselasky */ 5964335640Shselasky struct pcap_linux *handlep = handle->priv; 5965335640Shselasky int err; 5966335640Shselasky struct iwreq ireq; 5967335640Shselasky struct iw_priv_args *priv; 5968335640Shselasky monitor_type montype; 5969335640Shselasky int i; 5970335640Shselasky __u32 cmd; 5971335640Shselasky struct ifreq ifr; 5972335640Shselasky int oldflags; 5973335640Shselasky int args[2]; 5974335640Shselasky int channel; 5975335640Shselasky 5976335640Shselasky /* 5977335640Shselasky * Does this device *support* the Wireless Extensions? 5978335640Shselasky */ 5979335640Shselasky err = has_wext(sock_fd, device, handle->errbuf); 5980335640Shselasky if (err <= 0) 5981335640Shselasky return err; /* either it doesn't or the device doesn't even exist */ 5982335640Shselasky /* 5983335640Shselasky * Start out assuming we have no private extensions to control 5984335640Shselasky * radio metadata. 5985335640Shselasky */ 5986335640Shselasky montype = MONITOR_WEXT; 5987335640Shselasky cmd = 0; 5988335640Shselasky 5989335640Shselasky /* 5990335640Shselasky * Try to get all the Wireless Extensions private ioctls 5991335640Shselasky * supported by this device. 5992335640Shselasky * 5993335640Shselasky * First, get the size of the buffer we need, by supplying no 5994335640Shselasky * buffer and a length of 0. If the device supports private 5995335640Shselasky * ioctls, it should return E2BIG, with ireq.u.data.length set 5996335640Shselasky * to the length we need. If it doesn't support them, it should 5997335640Shselasky * return EOPNOTSUPP. 5998335640Shselasky */ 5999335640Shselasky memset(&ireq, 0, sizeof ireq); 6000356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6001335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6002335640Shselasky ireq.u.data.pointer = (void *)args; 6003335640Shselasky ireq.u.data.length = 0; 6004335640Shselasky ireq.u.data.flags = 0; 6005335640Shselasky if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) != -1) { 6006335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 6007335640Shselasky "%s: SIOCGIWPRIV with a zero-length buffer didn't fail!", 6008335640Shselasky device); 6009335640Shselasky return PCAP_ERROR; 6010335640Shselasky } 6011335640Shselasky if (errno != EOPNOTSUPP) { 6012335640Shselasky /* 6013335640Shselasky * OK, it's not as if there are no private ioctls. 6014335640Shselasky */ 6015335640Shselasky if (errno != E2BIG) { 6016335640Shselasky /* 6017335640Shselasky * Failed. 6018335640Shselasky */ 6019335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6020335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device); 6021335640Shselasky return PCAP_ERROR; 6022335640Shselasky } 6023335640Shselasky 6024335640Shselasky /* 6025335640Shselasky * OK, try to get the list of private ioctls. 6026335640Shselasky */ 6027335640Shselasky priv = malloc(ireq.u.data.length * sizeof (struct iw_priv_args)); 6028335640Shselasky if (priv == NULL) { 6029335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6030335640Shselasky PCAP_ERRBUF_SIZE, errno, "malloc"); 6031335640Shselasky return PCAP_ERROR; 6032335640Shselasky } 6033335640Shselasky ireq.u.data.pointer = (void *)priv; 6034335640Shselasky if (ioctl(sock_fd, SIOCGIWPRIV, &ireq) == -1) { 6035335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6036335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWPRIV", device); 6037335640Shselasky free(priv); 6038335640Shselasky return PCAP_ERROR; 6039335640Shselasky } 6040335640Shselasky 6041335640Shselasky /* 6042335640Shselasky * Look for private ioctls to turn monitor mode on or, if 6043335640Shselasky * monitor mode is on, to set the header type. 6044335640Shselasky */ 6045335640Shselasky for (i = 0; i < ireq.u.data.length; i++) { 6046335640Shselasky if (strcmp(priv[i].name, "monitor_type") == 0) { 6047335640Shselasky /* 6048335640Shselasky * Hostap driver, use this one. 6049335640Shselasky * Set monitor mode first. 6050335640Shselasky * You can set it to 0 to get DLT_IEEE80211, 6051335640Shselasky * 1 to get DLT_PRISM, 2 to get 6052335640Shselasky * DLT_IEEE80211_RADIO_AVS, and, with more 6053335640Shselasky * recent versions of the driver, 3 to get 6054335640Shselasky * DLT_IEEE80211_RADIO. 6055335640Shselasky */ 6056335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6057335640Shselasky break; 6058335640Shselasky if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) 6059335640Shselasky break; 6060335640Shselasky if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) 6061335640Shselasky break; 6062335640Shselasky montype = MONITOR_HOSTAP; 6063335640Shselasky cmd = priv[i].cmd; 6064335640Shselasky break; 6065335640Shselasky } 6066335640Shselasky if (strcmp(priv[i].name, "set_prismhdr") == 0) { 6067335640Shselasky /* 6068335640Shselasky * Prism54 driver, use this one. 6069335640Shselasky * Set monitor mode first. 6070335640Shselasky * You can set it to 2 to get DLT_IEEE80211 6071335640Shselasky * or 3 or get DLT_PRISM. 6072335640Shselasky */ 6073335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6074335640Shselasky break; 6075335640Shselasky if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) 6076335640Shselasky break; 6077335640Shselasky if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) 6078335640Shselasky break; 6079335640Shselasky montype = MONITOR_PRISM54; 6080335640Shselasky cmd = priv[i].cmd; 6081335640Shselasky break; 6082335640Shselasky } 6083335640Shselasky if (strcmp(priv[i].name, "forceprismheader") == 0) { 6084335640Shselasky /* 6085335640Shselasky * RT2570 driver, use this one. 6086335640Shselasky * Do this after turning monitor mode on. 6087335640Shselasky * You can set it to 1 to get DLT_PRISM or 2 6088335640Shselasky * to get DLT_IEEE80211. 6089335640Shselasky */ 6090335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6091335640Shselasky break; 6092335640Shselasky if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) 6093335640Shselasky break; 6094335640Shselasky if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) 6095335640Shselasky break; 6096335640Shselasky montype = MONITOR_RT2570; 6097335640Shselasky cmd = priv[i].cmd; 6098335640Shselasky break; 6099335640Shselasky } 6100335640Shselasky if (strcmp(priv[i].name, "forceprism") == 0) { 6101335640Shselasky /* 6102335640Shselasky * RT73 driver, use this one. 6103335640Shselasky * Do this after turning monitor mode on. 6104335640Shselasky * Its argument is a *string*; you can 6105335640Shselasky * set it to "1" to get DLT_PRISM or "2" 6106335640Shselasky * to get DLT_IEEE80211. 6107335640Shselasky */ 6108335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_CHAR) 6109335640Shselasky break; 6110335640Shselasky if (priv[i].set_args & IW_PRIV_SIZE_FIXED) 6111335640Shselasky break; 6112335640Shselasky montype = MONITOR_RT73; 6113335640Shselasky cmd = priv[i].cmd; 6114335640Shselasky break; 6115335640Shselasky } 6116335640Shselasky if (strcmp(priv[i].name, "prismhdr") == 0) { 6117335640Shselasky /* 6118335640Shselasky * One of the RTL8xxx drivers, use this one. 6119335640Shselasky * It can only be done after monitor mode 6120335640Shselasky * has been turned on. You can set it to 1 6121335640Shselasky * to get DLT_PRISM or 0 to get DLT_IEEE80211. 6122335640Shselasky */ 6123335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6124335640Shselasky break; 6125335640Shselasky if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) 6126335640Shselasky break; 6127335640Shselasky if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 1) 6128335640Shselasky break; 6129335640Shselasky montype = MONITOR_RTL8XXX; 6130335640Shselasky cmd = priv[i].cmd; 6131335640Shselasky break; 6132335640Shselasky } 6133335640Shselasky if (strcmp(priv[i].name, "rfmontx") == 0) { 6134335640Shselasky /* 6135335640Shselasky * RT2500 or RT61 driver, use this one. 6136335640Shselasky * It has one one-byte parameter; set 6137335640Shselasky * u.data.length to 1 and u.data.pointer to 6138335640Shselasky * point to the parameter. 6139335640Shselasky * It doesn't itself turn monitor mode on. 6140335640Shselasky * You can set it to 1 to allow transmitting 6141335640Shselasky * in monitor mode(?) and get DLT_IEEE80211, 6142335640Shselasky * or set it to 0 to disallow transmitting in 6143335640Shselasky * monitor mode(?) and get DLT_PRISM. 6144335640Shselasky */ 6145335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6146335640Shselasky break; 6147335640Shselasky if ((priv[i].set_args & IW_PRIV_SIZE_MASK) != 2) 6148335640Shselasky break; 6149335640Shselasky montype = MONITOR_RT2500; 6150335640Shselasky cmd = priv[i].cmd; 6151335640Shselasky break; 6152335640Shselasky } 6153335640Shselasky if (strcmp(priv[i].name, "monitor") == 0) { 6154335640Shselasky /* 6155335640Shselasky * Either ACX100 or hostap, use this one. 6156335640Shselasky * It turns monitor mode on. 6157335640Shselasky * If it takes two arguments, it's ACX100; 6158335640Shselasky * the first argument is 1 for DLT_PRISM 6159335640Shselasky * or 2 for DLT_IEEE80211, and the second 6160335640Shselasky * argument is the channel on which to 6161335640Shselasky * run. If it takes one argument, it's 6162335640Shselasky * HostAP, and the argument is 2 for 6163335640Shselasky * DLT_IEEE80211 and 3 for DLT_PRISM. 6164335640Shselasky * 6165335640Shselasky * If we see this, we don't quit, as this 6166335640Shselasky * might be a version of the hostap driver 6167335640Shselasky * that also supports "monitor_type". 6168335640Shselasky */ 6169335640Shselasky if ((priv[i].set_args & IW_PRIV_TYPE_MASK) != IW_PRIV_TYPE_INT) 6170335640Shselasky break; 6171335640Shselasky if (!(priv[i].set_args & IW_PRIV_SIZE_FIXED)) 6172335640Shselasky break; 6173335640Shselasky switch (priv[i].set_args & IW_PRIV_SIZE_MASK) { 6174335640Shselasky 6175335640Shselasky case 1: 6176335640Shselasky montype = MONITOR_PRISM; 6177335640Shselasky cmd = priv[i].cmd; 6178335640Shselasky break; 6179335640Shselasky 6180335640Shselasky case 2: 6181335640Shselasky montype = MONITOR_ACX100; 6182335640Shselasky cmd = priv[i].cmd; 6183335640Shselasky break; 6184335640Shselasky 6185335640Shselasky default: 6186335640Shselasky break; 6187335640Shselasky } 6188335640Shselasky } 6189335640Shselasky } 6190335640Shselasky free(priv); 6191335640Shselasky } 6192335640Shselasky 6193335640Shselasky /* 6194335640Shselasky * XXX - ipw3945? islism? 6195335640Shselasky */ 6196335640Shselasky 6197335640Shselasky /* 6198335640Shselasky * Get the old mode. 6199335640Shselasky */ 6200356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6201335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6202335640Shselasky if (ioctl(sock_fd, SIOCGIWMODE, &ireq) == -1) { 6203335640Shselasky /* 6204335640Shselasky * We probably won't be able to set the mode, either. 6205335640Shselasky */ 6206335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 6207335640Shselasky } 6208335640Shselasky 6209335640Shselasky /* 6210335640Shselasky * Is it currently in monitor mode? 6211335640Shselasky */ 6212335640Shselasky if (ireq.u.mode == IW_MODE_MONITOR) { 6213335640Shselasky /* 6214335640Shselasky * Yes. Just leave things as they are. 6215335640Shselasky * We don't offer multiple link-layer types, as 6216335640Shselasky * changing the link-layer type out from under 6217335640Shselasky * somebody else capturing in monitor mode would 6218335640Shselasky * be considered rude. 6219335640Shselasky */ 6220335640Shselasky return 1; 6221335640Shselasky } 6222335640Shselasky /* 6223335640Shselasky * No. We have to put the adapter into rfmon mode. 6224335640Shselasky */ 6225335640Shselasky 6226335640Shselasky /* 6227335640Shselasky * If we haven't already done so, arrange to have 6228335640Shselasky * "pcap_close_all()" called when we exit. 6229335640Shselasky */ 6230335640Shselasky if (!pcap_do_addexit(handle)) { 6231335640Shselasky /* 6232335640Shselasky * "atexit()" failed; don't put the interface 6233335640Shselasky * in rfmon mode, just give up. 6234335640Shselasky */ 6235335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 6236335640Shselasky } 6237335640Shselasky 6238335640Shselasky /* 6239335640Shselasky * Save the old mode. 6240335640Shselasky */ 6241335640Shselasky handlep->oldmode = ireq.u.mode; 6242335640Shselasky 6243335640Shselasky /* 6244335640Shselasky * Put the adapter in rfmon mode. How we do this depends 6245335640Shselasky * on whether we have a special private ioctl or not. 6246335640Shselasky */ 6247335640Shselasky if (montype == MONITOR_PRISM) { 6248335640Shselasky /* 6249335640Shselasky * We have the "monitor" private ioctl, but none of 6250335640Shselasky * the other private ioctls. Use this, and select 6251335640Shselasky * the Prism header. 6252335640Shselasky * 6253335640Shselasky * If it fails, just fall back on SIOCSIWMODE. 6254335640Shselasky */ 6255335640Shselasky memset(&ireq, 0, sizeof ireq); 6256356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6257335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6258335640Shselasky ireq.u.data.length = 1; /* 1 argument */ 6259335640Shselasky args[0] = 3; /* request Prism header */ 6260335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6261335640Shselasky if (ioctl(sock_fd, cmd, &ireq) != -1) { 6262335640Shselasky /* 6263335640Shselasky * Success. 6264335640Shselasky * Note that we have to put the old mode back 6265335640Shselasky * when we close the device. 6266335640Shselasky */ 6267335640Shselasky handlep->must_do_on_close |= MUST_CLEAR_RFMON; 6268335640Shselasky 6269335640Shselasky /* 6270335640Shselasky * Add this to the list of pcaps to close 6271335640Shselasky * when we exit. 6272335640Shselasky */ 6273335640Shselasky pcap_add_to_pcaps_to_close(handle); 6274335640Shselasky 6275335640Shselasky return 1; 6276335640Shselasky } 6277335640Shselasky 6278335640Shselasky /* 6279335640Shselasky * Failure. Fall back on SIOCSIWMODE. 6280335640Shselasky */ 6281335640Shselasky } 6282335640Shselasky 6283335640Shselasky /* 6284335640Shselasky * First, take the interface down if it's up; otherwise, we 6285335640Shselasky * might get EBUSY. 6286335640Shselasky */ 6287335640Shselasky memset(&ifr, 0, sizeof(ifr)); 6288356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 6289335640Shselasky if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr) == -1) { 6290335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 6291335640Shselasky errno, "%s: Can't get flags", device); 6292335640Shselasky return PCAP_ERROR; 6293335640Shselasky } 6294335640Shselasky oldflags = 0; 6295335640Shselasky if (ifr.ifr_flags & IFF_UP) { 6296335640Shselasky oldflags = ifr.ifr_flags; 6297335640Shselasky ifr.ifr_flags &= ~IFF_UP; 6298335640Shselasky if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { 6299335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6300335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags", 6301335640Shselasky device); 6302335640Shselasky return PCAP_ERROR; 6303335640Shselasky } 6304335640Shselasky } 6305335640Shselasky 6306335640Shselasky /* 6307335640Shselasky * Then turn monitor mode on. 6308335640Shselasky */ 6309356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6310335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6311335640Shselasky ireq.u.mode = IW_MODE_MONITOR; 6312335640Shselasky if (ioctl(sock_fd, SIOCSIWMODE, &ireq) == -1) { 6313335640Shselasky /* 6314335640Shselasky * Scientist, you've failed. 6315335640Shselasky * Bring the interface back up if we shut it down. 6316335640Shselasky */ 6317335640Shselasky ifr.ifr_flags = oldflags; 6318335640Shselasky if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { 6319335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6320335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags", 6321335640Shselasky device); 6322335640Shselasky return PCAP_ERROR; 6323335640Shselasky } 6324335640Shselasky return PCAP_ERROR_RFMON_NOTSUP; 6325335640Shselasky } 6326335640Shselasky 6327335640Shselasky /* 6328335640Shselasky * XXX - airmon-ng does "iwconfig {if} key off" after setting 6329335640Shselasky * monitor mode and setting the channel, and then does 6330335640Shselasky * "iwconfig up". 6331335640Shselasky */ 6332335640Shselasky 6333335640Shselasky /* 6334335640Shselasky * Now select the appropriate radio header. 6335335640Shselasky */ 6336335640Shselasky switch (montype) { 6337335640Shselasky 6338335640Shselasky case MONITOR_WEXT: 6339335640Shselasky /* 6340335640Shselasky * We don't have any private ioctl to set the header. 6341335640Shselasky */ 6342335640Shselasky break; 6343335640Shselasky 6344335640Shselasky case MONITOR_HOSTAP: 6345335640Shselasky /* 6346335640Shselasky * Try to select the radiotap header. 6347335640Shselasky */ 6348335640Shselasky memset(&ireq, 0, sizeof ireq); 6349356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6350335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6351335640Shselasky args[0] = 3; /* request radiotap header */ 6352335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6353335640Shselasky if (ioctl(sock_fd, cmd, &ireq) != -1) 6354335640Shselasky break; /* success */ 6355335640Shselasky 6356335640Shselasky /* 6357335640Shselasky * That failed. Try to select the AVS header. 6358335640Shselasky */ 6359335640Shselasky memset(&ireq, 0, sizeof ireq); 6360356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6361335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6362335640Shselasky args[0] = 2; /* request AVS header */ 6363335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6364335640Shselasky if (ioctl(sock_fd, cmd, &ireq) != -1) 6365335640Shselasky break; /* success */ 6366335640Shselasky 6367335640Shselasky /* 6368335640Shselasky * That failed. Try to select the Prism header. 6369335640Shselasky */ 6370335640Shselasky memset(&ireq, 0, sizeof ireq); 6371356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6372335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6373335640Shselasky args[0] = 1; /* request Prism header */ 6374335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6375335640Shselasky ioctl(sock_fd, cmd, &ireq); 6376335640Shselasky break; 6377335640Shselasky 6378335640Shselasky case MONITOR_PRISM: 6379335640Shselasky /* 6380335640Shselasky * The private ioctl failed. 6381335640Shselasky */ 6382335640Shselasky break; 6383335640Shselasky 6384335640Shselasky case MONITOR_PRISM54: 6385335640Shselasky /* 6386335640Shselasky * Select the Prism header. 6387335640Shselasky */ 6388335640Shselasky memset(&ireq, 0, sizeof ireq); 6389356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6390335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6391335640Shselasky args[0] = 3; /* request Prism header */ 6392335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6393335640Shselasky ioctl(sock_fd, cmd, &ireq); 6394335640Shselasky break; 6395335640Shselasky 6396335640Shselasky case MONITOR_ACX100: 6397335640Shselasky /* 6398335640Shselasky * Get the current channel. 6399335640Shselasky */ 6400335640Shselasky memset(&ireq, 0, sizeof ireq); 6401356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6402335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6403335640Shselasky if (ioctl(sock_fd, SIOCGIWFREQ, &ireq) == -1) { 6404335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6405335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: SIOCGIWFREQ", device); 6406335640Shselasky return PCAP_ERROR; 6407335640Shselasky } 6408335640Shselasky channel = ireq.u.freq.m; 6409335640Shselasky 6410335640Shselasky /* 6411335640Shselasky * Select the Prism header, and set the channel to the 6412335640Shselasky * current value. 6413335640Shselasky */ 6414335640Shselasky memset(&ireq, 0, sizeof ireq); 6415356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6416335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6417335640Shselasky args[0] = 1; /* request Prism header */ 6418335640Shselasky args[1] = channel; /* set channel */ 6419335640Shselasky memcpy(ireq.u.name, args, 2*sizeof (int)); 6420335640Shselasky ioctl(sock_fd, cmd, &ireq); 6421335640Shselasky break; 6422335640Shselasky 6423335640Shselasky case MONITOR_RT2500: 6424335640Shselasky /* 6425335640Shselasky * Disallow transmission - that turns on the 6426335640Shselasky * Prism header. 6427335640Shselasky */ 6428335640Shselasky memset(&ireq, 0, sizeof ireq); 6429356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6430335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6431335640Shselasky args[0] = 0; /* disallow transmitting */ 6432335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6433335640Shselasky ioctl(sock_fd, cmd, &ireq); 6434335640Shselasky break; 6435335640Shselasky 6436335640Shselasky case MONITOR_RT2570: 6437335640Shselasky /* 6438335640Shselasky * Force the Prism header. 6439335640Shselasky */ 6440335640Shselasky memset(&ireq, 0, sizeof ireq); 6441356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6442335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6443335640Shselasky args[0] = 1; /* request Prism header */ 6444335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6445335640Shselasky ioctl(sock_fd, cmd, &ireq); 6446335640Shselasky break; 6447335640Shselasky 6448335640Shselasky case MONITOR_RT73: 6449335640Shselasky /* 6450335640Shselasky * Force the Prism header. 6451335640Shselasky */ 6452335640Shselasky memset(&ireq, 0, sizeof ireq); 6453356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6454335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6455335640Shselasky ireq.u.data.length = 1; /* 1 argument */ 6456335640Shselasky ireq.u.data.pointer = "1"; 6457335640Shselasky ireq.u.data.flags = 0; 6458335640Shselasky ioctl(sock_fd, cmd, &ireq); 6459335640Shselasky break; 6460335640Shselasky 6461335640Shselasky case MONITOR_RTL8XXX: 6462335640Shselasky /* 6463335640Shselasky * Force the Prism header. 6464335640Shselasky */ 6465335640Shselasky memset(&ireq, 0, sizeof ireq); 6466356341Scy pcap_strlcpy(ireq.ifr_ifrn.ifrn_name, device, 6467335640Shselasky sizeof ireq.ifr_ifrn.ifrn_name); 6468335640Shselasky args[0] = 1; /* request Prism header */ 6469335640Shselasky memcpy(ireq.u.name, args, sizeof (int)); 6470335640Shselasky ioctl(sock_fd, cmd, &ireq); 6471335640Shselasky break; 6472335640Shselasky } 6473335640Shselasky 6474335640Shselasky /* 6475335640Shselasky * Now bring the interface back up if we brought it down. 6476335640Shselasky */ 6477335640Shselasky if (oldflags != 0) { 6478335640Shselasky ifr.ifr_flags = oldflags; 6479335640Shselasky if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr) == -1) { 6480335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6481335640Shselasky PCAP_ERRBUF_SIZE, errno, "%s: Can't set flags", 6482335640Shselasky device); 6483335640Shselasky 6484335640Shselasky /* 6485335640Shselasky * At least try to restore the old mode on the 6486335640Shselasky * interface. 6487335640Shselasky */ 6488335640Shselasky if (ioctl(handle->fd, SIOCSIWMODE, &ireq) == -1) { 6489335640Shselasky /* 6490335640Shselasky * Scientist, you've failed. 6491335640Shselasky */ 6492335640Shselasky fprintf(stderr, 6493335640Shselasky "Can't restore interface wireless mode (SIOCSIWMODE failed: %s).\n" 6494335640Shselasky "Please adjust manually.\n", 6495335640Shselasky strerror(errno)); 6496335640Shselasky } 6497335640Shselasky return PCAP_ERROR; 6498335640Shselasky } 6499335640Shselasky } 6500335640Shselasky 6501335640Shselasky /* 6502335640Shselasky * Note that we have to put the old mode back when we 6503335640Shselasky * close the device. 6504335640Shselasky */ 6505335640Shselasky handlep->must_do_on_close |= MUST_CLEAR_RFMON; 6506335640Shselasky 6507335640Shselasky /* 6508335640Shselasky * Add this to the list of pcaps to close when we exit. 6509335640Shselasky */ 6510335640Shselasky pcap_add_to_pcaps_to_close(handle); 6511335640Shselasky 6512335640Shselasky return 1; 6513335640Shselasky} 6514335640Shselasky#endif /* IW_MODE_MONITOR */ 6515335640Shselasky 6516335640Shselasky/* 6517335640Shselasky * Try various mechanisms to enter monitor mode. 6518335640Shselasky */ 6519335640Shselaskystatic int 6520335640Shselaskyenter_rfmon_mode(pcap_t *handle, int sock_fd, const char *device) 6521335640Shselasky{ 6522335640Shselasky#if defined(HAVE_LIBNL) || defined(IW_MODE_MONITOR) 6523335640Shselasky int ret; 6524335640Shselasky#endif 6525335640Shselasky 6526335640Shselasky#ifdef HAVE_LIBNL 6527335640Shselasky ret = enter_rfmon_mode_mac80211(handle, sock_fd, device); 6528335640Shselasky if (ret < 0) 6529335640Shselasky return ret; /* error attempting to do so */ 6530335640Shselasky if (ret == 1) 6531335640Shselasky return 1; /* success */ 6532335640Shselasky#endif /* HAVE_LIBNL */ 6533335640Shselasky 6534335640Shselasky#ifdef IW_MODE_MONITOR 6535335640Shselasky ret = enter_rfmon_mode_wext(handle, sock_fd, device); 6536335640Shselasky if (ret < 0) 6537335640Shselasky return ret; /* error attempting to do so */ 6538335640Shselasky if (ret == 1) 6539335640Shselasky return 1; /* success */ 6540335640Shselasky#endif /* IW_MODE_MONITOR */ 6541335640Shselasky 6542335640Shselasky /* 6543335640Shselasky * Either none of the mechanisms we know about work or none 6544335640Shselasky * of those mechanisms are available, so we can't do monitor 6545335640Shselasky * mode. 6546335640Shselasky */ 6547335640Shselasky return 0; 6548335640Shselasky} 6549335640Shselasky 6550335640Shselasky#if defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) 6551335640Shselasky/* 6552335640Shselasky * Map SOF_TIMESTAMPING_ values to PCAP_TSTAMP_ values. 6553335640Shselasky */ 6554335640Shselaskystatic const struct { 6555335640Shselasky int soft_timestamping_val; 6556335640Shselasky int pcap_tstamp_val; 6557335640Shselasky} sof_ts_type_map[3] = { 6558335640Shselasky { SOF_TIMESTAMPING_SOFTWARE, PCAP_TSTAMP_HOST }, 6559335640Shselasky { SOF_TIMESTAMPING_SYS_HARDWARE, PCAP_TSTAMP_ADAPTER }, 6560335640Shselasky { SOF_TIMESTAMPING_RAW_HARDWARE, PCAP_TSTAMP_ADAPTER_UNSYNCED } 6561335640Shselasky}; 6562335640Shselasky#define NUM_SOF_TIMESTAMPING_TYPES (sizeof sof_ts_type_map / sizeof sof_ts_type_map[0]) 6563335640Shselasky 6564335640Shselasky/* 6565335640Shselasky * Set the list of time stamping types to include all types. 6566335640Shselasky */ 6567335640Shselaskystatic void 6568335640Shselaskyiface_set_all_ts_types(pcap_t *handle) 6569335640Shselasky{ 6570335640Shselasky u_int i; 6571335640Shselasky 6572335640Shselasky handle->tstamp_type_count = NUM_SOF_TIMESTAMPING_TYPES; 6573335640Shselasky handle->tstamp_type_list = malloc(NUM_SOF_TIMESTAMPING_TYPES * sizeof(u_int)); 6574335640Shselasky for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) 6575335640Shselasky handle->tstamp_type_list[i] = sof_ts_type_map[i].pcap_tstamp_val; 6576335640Shselasky} 6577335640Shselasky 6578335640Shselasky#ifdef ETHTOOL_GET_TS_INFO 6579335640Shselasky/* 6580335640Shselasky * Get a list of time stamping capabilities. 6581335640Shselasky */ 6582335640Shselaskystatic int 6583335640Shselaskyiface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf) 6584335640Shselasky{ 6585335640Shselasky int fd; 6586335640Shselasky struct ifreq ifr; 6587335640Shselasky struct ethtool_ts_info info; 6588335640Shselasky int num_ts_types; 6589335640Shselasky u_int i, j; 6590335640Shselasky 6591335640Shselasky /* 6592335640Shselasky * This doesn't apply to the "any" device; you can't say "turn on 6593335640Shselasky * hardware time stamping for all devices that exist now and arrange 6594335640Shselasky * that it be turned on for any device that appears in the future", 6595335640Shselasky * and not all devices even necessarily *support* hardware time 6596335640Shselasky * stamping, so don't report any time stamp types. 6597335640Shselasky */ 6598335640Shselasky if (strcmp(device, "any") == 0) { 6599335640Shselasky handle->tstamp_type_list = NULL; 6600335640Shselasky return 0; 6601335640Shselasky } 6602335640Shselasky 6603335640Shselasky /* 6604335640Shselasky * Create a socket from which to fetch time stamping capabilities. 6605335640Shselasky */ 6606335640Shselasky fd = socket(PF_UNIX, SOCK_RAW, 0); 6607335640Shselasky if (fd < 0) { 6608335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 6609335640Shselasky errno, "socket for SIOCETHTOOL(ETHTOOL_GET_TS_INFO)"); 6610335640Shselasky return -1; 6611335640Shselasky } 6612335640Shselasky 6613335640Shselasky memset(&ifr, 0, sizeof(ifr)); 6614356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 6615335640Shselasky memset(&info, 0, sizeof(info)); 6616335640Shselasky info.cmd = ETHTOOL_GET_TS_INFO; 6617335640Shselasky ifr.ifr_data = (caddr_t)&info; 6618335640Shselasky if (ioctl(fd, SIOCETHTOOL, &ifr) == -1) { 6619335640Shselasky int save_errno = errno; 6620335640Shselasky 6621335640Shselasky close(fd); 6622335640Shselasky switch (save_errno) { 6623335640Shselasky 6624335640Shselasky case EOPNOTSUPP: 6625335640Shselasky case EINVAL: 6626335640Shselasky /* 6627335640Shselasky * OK, this OS version or driver doesn't support 6628335640Shselasky * asking for the time stamping types, so let's 6629335640Shselasky * just return all the possible types. 6630335640Shselasky */ 6631335640Shselasky iface_set_all_ts_types(handle); 6632335640Shselasky return 0; 6633335640Shselasky 6634335640Shselasky case ENODEV: 6635335640Shselasky /* 6636335640Shselasky * OK, no such device. 6637335640Shselasky * The user will find that out when they try to 6638335640Shselasky * activate the device; just return an empty 6639335640Shselasky * list of time stamp types. 6640335640Shselasky */ 6641335640Shselasky handle->tstamp_type_list = NULL; 6642335640Shselasky return 0; 6643335640Shselasky 6644335640Shselasky default: 6645335640Shselasky /* 6646335640Shselasky * Other error. 6647335640Shselasky */ 6648335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 6649335640Shselasky save_errno, 6650335640Shselasky "%s: SIOCETHTOOL(ETHTOOL_GET_TS_INFO) ioctl failed", 6651335640Shselasky device); 6652335640Shselasky return -1; 6653335640Shselasky } 6654335640Shselasky } 6655335640Shselasky close(fd); 6656335640Shselasky 6657335640Shselasky /* 6658335640Shselasky * Do we support hardware time stamping of *all* packets? 6659335640Shselasky */ 6660335640Shselasky if (!(info.rx_filters & (1 << HWTSTAMP_FILTER_ALL))) { 6661335640Shselasky /* 6662335640Shselasky * No, so don't report any time stamp types. 6663335640Shselasky * 6664335640Shselasky * XXX - some devices either don't report 6665335640Shselasky * HWTSTAMP_FILTER_ALL when they do support it, or 6666335640Shselasky * report HWTSTAMP_FILTER_ALL but map it to only 6667335640Shselasky * time stamping a few PTP packets. See 6668335640Shselasky * http://marc.info/?l=linux-netdev&m=146318183529571&w=2 6669335640Shselasky */ 6670335640Shselasky handle->tstamp_type_list = NULL; 6671335640Shselasky return 0; 6672335640Shselasky } 6673335640Shselasky 6674335640Shselasky num_ts_types = 0; 6675335640Shselasky for (i = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) { 6676335640Shselasky if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) 6677335640Shselasky num_ts_types++; 6678335640Shselasky } 6679335640Shselasky handle->tstamp_type_count = num_ts_types; 6680335640Shselasky if (num_ts_types != 0) { 6681335640Shselasky handle->tstamp_type_list = malloc(num_ts_types * sizeof(u_int)); 6682335640Shselasky for (i = 0, j = 0; i < NUM_SOF_TIMESTAMPING_TYPES; i++) { 6683335640Shselasky if (info.so_timestamping & sof_ts_type_map[i].soft_timestamping_val) { 6684335640Shselasky handle->tstamp_type_list[j] = sof_ts_type_map[i].pcap_tstamp_val; 6685335640Shselasky j++; 6686335640Shselasky } 6687335640Shselasky } 6688335640Shselasky } else 6689335640Shselasky handle->tstamp_type_list = NULL; 6690335640Shselasky 6691335640Shselasky return 0; 6692335640Shselasky} 6693335640Shselasky#else /* ETHTOOL_GET_TS_INFO */ 6694335640Shselaskystatic int 6695335640Shselaskyiface_ethtool_get_ts_info(const char *device, pcap_t *handle, char *ebuf _U_) 6696335640Shselasky{ 6697335640Shselasky /* 6698335640Shselasky * This doesn't apply to the "any" device; you can't say "turn on 6699335640Shselasky * hardware time stamping for all devices that exist now and arrange 6700335640Shselasky * that it be turned on for any device that appears in the future", 6701335640Shselasky * and not all devices even necessarily *support* hardware time 6702335640Shselasky * stamping, so don't report any time stamp types. 6703335640Shselasky */ 6704335640Shselasky if (strcmp(device, "any") == 0) { 6705335640Shselasky handle->tstamp_type_list = NULL; 6706335640Shselasky return 0; 6707335640Shselasky } 6708335640Shselasky 6709335640Shselasky /* 6710335640Shselasky * We don't have an ioctl to use to ask what's supported, 6711335640Shselasky * so say we support everything. 6712335640Shselasky */ 6713335640Shselasky iface_set_all_ts_types(handle); 6714335640Shselasky return 0; 6715335640Shselasky} 6716335640Shselasky#endif /* ETHTOOL_GET_TS_INFO */ 6717335640Shselasky 6718335640Shselasky#endif /* defined(HAVE_LINUX_NET_TSTAMP_H) && defined(PACKET_TIMESTAMP) */ 6719335640Shselasky 6720335640Shselasky#ifdef HAVE_PACKET_RING 6721335640Shselasky/* 6722335640Shselasky * Find out if we have any form of fragmentation/reassembly offloading. 6723335640Shselasky * 6724335640Shselasky * We do so using SIOCETHTOOL checking for various types of offloading; 6725335640Shselasky * if SIOCETHTOOL isn't defined, or we don't have any #defines for any 6726335640Shselasky * of the types of offloading, there's nothing we can do to check, so 6727335640Shselasky * we just say "no, we don't". 6728356341Scy * 6729356341Scy * We treat EOPNOTSUPP, EINVAL and, if eperm_ok is true, EPERM as 6730356341Scy * indications that the operation isn't supported. We do EPERM 6731356341Scy * weirdly because the SIOCETHTOOL code in later kernels 1) doesn't 6732356341Scy * support ETHTOOL_GUFO, 2) also doesn't include it in the list 6733356341Scy * of ethtool operations that don't require CAP_NET_ADMIN privileges, 6734356341Scy * and 3) does the "is this permitted" check before doing the "is 6735356341Scy * this even supported" check, so it fails with "this is not permitted" 6736356341Scy * rather than "this is not even supported". To work around this 6737356341Scy * annoyance, we only treat EPERM as an error for the first feature, 6738356341Scy * and assume that they all do the same permission checks, so if the 6739356341Scy * first one is allowed all the others are allowed if supported. 6740335640Shselasky */ 6741335640Shselasky#if defined(SIOCETHTOOL) && (defined(ETHTOOL_GTSO) || defined(ETHTOOL_GUFO) || defined(ETHTOOL_GGSO) || defined(ETHTOOL_GFLAGS) || defined(ETHTOOL_GGRO)) 6742335640Shselaskystatic int 6743356341Scyiface_ethtool_flag_ioctl(pcap_t *handle, int cmd, const char *cmdname, 6744356341Scy int eperm_ok) 6745335640Shselasky{ 6746335640Shselasky struct ifreq ifr; 6747335640Shselasky struct ethtool_value eval; 6748335640Shselasky 6749335640Shselasky memset(&ifr, 0, sizeof(ifr)); 6750356341Scy pcap_strlcpy(ifr.ifr_name, handle->opt.device, sizeof(ifr.ifr_name)); 6751335640Shselasky eval.cmd = cmd; 6752335640Shselasky eval.data = 0; 6753335640Shselasky ifr.ifr_data = (caddr_t)&eval; 6754335640Shselasky if (ioctl(handle->fd, SIOCETHTOOL, &ifr) == -1) { 6755356341Scy if (errno == EOPNOTSUPP || errno == EINVAL || 6756356341Scy (errno == EPERM && eperm_ok)) { 6757335640Shselasky /* 6758335640Shselasky * OK, let's just return 0, which, in our 6759335640Shselasky * case, either means "no, what we're asking 6760335640Shselasky * about is not enabled" or "all the flags 6761335640Shselasky * are clear (i.e., nothing is enabled)". 6762335640Shselasky */ 6763335640Shselasky return 0; 6764335640Shselasky } 6765335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 6766335640Shselasky errno, "%s: SIOCETHTOOL(%s) ioctl failed", 6767335640Shselasky handle->opt.device, cmdname); 6768335640Shselasky return -1; 6769335640Shselasky } 6770335640Shselasky return eval.data; 6771335640Shselasky} 6772335640Shselasky 6773356341Scy/* 6774356341Scy * XXX - it's annoying that we have to check for offloading at all, but, 6775356341Scy * given that we have to, it's still annoying that we have to check for 6776356341Scy * particular types of offloading, especially that shiny new types of 6777356341Scy * offloading may be added - and, worse, may not be checkable with 6778356341Scy * a particular ETHTOOL_ operation; ETHTOOL_GFEATURES would, in 6779356341Scy * theory, give those to you, but the actual flags being used are 6780356341Scy * opaque (defined in a non-uapi header), and there doesn't seem to 6781356341Scy * be any obvious way to ask the kernel what all the offloading flags 6782356341Scy * are - at best, you can ask for a set of strings(!) to get *names* 6783356341Scy * for various flags. (That whole mechanism appears to have been 6784356341Scy * designed for the sole purpose of letting ethtool report flags 6785356341Scy * by name and set flags by name, with the names having no semantics 6786356341Scy * ethtool understands.) 6787356341Scy */ 6788335640Shselaskystatic int 6789335640Shselaskyiface_get_offload(pcap_t *handle) 6790335640Shselasky{ 6791335640Shselasky int ret; 6792335640Shselasky 6793335640Shselasky#ifdef ETHTOOL_GTSO 6794356341Scy ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GTSO, "ETHTOOL_GTSO", 0); 6795335640Shselasky if (ret == -1) 6796335640Shselasky return -1; 6797335640Shselasky if (ret) 6798335640Shselasky return 1; /* TCP segmentation offloading on */ 6799335640Shselasky#endif 6800335640Shselasky 6801335640Shselasky#ifdef ETHTOOL_GGSO 6802335640Shselasky /* 6803335640Shselasky * XXX - will this cause large unsegmented packets to be 6804335640Shselasky * handed to PF_PACKET sockets on transmission? If not, 6805335640Shselasky * this need not be checked. 6806335640Shselasky */ 6807356341Scy ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGSO, "ETHTOOL_GGSO", 0); 6808335640Shselasky if (ret == -1) 6809335640Shselasky return -1; 6810335640Shselasky if (ret) 6811335640Shselasky return 1; /* generic segmentation offloading on */ 6812335640Shselasky#endif 6813335640Shselasky 6814335640Shselasky#ifdef ETHTOOL_GFLAGS 6815356341Scy ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GFLAGS, "ETHTOOL_GFLAGS", 0); 6816335640Shselasky if (ret == -1) 6817335640Shselasky return -1; 6818335640Shselasky if (ret & ETH_FLAG_LRO) 6819335640Shselasky return 1; /* large receive offloading on */ 6820335640Shselasky#endif 6821335640Shselasky 6822335640Shselasky#ifdef ETHTOOL_GGRO 6823335640Shselasky /* 6824335640Shselasky * XXX - will this cause large reassembled packets to be 6825335640Shselasky * handed to PF_PACKET sockets on receipt? If not, 6826335640Shselasky * this need not be checked. 6827335640Shselasky */ 6828356341Scy ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GGRO, "ETHTOOL_GGRO", 0); 6829335640Shselasky if (ret == -1) 6830335640Shselasky return -1; 6831335640Shselasky if (ret) 6832335640Shselasky return 1; /* generic (large) receive offloading on */ 6833335640Shselasky#endif 6834335640Shselasky 6835356341Scy#ifdef ETHTOOL_GUFO 6836356341Scy /* 6837356341Scy * Do this one last, as support for it was removed in later 6838356341Scy * kernels, and it fails with EPERM on those kernels rather 6839356341Scy * than with EOPNOTSUPP (see explanation in comment for 6840356341Scy * iface_ethtool_flag_ioctl()). 6841356341Scy */ 6842356341Scy ret = iface_ethtool_flag_ioctl(handle, ETHTOOL_GUFO, "ETHTOOL_GUFO", 1); 6843356341Scy if (ret == -1) 6844356341Scy return -1; 6845356341Scy if (ret) 6846356341Scy return 1; /* UDP fragmentation offloading on */ 6847356341Scy#endif 6848356341Scy 6849335640Shselasky return 0; 6850335640Shselasky} 6851335640Shselasky#else /* SIOCETHTOOL */ 6852335640Shselaskystatic int 6853335640Shselaskyiface_get_offload(pcap_t *handle _U_) 6854335640Shselasky{ 6855335640Shselasky /* 6856335640Shselasky * XXX - do we need to get this information if we don't 6857335640Shselasky * have the ethtool ioctls? If so, how do we do that? 6858335640Shselasky */ 6859335640Shselasky return 0; 6860335640Shselasky} 6861335640Shselasky#endif /* SIOCETHTOOL */ 6862335640Shselasky 6863335640Shselasky#endif /* HAVE_PACKET_RING */ 6864335640Shselasky 6865335640Shselasky#endif /* HAVE_PF_PACKET_SOCKETS */ 6866335640Shselasky 6867335640Shselasky/* ===== Functions to interface to the older kernels ================== */ 6868335640Shselasky 6869335640Shselasky/* 6870335640Shselasky * Try to open a packet socket using the old kernel interface. 6871335640Shselasky * Returns 1 on success and a PCAP_ERROR_ value on an error. 6872335640Shselasky */ 6873335640Shselaskystatic int 6874335640Shselaskyactivate_old(pcap_t *handle) 6875335640Shselasky{ 6876335640Shselasky struct pcap_linux *handlep = handle->priv; 6877335640Shselasky int err; 6878335640Shselasky int arptype; 6879335640Shselasky struct ifreq ifr; 6880335640Shselasky const char *device = handle->opt.device; 6881335640Shselasky struct utsname utsname; 6882335640Shselasky int mtu; 6883335640Shselasky 6884356341Scy /* 6885356341Scy * PF_INET/SOCK_PACKET sockets must be bound to a device, so we 6886356341Scy * can't support the "any" device. 6887356341Scy */ 6888356341Scy if (strcmp(device, "any") == 0) { 6889356341Scy pcap_strlcpy(handle->errbuf, "pcap_activate: The \"any\" device isn't supported on 2.0[.x]-kernel systems", 6890356341Scy PCAP_ERRBUF_SIZE); 6891356341Scy return PCAP_ERROR; 6892356341Scy } 6893356341Scy 6894335640Shselasky /* Open the socket */ 6895335640Shselasky handle->fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_ALL)); 6896335640Shselasky if (handle->fd == -1) { 6897335640Shselasky err = errno; 6898335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 6899335640Shselasky err, "socket"); 6900335640Shselasky if (err == EPERM || err == EACCES) { 6901335640Shselasky /* 6902335640Shselasky * You don't have permission to open the 6903335640Shselasky * socket. 6904335640Shselasky */ 6905335640Shselasky return PCAP_ERROR_PERM_DENIED; 6906335640Shselasky } else { 6907335640Shselasky /* 6908335640Shselasky * Other error. 6909335640Shselasky */ 6910335640Shselasky return PCAP_ERROR; 6911335640Shselasky } 6912335640Shselasky } 6913335640Shselasky 6914335640Shselasky /* It worked - we are using the old interface */ 6915335640Shselasky handlep->sock_packet = 1; 6916335640Shselasky 6917335640Shselasky /* ...which means we get the link-layer header. */ 6918335640Shselasky handlep->cooked = 0; 6919335640Shselasky 6920335640Shselasky /* Bind to the given device */ 6921335640Shselasky if (iface_bind_old(handle->fd, device, handle->errbuf) == -1) 6922335640Shselasky return PCAP_ERROR; 6923335640Shselasky 6924335640Shselasky /* 6925335640Shselasky * Try to get the link-layer type. 6926335640Shselasky */ 6927335640Shselasky arptype = iface_get_arptype(handle->fd, device, handle->errbuf); 6928335640Shselasky if (arptype < 0) 6929335640Shselasky return PCAP_ERROR; 6930335640Shselasky 6931335640Shselasky /* 6932335640Shselasky * Try to find the DLT_ type corresponding to that 6933335640Shselasky * link-layer type. 6934335640Shselasky */ 6935335640Shselasky map_arphrd_to_dlt(handle, handle->fd, arptype, device, 0); 6936335640Shselasky if (handle->linktype == -1) { 6937335640Shselasky pcap_snprintf(handle->errbuf, PCAP_ERRBUF_SIZE, 6938335640Shselasky "unknown arptype %d", arptype); 6939335640Shselasky return PCAP_ERROR; 6940335640Shselasky } 6941335640Shselasky 6942335640Shselasky /* Go to promisc mode if requested */ 6943335640Shselasky 6944335640Shselasky if (handle->opt.promisc) { 6945335640Shselasky memset(&ifr, 0, sizeof(ifr)); 6946356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 6947335640Shselasky if (ioctl(handle->fd, SIOCGIFFLAGS, &ifr) == -1) { 6948335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6949335640Shselasky PCAP_ERRBUF_SIZE, errno, "SIOCGIFFLAGS"); 6950335640Shselasky return PCAP_ERROR; 6951335640Shselasky } 6952335640Shselasky if ((ifr.ifr_flags & IFF_PROMISC) == 0) { 6953335640Shselasky /* 6954335640Shselasky * Promiscuous mode isn't currently on, 6955335640Shselasky * so turn it on, and remember that 6956335640Shselasky * we should turn it off when the 6957335640Shselasky * pcap_t is closed. 6958335640Shselasky */ 6959335640Shselasky 6960335640Shselasky /* 6961335640Shselasky * If we haven't already done so, arrange 6962335640Shselasky * to have "pcap_close_all()" called when 6963335640Shselasky * we exit. 6964335640Shselasky */ 6965335640Shselasky if (!pcap_do_addexit(handle)) { 6966335640Shselasky /* 6967335640Shselasky * "atexit()" failed; don't put 6968335640Shselasky * the interface in promiscuous 6969335640Shselasky * mode, just give up. 6970335640Shselasky */ 6971335640Shselasky return PCAP_ERROR; 6972335640Shselasky } 6973335640Shselasky 6974335640Shselasky ifr.ifr_flags |= IFF_PROMISC; 6975335640Shselasky if (ioctl(handle->fd, SIOCSIFFLAGS, &ifr) == -1) { 6976335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 6977335640Shselasky PCAP_ERRBUF_SIZE, errno, "SIOCSIFFLAGS"); 6978335640Shselasky return PCAP_ERROR; 6979335640Shselasky } 6980335640Shselasky handlep->must_do_on_close |= MUST_CLEAR_PROMISC; 6981335640Shselasky 6982335640Shselasky /* 6983335640Shselasky * Add this to the list of pcaps 6984335640Shselasky * to close when we exit. 6985335640Shselasky */ 6986335640Shselasky pcap_add_to_pcaps_to_close(handle); 6987335640Shselasky } 6988335640Shselasky } 6989335640Shselasky 6990335640Shselasky /* 6991335640Shselasky * Compute the buffer size. 6992335640Shselasky * 6993335640Shselasky * We're using SOCK_PACKET, so this might be a 2.0[.x] 6994335640Shselasky * kernel, and might require special handling - check. 6995335640Shselasky */ 6996335640Shselasky if (uname(&utsname) < 0 || 6997335640Shselasky strncmp(utsname.release, "2.0", 3) == 0) { 6998335640Shselasky /* 6999335640Shselasky * Either we couldn't find out what kernel release 7000335640Shselasky * this is, or it's a 2.0[.x] kernel. 7001335640Shselasky * 7002335640Shselasky * In the 2.0[.x] kernel, a "recvfrom()" on 7003335640Shselasky * a SOCK_PACKET socket, with MSG_TRUNC set, will 7004335640Shselasky * return the number of bytes read, so if we pass 7005335640Shselasky * a length based on the snapshot length, it'll 7006335640Shselasky * return the number of bytes from the packet 7007335640Shselasky * copied to userland, not the actual length 7008335640Shselasky * of the packet. 7009335640Shselasky * 7010335640Shselasky * This means that, for example, the IP dissector 7011335640Shselasky * in tcpdump will get handed a packet length less 7012335640Shselasky * than the length in the IP header, and will 7013335640Shselasky * complain about "truncated-ip". 7014335640Shselasky * 7015335640Shselasky * So we don't bother trying to copy from the 7016335640Shselasky * kernel only the bytes in which we're interested, 7017335640Shselasky * but instead copy them all, just as the older 7018335640Shselasky * versions of libpcap for Linux did. 7019335640Shselasky * 7020335640Shselasky * The buffer therefore needs to be big enough to 7021335640Shselasky * hold the largest packet we can get from this 7022335640Shselasky * device. Unfortunately, we can't get the MRU 7023335640Shselasky * of the network; we can only get the MTU. The 7024335640Shselasky * MTU may be too small, in which case a packet larger 7025335640Shselasky * than the buffer size will be truncated *and* we 7026335640Shselasky * won't get the actual packet size. 7027335640Shselasky * 7028335640Shselasky * However, if the snapshot length is larger than 7029335640Shselasky * the buffer size based on the MTU, we use the 7030335640Shselasky * snapshot length as the buffer size, instead; 7031335640Shselasky * this means that with a sufficiently large snapshot 7032335640Shselasky * length we won't artificially truncate packets 7033335640Shselasky * to the MTU-based size. 7034335640Shselasky * 7035335640Shselasky * This mess just one of many problems with packet 7036335640Shselasky * capture on 2.0[.x] kernels; you really want a 7037335640Shselasky * 2.2[.x] or later kernel if you want packet capture 7038335640Shselasky * to work well. 7039335640Shselasky */ 7040335640Shselasky mtu = iface_get_mtu(handle->fd, device, handle->errbuf); 7041335640Shselasky if (mtu == -1) 7042335640Shselasky return PCAP_ERROR; 7043335640Shselasky handle->bufsize = MAX_LINKHEADER_SIZE + mtu; 7044335640Shselasky if (handle->bufsize < (u_int)handle->snapshot) 7045335640Shselasky handle->bufsize = (u_int)handle->snapshot; 7046335640Shselasky } else { 7047335640Shselasky /* 7048335640Shselasky * This is a 2.2[.x] or later kernel. 7049335640Shselasky * 7050335640Shselasky * We can safely pass "recvfrom()" a byte count 7051335640Shselasky * based on the snapshot length. 7052356341Scy * 7053356341Scy * XXX - this "should not happen", as 2.2[.x] 7054356341Scy * kernels all have PF_PACKET sockets, and there's 7055356341Scy * no configuration option to disable them without 7056356341Scy * disabling SOCK_PACKET sockets, because 7057356341Scy * SOCK_PACKET sockets are implemented in the same 7058356341Scy * source file, net/packet/af_packet.c. There *is* 7059356341Scy * an option to disable SOCK_PACKET sockets so that 7060356341Scy * you only have PF_PACKET sockets, and the kernel 7061356341Scy * will log warning messages for code that uses 7062356341Scy * "obsolete (PF_INET,SOCK_PACKET)". 7063335640Shselasky */ 7064335640Shselasky handle->bufsize = (u_int)handle->snapshot; 7065335640Shselasky } 7066335640Shselasky 7067335640Shselasky /* 7068335640Shselasky * Default value for offset to align link-layer payload 7069335640Shselasky * on a 4-byte boundary. 7070335640Shselasky */ 7071335640Shselasky handle->offset = 0; 7072335640Shselasky 7073335640Shselasky /* 7074335640Shselasky * SOCK_PACKET sockets don't supply information from 7075335640Shselasky * stripped VLAN tags. 7076335640Shselasky */ 7077335640Shselasky handlep->vlan_offset = -1; /* unknown */ 7078335640Shselasky 7079335640Shselasky return 1; 7080335640Shselasky} 7081335640Shselasky 7082335640Shselasky/* 7083335640Shselasky * Bind the socket associated with FD to the given device using the 7084335640Shselasky * interface of the old kernels. 7085335640Shselasky */ 7086335640Shselaskystatic int 7087335640Shselaskyiface_bind_old(int fd, const char *device, char *ebuf) 7088335640Shselasky{ 7089335640Shselasky struct sockaddr saddr; 7090335640Shselasky int err; 7091335640Shselasky socklen_t errlen = sizeof(err); 7092335640Shselasky 7093335640Shselasky memset(&saddr, 0, sizeof(saddr)); 7094356341Scy pcap_strlcpy(saddr.sa_data, device, sizeof(saddr.sa_data)); 7095335640Shselasky if (bind(fd, &saddr, sizeof(saddr)) == -1) { 7096335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 7097335640Shselasky errno, "bind"); 7098335640Shselasky return -1; 7099335640Shselasky } 7100335640Shselasky 7101335640Shselasky /* Any pending errors, e.g., network is down? */ 7102335640Shselasky 7103335640Shselasky if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &err, &errlen) == -1) { 7104335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 7105356341Scy errno, "getsockopt (SO_ERROR)"); 7106335640Shselasky return -1; 7107335640Shselasky } 7108335640Shselasky 7109335640Shselasky if (err > 0) { 7110335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 7111335640Shselasky err, "bind"); 7112335640Shselasky return -1; 7113335640Shselasky } 7114335640Shselasky 7115335640Shselasky return 0; 7116335640Shselasky} 7117335640Shselasky 7118335640Shselasky 7119335640Shselasky/* ===== System calls available on all supported kernels ============== */ 7120335640Shselasky 7121335640Shselasky/* 7122335640Shselasky * Query the kernel for the MTU of the given interface. 7123335640Shselasky */ 7124335640Shselaskystatic int 7125335640Shselaskyiface_get_mtu(int fd, const char *device, char *ebuf) 7126335640Shselasky{ 7127335640Shselasky struct ifreq ifr; 7128335640Shselasky 7129335640Shselasky if (!device) 7130335640Shselasky return BIGGER_THAN_ALL_MTUS; 7131335640Shselasky 7132335640Shselasky memset(&ifr, 0, sizeof(ifr)); 7133356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 7134335640Shselasky 7135335640Shselasky if (ioctl(fd, SIOCGIFMTU, &ifr) == -1) { 7136335640Shselasky pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 7137335640Shselasky errno, "SIOCGIFMTU"); 7138335640Shselasky return -1; 7139335640Shselasky } 7140335640Shselasky 7141335640Shselasky return ifr.ifr_mtu; 7142335640Shselasky} 7143335640Shselasky 7144335640Shselasky/* 7145335640Shselasky * Get the hardware type of the given interface as ARPHRD_xxx constant. 7146335640Shselasky */ 7147335640Shselaskystatic int 7148335640Shselaskyiface_get_arptype(int fd, const char *device, char *ebuf) 7149335640Shselasky{ 7150335640Shselasky struct ifreq ifr; 7151356341Scy int ret; 7152335640Shselasky 7153335640Shselasky memset(&ifr, 0, sizeof(ifr)); 7154356341Scy pcap_strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 7155335640Shselasky 7156335640Shselasky if (ioctl(fd, SIOCGIFHWADDR, &ifr) == -1) { 7157335640Shselasky if (errno == ENODEV) { 7158335640Shselasky /* 7159335640Shselasky * No such device. 7160335640Shselasky */ 7161356341Scy ret = PCAP_ERROR_NO_SUCH_DEVICE; 7162356341Scy } else 7163356341Scy ret = PCAP_ERROR; 7164356341Scy pcap_fmt_errmsg_for_errno(ebuf, PCAP_ERRBUF_SIZE, 7165356341Scy errno, "SIOCGIFHWADDR"); 7166356341Scy return ret; 7167335640Shselasky } 7168335640Shselasky 7169335640Shselasky return ifr.ifr_hwaddr.sa_family; 7170335640Shselasky} 7171335640Shselasky 7172335640Shselasky#ifdef SO_ATTACH_FILTER 7173335640Shselaskystatic int 7174335640Shselaskyfix_program(pcap_t *handle, struct sock_fprog *fcode, int is_mmapped) 7175335640Shselasky{ 7176335640Shselasky struct pcap_linux *handlep = handle->priv; 7177335640Shselasky size_t prog_size; 7178335640Shselasky register int i; 7179335640Shselasky register struct bpf_insn *p; 7180335640Shselasky struct bpf_insn *f; 7181335640Shselasky int len; 7182335640Shselasky 7183335640Shselasky /* 7184335640Shselasky * Make a copy of the filter, and modify that copy if 7185335640Shselasky * necessary. 7186335640Shselasky */ 7187335640Shselasky prog_size = sizeof(*handle->fcode.bf_insns) * handle->fcode.bf_len; 7188335640Shselasky len = handle->fcode.bf_len; 7189335640Shselasky f = (struct bpf_insn *)malloc(prog_size); 7190335640Shselasky if (f == NULL) { 7191335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, PCAP_ERRBUF_SIZE, 7192335640Shselasky errno, "malloc"); 7193335640Shselasky return -1; 7194335640Shselasky } 7195335640Shselasky memcpy(f, handle->fcode.bf_insns, prog_size); 7196335640Shselasky fcode->len = len; 7197335640Shselasky fcode->filter = (struct sock_filter *) f; 7198335640Shselasky 7199335640Shselasky for (i = 0; i < len; ++i) { 7200335640Shselasky p = &f[i]; 7201335640Shselasky /* 7202335640Shselasky * What type of instruction is this? 7203335640Shselasky */ 7204335640Shselasky switch (BPF_CLASS(p->code)) { 7205335640Shselasky 7206335640Shselasky case BPF_RET: 7207335640Shselasky /* 7208335640Shselasky * It's a return instruction; are we capturing 7209335640Shselasky * in memory-mapped mode? 7210335640Shselasky */ 7211335640Shselasky if (!is_mmapped) { 7212335640Shselasky /* 7213335640Shselasky * No; is the snapshot length a constant, 7214335640Shselasky * rather than the contents of the 7215335640Shselasky * accumulator? 7216335640Shselasky */ 7217335640Shselasky if (BPF_MODE(p->code) == BPF_K) { 7218335640Shselasky /* 7219335640Shselasky * Yes - if the value to be returned, 7220335640Shselasky * i.e. the snapshot length, is 7221335640Shselasky * anything other than 0, make it 7222335640Shselasky * MAXIMUM_SNAPLEN, so that the packet 7223335640Shselasky * is truncated by "recvfrom()", 7224335640Shselasky * not by the filter. 7225335640Shselasky * 7226335640Shselasky * XXX - there's nothing we can 7227335640Shselasky * easily do if it's getting the 7228335640Shselasky * value from the accumulator; we'd 7229335640Shselasky * have to insert code to force 7230335640Shselasky * non-zero values to be 7231335640Shselasky * MAXIMUM_SNAPLEN. 7232335640Shselasky */ 7233335640Shselasky if (p->k != 0) 7234335640Shselasky p->k = MAXIMUM_SNAPLEN; 7235335640Shselasky } 7236335640Shselasky } 7237335640Shselasky break; 7238335640Shselasky 7239335640Shselasky case BPF_LD: 7240335640Shselasky case BPF_LDX: 7241335640Shselasky /* 7242335640Shselasky * It's a load instruction; is it loading 7243335640Shselasky * from the packet? 7244335640Shselasky */ 7245335640Shselasky switch (BPF_MODE(p->code)) { 7246335640Shselasky 7247335640Shselasky case BPF_ABS: 7248335640Shselasky case BPF_IND: 7249335640Shselasky case BPF_MSH: 7250335640Shselasky /* 7251335640Shselasky * Yes; are we in cooked mode? 7252335640Shselasky */ 7253335640Shselasky if (handlep->cooked) { 7254335640Shselasky /* 7255335640Shselasky * Yes, so we need to fix this 7256335640Shselasky * instruction. 7257335640Shselasky */ 7258356341Scy if (fix_offset(handle, p) < 0) { 7259335640Shselasky /* 7260335640Shselasky * We failed to do so. 7261335640Shselasky * Return 0, so our caller 7262335640Shselasky * knows to punt to userland. 7263335640Shselasky */ 7264335640Shselasky return 0; 7265335640Shselasky } 7266335640Shselasky } 7267335640Shselasky break; 7268335640Shselasky } 7269335640Shselasky break; 7270335640Shselasky } 7271335640Shselasky } 7272335640Shselasky return 1; /* we succeeded */ 7273335640Shselasky} 7274335640Shselasky 7275335640Shselaskystatic int 7276356341Scyfix_offset(pcap_t *handle, struct bpf_insn *p) 7277335640Shselasky{ 7278335640Shselasky /* 7279356341Scy * Existing references to auxiliary data shouldn't be adjusted. 7280356341Scy * 7281356341Scy * Note that SKF_AD_OFF is negative, but p->k is unsigned, so 7282356341Scy * we use >= and cast SKF_AD_OFF to unsigned. 7283335640Shselasky */ 7284356341Scy if (p->k >= (bpf_u_int32)SKF_AD_OFF) 7285356341Scy return 0; 7286356341Scy if (handle->linktype == DLT_LINUX_SLL2) { 7287335640Shselasky /* 7288356341Scy * What's the offset? 7289335640Shselasky */ 7290356341Scy if (p->k >= SLL2_HDR_LEN) { 7291356341Scy /* 7292356341Scy * It's within the link-layer payload; that starts 7293356341Scy * at an offset of 0, as far as the kernel packet 7294356341Scy * filter is concerned, so subtract the length of 7295356341Scy * the link-layer header. 7296356341Scy */ 7297356341Scy p->k -= SLL2_HDR_LEN; 7298356341Scy } else if (p->k == 0) { 7299356341Scy /* 7300356341Scy * It's the protocol field; map it to the 7301356341Scy * special magic kernel offset for that field. 7302356341Scy */ 7303356341Scy p->k = SKF_AD_OFF + SKF_AD_PROTOCOL; 7304356341Scy } else if (p->k == 10) { 7305356341Scy /* 7306356341Scy * It's the packet type field; map it to the 7307356341Scy * special magic kernel offset for that field. 7308356341Scy */ 7309356341Scy p->k = SKF_AD_OFF + SKF_AD_PKTTYPE; 7310356341Scy } else if ((bpf_int32)(p->k) > 0) { 7311356341Scy /* 7312356341Scy * It's within the header, but it's not one of 7313356341Scy * those fields; we can't do that in the kernel, 7314356341Scy * so punt to userland. 7315356341Scy */ 7316356341Scy return -1; 7317356341Scy } 7318356341Scy } else { 7319335640Shselasky /* 7320356341Scy * What's the offset? 7321335640Shselasky */ 7322356341Scy if (p->k >= SLL_HDR_LEN) { 7323356341Scy /* 7324356341Scy * It's within the link-layer payload; that starts 7325356341Scy * at an offset of 0, as far as the kernel packet 7326356341Scy * filter is concerned, so subtract the length of 7327356341Scy * the link-layer header. 7328356341Scy */ 7329356341Scy p->k -= SLL_HDR_LEN; 7330356341Scy } else if (p->k == 0) { 7331356341Scy /* 7332356341Scy * It's the packet type field; map it to the 7333356341Scy * special magic kernel offset for that field. 7334356341Scy */ 7335356341Scy p->k = SKF_AD_OFF + SKF_AD_PKTTYPE; 7336356341Scy } else if (p->k == 14) { 7337356341Scy /* 7338356341Scy * It's the protocol field; map it to the 7339356341Scy * special magic kernel offset for that field. 7340356341Scy */ 7341356341Scy p->k = SKF_AD_OFF + SKF_AD_PROTOCOL; 7342356341Scy } else if ((bpf_int32)(p->k) > 0) { 7343356341Scy /* 7344356341Scy * It's within the header, but it's not one of 7345356341Scy * those fields; we can't do that in the kernel, 7346356341Scy * so punt to userland. 7347356341Scy */ 7348356341Scy return -1; 7349356341Scy } 7350335640Shselasky } 7351335640Shselasky return 0; 7352335640Shselasky} 7353335640Shselasky 7354335640Shselaskystatic int 7355335640Shselaskyset_kernel_filter(pcap_t *handle, struct sock_fprog *fcode) 7356335640Shselasky{ 7357335640Shselasky int total_filter_on = 0; 7358335640Shselasky int save_mode; 7359335640Shselasky int ret; 7360335640Shselasky int save_errno; 7361335640Shselasky 7362335640Shselasky /* 7363335640Shselasky * The socket filter code doesn't discard all packets queued 7364335640Shselasky * up on the socket when the filter is changed; this means 7365335640Shselasky * that packets that don't match the new filter may show up 7366335640Shselasky * after the new filter is put onto the socket, if those 7367335640Shselasky * packets haven't yet been read. 7368335640Shselasky * 7369335640Shselasky * This means, for example, that if you do a tcpdump capture 7370335640Shselasky * with a filter, the first few packets in the capture might 7371335640Shselasky * be packets that wouldn't have passed the filter. 7372335640Shselasky * 7373335640Shselasky * We therefore discard all packets queued up on the socket 7374335640Shselasky * when setting a kernel filter. (This isn't an issue for 7375335640Shselasky * userland filters, as the userland filtering is done after 7376335640Shselasky * packets are queued up.) 7377335640Shselasky * 7378335640Shselasky * To flush those packets, we put the socket in read-only mode, 7379335640Shselasky * and read packets from the socket until there are no more to 7380335640Shselasky * read. 7381335640Shselasky * 7382335640Shselasky * In order to keep that from being an infinite loop - i.e., 7383335640Shselasky * to keep more packets from arriving while we're draining 7384335640Shselasky * the queue - we put the "total filter", which is a filter 7385335640Shselasky * that rejects all packets, onto the socket before draining 7386335640Shselasky * the queue. 7387335640Shselasky * 7388335640Shselasky * This code deliberately ignores any errors, so that you may 7389335640Shselasky * get bogus packets if an error occurs, rather than having 7390335640Shselasky * the filtering done in userland even if it could have been 7391335640Shselasky * done in the kernel. 7392335640Shselasky */ 7393335640Shselasky if (setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, 7394335640Shselasky &total_fcode, sizeof(total_fcode)) == 0) { 7395335640Shselasky char drain[1]; 7396335640Shselasky 7397335640Shselasky /* 7398335640Shselasky * Note that we've put the total filter onto the socket. 7399335640Shselasky */ 7400335640Shselasky total_filter_on = 1; 7401335640Shselasky 7402335640Shselasky /* 7403335640Shselasky * Save the socket's current mode, and put it in 7404335640Shselasky * non-blocking mode; we drain it by reading packets 7405335640Shselasky * until we get an error (which is normally a 7406335640Shselasky * "nothing more to be read" error). 7407335640Shselasky */ 7408335640Shselasky save_mode = fcntl(handle->fd, F_GETFL, 0); 7409335640Shselasky if (save_mode == -1) { 7410335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 7411335640Shselasky PCAP_ERRBUF_SIZE, errno, 7412335640Shselasky "can't get FD flags when changing filter"); 7413335640Shselasky return -2; 7414335640Shselasky } 7415335640Shselasky if (fcntl(handle->fd, F_SETFL, save_mode | O_NONBLOCK) < 0) { 7416335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 7417335640Shselasky PCAP_ERRBUF_SIZE, errno, 7418335640Shselasky "can't set nonblocking mode when changing filter"); 7419335640Shselasky return -2; 7420335640Shselasky } 7421335640Shselasky while (recv(handle->fd, &drain, sizeof drain, MSG_TRUNC) >= 0) 7422335640Shselasky ; 7423335640Shselasky save_errno = errno; 7424335640Shselasky if (save_errno != EAGAIN) { 7425335640Shselasky /* 7426335640Shselasky * Fatal error. 7427335640Shselasky * 7428335640Shselasky * If we can't restore the mode or reset the 7429335640Shselasky * kernel filter, there's nothing we can do. 7430335640Shselasky */ 7431335640Shselasky (void)fcntl(handle->fd, F_SETFL, save_mode); 7432335640Shselasky (void)reset_kernel_filter(handle); 7433335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 7434335640Shselasky PCAP_ERRBUF_SIZE, save_errno, 7435335640Shselasky "recv failed when changing filter"); 7436335640Shselasky return -2; 7437335640Shselasky } 7438335640Shselasky if (fcntl(handle->fd, F_SETFL, save_mode) == -1) { 7439335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 7440335640Shselasky PCAP_ERRBUF_SIZE, errno, 7441335640Shselasky "can't restore FD flags when changing filter"); 7442335640Shselasky return -2; 7443335640Shselasky } 7444335640Shselasky } 7445335640Shselasky 7446335640Shselasky /* 7447335640Shselasky * Now attach the new filter. 7448335640Shselasky */ 7449335640Shselasky ret = setsockopt(handle->fd, SOL_SOCKET, SO_ATTACH_FILTER, 7450335640Shselasky fcode, sizeof(*fcode)); 7451335640Shselasky if (ret == -1 && total_filter_on) { 7452335640Shselasky /* 7453335640Shselasky * Well, we couldn't set that filter on the socket, 7454335640Shselasky * but we could set the total filter on the socket. 7455335640Shselasky * 7456335640Shselasky * This could, for example, mean that the filter was 7457335640Shselasky * too big to put into the kernel, so we'll have to 7458335640Shselasky * filter in userland; in any case, we'll be doing 7459335640Shselasky * filtering in userland, so we need to remove the 7460335640Shselasky * total filter so we see packets. 7461335640Shselasky */ 7462335640Shselasky save_errno = errno; 7463335640Shselasky 7464335640Shselasky /* 7465335640Shselasky * If this fails, we're really screwed; we have the 7466335640Shselasky * total filter on the socket, and it won't come off. 7467335640Shselasky * Report it as a fatal error. 7468335640Shselasky */ 7469335640Shselasky if (reset_kernel_filter(handle) == -1) { 7470335640Shselasky pcap_fmt_errmsg_for_errno(handle->errbuf, 7471335640Shselasky PCAP_ERRBUF_SIZE, errno, 7472335640Shselasky "can't remove kernel total filter"); 7473335640Shselasky return -2; /* fatal error */ 7474335640Shselasky } 7475335640Shselasky 7476335640Shselasky errno = save_errno; 7477335640Shselasky } 7478335640Shselasky return ret; 7479335640Shselasky} 7480335640Shselasky 7481335640Shselaskystatic int 7482335640Shselaskyreset_kernel_filter(pcap_t *handle) 7483335640Shselasky{ 7484335640Shselasky int ret; 7485335640Shselasky /* 7486335640Shselasky * setsockopt() barfs unless it get a dummy parameter. 7487335640Shselasky * valgrind whines unless the value is initialized, 7488335640Shselasky * as it has no idea that setsockopt() ignores its 7489335640Shselasky * parameter. 7490335640Shselasky */ 7491335640Shselasky int dummy = 0; 7492335640Shselasky 7493335640Shselasky ret = setsockopt(handle->fd, SOL_SOCKET, SO_DETACH_FILTER, 7494335640Shselasky &dummy, sizeof(dummy)); 7495335640Shselasky /* 7496335640Shselasky * Ignore ENOENT - it means "we don't have a filter", so there 7497335640Shselasky * was no filter to remove, and there's still no filter. 7498335640Shselasky * 7499335640Shselasky * Also ignore ENONET, as a lot of kernel versions had a 7500335640Shselasky * typo where ENONET, rather than ENOENT, was returned. 7501335640Shselasky */ 7502335640Shselasky if (ret == -1 && errno != ENOENT && errno != ENONET) 7503335640Shselasky return -1; 7504335640Shselasky return 0; 7505335640Shselasky} 7506335640Shselasky#endif 7507335640Shselasky 7508335640Shselaskyint 7509356341Scypcap_set_protocol_linux(pcap_t *p, int protocol) 7510335640Shselasky{ 7511335640Shselasky if (pcap_check_activated(p)) 7512335640Shselasky return (PCAP_ERROR_ACTIVATED); 7513335640Shselasky p->opt.protocol = protocol; 7514335640Shselasky return (0); 7515335640Shselasky} 7516335640Shselasky 7517335640Shselasky/* 7518335640Shselasky * Libpcap version string. 7519335640Shselasky */ 7520335640Shselaskyconst char * 7521335640Shselaskypcap_lib_version(void) 7522335640Shselasky{ 7523335640Shselasky#ifdef HAVE_PACKET_RING 7524335640Shselasky #if defined(HAVE_TPACKET3) 7525335640Shselasky return (PCAP_VERSION_STRING " (with TPACKET_V3)"); 7526335640Shselasky #elif defined(HAVE_TPACKET2) 7527335640Shselasky return (PCAP_VERSION_STRING " (with TPACKET_V2)"); 7528335640Shselasky #else 7529335640Shselasky return (PCAP_VERSION_STRING " (with TPACKET_V1)"); 7530335640Shselasky #endif 7531335640Shselasky#else 7532335640Shselasky return (PCAP_VERSION_STRING " (without TPACKET)"); 7533335640Shselasky#endif 7534335640Shselasky} 7535