/*-1* SPDX-License-Identifier: BSD-3-Clause2*3* Copyright (c) 2007 Seccuris Inc.4* All rights reserved.5*6* This software was developed by Robert N. M. Watson under contract to7* Seccuris Inc.8*9* Redistribution and use in source and binary forms, with or without10* modification, are permitted provided that the following conditions11* are met:12* 1. Redistributions of source code must retain the above copyright13* notice, this list of conditions and the following disclaimer.14* 2. Redistributions in binary form must reproduce the above copyright15* notice, this list of conditions and the following disclaimer in the16* documentation and/or other materials provided with the distribution.17*18* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND19* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE20* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE21* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE22* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL23* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS24* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)25* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT26* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY27* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF28* SUCH DAMAGE.29*30* Copyright (c) 1990, 1991, 199331* The Regents of the University of California. All rights reserved.32*33* This code is derived from the Stanford/CMU enet packet filter,34* (net/enet.c) distributed as part of 4.3BSD, and code contributed35* to Berkeley by Steven McCanne and Van Jacobson both of Lawrence36* Berkeley Laboratory.37*38* Redistribution and use in source and binary forms, with or without39* modification, are permitted provided that the following conditions40* are met:41* 1. Redistributions of source code must retain the above copyright42* notice, this list of conditions and the following disclaimer.43* 2. Redistributions in binary form must reproduce the above copyright44* notice, this list of conditions and the following disclaimer in the45* documentation and/or other materials provided with the distribution.46* 3. Neither the name of the University nor the names of its contributors47* may be used to endorse or promote products derived from this software48* without specific prior written permission.49*50* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND51* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE52* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE53* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE54* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL55* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS56* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)57* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT58* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY59* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF60* SUCH DAMAGE.61*/6263#include <sys/cdefs.h>64#include "opt_bpf.h"6566#include <sys/param.h>67#include <sys/lock.h>68#include <sys/malloc.h>69#include <sys/mbuf.h>70#include <sys/mutex.h>71#include <sys/socket.h>72#include <sys/uio.h>73#include <sys/kernel.h>74#include <sys/sysctl.h>7576#include <net/if.h>77#include <net/bpf.h>78#include <net/bpf_buffer.h>79#include <net/bpfdesc.h>8081/*82* Implement historical kernel memory buffering model for BPF: two malloc(9)83* kernel buffers are hung off of the descriptor. The size is fixed prior to84* attaching to an ifnet, ad cannot be changed after that. read(2) simply85* copies the data to user space using uiomove(9).86*/8788static int bpf_bufsize = 4096;89SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,90&bpf_bufsize, 0, "Default capture buffer size in bytes");91static int bpf_maxbufsize = BPF_MAXBUFSIZE;92SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,93&bpf_maxbufsize, 0, "Maximum capture buffer in bytes");9495/*96* Simple data copy to the current kernel buffer.97*/98void99bpf_buffer_append_bytes(struct bpf_d *d, caddr_t buf, u_int offset,100void *src, u_int len)101{102u_char *src_bytes;103104src_bytes = (u_char *)src;105bcopy(src_bytes, buf + offset, len);106}107108/*109* Scatter-gather data copy from an mbuf chain to the current kernel buffer.110*/111void112bpf_buffer_append_mbuf(struct bpf_d *d, caddr_t buf, u_int offset, void *src,113u_int len)114{115const struct mbuf *m;116u_char *dst;117118m = (struct mbuf *)src;119dst = (u_char *)buf + offset;120m_copydata(m, 0, len, dst);121}122123/*124* Free BPF kernel buffers on device close.125*/126void127bpf_buffer_free(struct bpf_d *d)128{129130if (d->bd_sbuf != NULL)131free(d->bd_sbuf, M_BPF);132if (d->bd_hbuf != NULL)133free(d->bd_hbuf, M_BPF);134if (d->bd_fbuf != NULL)135free(d->bd_fbuf, M_BPF);136137#ifdef INVARIANTS138d->bd_sbuf = d->bd_hbuf = d->bd_fbuf = (caddr_t)~0;139#endif140}141142/*143* This is a historical initialization that occurs when the BPF descriptor is144* first opened. It does not imply selection of a buffer mode, so we don't145* allocate buffers here.146*/147void148bpf_buffer_init(struct bpf_d *d)149{150151d->bd_bufsize = bpf_bufsize;152}153154/*155* Allocate or resize buffers.156*/157int158bpf_buffer_ioctl_sblen(struct bpf_d *d, u_int *i)159{160u_int size;161caddr_t fbuf, sbuf;162163size = *i;164if (size > bpf_maxbufsize)165*i = size = bpf_maxbufsize;166else if (size < BPF_MINBUFSIZE)167*i = size = BPF_MINBUFSIZE;168169/* Allocate buffers immediately */170fbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);171sbuf = (caddr_t)malloc(size, M_BPF, M_WAITOK);172173BPFD_LOCK(d);174if (d->bd_bif != NULL) {175/* Interface already attached, unable to change buffers */176BPFD_UNLOCK(d);177free(fbuf, M_BPF);178free(sbuf, M_BPF);179return (EINVAL);180}181182/* Free old buffers if set */183if (d->bd_fbuf != NULL)184free(d->bd_fbuf, M_BPF);185if (d->bd_sbuf != NULL)186free(d->bd_sbuf, M_BPF);187188/* Fill in new data */189d->bd_bufsize = size;190d->bd_fbuf = fbuf;191d->bd_sbuf = sbuf;192193d->bd_hbuf = NULL;194d->bd_slen = 0;195d->bd_hlen = 0;196197BPFD_UNLOCK(d);198return (0);199}200201/*202* Copy buffer storage to user space in read().203*/204int205bpf_buffer_uiomove(struct bpf_d *d, caddr_t buf, u_int len, struct uio *uio)206{207208return (uiomove(buf, len, uio));209}210211212