Synch with HEAD, this brings in net.bpf.stats.
MFC revision 1.155 (bpf.c) MFC revision 1.30 (bpfdesc.h) Approved by: re@ (kensmith)
This commit is contained in:
parent
f087bcb30a
commit
012dd88ba4
107
sys/net/bpf.c
107
sys/net/bpf.c
@ -78,20 +78,6 @@ static MALLOC_DEFINE(M_BPF, "BPF", "BPF data");
|
||||
|
||||
#define PRINET 26 /* interruptible */
|
||||
|
||||
/*
|
||||
* The default read buffer size is patchable.
|
||||
*/
|
||||
SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl");
|
||||
static int bpf_bufsize = 4096;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
|
||||
&bpf_bufsize, 0, "");
|
||||
static int bpf_maxbufsize = BPF_MAXBUFSIZE;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
|
||||
&bpf_maxbufsize, 0, "");
|
||||
static int bpf_maxinsns = BPF_MAXINSNS;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW,
|
||||
&bpf_maxinsns, 0, "Maximum bpf program instructions");
|
||||
|
||||
/*
|
||||
* bpf_iflist is a list of BPF interface structures, each corresponding to a
|
||||
* specific DLT. The same network interface might have several BPF interface
|
||||
@ -100,6 +86,7 @@ SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW,
|
||||
*/
|
||||
static LIST_HEAD(, bpf_if) bpf_iflist;
|
||||
static struct mtx bpf_mtx; /* bpf global lock */
|
||||
static int bpf_bpfd_cnt;
|
||||
|
||||
static int bpf_allocbufs(struct bpf_d *);
|
||||
static void bpf_attachd(struct bpf_d *d, struct bpf_if *bp);
|
||||
@ -122,6 +109,23 @@ static void filt_bpfdetach(struct knote *);
|
||||
static int filt_bpfread(struct knote *, long);
|
||||
static void bpf_drvinit(void *);
|
||||
static void bpf_clone(void *, char *, int, struct cdev **);
|
||||
static int bpf_stats_sysctl(SYSCTL_HANDLER_ARGS);
|
||||
|
||||
/*
|
||||
* The default read buffer size is patchable.
|
||||
*/
|
||||
SYSCTL_NODE(_net, OID_AUTO, bpf, CTLFLAG_RW, 0, "bpf sysctl");
|
||||
static int bpf_bufsize = 4096;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, bufsize, CTLFLAG_RW,
|
||||
&bpf_bufsize, 0, "");
|
||||
static int bpf_maxbufsize = BPF_MAXBUFSIZE;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, maxbufsize, CTLFLAG_RW,
|
||||
&bpf_maxbufsize, 0, "");
|
||||
static int bpf_maxinsns = BPF_MAXINSNS;
|
||||
SYSCTL_INT(_net_bpf, OID_AUTO, maxinsns, CTLFLAG_RW,
|
||||
&bpf_maxinsns, 0, "Maximum bpf program instructions");
|
||||
SYSCTL_NODE(_net_bpf, OID_AUTO, stats, CTLFLAG_RW,
|
||||
bpf_stats_sysctl, "bpf statistics portal");
|
||||
|
||||
static d_open_t bpfopen;
|
||||
static d_close_t bpfclose;
|
||||
@ -279,6 +283,7 @@ bpf_attachd(d, bp)
|
||||
d->bd_bif = bp;
|
||||
LIST_INSERT_HEAD(&bp->bif_dlist, d, bd_next);
|
||||
|
||||
bpf_bpfd_cnt++;
|
||||
*bp->bif_driverp = bp;
|
||||
BPFIF_UNLOCK(bp);
|
||||
}
|
||||
@ -304,6 +309,7 @@ bpf_detachd(d)
|
||||
*/
|
||||
LIST_REMOVE(d, bd_next);
|
||||
|
||||
bpf_bpfd_cnt--;
|
||||
/*
|
||||
* Let the driver know that there are no more listeners.
|
||||
*/
|
||||
@ -369,6 +375,8 @@ bpfopen(dev, flags, fmt, td)
|
||||
d->bd_bufsize = bpf_bufsize;
|
||||
d->bd_sig = SIGIO;
|
||||
d->bd_seesent = 1;
|
||||
d->bd_pid = td->td_proc->p_pid;
|
||||
strlcpy(d->bd_pcomm, td->td_proc->p_comm, MAXCOMLEN);
|
||||
#ifdef MAC
|
||||
mac_init_bpfdesc(d);
|
||||
mac_create_bpfdesc(td->td_ucred, d);
|
||||
@ -634,6 +642,7 @@ reset_d(d)
|
||||
d->bd_hlen = 0;
|
||||
d->bd_rcount = 0;
|
||||
d->bd_dcount = 0;
|
||||
d->bd_fcount = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1178,6 +1187,7 @@ bpf_tap(bp, pkt, pktlen)
|
||||
++d->bd_rcount;
|
||||
slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
|
||||
if (slen != 0) {
|
||||
d->bd_fcount++;
|
||||
#ifdef MAC
|
||||
if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
|
||||
#endif
|
||||
@ -1247,6 +1257,7 @@ bpf_mtap(bp, m)
|
||||
++d->bd_rcount;
|
||||
slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
|
||||
if (slen != 0)
|
||||
d->bd_fcount++;
|
||||
#ifdef MAC
|
||||
if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
|
||||
#endif
|
||||
@ -1298,6 +1309,7 @@ bpf_mtap2(bp, data, dlen, m)
|
||||
++d->bd_rcount;
|
||||
slen = bpf_filter(d->bd_filter, (u_char *)&mb, pktlen, 0);
|
||||
if (slen != 0)
|
||||
d->bd_fcount++;
|
||||
#ifdef MAC
|
||||
if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
|
||||
#endif
|
||||
@ -1631,6 +1643,73 @@ bpf_drvinit(unused)
|
||||
EVENTHANDLER_REGISTER(dev_clone, bpf_clone, 0, 1000);
|
||||
}
|
||||
|
||||
static void
|
||||
bpfstats_fill_xbpf(struct xbpf_d *d, struct bpf_d *bd)
|
||||
{
|
||||
|
||||
bzero(d, sizeof(*d));
|
||||
BPFD_LOCK_ASSERT(bd);
|
||||
d->bd_immediate = bd->bd_immediate;
|
||||
d->bd_promisc = bd->bd_promisc;
|
||||
d->bd_hdrcmplt = bd->bd_hdrcmplt;
|
||||
d->bd_seesent = bd->bd_seesent;
|
||||
d->bd_async = bd->bd_async;
|
||||
d->bd_rcount = bd->bd_rcount;
|
||||
d->bd_dcount = bd->bd_dcount;
|
||||
d->bd_fcount = bd->bd_fcount;
|
||||
d->bd_sig = bd->bd_sig;
|
||||
d->bd_slen = bd->bd_slen;
|
||||
d->bd_hlen = bd->bd_hlen;
|
||||
d->bd_bufsize = bd->bd_bufsize;
|
||||
d->bd_pid = bd->bd_pid;
|
||||
strlcpy(d->bd_ifname,
|
||||
bd->bd_bif->bif_ifp->if_xname, IFNAMSIZ);
|
||||
strlcpy(d->bd_pcomm, bd->bd_pcomm, MAXCOMLEN);
|
||||
}
|
||||
|
||||
static int
|
||||
bpf_stats_sysctl(SYSCTL_HANDLER_ARGS)
|
||||
{
|
||||
struct xbpf_d *xbdbuf, *xbd;
|
||||
int index, error;
|
||||
struct bpf_if *bp;
|
||||
struct bpf_d *bd;
|
||||
|
||||
/*
|
||||
* XXX This is not technically correct. It is possible for non
|
||||
* privileged users to open bpf devices. It would make sense
|
||||
* if the users who opened the devices were able to retrieve
|
||||
* the statistics for them, too.
|
||||
*/
|
||||
error = suser(req->td);
|
||||
if (error)
|
||||
return (error);
|
||||
if (req->oldptr == NULL)
|
||||
return (SYSCTL_OUT(req, 0, bpf_bpfd_cnt * sizeof(*xbd)));
|
||||
if (bpf_bpfd_cnt == 0)
|
||||
return (SYSCTL_OUT(req, 0, 0));
|
||||
xbdbuf = malloc(req->oldlen, M_BPF, M_WAITOK);
|
||||
mtx_lock(&bpf_mtx);
|
||||
if (req->oldlen < (bpf_bpfd_cnt * sizeof(*xbd))) {
|
||||
mtx_unlock(&bpf_mtx);
|
||||
free(xbdbuf, M_BPF);
|
||||
return (ENOMEM);
|
||||
}
|
||||
index = 0;
|
||||
LIST_FOREACH(bp, &bpf_iflist, bif_next) {
|
||||
LIST_FOREACH(bd, &bp->bif_dlist, bd_next) {
|
||||
xbd = &xbdbuf[index++];
|
||||
BPFD_LOCK(bd);
|
||||
bpfstats_fill_xbpf(xbd, bd);
|
||||
BPFD_UNLOCK(bd);
|
||||
}
|
||||
}
|
||||
mtx_unlock(&bpf_mtx);
|
||||
error = SYSCTL_OUT(req, xbdbuf, index * sizeof(*xbd));
|
||||
free(xbdbuf, M_BPF);
|
||||
return (error);
|
||||
}
|
||||
|
||||
SYSINIT(bpfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE,bpf_drvinit,NULL)
|
||||
|
||||
#else /* !DEV_BPF && !NETGRAPH_BPF */
|
||||
|
@ -42,6 +42,8 @@
|
||||
#include <sys/callout.h>
|
||||
#include <sys/selinfo.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/conf.h>
|
||||
#include <net/if.h>
|
||||
|
||||
/*
|
||||
* Descriptor associated with each open bpf file.
|
||||
@ -90,6 +92,9 @@ struct bpf_d {
|
||||
struct mtx bd_mtx; /* mutex for this descriptor */
|
||||
struct callout bd_callout; /* for BPF timeouts with select */
|
||||
struct label *bd_label; /* MAC label for descriptor */
|
||||
u_long bd_fcount; /* number of packets which matched filter */
|
||||
pid_t bd_pid; /* PID which created descriptor */
|
||||
char bd_pcomm[MAXCOMLEN + 1];
|
||||
};
|
||||
|
||||
/* Values for bd_state */
|
||||
@ -123,6 +128,27 @@ struct bpf_if {
|
||||
struct mtx bif_mtx; /* mutex for interface */
|
||||
};
|
||||
|
||||
/*
|
||||
* External representation of the bpf descriptor
|
||||
*/
|
||||
struct xbpf_d {
|
||||
u_char bd_promisc;
|
||||
u_char bd_immediate;
|
||||
int bd_hdrcmplt;
|
||||
int bd_seesent;
|
||||
int bd_async;
|
||||
u_long bd_rcount;
|
||||
u_long bd_dcount;
|
||||
u_long bd_fcount;
|
||||
int bd_sig;
|
||||
int bd_slen;
|
||||
int bd_hlen;
|
||||
int bd_bufsize;
|
||||
pid_t bd_pid;
|
||||
char bd_ifname[IFNAMSIZ];
|
||||
char bd_pcomm[MAXCOMLEN + 1];
|
||||
};
|
||||
|
||||
#define BPFIF_LOCK(bif) mtx_lock(&(bif)->bif_mtx)
|
||||
#define BPFIF_UNLOCK(bif) mtx_unlock(&(bif)->bif_mtx)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user