pcap-bpf.c revision 39291
117683Spst/* 239291Sfenner * Copyright (c) 1993, 1994, 1995, 1996, 1998 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. 2017683Spst */ 2117683Spst#ifndef lint 2226175Sfennerstatic const char rcsid[] = 2339291Sfenner "@(#) $Header: pcap-bpf.c,v 1.31 98/07/12 13:14:55 leres Exp $ (LBL)"; 2417683Spst#endif 2517683Spst 2617683Spst#include <sys/param.h> /* optionally get BSD define */ 2717683Spst#include <sys/time.h> 2817683Spst#include <sys/timeb.h> 2917683Spst#include <sys/socket.h> 3017683Spst#include <sys/file.h> 3117683Spst#include <sys/ioctl.h> 3217683Spst 3317683Spst#include <net/if.h> 3417683Spst 3517683Spst#include <ctype.h> 3617683Spst#include <errno.h> 3717683Spst#include <netdb.h> 3817683Spst#include <stdio.h> 3917683Spst#include <stdlib.h> 4017683Spst#include <string.h> 4117683Spst#include <unistd.h> 4217683Spst 4317683Spst#include "pcap-int.h" 4417683Spst 4517683Spst#include "gnuc.h" 4617683Spst#ifdef HAVE_OS_PROTO_H 4717683Spst#include "os-proto.h" 4817683Spst#endif 4917683Spst 5017683Spstint 5117683Spstpcap_stats(pcap_t *p, struct pcap_stat *ps) 5217683Spst{ 5317683Spst struct bpf_stat s; 5417683Spst 5517683Spst if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { 5617683Spst sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno)); 5717683Spst return (-1); 5817683Spst } 5917683Spst 6017683Spst ps->ps_recv = s.bs_recv; 6117683Spst ps->ps_drop = s.bs_drop; 6217683Spst return (0); 6317683Spst} 6417683Spst 6517683Spstint 6617683Spstpcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 6717683Spst{ 6817683Spst int cc; 6917683Spst int n = 0; 7017683Spst register u_char *bp, *ep; 7117683Spst 7217683Spst again: 7317683Spst cc = p->cc; 7417683Spst if (p->cc == 0) { 7517683Spst cc = read(p->fd, (char *)p->buffer, p->bufsize); 7617683Spst if (cc < 0) { 7717683Spst /* Don't choke when we get ptraced */ 7817683Spst switch (errno) { 7917683Spst 8017683Spst case EINTR: 8117683Spst goto again; 8217683Spst 8317683Spst case EWOULDBLOCK: 8417683Spst return (0); 8517683Spst#if defined(sun) && !defined(BSD) 8617683Spst /* 8717683Spst * Due to a SunOS bug, after 2^31 bytes, the kernel 8817683Spst * file offset overflows and read fails with EINVAL. 8917683Spst * The lseek() to 0 will fix things. 9017683Spst */ 9117683Spst case EINVAL: 9217683Spst if (lseek(p->fd, 0L, SEEK_CUR) + 9317683Spst p->bufsize < 0) { 9417683Spst (void)lseek(p->fd, 0L, SEEK_SET); 9517683Spst goto again; 9617683Spst } 9717683Spst /* fall through */ 9817683Spst#endif 9917683Spst } 10017683Spst sprintf(p->errbuf, "read: %s", pcap_strerror(errno)); 10117683Spst return (-1); 10217683Spst } 10317683Spst bp = p->buffer; 10417683Spst } else 10517683Spst bp = p->bp; 10617683Spst 10717683Spst /* 10817683Spst * Loop through each packet. 10917683Spst */ 11017683Spst#define bhp ((struct bpf_hdr *)bp) 11117683Spst ep = bp + cc; 11217683Spst while (bp < ep) { 11317683Spst register int caplen, hdrlen; 11417683Spst caplen = bhp->bh_caplen; 11517683Spst hdrlen = bhp->bh_hdrlen; 11617683Spst /* 11717683Spst * XXX A bpf_hdr matches a pcap_pkthdr. 11817683Spst */ 11917683Spst (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 12017683Spst bp += BPF_WORDALIGN(caplen + hdrlen); 12117683Spst if (++n >= cnt && cnt > 0) { 12217683Spst p->bp = bp; 12317683Spst p->cc = ep - bp; 12417683Spst return (n); 12517683Spst } 12617683Spst } 12717683Spst#undef bhp 12817683Spst p->cc = 0; 12917683Spst return (n); 13017683Spst} 13117683Spst 13217683Spststatic inline int 13317683Spstbpf_open(pcap_t *p, char *errbuf) 13417683Spst{ 13517683Spst int fd; 13617683Spst int n = 0; 13717683Spst char device[sizeof "/dev/bpf000"]; 13817683Spst 13917683Spst /* 14017683Spst * Go through all the minors and find one that isn't in use. 14117683Spst */ 14217683Spst do { 14317683Spst (void)sprintf(device, "/dev/bpf%d", n++); 14417683Spst fd = open(device, O_RDONLY); 14517683Spst } while (fd < 0 && errno == EBUSY); 14617683Spst 14717683Spst /* 14817683Spst * XXX better message for all minors used 14917683Spst */ 15017683Spst if (fd < 0) 15117683Spst sprintf(errbuf, "%s: %s", device, pcap_strerror(errno)); 15217683Spst 15317683Spst return (fd); 15417683Spst} 15517683Spst 15617683Spstpcap_t * 15717683Spstpcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 15817683Spst{ 15917683Spst int fd; 16017683Spst struct ifreq ifr; 16117683Spst struct bpf_version bv; 16217683Spst u_int v; 16317683Spst pcap_t *p; 16417683Spst 16517683Spst p = (pcap_t *)malloc(sizeof(*p)); 16617683Spst if (p == NULL) { 16717683Spst sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); 16817683Spst return (NULL); 16917683Spst } 17017683Spst bzero(p, sizeof(*p)); 17117683Spst fd = bpf_open(p, ebuf); 17217683Spst if (fd < 0) 17317683Spst goto bad; 17417683Spst 17517683Spst p->fd = fd; 17617683Spst p->snapshot = snaplen; 17717683Spst 17817683Spst if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { 17917683Spst sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno)); 18017683Spst goto bad; 18117683Spst } 18217683Spst if (bv.bv_major != BPF_MAJOR_VERSION || 18317683Spst bv.bv_minor < BPF_MINOR_VERSION) { 18417683Spst sprintf(ebuf, "kernel bpf filter out of date"); 18517683Spst goto bad; 18617683Spst } 18739291Sfenner v = 32768; /* XXX this should be a user-accessible hook */ 18839291Sfenner /* Ignore the return value - this is because the call fails on 18939291Sfenner * BPF systems that don't have kernel malloc. And if the call 19039291Sfenner * fails, it's no big deal, we just continue to use the standard 19139291Sfenner * buffer size. 19239291Sfenner */ 19339291Sfenner (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); 19439291Sfenner 19517683Spst (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 19617683Spst if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { 19717683Spst sprintf(ebuf, "%s: %s", device, pcap_strerror(errno)); 19817683Spst goto bad; 19917683Spst } 20017683Spst /* Get the data link layer type. */ 20117683Spst if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { 20217683Spst sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno)); 20317683Spst goto bad; 20417683Spst } 20539291Sfenner#if _BSDI_VERSION - 0 >= 199510 20639291Sfenner /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ 20739291Sfenner switch (v) { 20839291Sfenner 20939291Sfenner case DLT_SLIP: 21039291Sfenner v = DLT_SLIP_BSDOS; 21139291Sfenner break; 21239291Sfenner 21339291Sfenner case DLT_PPP: 21439291Sfenner v = DLT_PPP_BSDOS; 21539291Sfenner break; 21639291Sfenner } 21739291Sfenner#endif 21817683Spst p->linktype = v; 21917683Spst 22017683Spst /* set timeout */ 22117683Spst if (to_ms != 0) { 22217683Spst struct timeval to; 22317683Spst to.tv_sec = to_ms / 1000; 22417683Spst to.tv_usec = (to_ms * 1000) % 1000000; 22517683Spst if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { 22617683Spst sprintf(ebuf, "BIOCSRTIMEOUT: %s", 22717683Spst pcap_strerror(errno)); 22817683Spst goto bad; 22917683Spst } 23017683Spst } 23117683Spst if (promisc) 23217683Spst /* set promiscuous mode, okay if it fails */ 23317683Spst (void)ioctl(p->fd, BIOCPROMISC, NULL); 23417683Spst 23517683Spst if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { 23617683Spst sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno)); 23717683Spst goto bad; 23817683Spst } 23917683Spst p->bufsize = v; 24017683Spst p->buffer = (u_char *)malloc(p->bufsize); 24117683Spst if (p->buffer == NULL) { 24217683Spst sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); 24317683Spst goto bad; 24417683Spst } 24517683Spst 24617683Spst return (p); 24717683Spst bad: 24817683Spst (void)close(fd); 24917683Spst free(p); 25017683Spst return (NULL); 25117683Spst} 25217683Spst 25317683Spstint 25417683Spstpcap_setfilter(pcap_t *p, struct bpf_program *fp) 25517683Spst{ 25617683Spst if (p->sf.rfile != NULL) 25717683Spst p->fcode = *fp; 25817683Spst else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { 25917683Spst sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno)); 26017683Spst return (-1); 26117683Spst } 26217683Spst return (0); 26317683Spst} 264