1177548Scsjp/*-
2177548Scsjp * Copyright (c) 2007 Seccuris Inc.
3177548Scsjp * All rights reserved.
4177548Scsjp *
5230108Seadler * This software was developed by Robert N. M. Watson under contract to
6177548Scsjp * Seccuris Inc.
7177548Scsjp *
8177548Scsjp * Redistribution and use in source and binary forms, with or without
9177548Scsjp * modification, are permitted provided that the following conditions
10177548Scsjp * are met:
11177548Scsjp * 1. Redistributions of source code must retain the above copyright
12177548Scsjp *    notice, this list of conditions and the following disclaimer.
13177548Scsjp * 2. Redistributions in binary form must reproduce the above copyright
14177548Scsjp *    notice, this list of conditions and the following disclaimer in the
15177548Scsjp *    documentation and/or other materials provided with the distribution.
16177548Scsjp *
17177548Scsjp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18177548Scsjp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19177548Scsjp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20177548Scsjp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21177548Scsjp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22177548Scsjp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23177548Scsjp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24177548Scsjp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25177548Scsjp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26177548Scsjp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27177548Scsjp * SUCH DAMAGE.
28177548Scsjp *
29177548Scsjp * Copyright (c) 1990, 1991, 1993
30177548Scsjp *	The Regents of the University of California.  All rights reserved.
31177548Scsjp *
32177548Scsjp * This code is derived from the Stanford/CMU enet packet filter,
33177548Scsjp * (net/enet.c) distributed as part of 4.3BSD, and code contributed
34177548Scsjp * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
35177548Scsjp * Berkeley Laboratory.
36177548Scsjp *
37177548Scsjp * Redistribution and use in source and binary forms, with or without
38177548Scsjp * modification, are permitted provided that the following conditions
39177548Scsjp * are met:
40177548Scsjp * 1. Redistributions of source code must retain the above copyright
41177548Scsjp *    notice, this list of conditions and the following disclaimer.
42177548Scsjp * 2. Redistributions in binary form must reproduce the above copyright
43177548Scsjp *    notice, this list of conditions and the following disclaimer in the
44177548Scsjp *    documentation and/or other materials provided with the distribution.
45177548Scsjp * 4. Neither the name of the University nor the names of its contributors
46177548Scsjp *    may be used to endorse or promote products derived from this software
47177548Scsjp *    without specific prior written permission.
48177548Scsjp *
49177548Scsjp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
50177548Scsjp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51177548Scsjp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
52177548Scsjp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
53177548Scsjp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
54177548Scsjp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
55177548Scsjp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
56177548Scsjp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
57177548Scsjp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
58177548Scsjp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
59177548Scsjp * SUCH DAMAGE.
60177548Scsjp *
61177548Scsjp *      @(#)bpf.c	8.4 (Berkeley) 1/9/95
62177548Scsjp */
63177548Scsjp
64177548Scsjp#include <sys/cdefs.h>
65177548Scsjp__FBSDID("$FreeBSD$");
66177548Scsjp
67177548Scsjp#include "opt_bpf.h"
68177548Scsjp
69177548Scsjp#include <sys/param.h>
70177548Scsjp#include <sys/malloc.h>
71177548Scsjp#include <sys/mbuf.h>
72177548Scsjp#include <sys/socket.h>
73177548Scsjp#include <sys/uio.h>
74177548Scsjp#include <sys/kernel.h>
75177548Scsjp#include <sys/sysctl.h>
76177548Scsjp
77177548Scsjp#include <net/if.h>
78177548Scsjp#include <net/bpf.h>
79177548Scsjp#include <net/bpf_buffer.h>
80177548Scsjp#include <net/bpfdesc.h>
81177548Scsjp
82177548Scsjp/*
83177548Scsjp * Implement historical kernel memory buffering model for BPF: two malloc(9)
84177548Scsjp * kernel buffers are hung off of the descriptor.  The size is fixed prior to
85177548Scsjp * attaching to an ifnet, ad cannot be changed after that.  read(2) simply
86177548Scsjp * copies the data to user space using uiomove(9).
87177548Scsjp */
88177548Scsjp
89177548Scsjpstatic int bpf_bufsize = 4096;
90177548ScsjpSYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
91215792Smaxim    &bpf_bufsize, 0, "Default capture buffer size in bytes");
92177548Scsjpstatic int bpf_maxbufsize = BPF_MAXBUFSIZE;
93177548ScsjpSYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
94215792Smaxim    &bpf_maxbufsize, 0, "Maximum capture buffer in bytes");
95177548Scsjp
96177548Scsjp/*
97177548Scsjp * Simple data copy to the current kernel buffer.
98177548Scsjp */
99177548Scsjpvoid
100177548Scsjpbpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,
101177548Scsjp    void *src, u_int len)
102177548Scsjp{
103177548Scsjp	u_char *src_bytes;
104177548Scsjp
105177548Scsjp	src_bytes = (u_char *)src;
106177548Scsjp	bcopy(src_bytes, buf + offset, len);
107177548Scsjp}
108177548Scsjp
109177548Scsjp/*
110177548Scsjp * Scatter-gather data copy from an mbuf chain to the current kernel buffer.
111177548Scsjp */
112177548Scsjpvoid
113177548Scsjpbpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset, void *src,
114177548Scsjp    u_int len)
115177548Scsjp{
116177548Scsjp	const struct mbuf *m;
117177548Scsjp	u_char *dst;
118177548Scsjp	u_int count;
119177548Scsjp
120177548Scsjp	m = (struct mbuf *)src;
121177548Scsjp	dst = (u_char *)buf + offset;
122177548Scsjp	while (len > 0) {
123177548Scsjp		if (m == NULL)
124177548Scsjp			panic("bpf_mcopy");
125177548Scsjp		count = min(m->m_len, len);
126177548Scsjp		bcopy(mtod(m, void *), dst, count);
127177548Scsjp		m = m->m_next;
128177548Scsjp		dst += count;
129177548Scsjp		len -= count;
130177548Scsjp	}
131177548Scsjp}
132177548Scsjp
133177548Scsjp/*
134177548Scsjp * Free BPF kernel buffers on device close.
135177548Scsjp */
136177548Scsjpvoid
137177548Scsjpbpf_buffer_free(struct bpf_d *d)
138177548Scsjp{
139177548Scsjp
140177548Scsjp	if (d->bd_sbuf != NULL)
141177548Scsjp		free(d->bd_sbuf, M_BPF);
142177548Scsjp	if (d->bd_hbuf != NULL)
143177548Scsjp		free(d->bd_hbuf, M_BPF);
144177548Scsjp	if (d->bd_fbuf != NULL)
145177548Scsjp		free(d->bd_fbuf, M_BPF);
146177548Scsjp
147177548Scsjp#ifdef INVARIANTS
148177548Scsjp	d->bd_sbuf = d->bd_hbuf = d->bd_fbuf = (caddr_t)~0;
149177548Scsjp#endif
150177548Scsjp}
151177548Scsjp
152177548Scsjp/*
153177548Scsjp * This is a historical initialization that occurs when the BPF descriptor is
154177548Scsjp * first opened.  It does not imply selection of a buffer mode, so we don't
155177548Scsjp * allocate buffers here.
156177548Scsjp */
157177548Scsjpvoid
158177548Scsjpbpf_buffer_init(struct bpf_d *d)
159177548Scsjp{
160177548Scsjp
161177548Scsjp	d->bd_bufsize = bpf_bufsize;
162177548Scsjp}
163177548Scsjp
164177548Scsjp/*
165177548Scsjp * Allocate or resize buffers.
166177548Scsjp */
167177548Scsjpint
168177548Scsjpbpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)
169177548Scsjp{
170177548Scsjp	u_int size;
171235746Smelifaro	caddr_t fbuf, sbuf;
172177548Scsjp
173235746Smelifaro	size = *i;
174235746Smelifaro	if (size > bpf_maxbufsize)
175235746Smelifaro		*i = size = bpf_maxbufsize;
176235746Smelifaro	else if (size < BPF_MINBUFSIZE)
177235746Smelifaro		*i = size = BPF_MINBUFSIZE;
178235746Smelifaro
179235746Smelifaro	/* Allocate buffers immediately */
180235746Smelifaro	fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
181235746Smelifaro	sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);
182235746Smelifaro
183235745Smelifaro	BPFD_LOCK(d);
184177548Scsjp	if (d->bd_bif != NULL) {
185235746Smelifaro		/* Interface already attached, unable to change buffers */
186235745Smelifaro		BPFD_UNLOCK(d);
187235746Smelifaro		free(fbuf, M_BPF);
188235746Smelifaro		free(sbuf, M_BPF);
189177548Scsjp		return (EINVAL);
190177548Scsjp	}
191235746Smelifaro
192235746Smelifaro	/* Free old buffers if set */
193235746Smelifaro	if (d->bd_fbuf != NULL)
194235746Smelifaro		free(d->bd_fbuf, M_BPF);
195235746Smelifaro	if (d->bd_sbuf != NULL)
196235746Smelifaro		free(d->bd_sbuf, M_BPF);
197235746Smelifaro
198235746Smelifaro	/* Fill in new data */
199177548Scsjp	d->bd_bufsize = size;
200235746Smelifaro	d->bd_fbuf = fbuf;
201235746Smelifaro	d->bd_sbuf = sbuf;
202235746Smelifaro
203235746Smelifaro	d->bd_hbuf = NULL;
204235746Smelifaro	d->bd_slen = 0;
205235746Smelifaro	d->bd_hlen = 0;
206235746Smelifaro
207235745Smelifaro	BPFD_UNLOCK(d);
208177548Scsjp	return (0);
209177548Scsjp}
210177548Scsjp
211177548Scsjp/*
212177548Scsjp * Copy buffer storage to user space in read().
213177548Scsjp */
214177548Scsjpint
215177548Scsjpbpf_buffer_uiomove(struct bpf_d *d, caddr_t buf, u_int len, struct uio *uio)
216177548Scsjp{
217177548Scsjp
218177548Scsjp	return (uiomove(buf, len, uio));
219177548Scsjp}
220