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