Introduce a bpfstat utility. This program can be used to retrieve

stats provided by bpf(4). This program will live in tools/ for now
until we figure out where it will live permanently. Based on some
discussions on developers@, it is likely that we will be adding
this functionality to netstat(1) at some point.
This commit is contained in:
csjp 2005-07-26 21:38:54 +00:00
parent f0d1c908d8
commit e5ca7cc52f
4 changed files with 402 additions and 0 deletions

View File

@ -0,0 +1,17 @@
# $FreeBSD$
OBJS= bpfstat.o
CC?= CC
PROG= bpfstat
PREFIX?=/usr/local
bpfstat: $(OBJS)
$(CC) -lm -o $(PROG) $(OBJS)
install:
cp $(PROG) $(PREFIX)/sbin
cp $(PROG).8 $(PREFIX)/man/man8/
clean:
rm -f *.o $(PROG)
all: bpfstat

View File

@ -0,0 +1,83 @@
.\" Copyright (c) 2005 Christian S.J. Peron
.\" All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
.Dd July 22, 2005
.Os
.Dt BPFSTAT 8
.Sh NAME
.Nm bpfstat
.Nd "retrieve bpf statistics"
.Sh SYNOPSIS
.Nm
.Op Fl q
.Op Fl c Ar procname
.Op Fl i Ar seconds
.Op Fl I Ar interface
.Op Fl p Ar pid
.Sh DESCRIPTION
The
.Nm
utility will print statistics associated with active
.Xr bpf 4
devices.
These statistics contain information about device state as
well as packets which have been received, dropped or
matched by the bpf filter program.
.Pp
The following options are available:
.Bl -tag -width indent
.It Fl c Ar procname
Print information about devices which were opened by processes named
.Ar procname .
.It Fl i Ar seconds
Continuously retrieve statistics for devices, sleeping for
.Ar seconds
seconds after each iteration.
.It Fl I Ar interface
Print information about devices if they are attached to network
interface
.Ar interface .
.It Fl p Ar pid
Print information about devices if they were opened by process ID
.Ar pid .
.It Fl q
Suppress printing of column names.
.El
.Sh "EXIT STATUS"
The
.Nm
utility exits 0 on success, and >0 if an error occurs.
.Sh "SEE ALSO"
.Xr pcap 3 ,
.Xr bpf 4 ,
.Xr tcpdump 8
.Sh HISTORY
The
.Nm
utility first appeared in
.Fx 7.0 .
.Sh AUTHORS
.An "Christian S.J. Peron" Aq csjp@FreeBSD.org

View File

@ -0,0 +1,249 @@
/*-
* Copyright (c) 2005 Christian S.J. Peron
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/time.h>
#include <sys/proc.h>
#include <sys/user.h>
#include <sys/stat.h>
#include <sys/vnode.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
#include <net/bpfdesc.h>
#include <ctype.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <math.h>
#include "bpfstat.h"
/* Function prototypes */
static void bpfd_print_header(struct conf *);
static void bpfd_parse_flags(struct xbpf_d *, char *);
static struct xbpf_d *
bpfd_get_descs(struct conf *);
static void bpfd_print_row(struct xbpf_d *, struct conf *);
static void usage(char *);
static void setwidths(struct colwidths *);
static int diglen(double);
static void
setwidths(struct colwidths *c)
{
c->rc_width = 4;
c->dc_width = 4;
c->pd_width = 3;
c->hb_width = 5;
c->sb_width = 5;
c->fc_width = 5;
}
static int
diglen(double n)
{
int width;
width = (int)ceil(log10(n));
return (width);
}
static void
calcwidths(struct conf *conf, struct xbpf_d *bd)
{
struct colwidths *c;
int width;
c = &conf->cw;
width = diglen((double)bd->bd_rcount);
if (width > c->rc_width)
c->rc_width = width;
width = diglen((double)bd->bd_dcount);
if (width > c->dc_width)
c->dc_width = width;
width = diglen((double)bd->bd_pid);
if (width > c->pd_width)
c->pd_width = width;
width = diglen((double)bd->bd_slen);
if (width > c->sb_width)
c->sb_width = width;
width = diglen((double)bd->bd_hlen);
if (width > c->hb_width)
c->hb_width = width;
width = diglen((double)bd->bd_fcount);
if (width > c->fc_width)
c->fc_width = width;
}
static void
bpfd_print_header(struct conf *conf)
{
struct colwidths *c;
if (conf->qflag || conf->lps > 0)
return;
c = &conf->cw;
printf("%*s %*s %*s %*s %*s %*s %*s %*s %s\n",
c->pd_width, "pid",
7, "netif",
6, "flags",
c->rc_width, "recv",
c->dc_width, "drop",
c->fc_width, "match",
c->sb_width, "sblen",
c->hb_width, "hblen",
"command");
}
static void
bpfd_print_row(struct xbpf_d *bd, struct conf *conf)
{
struct colwidths *c;
char flagbuf[8];
c = &conf->cw;
bpfd_parse_flags(bd, &flagbuf[0]);
printf("%*d %*s %*s %*lu %*lu %*lu %*d %*d %s\n",
c->pd_width, bd->bd_pid,
7, bd->bd_ifname,
6, flagbuf,
c->rc_width, bd->bd_rcount,
c->dc_width, bd->bd_dcount,
c->fc_width, bd->bd_fcount,
c->sb_width, bd->bd_slen,
c->hb_width, bd->bd_hlen,
bd->bd_pcomm);
}
static void
bpfd_parse_flags(struct xbpf_d *bd, char *flagbuf)
{
*flagbuf++ = bd->bd_promisc ? 'p' : '-';
*flagbuf++ = bd->bd_immediate ? 'i' : '-';
*flagbuf++ = bd->bd_hdrcmplt ? '-' : 'f';
*flagbuf++ = bd->bd_seesent ? 's' : '.';
*flagbuf++ = bd->bd_async ? 'a' : '-';
*flagbuf++ = '\0';
}
static struct xbpf_d *
bpfd_get_descs(struct conf *conf)
{
size_t bpf_alloc;
int error;
error = sysctlbyname(BPFSOID, NULL, &bpf_alloc,
NULL, 0);
if (error < 0)
err(1, "get buffer size");
if (bpf_alloc == 0)
return (NULL);
conf->bpf_vec = malloc(bpf_alloc);
if (conf->bpf_vec == NULL)
return (NULL);
conf->nbdevs = bpf_alloc / sizeof(struct xbpf_d);
bzero(conf->bpf_vec, bpf_alloc);
error = sysctlbyname(BPFSOID, conf->bpf_vec,
&bpf_alloc, NULL, 0);
if (error < 0)
err(1, "get descriptors failed");
if (bpf_alloc == 0)
return (NULL);
return (conf->bpf_vec);
}
int
main(int argc, char *argv [])
{
struct xbpf_d *bd, *bpfds;
int ch;
char *rem;
struct conf cf;
memset(&cf, 0, sizeof(cf));
setwidths(&cf.cw);
while ((ch = getopt(argc, argv, "c:i:I:p:q")) != -1)
switch (ch) {
case 'c':
cf.cflag = optarg;
break;
case 'i':
cf.iflag = strtol(optarg, &rem, 0);
break;
case 'I':
cf.Iflag = optarg;
break;
case 'p':
cf.pflag = strtol(optarg, &rem, 0);
break;
case 'q':
cf.qflag++;
break;
default:
usage(argv[0]);
}
do {
bpfds = bpfd_get_descs(&cf);
if (bpfds == NULL)
break;
for (bd = &bpfds[0]; bd < &bpfds[cf.nbdevs]; bd++)
calcwidths(&cf, bd);
bpfd_print_header(&cf);
for (bd = &bpfds[0]; bd < &bpfds[cf.nbdevs]; bd++) {
if (cf.pflag && cf.pflag != bd->bd_pid)
continue;
if (cf.Iflag &&
strcmp(bd->bd_ifname, cf.Iflag) != 0)
continue;
if (cf.cflag &&
strcmp(bd->bd_pcomm, cf.cflag) != 0)
continue;
bpfd_print_row(bd, &cf);
}
cf.lps++;
free(bpfds);
(void)sleep(cf.iflag);
} while (cf.iflag > 0);
return (0);
}
static void
usage(char *prog)
{
fprintf(stderr,
"usage: %s [-q] [-c procname] [-i wait] [-I interface] [-p pid]\n",
prog);
exit(1);
}

View File

@ -0,0 +1,53 @@
/*-
* Copyright (c) 2005 Christian S J Peron
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef BPFSTAT_H_
#define BPFSTAT_H_
struct colwidths {
int rc_width;
int dc_width;
int pd_width;
int hb_width;
int sb_width;
int fc_width;
};
struct conf {
char *cflag;
char *Iflag;
pid_t pflag;
int qflag;
int iflag;
int nbdevs;
int lps;
struct colwidths cw;
struct xbpf_d *bpf_vec;
};
#define BPFSOID "net.bpf.stats"
#endif /* BPFSTAT_H_ */