From 012dd88ba4497c601d0a27903acf37c240797816 Mon Sep 17 00:00:00 2001 From: csjp Date: Sun, 31 Jul 2005 00:48:18 +0000 Subject: [PATCH] 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) --- sys/net/bpf.c | 107 ++++++++++++++++++++++++++++++++++++++++------ sys/net/bpfdesc.h | 26 +++++++++++ 2 files changed, 119 insertions(+), 14 deletions(-) diff --git a/sys/net/bpf.c b/sys/net/bpf.c index e917866f3c0e..c42ea8178364 100644 --- a/sys/net/bpf.c +++ b/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 */ diff --git a/sys/net/bpfdesc.h b/sys/net/bpfdesc.h index 5e0eca447bc8..63f898783119 100644 --- a/sys/net/bpfdesc.h +++ b/sys/net/bpfdesc.h @@ -42,6 +42,8 @@ #include #include #include +#include +#include /* * 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)