From 682952bd0cc8980caff3a517215b6bff24209daa Mon Sep 17 00:00:00 2001 From: Reyk Floeter Date: Fri, 7 Jan 2005 16:28:39 +0000 Subject: add support for BIOCGDLTLIST and BIOCSDLT, see bpf(4) ok canacar@, fgsch@, tested by some other people --- share/man/man4/bpf.4 | 40 +++++++++++++++++- sys/net/bpf.c | 85 ++++++++++++++++++++++++++++++++++++++- sys/net/bpf.h | 13 +++++- sys/net80211/ieee80211_radiotap.h | 7 +--- 4 files changed, 136 insertions(+), 9 deletions(-) diff --git a/share/man/man4/bpf.4 b/share/man/man4/bpf.4 index 59caba0ac2a..348ec0d7ea2 100644 --- a/share/man/man4/bpf.4 +++ b/share/man/man4/bpf.4 @@ -1,4 +1,4 @@ -.\" $OpenBSD: bpf.4,v 1.22 2004/05/31 17:06:37 canacar Exp $ +.\" $OpenBSD: bpf.4,v 1.23 2005/01/07 16:28:38 reyk Exp $ .\" $NetBSD: bpf.4,v 1.7 1995/09/27 18:31:50 thorpej Exp $ .\" .\" Copyright (c) 1990 The Regents of the University of California. @@ -146,6 +146,44 @@ The device types, prefixed with .Dq DLT_ , are defined in .Aq Pa net/bpf.h . +.It Dv BIOCGDLTLIST (struct bpf_dltlist) +Returns an array of the available types of the data link layer +underlying the attached interface: +.Bd -literal -offset indent +struct bpf_dltlist { + u_int bfl_len; + u_int *bfl_list; +}; +.Ed +.Pp +The available types are returned in the array pointed to by the +.Va bfl_list +field while their length in +.Vt u_int +is supplied to the +.Va bfl_len +field. +.Er ENOMEM +is returned if there is not enough buffer space and +.Er EFAULT +is returned if a bad address is encountered. The +.Va bfl_len +field is modified on return to indicate the actual length in +.Vt u_int +of the array returned. +If +.Va bfl_list +is +.Dv NULL , +the +.Va bfl_len +field is set to indicate the required length of the array in +.Vt u_int . +.It Dv BIOCSDLT (u_int) +Changes the type of the data link layer underlying the attached interface. +.Er EINVAL +is returned if no interface has been specified or the specified +type is not available for the interface. .It Dv BIOCPROMISC Forces the interface into promiscuous mode. All packets, not just those destined for the local host, are processed. diff --git a/sys/net/bpf.c b/sys/net/bpf.c index 25440ec33ec..b1d29bba72d 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.c,v 1.55 2004/12/17 15:56:58 reyk Exp $ */ +/* $OpenBSD: bpf.c,v 1.56 2005/01/07 16:28:38 reyk Exp $ */ /* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */ /* @@ -92,6 +92,8 @@ static __inline void bpf_wakeup(struct bpf_d *); void bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t, void (*)(const void *, void *, size_t)); void bpf_reset_d(struct bpf_d *); +int bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *); +int bpf_setdlt(struct bpf_d *, u_int); void filt_bpfrdetach(struct knote *); int filt_bpfread(struct knote *, long); @@ -573,7 +575,9 @@ bpf_reset_d(struct bpf_d *d) * BIOCSETF Set ethernet read filter. * BIOCFLUSH Flush read packet buffer. * BIOCPROMISC Put interface into promiscuous mode. + * BIOCGDLTLIST Get supported link layer types. * BIOCGDLT Get link layer type. + * BIOCSDLT Set link layer type. * BIOCGETIF Get interface name. * BIOCSETIF Set interface. * BIOCSRTIMEOUT Set read timeout. @@ -598,6 +602,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) case BIOCGBLEN: case BIOCFLUSH: case BIOCGDLT: + case BIOCGDLTLIST: case BIOCGETIF: case BIOCGRTIMEOUT: case BIOCGSTATS: @@ -705,6 +710,16 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) splx(s); break; + /* + * Get a list of supported device parameters. + */ + case BIOCGDLTLIST: + if (d->bd_bif == NULL) + error = EINVAL; + else + error = bpf_getdltlist(d, (struct bpf_dltlist *)addr); + break; + /* * Get device parameters. */ @@ -715,6 +730,16 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) *(u_int *)addr = d->bd_bif->bif_dlt; break; + /* + * Set device parameters. + */ + case BIOCSDLT: + if (d->bd_bif == NULL) + error = EINVAL; + else + error = bpf_setdlt(d, *(u_int *)addr); + break; + /* * Set interface name. */ @@ -1420,3 +1445,61 @@ bpfilter_destroy(struct bpf_d *bd) LIST_REMOVE(bd, bd_list); free(bd, M_DEVBUF); } + +/* + * Get a list of available data link type of the interface. + */ +int +bpf_getdltlist(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; + 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) + return (ENOMEM); + error = copyout(&bp->bif_dlt, + bfl->bfl_list + n, sizeof(u_int)); + if (error) + break; + } + n++; + } + + bfl->bfl_len = n; + return (error); +} + +/* + * Set the data link type of a BPF instance. + */ +int +bpf_setdlt(struct bpf_d *d, u_int dlt) +{ + int s; + struct ifnet *ifp; + struct bpf_if *bp; + + if (d->bd_bif->bif_dlt == dlt) + return (0); + ifp = d->bd_bif->bif_ifp; + for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) { + if (bp->bif_ifp == ifp && bp->bif_dlt == dlt) + break; + } + if (bp == NULL) + return (EINVAL); + s = splimp(); + bpf_detachd(d); + bpf_attachd(d, bp); + bpf_reset_d(d); + splx(s); + return (0); +} diff --git a/sys/net/bpf.h b/sys/net/bpf.h index da4dc8a06ae..c8465ea15c7 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bpf.h,v 1.29 2004/12/17 15:56:58 reyk Exp $ */ +/* $OpenBSD: bpf.h,v 1.30 2005/01/07 16:28:38 reyk Exp $ */ /* $NetBSD: bpf.h,v 1.15 1996/12/13 07:57:33 mikel Exp $ */ /* @@ -115,6 +115,8 @@ struct bpf_version { #define BIOCSETWF _IOW('B',119, struct bpf_program) #define BIOCGFILDROP _IOR('B',120, u_int) #define BIOCSFILDROP _IOW('B',121, u_int) +#define BIOCSDLT _IOW('B',122, u_int) +#define BIOCGDLTLIST _IOWR('B',123, struct bpf_dltlist) struct bpf_timeval { u_int32_t tv_sec; @@ -174,6 +176,7 @@ struct bpf_hdr { #define DLT_PPP_ETHER 51 /* PPP over Ethernet; session only w/o ether header */ #define DLT_IEEE802_11 105 /* IEEE 802.11 wireless */ #define DLT_PFLOG 117 /* Packet filter logging, by pcap people */ +#define DLT_IEEE802_11_RADIO 127 /* IEEE 802.11 plus WLAN header */ /* * The instruction encodings. @@ -241,6 +244,14 @@ struct bpf_insn { u_int32_t 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 */ +}; + /* * Macros for insn array initializers. */ diff --git a/sys/net80211/ieee80211_radiotap.h b/sys/net80211/ieee80211_radiotap.h index d0559e3fc01..1d355d2af0e 100644 --- a/sys/net80211/ieee80211_radiotap.h +++ b/sys/net80211/ieee80211_radiotap.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ieee80211_radiotap.h,v 1.4 2004/12/30 23:32:55 reyk Exp $ */ +/* $OpenBSD: ieee80211_radiotap.h,v 1.5 2005/01/07 16:28:38 reyk Exp $ */ /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.3 2004/04/05 22:13:21 sam Exp $ */ /* $NetBSD: ieee80211_radiotap.h,v 1.9 2004/06/06 04:13:28 dyoung Exp $ */ @@ -47,11 +47,6 @@ * function of...") that I cannot set false expectations for lawyerly * readers. */ -#ifdef _KERNEL -#ifndef DLT_IEEE802_11_RADIO -#define DLT_IEEE802_11_RADIO 127 /* 802.11 plus WLAN header */ -#endif -#endif /* _KERNEL */ /* XXX tcpdump/libpcap do not tolerate variable-length headers, * yet, so we pad every radiotap header to 64 bytes. Ugh. -- cgit v1.2.3