Example #1
0
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);
}
Example #2
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);
}
Example #3
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);
}