List Info

Thread: BPF support for writing raw IEEE 802.11 frames




BPF support for writing raw IEEE 802.11 frames
user name
2006-08-01 18:19:15
Hello all,

(Long email)

I am currently working at BBN Technologies with Greg Troxel
on a project to
virtualize an IEEE 802.11 interface over a network. The
broad
architecture is as follows: (real/virtual host refers to the
host on which
the real/virtual interface is attached.)

1. Frames arriving on the real interface are read by a
userspace
daemon using BPF, encapsulated in UDP packets and passed off
to a
userspace daemon running on the virtual host. This daemon
decapsulates
the UDP packets and injects the extracted 802.11 frames into
the
kernel stack at the virtual host. This injection is done by
extending
the tap(4) interface to support 802.11 in addition to
Ethernet.

2. When a packet is to be transmitted out the virtual
interface, it is
encapsulated in 802.11 headers and passed to userspace using
the
extended tap(4) interface mentioned above. The userspace
daemon at the
virtual host encapsulates the frames in UDP, and sends them
to the
userspace daemon at the real host, where they are injected
into the
real interface using BPF.

(There are a lot of additional details here on what it means
to
 virtualize an IEEE 802.11 interface over a network - that
is the
 subject of another email.)

As part of this project, we need the ability to inject raw
IEEE 802.11
frames from userspace using BPF. It seems like the current
NetBSD
bpf_write path does not support DLT_IEEE802_11, or
DLT_IEEE802_11_RADIO. This is because:

1. (minor) net/bpf.c: bpf_write calls bpf_movein, which does
not
recognize the dlt DLT_IEEE802_11/DLT_IEEE802_11_RADIO and
returns EIO.
This is easily fixable.

2. net/bpf.c: bpf_write passes an mbuf to ifp->if_output.
All 802.11
drivers invoke ether_ifattach via ieee80211_ifattach, and
ether_ifattach sets ifp->if_output = ether_output. Thus,
bpf_write
ends up passing raw DLT_IEEE802_11 mbufs to ether_output.
This causes
DLT_IEEE80211 raw frame writes on a BPF to break:

a. ether_output expects raw frames with an attached Ethernet
header.
DLT_IEEE80211 raw frames do not have an Ethernet header.

b. ether_output enqueues the frame and calls the
driver-provided
foo_start routine, which typically calls ieee80211_encap to
do
IEEE 802.11 encapsulation. If this worked, it would
incorrectly put an
802.11 header on the raw 802.11 frame. (In practice, it
won't work
          because ieee80211_encap expects its input to be
Ethernet
          encapsulated; it strips off the
          Ethernet header and adds an IEEE 802.11 header and
a LLC
          header. Here the raw DLT_IEEE802_11 frame does not
have an
          Ethernet header.)


I am currently working on fixing this, and adding support
for
DLT_IEEE802_11 to the BPF write path. We expect raw
DLT_IEEE802_11
frames to be injected in the same format as they are read:
data frames
consist of a 802.11 header, and LLC header+IP packet in the
802.11
payload. Management frames consist of an 802.11 header and
the
management frame. There are multiple options on how to
implement this,
           and as I am fairly new to the NetBSD kernel, I
was hoping
           to get some feedback on which way to proceed:

Option 1: When net80211 code registers DLT_IEEE802_11 with
bpf using
bpfattach, it also pass a callback to be invoked whenever a
raw packet
is written to the bpf device. This callback enqueues the raw
802.11
frames in the management queue (ieee80211com->mgtq)
(whose present
          semantics are post-802.11 encap).

Advantage: no changes to driver specific code
Disadvantage: won't work with drivers that don't poll the
management
queue (e.g., dev/ic/an.c); hack.

Details:
a. net/bpf.c: Add a bpf_output function pointer to struct
bpf_if, and a bpfattach3 function, which is basically
bpfattach2 with
an additional bpf_output parameter that is used to set
bpf_output in
the bpf_if structure.

b. net/bpf.c: bpf_write - On the bpf_write path,
     if(bpf_d->bd_bif->bpf_output), call it instead of
calling
     bpf_d->bd_bif->bif_ifp->if_output.

c. net80211/ieee80211.c:ieee80211_ifattach - use bpfattach3
to install
DLT_IEEE802_11

d. (HACK) net80211/ieee80211_output.c: ieee80211_bpf_output
- simply
enqueues the raw frame in the management queue
(ic->mgtq), and does
ifp->if_start

The hack ensures that we do not need to change each
driver's foo_start
function.

Option 2: When net80211 code registers DLT_IEEE802_11 with
bpf using
bpfattach, it also pass a callback to be invoked whenever a
raw packet
is written to the bpf device. This callback enqueues the raw
802.11
frames in a new queue (rawq) in the ieee80211com structure.
For each
driver that wishes to support raw frame injection, we will
have to
(trivially) modify it to poll the raw frame queue in
foo_start. This
option is the same as option 1, except that we add a raw
frame queue to
the ieee80211com structure (ic->rawq) instead of using
the management
queue (ic->mgtq).

Advantage: cleaner than option 1
Disadvantage: need to modify each driver's foo_start
function.

Details:
a, b, c same as Option 1.

d*. net80211/ieee80211_output.c: ieee80211_bpf_output -
enqueues the
raw frame in the raw frame queue (ic->rawq) and does
ifp->if_start

e. dev/ic/foo.c:foo_start - Drivers that support raw frame
BPF writes
will service the raw frame queue in foo_start similar to how
management frames are serviced. In other words, no 802.11
encap, and
foo_start does no checks on the state of the IEEE 802.11
state machine
for these packets. (Thus, potentially it would be possible
to inject a
          data frame before associating with an AP.)

Option 3: Change the semantics of BIOCSHDRCMPLT to indicate
which
headers are already present on the written frame. These
flags are
copied into a m_tag and passed around. The current code path
is
modified so that all functions that add headers check the
m_tag and
skip header encapsulation if the corresponding flag is set.

Advantage: ?
Disadvantage: ?

Details:
a. net/bpf.c:bpf_ioctl - change the semantics of
BIOCSHDRCMPLT: the
value is now a combination of flags representing which
headers are
switched on. Only two are defined for now: HDR_ETHER and
HDR_IEEE80211.

b. net/bpf.c:bpf_write - For Ethernet as well as IEEE
802.11,
     bpf_write constructs and passes the mbuf as before to
     ifp->if_output = ether_output. It also attaches an
m_tag to the
     mbuf indicating which headers are already present. If
the dlt =
     DLT_IEEE802_11, then m_tag indicates that Ethernet is
present,
     even though it is not actually there.

c. net/if_ethersubr.c:ether_output - code now checks if the
Ethernet
header is already complete from the m_tag and skips header
construction.

d. dev/ic/foo.c:foo_start - driver's foo_start fn checks if
the 802.11
header is already complete from the m_tag and skips IEEE
802.11
encapsulation.

-Vivek


-- 

---

*************************************
Vivek Raghunathan,
Intern - Internetwork Research Group,
BBN Technologies.

PhD student,
University of Illinois, Urbana-Champaign

Contact Details:
1012 W. Clark St #31,
Urbana IL 61801

ph: 217-766-1868 (cell)
    217-333-7541 (off)
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-01 18:30:33
  [802.11 frame writing via bpf]

The plan is to merge this work into NetBSD once it works. 
We'll also
be contributing back changes to make tap(4) be able to do
point-to-point (e.g. like tun(4)) or 802_11_RADIO, but
defaulting to
the current behavior.  The code will of course be posted for
review
before committing.

The remote interface code will also be available, as a
separate
program with a pkgsrc entry.

My own take on the options is that flags for what encap has
been done
feels kludgy, and that having an explicit raw queue is
cleaner.

-- 
    Greg Troxel <gdtir.bbn.com>
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-01 18:42:31
On Tue, Aug 01, 2006 at 02:19:15PM -0400, Vivek raghunathan
wrote:
> Hello all,
> 
> (Long email)
> 
> I am currently working at BBN Technologies with Greg
Troxel on a project to
> virtualize an IEEE 802.11 interface over a network. The
broad
> architecture is as follows: (real/virtual host refers
to the host on which
> the real/virtual interface is attached.)
> 
> 1. Frames arriving on the real interface are read by a
userspace
> daemon using BPF, encapsulated in UDP packets and
passed off to a
> userspace daemon running on the virtual host. This
daemon decapsulates
> the UDP packets and injects the extracted 802.11 frames
into the
> kernel stack at the virtual host. This injection is
done by extending
> the tap(4) interface to support 802.11 in addition to
Ethernet.
> 
> 2. When a packet is to be transmitted out the virtual
interface, it is
> encapsulated in 802.11 headers and passed to userspace
using the
> extended tap(4) interface mentioned above. The
userspace daemon at the
> virtual host encapsulates the frames in UDP, and sends
them to the
> userspace daemon at the real host, where they are
injected into the
> real interface using BPF.
> 
> (There are a lot of additional details here on what it
means to
> virtualize an IEEE 802.11 interface over a network -
that is the
> subject of another email.)
> 
> As part of this project, we need the ability to inject
raw IEEE 802.11
> frames from userspace using BPF. It seems like the
current NetBSD
> bpf_write path does not support DLT_IEEE802_11, or
> DLT_IEEE802_11_RADIO. This is because:
> 
> 1. (minor) net/bpf.c: bpf_write calls bpf_movein, which
does not
> recognize the dlt DLT_IEEE802_11/DLT_IEEE802_11_RADIO
and returns EIO.
> This is easily fixable.
> 
> 2. net/bpf.c: bpf_write passes an mbuf to
ifp->if_output. All 802.11
> drivers invoke ether_ifattach via ieee80211_ifattach,
and
> ether_ifattach sets ifp->if_output = ether_output.
Thus, bpf_write
> ends up passing raw DLT_IEEE802_11 mbufs to
ether_output. This causes
> DLT_IEEE80211 raw frame writes on a BPF to break:
> 
> a. ether_output expects raw frames with an attached
Ethernet header.
> DLT_IEEE80211 raw frames do not have an Ethernet
header.
> 
> b. ether_output enqueues the frame and calls the
driver-provided
> foo_start routine, which typically calls
ieee80211_encap to do
> IEEE 802.11 encapsulation. If this worked, it would
incorrectly put an
> 802.11 header on the raw 802.11 frame. (In practice, it
won't work
>          because ieee80211_encap expects its input to
be Ethernet
>          encapsulated; it strips off the
>          Ethernet header and adds an IEEE 802.11 header
and a LLC
>          header. Here the raw DLT_IEEE802_11 frame does
not have an
>          Ethernet header.)

Why do the 802.11 drivers use ether_output and other
Ethernet routines
if the frames are actually in a different format? FDDI and
Token Ring also
have their own _output routines. Shouldn't we have a
similar
ieee80211_output function which would be used instead of
ether_output?

Pavel
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-01 19:11:54
Pavel Cahyna <pavelnetbsd.org> writes:

> Why do the 802.11 drivers use ether_output and other
Ethernet routines
> if the frames are actually in a different format? FDDI
and Token Ring also
> have their own _output routines. Shouldn't we have a
similar
> ieee80211_output function which would be used instead
of ether_output?

Probably.  Basically 802.11 is designed to be bridged to
Ethernet, and
most programs treat it like an ethernet, so my take is that
802.11
support in *BSD presents an Ethernet-like interface.  The
basic type
of 802.11 devices is DLT_EN10MB.

The odd bit is that the packets in the output queue are in
Ethernet
format instead of 802.11 format, and the start routine does
the encap.

An alternative is to have a new output routine for 802.11
that does
the encap and have the output queue then be in 802.11
format.

That would still leave us with the question of how to handle
different
DLTs on output, since an 802.11 device would have to handle
bpf writes
with type DLT_EN10MB.  So the part of Vivek's proposal that
adds a
write callback to the bpf attachment would remain; we'd
just move the
encap in the processing chain and change the rules for the
output
queue.  But then we could skip the raw output queue and just
put
packets in the output queue.  We probably then have to
factor out the
part of ether_output that does encap from the part that puts
packets
on queues.

An issue here is FreeBSD divergence, so I'd be particularly
interested
in Sam's thoughts.

On balance, I don't see the need to change 802.11 device's
output
queues to have 802.11 encap at the same time as adding the
output
ability - the changes are 95% orthogonal.

-- 
    Greg Troxel <gdtir.bbn.com>
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-02 03:59:26
On Tue, Aug 01, 2006 at 02:19:15PM -0400, Vivek raghunathan
wrote:

> Hello all,
>
> (Long email)
>
> I am currently working at BBN Technologies with Greg
Troxel on a project to
> virtualize an IEEE 802.11 interface over a network. The
broad
> architecture is as follows: (real/virtual host refers
to the host on which
> the real/virtual interface is attached.)
>
> 1. Frames arriving on the real interface are read by a
userspace
> daemon using BPF, encapsulated in UDP packets and
passed off to a
> userspace daemon running on the virtual host. This
daemon decapsulates
> the UDP packets and injects the extracted 802.11 frames
into the
> kernel stack at the virtual host. This injection is
done by extending
> the tap(4) interface to support 802.11 in addition to
Ethernet.
>
> 2. When a packet is to be transmitted out the virtual
interface, it is
> encapsulated in 802.11 headers and passed to userspace
using the
> extended tap(4) interface mentioned above. The
userspace daemon at the
> virtual host encapsulates the frames in UDP, and sends
them to the
> userspace daemon at the real host, where they are
injected into the
> real interface using BPF.
>
> (There are a lot of additional details here on what it
means to
> virtualize an IEEE 802.11 interface over a network -
that is the
> subject of another email.)
>
> As part of this project, we need the ability to inject
raw IEEE 802.11
> frames from userspace using BPF. It seems like the
current NetBSD
> bpf_write path does not support DLT_IEEE802_11, or
> DLT_IEEE802_11_RADIO. This is because:
>
> 1. (minor) net/bpf.c: bpf_write calls bpf_movein, which
does not
> recognize the dlt DLT_IEEE802_11/DLT_IEEE802_11_RADIO
and returns EIO.
> This is easily fixable.
>
> 2. net/bpf.c: bpf_write passes an mbuf to
ifp->if_output. All 802.11
> drivers invoke ether_ifattach via ieee80211_ifattach,
and
> ether_ifattach sets ifp->if_output = ether_output.
Thus, bpf_write
> ends up passing raw DLT_IEEE802_11 mbufs to
ether_output. This causes
> DLT_IEEE80211 raw frame writes on a BPF to break:
>
> a. ether_output expects raw frames with an attached
Ethernet header.
> DLT_IEEE80211 raw frames do not have an Ethernet
header.
>
> b. ether_output enqueues the frame and calls the
driver-provided
> foo_start routine, which typically calls
ieee80211_encap to do
> IEEE 802.11 encapsulation. If this worked, it would
incorrectly put an
> 802.11 header on the raw 802.11 frame. (In practice, it
won't work
>          because ieee80211_encap expects its input to
be Ethernet
>          encapsulated; it strips off the
>          Ethernet header and adds an IEEE 802.11 header
and a LLC
>          header. Here the raw DLT_IEEE802_11 frame does
not have an
>          Ethernet header.)
>
>
> I am currently working on fixing this, and adding
support for
> DLT_IEEE802_11 to the BPF write path. We expect raw
DLT_IEEE802_11
> frames to be injected in the same format as they are
read: data frames
> consist of a 802.11 header, and LLC header+IP packet in
the 802.11
> payload. Management frames consist of an 802.11 header
and the
> management frame. There are multiple options on how to
implement this,
>           and as I am fairly new to the NetBSD kernel,
I was hoping
>           to get some feedback on which way to proceed:
>
> Option 1: When net80211 code registers DLT_IEEE802_11
with bpf using
> bpfattach, it also pass a callback to be invoked
whenever a raw packet
> is written to the bpf device. This callback enqueues
the raw 802.11
> frames in the management queue (ieee80211com->mgtq)
(whose present
>          semantics are post-802.11 encap).
>
> Advantage: no changes to driver specific code
> Disadvantage: won't work with drivers that don't poll
the management
> queue (e.g., dev/ic/an.c); hack.
>
> Details:
> a. net/bpf.c: Add a bpf_output function pointer to
struct
> bpf_if, and a bpfattach3 function, which is basically
bpfattach2 with
> an additional bpf_output parameter that is used to set
bpf_output in
> the bpf_if structure.
>
> b. net/bpf.c: bpf_write - On the bpf_write path,
>     if(bpf_d->bd_bif->bpf_output), call it
instead of calling
>     bpf_d->bd_bif->bif_ifp->if_output.
>
> c. net80211/ieee80211.c:ieee80211_ifattach - use
bpfattach3 to install
> DLT_IEEE802_11
>
> d. (HACK) net80211/ieee80211_output.c:
ieee80211_bpf_output - simply
> enqueues the raw frame in the management queue
(ic->mgtq), and does
> ifp->if_start
>
> The hack ensures that we do not need to change each
driver's foo_start
> function.
>
> Option 2: When net80211 code registers DLT_IEEE802_11
with bpf using
> bpfattach, it also pass a callback to be invoked
whenever a raw packet
> is written to the bpf device. This callback enqueues
the raw 802.11
> frames in a new queue (rawq) in the ieee80211com
structure. For each
> driver that wishes to support raw frame injection, we
will have to
> (trivially) modify it to poll the raw frame queue in
foo_start. This
> option is the same as option 1, except that we add a
raw frame queue to
> the ieee80211com structure (ic->rawq) instead of
using the management
> queue (ic->mgtq).
>
> Advantage: cleaner than option 1
> Disadvantage: need to modify each driver's foo_start
function.
>
> Details:
> a, b, c same as Option 1.
>
> d*. net80211/ieee80211_output.c: ieee80211_bpf_output -
enqueues the
> raw frame in the raw frame queue (ic->rawq) and does
ifp->if_start
>
> e. dev/ic/foo.c:foo_start - Drivers that support raw
frame BPF writes
> will service the raw frame queue in foo_start similar
to how
> management frames are serviced. In other words, no
802.11 encap, and
> foo_start does no checks on the state of the IEEE
802.11 state machine
> for these packets. (Thus, potentially it would be
possible to inject a
>          data frame before associating with an AP.)
>
> Option 3: Change the semantics of BIOCSHDRCMPLT to
indicate which
> headers are already present on the written frame. These
flags are
> copied into a m_tag and passed around. The current code
path is
> modified so that all functions that add headers check
the m_tag and
> skip header encapsulation if the corresponding flag is
set.
>
> Advantage: ?
> Disadvantage: ?
>
> Details:
> a. net/bpf.c:bpf_ioctl - change the semantics of
BIOCSHDRCMPLT: the
> value is now a combination of flags representing which
headers are
> switched on. Only two are defined for now: HDR_ETHER
and
> HDR_IEEE80211.
>
> b. net/bpf.c:bpf_write - For Ethernet as well as IEEE
802.11,
>     bpf_write constructs and passes the mbuf as before
to
>     ifp->if_output = ether_output. It also attaches
an m_tag to the
>     mbuf indicating which headers are already present.
If the dlt =
>     DLT_IEEE802_11, then m_tag indicates that Ethernet
is present,
>     even though it is not actually there.
>
> c. net/if_ethersubr.c:ether_output - code now checks if
the Ethernet
> header is already complete from the m_tag and skips
header
> construction.
>
> d. dev/ic/foo.c:foo_start - driver's foo_start fn
checks if the 802.11
> header is already complete from the m_tag and skips
IEEE 802.11
> encapsulation.
>
> -Vivek
>

You might also want to incorporate David's views regarding
the new DLTs for
802.11 injection.

http://mail-index.netbsd.org/current-users/2006/0
7/07/0010.html

and the corresponding thread.

--
dheeraj
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-02 16:11:56
David's post has a pointer to Sam Leffler's raw frame
injection patch
for FreeBSD (h
ttp://people.freebsd.org/~sam/tx80211/kernel.patch). It
seems like he rewires ifp->if_output to ieee80211_output,
and writes a
new ieee80211_output function which enqueues raw frames into
the
management queue (in ieee80211_raw_xmit). This method is
identical to
the first option I had described; I don't like it because
it feels
kludgey to enqueue raw (data/ management) frames in the
management
queue just to avoid 802.11 encapsulation.

This may have unintended side effects - for example, the
Atheros
driver's ath_start function prioritizes service to the
management
queue; and may end up starving the normal transmit path when
packets
are injected continuously via the bpf write path. I would
prefer to
have a separate raw frame queue in the ieee80211com
structure, and let
drivers figure out how to service the raw frame queue.

(Correct me if I am wrong here) A separate raw frame queue
will also
enable drivers which do not service the management queue at
all (e.g.
Aironet) to add raw frame support for the data path cleanly
without
having to worry about accidentally transmitting management
frames out
when they service the management queue.

Vivek


On 8/1/06, Dheeraj S <dheerajece.gatech.edu> wrote:
> On Tue, Aug 01, 2006 at 02:19:15PM -0400, Vivek
raghunathan wrote:
>
> > Hello all,
> >
> > (Long email)
> >
> > I am currently working at BBN Technologies with
Greg Troxel on a project to
> > virtualize an IEEE 802.11 interface over a
network. The broad
> > architecture is as follows: (real/virtual host
refers to the host on which
> > the real/virtual interface is attached.)
> >
> > 1. Frames arriving on the real interface are read
by a userspace
> > daemon using BPF, encapsulated in UDP packets and
passed off to a
> > userspace daemon running on the virtual host. This
daemon decapsulates
> > the UDP packets and injects the extracted 802.11
frames into the
> > kernel stack at the virtual host. This injection
is done by extending
> > the tap(4) interface to support 802.11 in addition
to Ethernet.
> >
> > 2. When a packet is to be transmitted out the
virtual interface, it is
> > encapsulated in 802.11 headers and passed to
userspace using the
> > extended tap(4) interface mentioned above. The
userspace daemon at the
> > virtual host encapsulates the frames in UDP, and
sends them to the
> > userspace daemon at the real host, where they are
injected into the
> > real interface using BPF.
> >
> > (There are a lot of additional details here on
what it means to
> > virtualize an IEEE 802.11 interface over a network
- that is the
> > subject of another email.)
> >
> > As part of this project, we need the ability to
inject raw IEEE 802.11
> > frames from userspace using BPF. It seems like the
current NetBSD
> > bpf_write path does not support DLT_IEEE802_11, or
> > DLT_IEEE802_11_RADIO. This is because:
> >
> > 1. (minor) net/bpf.c: bpf_write calls bpf_movein,
which does not
> > recognize the dlt
DLT_IEEE802_11/DLT_IEEE802_11_RADIO and returns EIO.
> > This is easily fixable.
> >
> > 2. net/bpf.c: bpf_write passes an mbuf to
ifp->if_output. All 802.11
> > drivers invoke ether_ifattach via
ieee80211_ifattach, and
> > ether_ifattach sets ifp->if_output =
ether_output. Thus, bpf_write
> > ends up passing raw DLT_IEEE802_11 mbufs to
ether_output. This causes
> > DLT_IEEE80211 raw frame writes on a BPF to break:
> >
> > a. ether_output expects raw frames with an
attached Ethernet header.
> > DLT_IEEE80211 raw frames do not have an Ethernet
header.
> >
> > b. ether_output enqueues the frame and calls the
driver-provided
> > foo_start routine, which typically calls
ieee80211_encap to do
> > IEEE 802.11 encapsulation. If this worked, it
would incorrectly put an
> > 802.11 header on the raw 802.11 frame. (In
practice, it won't work
> >          because ieee80211_encap expects its input
to be Ethernet
> >          encapsulated; it strips off the
> >          Ethernet header and adds an IEEE 802.11
header and a LLC
> >          header. Here the raw DLT_IEEE802_11 frame
does not have an
> >          Ethernet header.)
> >
> >
> > I am currently working on fixing this, and adding
support for
> > DLT_IEEE802_11 to the BPF write path. We expect
raw DLT_IEEE802_11
> > frames to be injected in the same format as they
are read: data frames
> > consist of a 802.11 header, and LLC header+IP
packet in the 802.11
> > payload. Management frames consist of an 802.11
header and the
> > management frame. There are multiple options on
how to implement this,
> >           and as I am fairly new to the NetBSD
kernel, I was hoping
> >           to get some feedback on which way to
proceed:
> >
> > Option 1: When net80211 code registers
DLT_IEEE802_11 with bpf using
> > bpfattach, it also pass a callback to be invoked
whenever a raw packet
> > is written to the bpf device. This callback
enqueues the raw 802.11
> > frames in the management queue
(ieee80211com->mgtq) (whose present
> >          semantics are post-802.11 encap).
> >
> > Advantage: no changes to driver specific code
> > Disadvantage: won't work with drivers that don't
poll the management
> > queue (e.g., dev/ic/an.c); hack.
> >
> > Details:
> > a. net/bpf.c: Add a bpf_output function pointer to
struct
> > bpf_if, and a bpfattach3 function, which is
basically bpfattach2 with
> > an additional bpf_output parameter that is used to
set bpf_output in
> > the bpf_if structure.
> >
> > b. net/bpf.c: bpf_write - On the bpf_write path,
> >     if(bpf_d->bd_bif->bpf_output), call it
instead of calling
> >     bpf_d->bd_bif->bif_ifp->if_output.
> >
> > c. net80211/ieee80211.c:ieee80211_ifattach - use
bpfattach3 to install
> > DLT_IEEE802_11
> >
> > d. (HACK) net80211/ieee80211_output.c:
ieee80211_bpf_output - simply
> > enqueues the raw frame in the management queue
(ic->mgtq), and does
> > ifp->if_start
> >
> > The hack ensures that we do not need to change
each driver's foo_start
> > function.
> >
> > Option 2: When net80211 code registers
DLT_IEEE802_11 with bpf using
> > bpfattach, it also pass a callback to be invoked
whenever a raw packet
> > is written to the bpf device. This callback
enqueues the raw 802.11
> > frames in a new queue (rawq) in the ieee80211com
structure. For each
> > driver that wishes to support raw frame injection,
we will have to
> > (trivially) modify it to poll the raw frame queue
in foo_start. This
> > option is the same as option 1, except that we add
a raw frame queue to
> > the ieee80211com structure (ic->rawq) instead
of using the management
> > queue (ic->mgtq).
> >
> > Advantage: cleaner than option 1
> > Disadvantage: need to modify each driver's
foo_start function.
> >
> > Details:
> > a, b, c same as Option 1.
> >
> > d*. net80211/ieee80211_output.c:
ieee80211_bpf_output - enqueues the
> > raw frame in the raw frame queue (ic->rawq) and
does ifp->if_start
> >
> > e. dev/ic/foo.c:foo_start - Drivers that support
raw frame BPF writes
> > will service the raw frame queue in foo_start
similar to how
> > management frames are serviced. In other words, no
802.11 encap, and
> > foo_start does no checks on the state of the IEEE
802.11 state machine
> > for these packets. (Thus, potentially it would be
possible to inject a
> >          data frame before associating with an
AP.)
> >
> > Option 3: Change the semantics of BIOCSHDRCMPLT to
indicate which
> > headers are already present on the written frame.
These flags are
> > copied into a m_tag and passed around. The current
code path is
> > modified so that all functions that add headers
check the m_tag and
> > skip header encapsulation if the corresponding
flag is set.
> >
> > Advantage: ?
> > Disadvantage: ?
> >
> > Details:
> > a. net/bpf.c:bpf_ioctl - change the semantics of
BIOCSHDRCMPLT: the
> > value is now a combination of flags representing
which headers are
> > switched on. Only two are defined for now:
HDR_ETHER and
> > HDR_IEEE80211.
> >
> > b. net/bpf.c:bpf_write - For Ethernet as well as
IEEE 802.11,
> >     bpf_write constructs and passes the mbuf as
before to
> >     ifp->if_output = ether_output. It also
attaches an m_tag to the
> >     mbuf indicating which headers are already
present. If the dlt =
> >     DLT_IEEE802_11, then m_tag indicates that
Ethernet is present,
> >     even though it is not actually there.
> >
> > c. net/if_ethersubr.c:ether_output - code now
checks if the Ethernet
> > header is already complete from the m_tag and
skips header
> > construction.
> >
> > d. dev/ic/foo.c:foo_start - driver's foo_start fn
checks if the 802.11
> > header is already complete from the m_tag and
skips IEEE 802.11
> > encapsulation.
> >
> > -Vivek
> >
>
> You might also want to incorporate David's views
regarding the new DLTs for
> 802.11 injection.
>
> http://mail-index.netbsd.org/current-users/2006/0
7/07/0010.html
>
> and the corresponding thread.
>
> --
> dheeraj
>


-- 

---

*************************************
Vivek Raghunathan,
PhD student,
University of Illinois, Urbana-Champaign

Contact Details:
1012 W. Clark St #31,
Urbana IL 61801

ph: 217-766-1868 (cell)
    217-333-7541 (off)
BPF support for writing raw IEEE 802.11 frames
user name
2006-08-06 16:51:47
On Tue, Aug 01, 2006 at 02:19:15PM -0400, Vivek raghunathan
wrote:
> Option 1: When net80211 code registers DLT_IEEE802_11
with bpf using
> bpfattach, it also pass a callback to be invoked
whenever a raw packet
> is written to the bpf device. This callback enqueues
the raw 802.11
> frames in the management queue (ieee80211com->mgtq)
(whose present
>          semantics are post-802.11 encap).
> 
> Advantage: no changes to driver specific code
> Disadvantage: won't work with drivers that don't poll
the management
> queue (e.g., dev/ic/an.c); hack.
> 
> Details:
> a. net/bpf.c: Add a bpf_output function pointer to
struct
> bpf_if, and a bpfattach3 function, which is basically
bpfattach2 with
> an additional bpf_output parameter that is used to set
bpf_output in
> the bpf_if structure.
> 
> b. net/bpf.c: bpf_write - On the bpf_write path,
>     if(bpf_d->bd_bif->bpf_output), call it
instead of calling
>     bpf_d->bd_bif->bif_ifp->if_output.
> 
> c. net80211/ieee80211.c:ieee80211_ifattach - use
bpfattach3 to install
> DLT_IEEE802_11
> 
> d. (HACK) net80211/ieee80211_output.c:
ieee80211_bpf_output - simply
> enqueues the raw frame in the management queue
(ic->mgtq), and does
> ifp->if_start
> 
> The hack ensures that we do not need to change each
driver's foo_start
> function.

In some work for a client, took almost the identical
approach to Option
1, adding bpfattach3(..., callback).  I modified
bpfattach2() so that it
calls bpfattach3(, ifp->if_output).  In this way,
bpf_write can always
call bpf_d->bd_bif->bif_output.

I do not have an opinion one way or another whether the
ieee80211com
should grow an rawq member.  It sounds like the principal
difference
between the approaches is that you will modify every WLAN
driver's
if_start routine for rawq, or only a few for mgtq.

I favor Option 1 or Option 2 over Option 3.  I will say this
about BIOCSHDRCMPLT, though: it helps application
programmers if
ieee80211_bpf_output fills out the source/destination/bssid
on injected
DLT_IEEE802_11 frames when BIOCSHDRCMPLT is
"off". 

Dave

-- 
David Young             OJC Technologies
dyoungojctech.com      Urbana, IL * (217) 278-3933
[1-7]

about | contact  Other archives ( Real Estate discussion Medical topics )