bpf_buffer.c revision 286856
119370Spst/*-
219370Spst * Copyright (c) 2007 Seccuris Inc.
319370Spst * All rights reserved.
4130803Smarcel *
5130803Smarcel * This software was developed by Robert N. M. Watson under contract to
6130803Smarcel * Seccuris Inc.
798944Sobrien *
819370Spst * Redistribution and use in source and binary forms, with or without
998944Sobrien * modification, are permitted provided that the following conditions
1098944Sobrien * are met:
1198944Sobrien * 1. Redistributions of source code must retain the above copyright
1298944Sobrien *    notice, this list of conditions and the following disclaimer.
1319370Spst * 2. Redistributions in binary form must reproduce the above copyright
1498944Sobrien *    notice, this list of conditions and the following disclaimer in the
1598944Sobrien *    documentation and/or other materials provided with the distribution.
1698944Sobrien *
1798944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1819370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1998944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2098944Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2198944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2298944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2319370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2419370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2519370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2619370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27130803Smarcel * SUCH DAMAGE.
28130803Smarcel *
29130803Smarcel * Copyright (c) 1990, 1991, 1993
30130803Smarcel *	The Regents of the University of California.  All rights reserved.
31130803Smarcel *
32130803Smarcel * This code is derived from the Stanford/CMU enet packet filter,
33130803Smarcel * (net/enet.c) distributed as part of 4.3BSD, and code contributed
3419370Spst * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
3519370Spst * Berkeley Laboratory.
3619370Spst *
3719370Spst * Redistribution and use in source and binary forms, with or without
3819370Spst * modification, are permitted provided that the following conditions
3919370Spst * are met:
40130803Smarcel * 1. Redistributions of source code must retain the above copyright
41130803Smarcel *    notice, this list of conditions and the following disclaimer.
42130803Smarcel * 2. Redistributions in binary form must reproduce the above copyright
4398944Sobrien *    notice, this list of conditions and the following disclaimer in the
4419370Spst *    documentation and/or other materials provided with the distribution.
4519370Spst * 4. Neither the name of the University nor the names of its contributors
4698944Sobrien *    may be used to endorse or promote products derived from this software
4719370Spst *    without specific prior written permission.
4819370Spst *
4919370Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
5019370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
5198944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
5219370Spst * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
5398944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
5419370Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
5598944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
5619370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
5798944Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
5819370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
5998944Sobrien * SUCH DAMAGE.
6019370Spst *
6198944Sobrien *      @(#)bpf.c	8.4 (Berkeley) 1/9/95
6298944Sobrien */
6398944Sobrien
6419370Spst#include <sys/cdefs.h>
6598944Sobrien__FBSDID("$FreeBSD: stable/10/sys/net/bpf_buffer.c 286856 2015-08-17 18:43:39Z loos $");
6698944Sobrien
6798944Sobrien#include "opt_bpf.h"
6819370Spst
6998944Sobrien#include <sys/param.h>
7098944Sobrien#include <sys/malloc.h>
7119370Spst#include <sys/mbuf.h>
7298944Sobrien#include <sys/socket.h>
7398944Sobrien#include <sys/uio.h>
7498944Sobrien#include <sys/kernel.h>
7598944Sobrien#include <sys/sysctl.h>
7619370Spst
7798944Sobrien#include <net/if.h>
7898944Sobrien#include <net/bpf.h>
7919370Spst#include <net/bpf_buffer.h>
8098944Sobrien#include <net/bpfdesc.h>
8198944Sobrien
8219370Spst/*
8398944Sobrien * Implement historical kernel memory buffering model for BPF: two malloc(9)
8498944Sobrien * kernel buffers are hung off of the descriptor.  The size is fixed prior to
8598944Sobrien * attaching to an ifnet, ad cannot be changed after that.  read(2) simply
8698944Sobrien * copies the data to user space using uiomove(9).
8798944Sobrien */
8898944Sobrien
8998944Sobrienstatic int bpf_bufsize = 4096;
9098944SobrienSYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
9198944Sobrien    &bpf_bufsize, 0, "Default capture buffer size in bytes");
9298944Sobrienstatic int bpf_maxbufsize = BPF_MAXBUFSIZE;
9398944SobrienSYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
9498944Sobrien    &bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
9598944Sobrien
9698944Sobrien/*
9798944Sobrien * Simple data copy to the current kernel buffer.
9898944Sobrien */
9998944Sobrienvoid
10098944Sobrienbpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
10198944Sobrien    void *src, u_int len)
10298944Sobrien{
10398944Sobrien	u_char *src_bytes;
10498944Sobrien
10519370Spst	src_bytes = (u_char *)src;
10619370Spst	bcopy(src_bytes, buf + offset, len);
10719370Spst}
10819370Spst
10998944Sobrien/*
11098944Sobrien * Scatter-gather data copy from an mbuf chain to the current kernel buffer.
11119370Spst */
11298944Sobrienvoid
11319370Spstbpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset, void *src,
11498944Sobrien    u_int len)
11598944Sobrien{
11698944Sobrien	const struct mbuf *m;
11798944Sobrien	u_char *dst;
11898944Sobrien	u_int count;
11946283Sdfr
12098944Sobrien	m = (struct mbuf *)src;
12198944Sobrien	dst = (u_char *)buf + offset;
12298944Sobrien	while (len > 0) {
12398944Sobrien		if (m == NULL)
12498944Sobrien			panic("bpf_mcopy");
12598944Sobrien		count = min(m->m_len, len);
12698944Sobrien		bcopy(mtod(m, void *), dst, count);
12746283Sdfr		m = m->m_next;
12846283Sdfr		dst += count;
12946283Sdfr		len -= count;
13046283Sdfr	}
13146283Sdfr}
13298944Sobrien
13346283Sdfr/*
13446283Sdfr * Free BPF kernel buffers on device close.
13546283Sdfr */
13646283Sdfrvoid
13746283Sdfrbpf_buffer_free(struct bpf_d *d)
13846283Sdfr{
13946283Sdfr
14046283Sdfr	if (d->bd_sbuf != NULL)
14146283Sdfr		free(d->bd_sbuf, M_BPF);
14246283Sdfr	if (d->bd_hbuf != NULL)
14398944Sobrien		free(d->bd_hbuf, M_BPF);
14446283Sdfr	if (d->bd_fbuf != NULL)
14546283Sdfr		free(d->bd_fbuf, M_BPF);
14619370Spst
14719370Spst#ifdef INVARIANTS
14819370Spst	d->bd_sbuf = d->bd_hbuf = d->bd_fbuf = (caddr_t)~0;
14919370Spst#endif
15098944Sobrien}
15119370Spst
15298944Sobrien/*
15319370Spst * This is a historical initialization that occurs when the BPF descriptor is
15498944Sobrien * first opened.  It does not imply selection of a buffer mode, so we don't
15598944Sobrien * allocate buffers here.
15698944Sobrien */
15798944Sobrienvoid
15819370Spstbpf_buffer_init(struct bpf_d *d)
15998944Sobrien{
16019370Spst
16198944Sobrien	d->bd_bufsize = bpf_bufsize;
16219370Spst}
163130803Smarcel
164130803Smarcel/*
16598944Sobrien * Allocate or resize buffers.
16619370Spst */
16798944Sobrienint
16819370Spstbpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
16998944Sobrien{
17019370Spst	u_int size;
17198944Sobrien	caddr_t fbuf, sbuf;
17219370Spst
17398944Sobrien	size = *i;
17419370Spst	if (size > bpf_maxbufsize)
17598944Sobrien		*i = size = bpf_maxbufsize;
17619370Spst	else if (size < BPF_MINBUFSIZE)
17798944Sobrien		*i = size = BPF_MINBUFSIZE;
17846283Sdfr
179130803Smarcel	/* Allocate buffers immediately */
18019370Spst	fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
181130803Smarcel	sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
18219370Spst
183130803Smarcel	BPFD_LOCK(d);
18419370Spst	if (d->bd_bif != NULL) {
18598944Sobrien		/* Interface already attached, unable to change buffers */
18698944Sobrien		BPFD_UNLOCK(d);
187130803Smarcel		free(fbuf, M_BPF);
188130803Smarcel		free(sbuf, M_BPF);
18998944Sobrien		return (EINVAL);
19098944Sobrien	}
19198944Sobrien
19298944Sobrien	/* Free old buffers if set */
19398944Sobrien	if (d->bd_fbuf != NULL)
19498944Sobrien		free(d->bd_fbuf, M_BPF);
19598944Sobrien	if (d->bd_sbuf != NULL)
19698944Sobrien		free(d->bd_sbuf, M_BPF);
19798944Sobrien
19898944Sobrien	/* Fill in new data */
19998944Sobrien	d->bd_bufsize = size;
20098944Sobrien	d->bd_fbuf = fbuf;
20198944Sobrien	d->bd_sbuf = sbuf;
20219370Spst
20319370Spst	d->bd_hbuf = NULL;
20419370Spst	d->bd_slen = 0;
20598944Sobrien	d->bd_hlen = 0;
20619370Spst
20719370Spst	BPFD_UNLOCK(d);
20819370Spst	return (0);
209130803Smarcel}
210130803Smarcel
211130803Smarcel/*
212130803Smarcel * Copy buffer storage to user space in read().
21319370Spst */
21498944Sobrienint
21519370Spstbpf_buffer_uiomove(struct bpf_d *d, caddr_t buf, u_int len, struct uio *uio)
21698944Sobrien{
21719370Spst
21898944Sobrien	return (uiomove(buf, len, uio));
21919370Spst}
22098944Sobrien