tech-net archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Possible fix for wpa_supplicant(8) WPA re-key lossage
Hi,
Since the last import back in January, wpa_supplicant(8) in
NetBSD-current has been unable to maintain a WPA session with a
wireless AP due to lossage during re-keying. The work-around thus far
has been to keep a wpa_cli(8) instance running for the duration of the
session.
After some playing around this evening, I believe I have tracked down
the cause of the bug to lossage within bpf(4)'s bpf_poll() function.
The bottom line is that wpa_supplicant(8) does not receive the re-key
packet from the AP because the select(2) call in
dist/wpa/src/utils/eloop.c does not report the event promptly. The
wpa_cli(8) hack works because it sends a PING request over
wpa_supplicant's control socket once per second, resulting in the
select(2) call returning each time. The next call to select(2) returns
a bpf(2) readable status, so re-keying proceeds normally albeit delayed
slightly.
The attached patch to sys/net/bpf.c contains two changes lifted from
FreeBSD's bpf.c:
- A "fix" for bpf_poll() to address the above problem (but see below).
- A fix for catchpacket() which delays calling bpf_wakeup() until
the state has been updated.
I'd like someone with more bpf(4) clue to look over the first fix, as
I'm somewhat perplexed as to why it fixes the problem. (Maybe it's the
beer, maybe I need to spend more time staring at it, or maybe I'm just
getting too old ;-)
In anycase, if you have been experiencing this wpa_supplicant(8)
problem, please try the patch and report back.
Cheers, Steve
Index: bpf.c
===================================================================
RCS file: /cvsroot/src/sys/net/bpf.c,v
retrieving revision 1.137
diff -u -p -r1.137 bpf.c
--- bpf.c 26 Mar 2008 02:21:52 -0000 1.137
+++ bpf.c 18 Apr 2008 20:31:05 -0000
@@ -1084,14 +1084,10 @@ bpf_poll(struct file *fp, int events)
/*
* An imitation of the FIONREAD ioctl code.
*/
- if ((d->bd_hlen != 0) ||
- (d->bd_immediate && d->bd_slen != 0)) {
+ if (d->bd_hlen != 0 ||
+ ((d->bd_immediate || d->bd_state == BPF_TIMED_OUT) &&
+ d->bd_slen != 0)) {
revents |= events & (POLLIN | POLLRDNORM);
- } else if (d->bd_state == BPF_TIMED_OUT) {
- if (d->bd_slen != 0)
- revents |= events & (POLLIN | POLLRDNORM);
- else
- revents |= events & POLLIN;
} else {
selrecord(curlwp, &d->bd_sel);
/* Start the read timeout if necessary */
@@ -1416,6 +1412,7 @@ catchpacket(struct bpf_d *d, u_char *pkt
struct bpf_hdr *hp;
int totlen, curlen;
int hdrlen = d->bd_bif->bif_hdrlen;
+ int do_wakeup = 0;
++d->bd_ccount;
++bpf_gstats.bs_capt;
@@ -1449,8 +1446,15 @@ catchpacket(struct bpf_d *d, u_char *pkt
return;
}
ROTATE_BUFFERS(d);
- bpf_wakeup(d);
+ do_wakeup = 1;
curlen = 0;
+ } else if (d->bd_immediate || d->bd_state == BPF_TIMED_OUT) {
+ /*
+ * Immediate mode is set, or the read timeout has
+ * already expired during a select call. A packet
+ * arrived, so the reader should be woken up.
+ */
+ do_wakeup = 1;
}
/*
@@ -1470,12 +1474,7 @@ catchpacket(struct bpf_d *d, u_char *pkt
* Call bpf_wakeup after bd_slen has been updated so that kevent(2)
* will cause filt_bpfread() to be called with it adjusted.
*/
- if (d->bd_immediate || d->bd_state == BPF_TIMED_OUT)
- /*
- * Immediate mode is set, or the read timeout has
- * already expired during a select call. A packet
- * arrived, so the reader should be woken up.
- */
+ if (do_wakeup)
bpf_wakeup(d);
}
Home |
Main Index |
Thread Index |
Old Index