summaryrefslogtreecommitdiff
path: root/sys/net
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2012-01-16 03:34:59 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2012-01-16 03:34:59 +0000
commit763da0b9d849c256a625207cb1d8de211e384f5a (patch)
tree91d4828079301b5b17f17d38f25b6312b40d98b7 /sys/net
parent59eb95b12ba3893cb94fb1ed458fcc6e104ed928 (diff)
bpf devices behave similar to raw sockets and never block on write,
so always show as writable to poll()/select(). Behavior pointed out by Fernando Gont. ok deraadt@
Diffstat (limited to 'sys/net')
-rw-r--r--sys/net/bpf.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index c602a6a4e11..93eddc654a9 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.c,v 1.78 2011/07/02 22:20:08 nicm Exp $ */
+/* $OpenBSD: bpf.c,v 1.79 2012/01/16 03:34:58 guenther Exp $ */
/* $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */
/*
@@ -1022,14 +1022,11 @@ bpfpoll(dev_t dev, int events, struct proc *p)
struct bpf_d *d;
int s, revents;
- revents = events & (POLLIN | POLLRDNORM);
- if (revents == 0)
- return (0); /* only support reading */
-
/*
* An imitation of the FIONREAD ioctl code.
*/
d = bpfilter_lookup(minor(dev));
+
/*
* XXX The USB stack manages it to trigger some race condition
* which causes bpfilter_lookup to return NULL when a USB device
@@ -1039,17 +1036,25 @@ bpfpoll(dev_t dev, int events, struct proc *p)
*/
if (d == NULL)
return (POLLERR);
- s = splnet();
- if (d->bd_hlen == 0 && (!d->bd_immediate || d->bd_slen == 0)) {
- revents = 0; /* no data waiting */
- /*
- * if there's a timeout, mark the time we started waiting.
- */
- if (d->bd_rtout != -1 && d->bd_rdStart == 0)
- d->bd_rdStart = ticks;
- selrecord(p, &d->bd_sel);
+
+ /* Always ready to write data */
+ revents = events & (POLLOUT | POLLWRNORM);
+
+ if (events & (POLLIN | POLLRDNORM)) {
+ s = splnet();
+ if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0))
+ revents |= events & (POLLIN | POLLRDNORM);
+ else {
+ /*
+ * if there's a timeout, mark the time we
+ * started waiting.
+ */
+ if (d->bd_rtout != -1 && d->bd_rdStart == 0)
+ d->bd_rdStart = ticks;
+ selrecord(p, &d->bd_sel);
+ }
+ splx(s);
}
- splx(s);
return (revents);
}