o add BIOCGDLTLIST and BIOCSDLT ioctls to get the data link type list
and set the link type for use by libpcap and tcpdump o move mtx unlock in bpfdetach up; it doesn't need to be held so long o change printf in bpf_detach to distinguish it from the same one in bpfsetdlt Note there are locking issues here related to ioctl processing; they have not been addressed here. Submitted by: Guy Harris <guy@alum.mit.edu> Obtained from: NetBSD (w/ locking modifications)
This commit is contained in:
parent
63b49e34b0
commit
e74e7998d8
105
sys/net/bpf.c
105
sys/net/bpf.c
@ -109,6 +109,8 @@ static void catchpacket(struct bpf_d *, u_char *, u_int,
|
||||
u_int, void (*)(const void *, void *, size_t));
|
||||
static void reset_d(struct bpf_d *);
|
||||
static int bpf_setf(struct bpf_d *, struct bpf_program *);
|
||||
static int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
|
||||
static int bpf_setdlt(struct bpf_d *, u_int);
|
||||
|
||||
static d_open_t bpfopen;
|
||||
static d_close_t bpfclose;
|
||||
@ -286,7 +288,8 @@ bpf_detachd(d)
|
||||
* the driver into promiscuous mode, but can't
|
||||
* take it out.
|
||||
*/
|
||||
if_printf(bp->bif_ifp, "ifpromisc failed %d\n", error);
|
||||
if_printf(bp->bif_ifp,
|
||||
"bpf_detach: ifpromisc failed (%d)\n", error);
|
||||
}
|
||||
}
|
||||
/* Remove d from the interface's descriptor list. */
|
||||
@ -736,7 +739,7 @@ bpfioctl(dev, cmd, addr, flags, td)
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get device parameters.
|
||||
* Get current data link type.
|
||||
*/
|
||||
case BIOCGDLT:
|
||||
if (d->bd_bif == 0)
|
||||
@ -745,6 +748,26 @@ bpfioctl(dev, cmd, addr, flags, td)
|
||||
*(u_int *)addr = d->bd_bif->bif_dlt;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get a list of supported data link types.
|
||||
*/
|
||||
case BIOCGDLTLIST:
|
||||
if (d->bd_bif == 0)
|
||||
error = EINVAL;
|
||||
else
|
||||
error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Set data link type.
|
||||
*/
|
||||
case BIOCSDLT:
|
||||
if (d->bd_bif == 0)
|
||||
error = EINVAL;
|
||||
else
|
||||
error = bpf_setdlt(d, *(u_int *)addr);
|
||||
break;
|
||||
|
||||
/*
|
||||
* Get interface name.
|
||||
*/
|
||||
@ -1331,10 +1354,10 @@ bpfdetach(ifp)
|
||||
struct bpf_if *bp, *bp_prev;
|
||||
struct bpf_d *d;
|
||||
|
||||
mtx_lock(&bpf_mtx);
|
||||
|
||||
/* Locate BPF interface information */
|
||||
bp_prev = NULL;
|
||||
|
||||
mtx_lock(&bpf_mtx);
|
||||
for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
|
||||
if (ifp == bp->bif_ifp)
|
||||
break;
|
||||
@ -1354,6 +1377,7 @@ bpfdetach(ifp)
|
||||
} else {
|
||||
bpf_iflist = bp->bif_next;
|
||||
}
|
||||
mtx_unlock(&bpf_mtx);
|
||||
|
||||
while ((d = bp->bif_dlist) != NULL) {
|
||||
bpf_detachd(d);
|
||||
@ -1364,8 +1388,81 @@ bpfdetach(ifp)
|
||||
|
||||
mtx_destroy(&bp->bif_mtx);
|
||||
free(bp, M_BPF);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a list of available data link type of the interface.
|
||||
*/
|
||||
static int
|
||||
bpf_getdltlist(d, bfl)
|
||||
struct bpf_d *d;
|
||||
struct bpf_dltlist *bfl;
|
||||
{
|
||||
int n, error;
|
||||
struct ifnet *ifp;
|
||||
struct bpf_if *bp;
|
||||
|
||||
ifp = d->bd_bif->bif_ifp;
|
||||
n = 0;
|
||||
error = 0;
|
||||
mtx_lock(&bpf_mtx);
|
||||
for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
|
||||
if (bp->bif_ifp != ifp)
|
||||
continue;
|
||||
if (bfl->bfl_list != NULL) {
|
||||
if (n >= bfl->bfl_len) {
|
||||
mtx_unlock(&bpf_mtx);
|
||||
return (ENOMEM);
|
||||
}
|
||||
error = copyout(&bp->bif_dlt,
|
||||
bfl->bfl_list + n, sizeof(u_int));
|
||||
}
|
||||
n++;
|
||||
}
|
||||
mtx_unlock(&bpf_mtx);
|
||||
bfl->bfl_len = n;
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the data link type of a BPF instance.
|
||||
*/
|
||||
static int
|
||||
bpf_setdlt(d, dlt)
|
||||
struct bpf_d *d;
|
||||
u_int dlt;
|
||||
{
|
||||
int error, opromisc;
|
||||
struct ifnet *ifp;
|
||||
struct bpf_if *bp;
|
||||
|
||||
if (d->bd_bif->bif_dlt == dlt)
|
||||
return (0);
|
||||
ifp = d->bd_bif->bif_ifp;
|
||||
mtx_lock(&bpf_mtx);
|
||||
for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
|
||||
if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
|
||||
break;
|
||||
}
|
||||
mtx_unlock(&bpf_mtx);
|
||||
if (bp != NULL) {
|
||||
BPFD_LOCK(d);
|
||||
opromisc = d->bd_promisc;
|
||||
bpf_detachd(d);
|
||||
bpf_attachd(d, bp);
|
||||
reset_d(d);
|
||||
BPFD_UNLOCK(d);
|
||||
if (opromisc) {
|
||||
error = ifpromisc(bp->bif_ifp, 1);
|
||||
if (error)
|
||||
if_printf(bp->bif_ifp,
|
||||
"bpf_setdlt: ifpromisc failed (%d)\n",
|
||||
error);
|
||||
else
|
||||
d->bd_promisc = 1;
|
||||
}
|
||||
}
|
||||
return (bp == NULL ? EINVAL : 0);
|
||||
}
|
||||
|
||||
static void bpf_drvinit(void *unused);
|
||||
|
@ -115,6 +115,8 @@ struct bpf_version {
|
||||
#define BIOCSHDRCMPLT _IOW('B',117, u_int)
|
||||
#define BIOCGSEESENT _IOR('B',118, u_int)
|
||||
#define BIOCSSEESENT _IOW('B',119, u_int)
|
||||
#define BIOCSDLT _IOW('B',120, u_int)
|
||||
#define BIOCGDLTLIST _IOWR('B',121, struct bpf_dltlist)
|
||||
|
||||
/*
|
||||
* Structure prepended to each packet.
|
||||
@ -339,6 +341,14 @@ struct bpf_insn {
|
||||
#define BPF_STMT(code, k) { (u_short)(code), 0, 0, k }
|
||||
#define BPF_JUMP(code, k, jt, jf) { (u_short)(code), jt, jf, k }
|
||||
|
||||
/*
|
||||
* Structure to retrieve available DLTs for the interface.
|
||||
*/
|
||||
struct bpf_dltlist {
|
||||
u_int bfl_len; /* number of bfd_list array */
|
||||
u_int *bfl_list; /* array of DLTs */
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
struct bpf_if;
|
||||
int bpf_validate(const struct bpf_insn *, int);
|
||||
|
Loading…
x
Reference in New Issue
Block a user