diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-01-16 03:34:59 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-01-16 03:34:59 +0000 |
commit | 763da0b9d849c256a625207cb1d8de211e384f5a (patch) | |
tree | 91d4828079301b5b17f17d38f25b6312b40d98b7 /sys/net | |
parent | 59eb95b12ba3893cb94fb1ed458fcc6e104ed928 (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.c | 35 |
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); } |