pcap-pf.c revision 147894
117683Spst/* 217683Spst * Copyright (c) 1990, 1991, 1992, 1993, 1994, 1995, 1996 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that: (1) source code distributions 717683Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817683Spst * distributions including binary code include the above copyright notice and 917683Spst * this paragraph in its entirety in the documentation or other materials 1017683Spst * provided with the distribution, and (3) all advertising materials mentioning 1117683Spst * features or use of this software display the following acknowledgement: 1217683Spst * ``This product includes software developed by the University of California, 1317683Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417683Spst * the University nor the names of its contributors may be used to endorse 1517683Spst * or promote products derived from this software without specific prior 1617683Spst * written permission. 1717683Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817683Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917683Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2026175Sfenner * 2126175Sfenner * packet filter subroutines for tcpdump 2226175Sfenner * Extraction/creation by Jeffrey Mogul, DECWRL 2317683Spst */ 2426175Sfenner 2517683Spst#ifndef lint 26127664Sbmsstatic const char rcsid[] _U_ = 27147894Ssam "@(#) $Header: /tcpdump/master/libpcap/pcap-pf.c,v 1.91.2.2 2005/05/03 18:54:37 guy Exp $ (LBL)"; 2817683Spst#endif 2917683Spst 3075107Sfenner#ifdef HAVE_CONFIG_H 3175107Sfenner#include "config.h" 3275107Sfenner#endif 3375107Sfenner 3417683Spst#include <sys/types.h> 3517683Spst#include <sys/time.h> 3617683Spst#include <sys/timeb.h> 3717683Spst#include <sys/socket.h> 3817683Spst#include <sys/file.h> 3917683Spst#include <sys/ioctl.h> 4017683Spst#include <net/pfilt.h> 4117683Spst 4217683Spststruct mbuf; 4317683Spststruct rtentry; 4417683Spst#include <net/if.h> 4517683Spst 4617683Spst#include <netinet/in.h> 4717683Spst#include <netinet/in_systm.h> 4817683Spst#include <netinet/ip.h> 4917683Spst#include <netinet/if_ether.h> 5017683Spst#include <netinet/ip_var.h> 5117683Spst#include <netinet/udp.h> 5217683Spst#include <netinet/udp_var.h> 5317683Spst#include <netinet/tcp.h> 5417683Spst#include <netinet/tcpip.h> 5517683Spst 5617683Spst#include <ctype.h> 5717683Spst#include <errno.h> 5817683Spst#include <netdb.h> 5917683Spst#include <stdio.h> 6017683Spst#include <stdlib.h> 6117683Spst#include <string.h> 6217683Spst#include <unistd.h> 6317683Spst 64127664Sbms/* 65127664Sbms * Make "pcap.h" not include "pcap-bpf.h"; we are going to include the 66127664Sbms * native OS version, as we need various BPF ioctls from it. 67127664Sbms */ 68127664Sbms#define PCAP_DONT_INCLUDE_PCAP_BPF_H 69127664Sbms#include <net/bpf.h> 70127664Sbms 7117683Spst#include "pcap-int.h" 7217683Spst 7317683Spst#ifdef HAVE_OS_PROTO_H 7417683Spst#include "os-proto.h" 7517683Spst#endif 7617683Spst 77127664Sbmsstatic int pcap_setfilter_pf(pcap_t *, struct bpf_program *); 78127664Sbms 7917683Spst/* 8017683Spst * BUFSPACE is the size in bytes of the packet read buffer. Most tcpdump 8117683Spst * applications aren't going to need more than 200 bytes of packet header 8217683Spst * and the read shouldn't return more packets than packetfilter's internal 8317683Spst * queue limit (bounded at 256). 8417683Spst */ 8517683Spst#define BUFSPACE (200 * 256) 8617683Spst 87127664Sbmsstatic int 88127664Sbmspcap_read_pf(pcap_t *pc, int cnt, pcap_handler callback, u_char *user) 8917683Spst{ 9017683Spst register u_char *p, *bp; 9117683Spst struct bpf_insn *fcode; 9217683Spst register int cc, n, buflen, inc; 9317683Spst register struct enstamp *sp; 9417683Spst#ifdef LBL_ALIGN 9517683Spst struct enstamp stamp; 9617683Spst#endif 9717683Spst#ifdef PCAP_FDDIPAD 9817683Spst register int pad; 9917683Spst#endif 10017683Spst 10117683Spst fcode = pc->md.use_bpf ? NULL : pc->fcode.bf_insns; 10217683Spst again: 10317683Spst cc = pc->cc; 10417683Spst if (cc == 0) { 10517683Spst cc = read(pc->fd, (char *)pc->buffer + pc->offset, pc->bufsize); 10617683Spst if (cc < 0) { 10717683Spst if (errno == EWOULDBLOCK) 10817683Spst return (0); 10917683Spst if (errno == EINVAL && 11017683Spst lseek(pc->fd, 0L, SEEK_CUR) + pc->bufsize < 0) { 11117683Spst /* 11217683Spst * Due to a kernel bug, after 2^31 bytes, 11317683Spst * the kernel file offset overflows and 11417683Spst * read fails with EINVAL. The lseek() 11517683Spst * to 0 will fix things. 11617683Spst */ 11717683Spst (void)lseek(pc->fd, 0L, SEEK_SET); 11817683Spst goto again; 11917683Spst } 12075107Sfenner snprintf(pc->errbuf, sizeof(pc->errbuf), "pf read: %s", 12117683Spst pcap_strerror(errno)); 12217683Spst return (-1); 12317683Spst } 12417683Spst bp = pc->buffer + pc->offset; 12517683Spst } else 12617683Spst bp = pc->bp; 12717683Spst /* 12817683Spst * Loop through each packet. 12917683Spst */ 13017683Spst n = 0; 13117683Spst#ifdef PCAP_FDDIPAD 132147894Ssam pad = pc->fddipad; 13317683Spst#endif 13417683Spst while (cc > 0) { 135127664Sbms /* 136127664Sbms * Has "pcap_breakloop()" been called? 137127664Sbms * If so, return immediately - if we haven't read any 138127664Sbms * packets, clear the flag and return -2 to indicate 139127664Sbms * that we were told to break out of the loop, otherwise 140127664Sbms * leave the flag set, so that the *next* call will break 141127664Sbms * out of the loop without having read any packets, and 142127664Sbms * return the number of packets we've processed so far. 143127664Sbms */ 144127664Sbms if (pc->break_loop) { 145127664Sbms if (n == 0) { 146127664Sbms pc->break_loop = 0; 147127664Sbms return (-2); 148127664Sbms } else { 149127664Sbms pc->cc = cc; 150127664Sbms pc->bp = bp; 151127664Sbms return (n); 152127664Sbms } 153127664Sbms } 15417683Spst if (cc < sizeof(*sp)) { 15575107Sfenner snprintf(pc->errbuf, sizeof(pc->errbuf), 15675107Sfenner "pf short read (%d)", cc); 15717683Spst return (-1); 15817683Spst } 15917683Spst#ifdef LBL_ALIGN 16017683Spst if ((long)bp & 3) { 16117683Spst sp = &stamp; 16217683Spst memcpy((char *)sp, (char *)bp, sizeof(*sp)); 16317683Spst } else 16417683Spst#endif 16517683Spst sp = (struct enstamp *)bp; 16617683Spst if (sp->ens_stamplen != sizeof(*sp)) { 16775107Sfenner snprintf(pc->errbuf, sizeof(pc->errbuf), 16875107Sfenner "pf short stamplen (%d)", 16917683Spst sp->ens_stamplen); 17017683Spst return (-1); 17117683Spst } 17217683Spst 17317683Spst p = bp + sp->ens_stamplen; 17417683Spst buflen = sp->ens_count; 17517683Spst if (buflen > pc->snapshot) 17617683Spst buflen = pc->snapshot; 17717683Spst 17817683Spst /* Calculate inc before possible pad update */ 17917683Spst inc = ENALIGN(buflen + sp->ens_stamplen); 18017683Spst cc -= inc; 18117683Spst bp += inc; 18217683Spst pc->md.TotPkts++; 18317683Spst pc->md.TotDrops += sp->ens_dropped; 18417683Spst pc->md.TotMissed = sp->ens_ifoverflows; 18517683Spst if (pc->md.OrigMissed < 0) 18617683Spst pc->md.OrigMissed = pc->md.TotMissed; 18717683Spst 18817683Spst /* 18917683Spst * Short-circuit evaluation: if using BPF filter 19017683Spst * in kernel, no need to do it now. 191146768Ssam * 192146768Ssam#ifdef PCAP_FDDIPAD 193146768Ssam * Note: the filter code was generated assuming 194147894Ssam * that pc->fddipad was the amount of padding 195146768Ssam * before the header, as that's what's required 196146768Ssam * in the kernel, so we run the filter before 197146768Ssam * skipping that padding. 198146768Ssam#endif 19917683Spst */ 20017683Spst if (fcode == NULL || 20117683Spst bpf_filter(fcode, p, sp->ens_count, buflen)) { 20217683Spst struct pcap_pkthdr h; 20317683Spst pc->md.TotAccepted++; 20417683Spst h.ts = sp->ens_tstamp; 20517683Spst#ifdef PCAP_FDDIPAD 20617683Spst h.len = sp->ens_count - pad; 20717683Spst#else 20817683Spst h.len = sp->ens_count; 20917683Spst#endif 210146768Ssam#ifdef PCAP_FDDIPAD 211146768Ssam p += pad; 212146768Ssam buflen -= pad; 213146768Ssam#endif 21417683Spst h.caplen = buflen; 21517683Spst (*callback)(user, &h, p); 21617683Spst if (++n >= cnt && cnt > 0) { 21717683Spst pc->cc = cc; 21817683Spst pc->bp = bp; 21917683Spst return (n); 22017683Spst } 22117683Spst } 22217683Spst } 22317683Spst pc->cc = 0; 22417683Spst return (n); 22517683Spst} 22617683Spst 227127664Sbmsstatic int 228146768Ssampcap_inject_pf(pcap_t *p, const void *buf, size_t size) 229146768Ssam{ 230146768Ssam int ret; 231146768Ssam 232146768Ssam ret = write(p->fd, buf, size); 233146768Ssam if (ret == -1) { 234146768Ssam snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "send: %s", 235146768Ssam pcap_strerror(errno)); 236146768Ssam return (-1); 237146768Ssam } 238146768Ssam return (ret); 239146768Ssam} 240146768Ssam 241146768Ssamstatic int 242127664Sbmspcap_stats_pf(pcap_t *p, struct pcap_stat *ps) 24317683Spst{ 24417683Spst 24598530Sfenner /* 24698530Sfenner * If packet filtering is being done in the kernel: 24798530Sfenner * 24898530Sfenner * "ps_recv" counts only packets that passed the filter. 24998530Sfenner * This does not include packets dropped because we 25098530Sfenner * ran out of buffer space. (XXX - perhaps it should, 25198530Sfenner * by adding "ps_drop" to "ps_recv", for compatibility 25298530Sfenner * with some other platforms. On the other hand, on 25398530Sfenner * some platforms "ps_recv" counts only packets that 25498530Sfenner * passed the filter, and on others it counts packets 25598530Sfenner * that didn't pass the filter....) 25698530Sfenner * 25798530Sfenner * "ps_drop" counts packets that passed the kernel filter 25898530Sfenner * (if any) but were dropped because the input queue was 25998530Sfenner * full. 26098530Sfenner * 26198530Sfenner * "ps_ifdrop" counts packets dropped by the network 26298530Sfenner * inteface (regardless of whether they would have passed 26398530Sfenner * the input filter, of course). 26498530Sfenner * 26598530Sfenner * If packet filtering is not being done in the kernel: 26698530Sfenner * 26798530Sfenner * "ps_recv" counts only packets that passed the filter. 26898530Sfenner * 26998530Sfenner * "ps_drop" counts packets that were dropped because the 27098530Sfenner * input queue was full, regardless of whether they passed 27198530Sfenner * the userland filter. 27298530Sfenner * 27398530Sfenner * "ps_ifdrop" counts packets dropped by the network 27498530Sfenner * inteface (regardless of whether they would have passed 27598530Sfenner * the input filter, of course). 27698530Sfenner * 27798530Sfenner * These statistics don't include packets not yet read from 27898530Sfenner * the kernel by libpcap, but they may include packets not 27998530Sfenner * yet read from libpcap by the application. 28098530Sfenner */ 28117683Spst ps->ps_recv = p->md.TotAccepted; 28217683Spst ps->ps_drop = p->md.TotDrops; 28317683Spst ps->ps_ifdrop = p->md.TotMissed - p->md.OrigMissed; 28417683Spst return (0); 28517683Spst} 28617683Spst 287146768Ssam/* 288146768Ssam * We include the OS's <net/bpf.h>, not our "pcap-bpf.h", so we probably 289146768Ssam * don't get DLT_DOCSIS defined. 290146768Ssam */ 291146768Ssam#ifndef DLT_DOCSIS 292146768Ssam#define DLT_DOCSIS 143 293146768Ssam#endif 294127664Sbms 29517683Spstpcap_t * 296127664Sbmspcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 297127664Sbms char *ebuf) 29817683Spst{ 29917683Spst pcap_t *p; 30017683Spst short enmode; 30117683Spst int backlog = -1; /* request the most */ 30217683Spst struct enfilter Filter; 30317683Spst struct endevp devparams; 30417683Spst 30517683Spst p = (pcap_t *)malloc(sizeof(*p)); 30617683Spst if (p == NULL) { 30775107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, 30875107Sfenner "pcap_open_live: %s", pcap_strerror(errno)); 30917683Spst return (0); 31017683Spst } 31175107Sfenner memset(p, 0, sizeof(*p)); 312127664Sbms /* 313146768Ssam * Initially try a read/write open (to allow the inject 314146768Ssam * method to work). If that fails due to permission 315146768Ssam * issues, fall back to read-only. This allows a 316146768Ssam * non-root user to be granted specific access to pcap 317146768Ssam * capabilities via file permissions. 318146768Ssam * 319146768Ssam * XXX - we should have an API that has a flag that 320146768Ssam * controls whether to open read-only or read-write, 321146768Ssam * so that denial of permission to send (or inability 322146768Ssam * to send, if sending packets isn't supported on 323146768Ssam * the device in question) can be indicated at open 324146768Ssam * time. 325146768Ssam * 326127664Sbms * XXX - we assume here that "pfopen()" does not, in fact, modify 327127664Sbms * its argument, even though it takes a "char *" rather than a 328127664Sbms * "const char *" as its first argument. That appears to be 329127664Sbms * the case, at least on Digital UNIX 4.0. 330127664Sbms */ 331146768Ssam p->fd = pfopen(device, O_RDWR); 332146768Ssam if (p->fd == -1 && errno == EACCES) 333146768Ssam p->fd = pfopen(device, O_RDONLY); 33417683Spst if (p->fd < 0) { 33575107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "pf open: %s: %s\n\ 336127664Sbmsyour system may not be properly configured; see the packetfilter(4) man page\n", 33717683Spst device, pcap_strerror(errno)); 33817683Spst goto bad; 33917683Spst } 34017683Spst p->md.OrigMissed = -1; 34117683Spst enmode = ENTSTAMP|ENBATCH|ENNONEXCL; 34217683Spst if (promisc) 34317683Spst enmode |= ENPROMISC; 34417683Spst if (ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode) < 0) { 34575107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCMBIS: %s", 34675107Sfenner pcap_strerror(errno)); 34717683Spst goto bad; 34817683Spst } 34917683Spst#ifdef ENCOPYALL 35017683Spst /* Try to set COPYALL mode so that we see packets to ourself */ 35117683Spst enmode = ENCOPYALL; 35217683Spst (void)ioctl(p->fd, EIOCMBIS, (caddr_t)&enmode);/* OK if this fails */ 35317683Spst#endif 35417683Spst /* set the backlog */ 35517683Spst if (ioctl(p->fd, EIOCSETW, (caddr_t)&backlog) < 0) { 35675107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETW: %s", 35775107Sfenner pcap_strerror(errno)); 35817683Spst goto bad; 35917683Spst } 36017683Spst /* discover interface type */ 36117683Spst if (ioctl(p->fd, EIOCDEVP, (caddr_t)&devparams) < 0) { 36275107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCDEVP: %s", 36375107Sfenner pcap_strerror(errno)); 36417683Spst goto bad; 36517683Spst } 36617683Spst /* HACK: to compile prior to Ultrix 4.2 */ 36717683Spst#ifndef ENDT_FDDI 36817683Spst#define ENDT_FDDI 4 36917683Spst#endif 37017683Spst switch (devparams.end_dev_type) { 37117683Spst 37217683Spst case ENDT_10MB: 37317683Spst p->linktype = DLT_EN10MB; 37417683Spst p->offset = 2; 375146768Ssam /* 376146768Ssam * This is (presumably) a real Ethernet capture; give it a 377146768Ssam * link-layer-type list with DLT_EN10MB and DLT_DOCSIS, so 378146768Ssam * that an application can let you choose it, in case you're 379146768Ssam * capturing DOCSIS traffic that a Cisco Cable Modem 380146768Ssam * Termination System is putting out onto an Ethernet (it 381146768Ssam * doesn't put an Ethernet header onto the wire, it puts raw 382146768Ssam * DOCSIS frames out on the wire inside the low-level 383146768Ssam * Ethernet framing). 384146768Ssam */ 385146768Ssam p->dlt_list = (u_int *) malloc(sizeof(u_int) * 2); 386146768Ssam /* 387146768Ssam * If that fails, just leave the list empty. 388146768Ssam */ 389146768Ssam if (p->dlt_list != NULL) { 390146768Ssam p->dlt_list[0] = DLT_EN10MB; 391146768Ssam p->dlt_list[1] = DLT_DOCSIS; 392146768Ssam p->dlt_count = 2; 393146768Ssam } 39417683Spst break; 39517683Spst 39617683Spst case ENDT_FDDI: 39717683Spst p->linktype = DLT_FDDI; 39817683Spst break; 39917683Spst 40098530Sfenner#ifdef ENDT_SLIP 40198530Sfenner case ENDT_SLIP: 40298530Sfenner p->linktype = DLT_SLIP; 40398530Sfenner break; 40498530Sfenner#endif 40598530Sfenner 40698530Sfenner#ifdef ENDT_PPP 40798530Sfenner case ENDT_PPP: 40898530Sfenner p->linktype = DLT_PPP; 40998530Sfenner break; 41098530Sfenner#endif 41198530Sfenner 41298530Sfenner#ifdef ENDT_LOOPBACK 41398530Sfenner case ENDT_LOOPBACK: 41417683Spst /* 41598530Sfenner * It appears to use Ethernet framing, at least on 41698530Sfenner * Digital UNIX 4.0. 41717683Spst */ 41817683Spst p->linktype = DLT_EN10MB; 41917683Spst p->offset = 2; 42017683Spst break; 42198530Sfenner#endif 42298530Sfenner 42398530Sfenner#ifdef ENDT_TRN 42498530Sfenner case ENDT_TRN: 42598530Sfenner p->linktype = DLT_IEEE802; 42698530Sfenner break; 42798530Sfenner#endif 42898530Sfenner 42998530Sfenner default: 43098530Sfenner /* 43198530Sfenner * XXX - what about ENDT_IEEE802? The pfilt.h header 43298530Sfenner * file calls this "IEEE 802 networks (non-Ethernet)", 43398530Sfenner * but that doesn't specify a specific link layer type; 43498530Sfenner * it could be 802.4, or 802.5 (except that 802.5 is 43598530Sfenner * ENDT_TRN), or 802.6, or 802.11, or.... That's why 43698530Sfenner * DLT_IEEE802 was hijacked to mean Token Ring in various 43798530Sfenner * BSDs, and why we went along with that hijacking. 43898530Sfenner * 43998530Sfenner * XXX - what about ENDT_HDLC and ENDT_NULL? 44098530Sfenner * Presumably, as ENDT_OTHER is just "Miscellaneous 44198530Sfenner * framing", there's not much we can do, as that 44298530Sfenner * doesn't specify a particular type of header. 44398530Sfenner */ 444127664Sbms snprintf(ebuf, PCAP_ERRBUF_SIZE, "unknown data-link type %u", 44598530Sfenner devparams.end_dev_type); 44698530Sfenner goto bad; 44717683Spst } 44817683Spst /* set truncation */ 44917683Spst#ifdef PCAP_FDDIPAD 450146768Ssam if (p->linktype == DLT_FDDI) { 451147894Ssam p->fddipad = PCAP_FDDIPAD; 452146768Ssam 45317683Spst /* packetfilter includes the padding in the snapshot */ 454146768Ssam snaplen += PCAP_FDDIPAD; 455146768Ssam } else 456146768Ssam p->fddipad = 0; 45717683Spst#endif 45817683Spst if (ioctl(p->fd, EIOCTRUNCATE, (caddr_t)&snaplen) < 0) { 45975107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCTRUNCATE: %s", 46075107Sfenner pcap_strerror(errno)); 46117683Spst goto bad; 46217683Spst } 46317683Spst p->snapshot = snaplen; 46417683Spst /* accept all packets */ 46575107Sfenner memset(&Filter, 0, sizeof(Filter)); 46617683Spst Filter.enf_Priority = 37; /* anything > 2 */ 46717683Spst Filter.enf_FilterLen = 0; /* means "always true" */ 46817683Spst if (ioctl(p->fd, EIOCSETF, (caddr_t)&Filter) < 0) { 46975107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSETF: %s", 47075107Sfenner pcap_strerror(errno)); 47117683Spst goto bad; 47217683Spst } 47317683Spst 47417683Spst if (to_ms != 0) { 47517683Spst struct timeval timeout; 47617683Spst timeout.tv_sec = to_ms / 1000; 47717683Spst timeout.tv_usec = (to_ms * 1000) % 1000000; 47817683Spst if (ioctl(p->fd, EIOCSRTIMEOUT, (caddr_t)&timeout) < 0) { 47975107Sfenner snprintf(ebuf, PCAP_ERRBUF_SIZE, "EIOCSRTIMEOUT: %s", 48017683Spst pcap_strerror(errno)); 48117683Spst goto bad; 48217683Spst } 48317683Spst } 484127664Sbms 48517683Spst p->bufsize = BUFSPACE; 48617683Spst p->buffer = (u_char*)malloc(p->bufsize + p->offset); 487127664Sbms if (p->buffer == NULL) { 488127664Sbms strlcpy(ebuf, pcap_strerror(errno), PCAP_ERRBUF_SIZE); 489127664Sbms goto bad; 490127664Sbms } 49117683Spst 492127664Sbms /* 493127664Sbms * "select()" and "poll()" work on packetfilter devices. 494127664Sbms */ 495127664Sbms p->selectable_fd = p->fd; 496127664Sbms 497127664Sbms p->read_op = pcap_read_pf; 498146768Ssam p->inject_op = pcap_inject_pf; 499127664Sbms p->setfilter_op = pcap_setfilter_pf; 500147894Ssam p->setdirection_op = NULL; /* Not implemented. */ 501127664Sbms p->set_datalink_op = NULL; /* can't change data link type */ 502127664Sbms p->getnonblock_op = pcap_getnonblock_fd; 503127664Sbms p->setnonblock_op = pcap_setnonblock_fd; 504127664Sbms p->stats_op = pcap_stats_pf; 505146768Ssam p->close_op = pcap_close_common; 506127664Sbms 50717683Spst return (p); 50817683Spst bad: 509127664Sbms if (p->fd >= 0) 510127664Sbms close(p->fd); 511146768Ssam /* 512146768Ssam * Get rid of any link-layer type list we allocated. 513146768Ssam */ 514146768Ssam if (p->dlt_list != NULL) 515146768Ssam free(p->dlt_list); 51617683Spst free(p); 51717683Spst return (NULL); 51817683Spst} 51917683Spst 52017683Spstint 521127664Sbmspcap_platform_finddevs(pcap_if_t **alldevsp, char *errbuf) 52217683Spst{ 523127664Sbms return (0); 524127664Sbms} 525127664Sbms 526127664Sbmsstatic int 527127664Sbmspcap_setfilter_pf(pcap_t *p, struct bpf_program *fp) 528127664Sbms{ 529127664Sbms struct bpf_version bv; 530127664Sbms 53117683Spst /* 532127664Sbms * See if BIOCVERSION works. If not, we assume the kernel doesn't 533127664Sbms * support BPF-style filters (it's not documented in the bpf(7) 534127664Sbms * or packetfiler(7) man pages, but the code used to fail if 535127664Sbms * BIOCSETF worked but BIOCVERSION didn't, and I've seen it do 536127664Sbms * kernel filtering in DU 4.0, so presumably BIOCVERSION works 537127664Sbms * there, at least). 53817683Spst */ 539127664Sbms if (ioctl(p->fd, BIOCVERSION, (caddr_t)&bv) >= 0) { 540127664Sbms /* 541127664Sbms * OK, we have the version of the BPF interpreter; 542127664Sbms * is it the same major version as us, and the same 543127664Sbms * or better minor version? 544127664Sbms */ 545127664Sbms if (bv.bv_major == BPF_MAJOR_VERSION && 546127664Sbms bv.bv_minor >= BPF_MINOR_VERSION) { 547127664Sbms /* 548127664Sbms * Yes. Try to install the filter. 549127664Sbms */ 550127664Sbms if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { 551127664Sbms snprintf(p->errbuf, sizeof(p->errbuf), 552127664Sbms "BIOCSETF: %s", pcap_strerror(errno)); 553127664Sbms return (-1); 554127664Sbms } 55517683Spst 556127664Sbms /* 557127664Sbms * OK, that succeeded. We're doing filtering in 558127664Sbms * the kernel. (We assume we don't have a 559127664Sbms * userland filter installed - that'd require 560127664Sbms * a previous version check to have failed but 561127664Sbms * this one to succeed.) 562127664Sbms * 563127664Sbms * XXX - this message should be supplied to the 564127664Sbms * application as a warning of some sort, 565127664Sbms * except that if it's a GUI application, it's 566127664Sbms * not clear that it should be displayed in 567127664Sbms * a window to annoy the user. 568127664Sbms */ 569127664Sbms fprintf(stderr, "tcpdump: Using kernel BPF filter\n"); 570127664Sbms p->md.use_bpf = 1; 571146768Ssam 572146768Ssam /* 573146768Ssam * Discard any previously-received packets, 574146768Ssam * as they might have passed whatever filter 575146768Ssam * was formerly in effect, but might not pass 576146768Ssam * this filter (BIOCSETF discards packets buffered 577146768Ssam * in the kernel, so you can lose packets in any 578146768Ssam * case). 579146768Ssam */ 580146768Ssam p->cc = 0; 581127664Sbms return (0); 58217683Spst } 583127664Sbms 584127664Sbms /* 585127664Sbms * We can't use the kernel's BPF interpreter; don't give 586127664Sbms * up, just log a message and be inefficient. 587127664Sbms * 588127664Sbms * XXX - this should really be supplied to the application 589127664Sbms * as a warning of some sort. 590127664Sbms */ 591127664Sbms fprintf(stderr, 592127664Sbms "tcpdump: Requires BPF language %d.%d or higher; kernel is %d.%d\n", 593127664Sbms BPF_MAJOR_VERSION, BPF_MINOR_VERSION, 594127664Sbms bv.bv_major, bv.bv_minor); 59575107Sfenner } 59617683Spst 597127664Sbms /* 598127664Sbms * We couldn't do filtering in the kernel; do it in userland. 599127664Sbms */ 600127664Sbms if (install_bpf_program(p, fp) < 0) 601127664Sbms return (-1); 602127664Sbms 603127664Sbms /* 604127664Sbms * XXX - this message should be supplied by the application as 605127664Sbms * a warning of some sort. 606127664Sbms */ 607127664Sbms fprintf(stderr, "tcpdump: Filtering in user process\n"); 608127664Sbms p->md.use_bpf = 0; 60917683Spst return (0); 61017683Spst} 611