int bpfkqfilter(dev_t dev, struct knote *kn) { struct bpf_d *d; struct klist *klist; int s; d = bpfilter_lookup(minor(dev)); switch (kn->kn_filter) { case EVFILT_READ: klist = &d->bd_sel.si_note; kn->kn_fop = &bpfread_filtops; break; default: return (EINVAL); } kn->kn_hook = (caddr_t)((u_long)dev); s = splnet(); D_GET(d); SLIST_INSERT_HEAD(klist, kn, kn_selnext); splx(s); return (0); }
/* ARGSUSED */ int bpfopen(dev_t dev, int flag, int mode, struct proc *p) { struct bpf_d *d; /* create on demand */ if ((d = bpfilter_create(minor(dev))) == NULL) return (EBUSY); /* Mark "free" and do most initialization. */ d->bd_bufsize = bpf_bufsize; d->bd_sig = SIGIO; D_GET(d); return (0); }
/* * bpfread - read next chunk of packets from buffers */ int bpfread(dev_t dev, struct uio *uio, int ioflag) { struct bpf_d *d; int error; int s; d = bpfilter_lookup(minor(dev)); if (d->bd_bif == 0) return (ENXIO); /* * Restrict application to use a buffer the same size as * as kernel buffers. */ if (uio->uio_resid != d->bd_bufsize) return (EINVAL); s = splnet(); D_GET(d); /* * bd_rdStart is tagged when we start the read, iff there's a timeout. * we can then figure out when we're done reading. */ if (d->bd_rtout != -1 && d->bd_rdStart == 0) d->bd_rdStart = ticks; else d->bd_rdStart = 0; /* * If the hold buffer is empty, then do a timed sleep, which * ends when the timeout expires or when enough packets * have arrived to fill the store buffer. */ while (d->bd_hbuf == 0) { if (d->bd_bif == NULL) { /* interface is gone */ if (d->bd_slen == 0) { D_PUT(d); splx(s); return (EIO); } ROTATE_BUFFERS(d); break; } if (d->bd_immediate && d->bd_slen != 0) { /* * A packet(s) either arrived since the previous * read or arrived while we were asleep. * Rotate the buffers and return what's here. */ ROTATE_BUFFERS(d); break; } if ((d->bd_rtout != -1) || (d->bd_rdStart + d->bd_rtout) < ticks) { error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf", d->bd_rtout); } else { if (d->bd_rtout == -1) { /* User requested non-blocking I/O */ error = EWOULDBLOCK; } else error = 0; } if (error == EINTR || error == ERESTART) { D_PUT(d); splx(s); return (error); } if (error == EWOULDBLOCK) { /* * On a timeout, return what's in the buffer, * which may be nothing. If there is something * in the store buffer, we can rotate the buffers. */ if (d->bd_hbuf) /* * We filled up the buffer in between * getting the timeout and arriving * here, so we don't need to rotate. */ break; if (d->bd_slen == 0) { D_PUT(d); splx(s); return (0); } ROTATE_BUFFERS(d); break; } } /* * At this point, we know we have something in the hold slot. */ splx(s); /* * Move data from hold buffer into user space. * We know the entire buffer is transferred since * we checked above that the read buffer is bpf_bufsize bytes. */ error = uiomove(d->bd_hbuf, d->bd_hlen, uio); s = splnet(); d->bd_fbuf = d->bd_hbuf; d->bd_hbuf = 0; d->bd_hlen = 0; D_PUT(d); splx(s); return (error); }