* Copyright (c) 1990-1991 The Regents of the University of California.
* This code is derived from the Stanford/CMU enet packet filter,
* (net/enet.c) distributed as part of 4.3BSD, and code contributed
* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* @(#)bpf.c 7.5 (Berkeley) 7/15/91
* "$Header: bpf.c,v 1.49 92/05/25 14:43:09 mccanne Exp $";
* PATCHES MAGIC LEVEL PATCH THAT GOT US HERE
* -------------------- ----- ----------------------
* CURRENT PATCH LEVEL: 1 00112
* -------------------- ----- ----------------------
* 14 Mar 93 David Greenman Upgrade bpf to match tcpdump 2.2.1
* 24 Mar 93 Rodney W. Grimes Fixed selwakeup to use pid_t from proc,
* disabled definition of inline.
#define inline __inline__
/* #include <sys/map.h> */
#if defined(sparc) && BSD < 199103
#include <netinet/if_ether.h>
* Older BSDs don't have kernel malloc.
static caddr_t
bpf_alloc();
#include <net/bpf_compat.h>
#define BPF_BUFSIZE (MCLBYTES-8)
#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio)
#define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
#define PRINET 26 /* interruptible */
* The default read buffer size is patchable.
int bpf_bufsize
= BPF_BUFSIZE
;
* bpf_iflist is the list of interfaces; each corresponds to an ifnet
* bpf_dtab holds the descriptors, indexed by minor device #
struct bpf_if
*bpf_iflist
;
struct bpf_d bpf_dtab
[NBPFILTER
];
static void bpf_ifname();
static void catchpacket();
static int bpf_allocbufs();
bpf_movein(uio
, linktype
, mp
, sockp
)
register struct uio
*uio
;
register struct mbuf
**mp
;
register struct sockaddr
*sockp
;
* Build a sockaddr based on the data link layer type.
* We do this at this level because the ethernet header
* is copied directly into the data field of the sockaddr.
* In the case of SLIP, there is no header and the packet
* Also, we are careful to leave room at the front of the mbuf
* for the link level header.
sockp
->sa_family
= AF_INET
;
sockp
->sa_family
= AF_UNSPEC
;
/* XXX Would MAXLINKHDR be better? */
hlen
= sizeof(struct ether_header
);
sockp
->sa_family
= AF_UNSPEC
;
/* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
sockp
->sa_family
= AF_UNSPEC
;
if ((unsigned)len
> MCLBYTES
)
MGET(m
, M_WAIT
, MT_DATA
);
if ((m
->m_flags
& M_EXT
) == 0) {
if (m
->m_len
!= MCLBYTES
) {
* Make room for link header.
m
->m_data
+= hlen
; /* XXX */
error
= UIOMOVE((caddr_t
)sockp
->sa_data
, hlen
, UIO_WRITE
, uio
);
error
= UIOMOVE(mtod(m
, caddr_t
), len
- hlen
, UIO_WRITE
, uio
);
* Attach file to the bpf interface, i.e. make d listen on bp.
* Must be called at splimp.
* Point d at bp, and add d to the interface's list of listeners.
* Finally, point the driver's bpf cookie at the interface so
* it will divert packets to bpf.
d
->bd_next
= bp
->bif_dlist
;
* Detach a file from its interface.
* Check if this descriptor had requested promiscuous mode.
if (ifpromisc(bp
->bif_ifp
, 0))
* Something is really wrong if we were able to put
* the driver into promiscuous mode, but can't
panic("bpf: ifpromisc failed");
/* Remove d from the interface's descriptor list. */
panic("bpf_detachd: descriptor not in list");
* Let the driver know that there are no more listeners.
*d
->bd_bif
->bif_driverp
= 0;
* Mark a descriptor free by making it point to itself.
* This is probably cheaper than marking with a constant since
* the address should be in a register anyway.
#define D_ISFREE(d) ((d) == (d)->bd_next)
#define D_MARKFREE(d) ((d)->bd_next = (d))
#define D_MARKUSED(d) ((d)->bd_next = 0)
* Open ethernet device. Returns ENXIO for illegal minor device number,
* EBUSY if file is open by another process.
register struct bpf_d
*d
;
if (minor(dev
) >= NBPFILTER
)
* Each minor can be opened by only one process. If the requested
* minor is in use, return EBUSY.
d
= &bpf_dtab
[minor(dev
)];
/* Mark "free" and do most initialization. */
bzero((char *)d
, sizeof(*d
));
d
->bd_bufsize
= bpf_bufsize
;
* Close the descriptor by detaching it from its interface,
* deallocating its buffers, and marking it free.
register struct bpf_d
*d
= &bpf_dtab
[minor(dev
)];
* Support for SunOS, which does not have tsleep.
struct bpf_d
*d
= (struct bpf_d
*)arg
;
#define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan)
register struct bpf_d
*d
;
register int rto
= d
->bd_rtout
;
timeout(bpf_timeout
, (caddr_t
)d
, rto
);
st
= sleep((caddr_t
)d
, PRINET
|PCATCH
);
untimeout(bpf_timeout
, (caddr_t
)d
);
return (st
!= 0) ? EINTR
: 0;
* Rotate the packet buffers in descriptor d. Move the store buffer
* into the hold slot, and the free buffer into the store slot.
* Zero the length of the new store buffer.
#define ROTATE_BUFFERS(d) \
(d)->bd_hbuf = (d)->bd_sbuf; \
(d)->bd_hlen = (d)->bd_slen; \
(d)->bd_sbuf = (d)->bd_fbuf; \
* bpfread - read next chunk of packets from buffers
register struct uio
*uio
;
register struct bpf_d
*d
= &bpf_dtab
[minor(dev
)];
* Restrict application to use a buffer the same size as
if (uio
->uio_resid
!= d
->bd_bufsize
)
* If the hold buffer is empty, then do a timed sleep, which
* ends when the timeout expires or when enough packets
* have arrived to fill the store buffer.
while (d
->bd_hbuf
== 0) {
if (d
->bd_immediate
&& d
->bd_slen
!= 0) {
* A packet(s) either arrived since the previous
* read or arrived while we were asleep.
* Rotate the buffers and return what's here.
error
= BPF_SLEEP((caddr_t
)d
, PRINET
|PCATCH
, "bpf",
if (error
== EINTR
|| error
== ERESTART
) {
if (error
== EWOULDBLOCK
) {
* On a timeout, return what's in the buffer,
* which may be nothing. If there is something
* in the store buffer, we can rotate the buffers.
* We filled up the buffer in between
* getting the timeout and arriving
* here, so we don't need to rotate.
* At this point, we know we have something in the hold slot.
* Move data from hold buffer into user space.
* We know the entire buffer is transferred since
* we checked above that the read buffer is bpf_bufsize bytes.
error
= UIOMOVE(d
->bd_hbuf
, d
->bd_hlen
, UIO_READ
, uio
);
* If there are processes sleeping on this descriptor, wake them up.
register struct bpf_d
*d
;
selwakeup(d
->bd_selproc
->p_pid
, (int)d
->bd_selcoll
);
register struct bpf_d
*d
= &bpf_dtab
[minor(dev
)];
static struct sockaddr dst
;
ifp
= d
->bd_bif
->bif_ifp
;
if (uio
->uio_resid
> ifp
->if_mtu
)
error
= bpf_movein(uio
, (int)d
->bd_bif
->bif_dlt
, &m
, &dst
);
error
= (*ifp
->if_output
)(ifp
, m
, &dst
, (struct rtentry
*)0);
error
= (*ifp
->if_output
)(ifp
, m
, &dst
);
* The driver frees the mbuf.
* Reset a descriptor by flushing its packet buffer and clearing the
* receive and drop counts. Should be called at splimp.
/* Free the hold buffer. */
* FIONREAD Check for read packet available.
* SIOCGIFADDR Get interface address - convenient hook to driver.
* BIOCGBLEN Get buffer len [for read()].
* BIOCSETF Set ethernet read filter.
* BIOCFLUSH Flush read packet buffer.
* BIOCPROMISC Put interface into promiscuous mode.
* BIOCGDLT Get link layer type.
* BIOCGETIF Get interface name.
* BIOCSETIF Set interface.
* BIOCSRTIMEOUT Set read timeout.
* BIOCGRTIMEOUT Get read timeout.
* BIOCGSTATS Get packet stats.
* BIOCIMMEDIATE Set immediate mode.
* BIOCVERSION Get filter language version.
bpfioctl(dev
, cmd
, addr
, flag
)
register struct bpf_d
*d
= &bpf_dtab
[minor(dev
)];
* Check for read packet available.
ifp
= d
->bd_bif
->bif_ifp
;
error
= (*ifp
->if_ioctl
)(ifp
, cmd
, addr
);
* Get buffer len [for read()].
*(u_int
*)addr
= d
->bd_bufsize
;
register u_int size
= *(u_int
*)addr
;
if (size
> BPF_MAXBUFSIZE
)
*(u_int
*)addr
= size
= BPF_MAXBUFSIZE
;
else if (size
< BPF_MINBUFSIZE
)
*(u_int
*)addr
= size
= BPF_MINBUFSIZE
;
* Set link layer read filter.
error
= bpf_setf(d
, (struct bpf_program
*)addr
);
* Flush read packet buffer.
* Put interface into promiscuous mode.
* No interface attached yet.
if (d
->bd_promisc
== 0) {
error
= ifpromisc(d
->bd_bif
->bif_ifp
, 1);
*(u_int
*)addr
= d
->bd_bif
->bif_dlt
;
bpf_ifname(d
->bd_bif
->bif_ifp
, (struct ifreq
*)addr
);
error
= bpf_setif(d
, (struct ifreq
*)addr
);
struct timeval
*tv
= (struct timeval
*)addr
;
/* Compute number of milliseconds. */
msec
= tv
->tv_sec
* 1000 + tv
->tv_usec
/ 1000;
/* Scale milliseconds to ticks. Assume hard
clock has millisecond or greater resolution
(i.e. tick >= 1000). For 10ms hardclock,
tick/1000 = 10, so rtout<-msec/10. */
d
->bd_rtout
= msec
/ (tick
/ 1000);
struct timeval
*tv
= (struct timeval
*)addr
;
u_long msec
= d
->bd_rtout
;
tv
->tv_sec
= msec
/ 1000;
tv
->tv_usec
= msec
% 1000;
struct bpf_stat
*bs
= (struct bpf_stat
*)addr
;
bs
->bs_recv
= d
->bd_rcount
;
bs
->bs_drop
= d
->bd_dcount
;
d
->bd_immediate
= *(u_int
*)addr
;
struct bpf_version
*bv
= (struct bpf_version
*)addr
;
bv
->bv_major
= BPF_MAJOR_VERSION
;
bv
->bv_minor
= BPF_MINOR_VERSION
;
* Set d's packet filter program to fp. If this file already has a filter,
* free it and replace it. Returns EINVAL for bogus requests.
struct bpf_insn
*fcode
, *old
;
free((caddr_t
)old
, M_DEVBUF
);
size
= flen
* sizeof(*fp
->bf_insns
);
fcode
= (struct bpf_insn
*)malloc(size
, M_DEVBUF
, M_WAITOK
);
if (copyin((caddr_t
)fp
->bf_insns
, (caddr_t
)fcode
, size
) == 0 &&
bpf_validate(fcode
, (int)flen
)) {
free((caddr_t
)old
, M_DEVBUF
);
free((caddr_t
)fcode
, M_DEVBUF
);
* Detach a file from its current interface (if attached at all) and attach
* to the interface indicated by the name stored in ifr.
* Separate string into name part and unit number. Put a null
* byte at the end of the name part, and compute the number.
* If the a unit number is unspecified, the default is 0,
* as initialized above. XXX This should be common code.
cp
[sizeof(ifr
->ifr_name
) - 1] = '\0';
if (*cp
>= '0' && *cp
<= '9') {
unit
= 10 * unit
+ *cp
++ - '0';
* Look through attached interfaces for the named one.
for (bp
= bpf_iflist
; bp
!= 0; bp
= bp
->bif_next
) {
struct ifnet
*ifp
= bp
->bif_ifp
;
if (ifp
== 0 || unit
!= ifp
->if_unit
|| strcmp(ifp
->if_name
, ifr
->ifr_name
) != 0)
* We found the requested interface.
* If it's not up, return an error.
* Allocate the packet buffers if we need to.
* If we're already attached to requested interface,
if ((ifp
->if_flags
& IFF_UP
) == 0)
error
= bpf_allocbufs(d
);
* Detach if attached to something else.
* Convert an interface name plus unit number of an ifp to a single
* name which is returned in the ifr.
/* XXX Assume that unit number is less than 10. */
*d
++ = ifp
->if_unit
+ '0';
* The new select interface passes down the proc pointer; the old select
* stubs had to grab it out of the user struct. This glue allows either case.
#define bpf_select bpfselect
return (bpf_select(dev
, rw
, u
.u_procp
));
* Support for select() system call
* Inspired by the code in tty.c for the same purpose.
* Return true iff the specific operation will not block indefinitely.
* Otherwise, return false but make a note that a selwakeup() must be done.
register struct bpf_d
*d
;
* An imitation of the FIONREAD ioctl code.
d
= &bpf_dtab
[minor(dev
)];
if (d
->bd_hlen
!= 0 || (d
->bd_immediate
&& d
->bd_slen
!= 0)) {
selrecord(p
, &d
->bd_sel
);
* No data ready. If there's already a select() waiting on this
* minor device then this is a collision. This shouldn't happen
* because minors really should not be shared, but if a process
* forks while one of these is open, it is possible that both
* processes could select on the same descriptor.
if (d
->bd_selproc
&& d
->bd_selproc
->p_wchan
== (caddr_t
)&selwait
)
* Incoming linkage from device drivers. Process the packet pkt, of length
* pktlen, which is stored in a contiguous buffer. The packet is parsed
* by each process' filter, and if accepted, stashed into the corresponding
bpf_tap(arg
, pkt
, pktlen
)
register struct bpf_d
*d
;
* Note that the ipl does not have to be raised at this point.
* The only problem that could arise here is that if two different
* interfaces shared any data. This is not the case.
bp
= (struct bpf_if
*)arg
;
for (d
= bp
->bif_dlist
; d
!= 0; d
= d
->bd_next
) {
slen
= bpf_filter(d
->bd_filter
, pkt
, pktlen
, pktlen
);
catchpacket(d
, pkt
, pktlen
, slen
, bcopy
);
* Copy data from an mbuf chain into a buffer. This code is derived
* from m_copydata in sys/uipc_mbuf.c.
register struct mbuf
*m
= (struct mbuf
*)src
;
count
= MIN(m
->m_len
, len
);
bcopy(mtod(m
, caddr_t
), (caddr_t
)dst
, count
);
* Incoming linkage from device drivers, when packet is in an mbuf chain.
struct bpf_if
*bp
= (struct bpf_if
*)arg
;
for (m0
= m
; m0
!= 0; m0
= m0
->m_next
)
for (d
= bp
->bif_dlist
; d
!= 0; d
= d
->bd_next
) {
slen
= bpf_filter(d
->bd_filter
, (u_char
*)m
, pktlen
, 0);
catchpacket(d
, (u_char
*)m
, pktlen
, slen
, bpf_mcopy
);
* Move the packet data from interface memory (pkt) into the
* store buffer. Return 1 if it's time to wakeup a listener (buffer full),
* otherwise 0. "copy" is the routine called to do the actual data
* transfer. bcopy is passed in to copy contiguous chunks, while
* bpf_mcopy is passed in to copy mbuf chains. In the latter case,
catchpacket(d
, pkt
, pktlen
, snaplen
, cpfn
)
register struct bpf_d
*d
;
register u_int pktlen
, snaplen
;
register struct bpf_hdr
*hp
;
register int totlen
, curlen
;
register int hdrlen
= d
->bd_bif
->bif_hdrlen
;
* Figure out how many bytes to move. If the packet is
* greater or equal to the snapshot length, transfer that
* much. Otherwise, transfer the whole packet (unless
* we hit the buffer size limit).
totlen
= hdrlen
+ MIN(snaplen
, pktlen
);
if (totlen
> d
->bd_bufsize
)
* Round up the end of the previous packet to the next longword.
curlen
= BPF_WORDALIGN(d
->bd_slen
);
if (curlen
+ totlen
> d
->bd_bufsize
) {
* This packet will overflow the storage buffer.
* Rotate the buffers if we can, then wakeup any
* We haven't completed the previous read yet,
else if (d
->bd_immediate
)
* Immediate mode is set. A packet arrived so any
* reads should be woken up.
hp
= (struct bpf_hdr
*)(d
->bd_sbuf
+ curlen
);
microtime(&hp
->bh_tstamp
);
uniqtime(&hp
->bh_tstamp
);
* Copy the packet data into the store buffer and update its length.
(*cpfn
)(pkt
, (u_char
*)hp
+ hdrlen
, (hp
->bh_caplen
= totlen
- hdrlen
));
d
->bd_slen
= curlen
+ totlen
;
* Initialize all nonzero fields of a descriptor.
register struct bpf_d
*d
;
d
->bd_fbuf
= (caddr_t
)malloc(d
->bd_bufsize
, M_DEVBUF
, M_WAITOK
);
d
->bd_sbuf
= (caddr_t
)malloc(d
->bd_bufsize
, M_DEVBUF
, M_WAITOK
);
free(d
->bd_fbuf
, M_DEVBUF
);
* Free buffers currently in use by a descriptor.
register struct bpf_d
*d
;
* We don't need to lock out interrupts since this descriptor has
* been detached from its interface and it yet hasn't been marked
free(d
->bd_sbuf
, M_DEVBUF
);
free(d
->bd_hbuf
, M_DEVBUF
);
free(d
->bd_fbuf
, M_DEVBUF
);
free((caddr_t
)d
->bd_filter
, M_DEVBUF
);
* Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *)
* in the driver's softc; dlt is the link layer type; hdrlen is the fixed
* size of the link header (variable length headers not yet supported).
bpfattach(driverp
, ifp
, dlt
, hdrlen
)
static struct bpf_if bpf_ifs
[NBPFILTER
];
bp
= (bpfifno
< NBPFILTER
) ? &bpf_ifs
[bpfifno
++] : 0;
bp
= (struct bpf_if
*)malloc(sizeof(*bp
), M_DEVBUF
, M_DONTWAIT
);
bp
->bif_driverp
= (struct bpf_if
**)driverp
;
bp
->bif_next
= bpf_iflist
;
* Compute the length of the bpf header. This is not necessarily
* equal to SIZEOF_BPF_HDR because we want to insert spacing such
* that the network layer header begins on a longword boundary (for
* performance reasons and to alleviate alignment restrictions).
bp
->bif_hdrlen
= BPF_WORDALIGN(hdrlen
+ SIZEOF_BPF_HDR
) - hdrlen
;
* Mark all the descriptors free if this hasn't been done.
if (!D_ISFREE(&bpf_dtab
[0]))
for (i
= 0; i
< NBPFILTER
; ++i
)
D_MARKFREE(&bpf_dtab
[i
]);
printf("bpf: %s%d attached\n", ifp
->if_name
, ifp
->if_unit
);
/* XXX This routine belongs in net/if.c. */
* Set/clear promiscuous mode on interface ifp based on the truth value
* of pswitch. The calls are reference counted so that only the first
* "on" request actually has an effect, as does the final "off" request.
* Results are undefined if the "off" and "on" requests are not matched.
* If the device is not configured up, we cannot put it in
if ((ifp
->if_flags
& IFF_UP
) == 0)
if (ifp
->if_pcount
++ != 0)
ifp
->if_flags
|= IFF_PROMISC
;
if (--ifp
->if_pcount
> 0)
ifp
->if_flags
&= ~IFF_PROMISC
;
ifr
.ifr_flags
= ifp
->if_flags
;
return ((*ifp
->if_ioctl
)(ifp
, SIOCSIFFLAGS
, (caddr_t
)&ifr
));
* Allocate some memory for bpf. This is temporary SunOS support, and
* If resources unavaiable, return 0.
if ((unsigned)size
> (MCLBYTES
-8))
MGET(m
, canwait
, MT_DATA
);
if ((unsigned)size
> (MLEN
-8)) {
if (m
->m_len
!= MCLBYTES
) {
*mtod(m
, struct mbuf
**) = m
;
return mtod(m
, caddr_t
) + 8;