summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorweongyo <weongyo@FreeBSD.org>2010-11-24 19:11:32 +0000
committerweongyo <weongyo@FreeBSD.org>2010-11-24 19:11:32 +0000
commit8a45a8e5b0137ac7d5d8075275a46ccafbfdff25 (patch)
tree786de02951f53c700caab280a0863db75bca3a41
parent6febd420298ec8b8ff8f0f166f529d08f2f17de5 (diff)
downloadFreeBSD-src-8a45a8e5b0137ac7d5d8075275a46ccafbfdff25.zip
FreeBSD-src-8a45a8e5b0137ac7d5d8075275a46ccafbfdff25.tar.gz
Removes all duplicated code with BPF that it's greatly simplified and
take all benefits whenever BPF code is improved. Pointed by: jkim Reviewed by: thompsa
-rw-r--r--sys/dev/usb/controller/usb_controller.c2
-rw-r--r--sys/dev/usb/usb_bus.h2
-rw-r--r--sys/dev/usb/usb_pf.c1675
-rw-r--r--sys/dev/usb/usb_pf.h225
4 files changed, 27 insertions, 1877 deletions
diff --git a/sys/dev/usb/controller/usb_controller.c b/sys/dev/usb/controller/usb_controller.c
index afc2118..a0b915c 100644
--- a/sys/dev/usb/controller/usb_controller.c
+++ b/sys/dev/usb/controller/usb_controller.c
@@ -548,7 +548,7 @@ usb_bus_mem_alloc_all(struct usb_bus *bus, bus_dma_tag_t dmat,
TAILQ_INIT(&bus->intr_q.head);
- usbpf_attach(bus, &bus->uif);
+ usbpf_attach(bus);
#if USB_HAVE_BUSDMA
usb_dma_tag_setup(bus->dma_parent_tag, bus->dma_tags,
diff --git a/sys/dev/usb/usb_bus.h b/sys/dev/usb/usb_bus.h
index c5dfeff..1dd9d6a 100644
--- a/sys/dev/usb/usb_bus.h
+++ b/sys/dev/usb/usb_bus.h
@@ -86,7 +86,7 @@ struct usb_bus {
struct usb_bus_methods *methods; /* filled by HC driver */
struct usb_device **devices;
- struct usbpf_if *uif; /* USB Packet Filter */
+ struct ifnet *ifp; /* only for USB Packet Filter */
usb_power_mask_t hw_power_state; /* see USB_HW_POWER_XXX */
usb_size_t uframe_usage[USB_HS_MICRO_FRAMES_MAX];
diff --git a/sys/dev/usb/usb_pf.c b/sys/dev/usb/usb_pf.c
index 0da4d88..3e6b7d1 100644
--- a/sys/dev/usb/usb_pf.c
+++ b/sys/dev/usb/usb_pf.c
@@ -43,6 +43,8 @@ __FBSDID("$FreeBSD$");
#include <sys/socket.h>
#include <sys/sockio.h>
#include <net/if.h>
+#include <net/if_types.h>
+#include <net/bpf.h>
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -55,1624 +57,39 @@ __FBSDID("$FreeBSD$");
#include <dev/usb/usb_pf.h>
#include <dev/usb/usb_transfer.h>
-/*
- * All usbpf implementations are extracted from bpf(9) APIs and it's
- * specialized for USB packet filtering between the driver and the host
- * controller.
- */
-
-MALLOC_DEFINE(M_USBPF, "USBPktFilter", "USB Packet Filter");
-
-/*
- * Rotate the packet buffers in descriptor ud. Move the store buffer into the
- * hold slot, and the free buffer ino the store slot. Zero the length of the
- * new store buffer. Descriptor lock should be held.
- */
-#define USBPF_ROTATE_BUFFERS(ud) do { \
- (ud)->ud_hbuf = (ud)->ud_sbuf; \
- (ud)->ud_hlen = (ud)->ud_slen; \
- (ud)->ud_sbuf = (ud)->ud_fbuf; \
- (ud)->ud_slen = 0; \
- (ud)->ud_fbuf = NULL; \
- usbpf_bufheld(ud); \
-} while (0)
-
-#ifndef __i386__
-#define USBPF_ALIGN
-#endif
-
-#ifndef USBPF_ALIGN
-#define USBPF_EXTRACT_SHORT(p) ((u_int16_t)ntohs(*(u_int16_t *)p))
-#define USBPF_EXTRACT_LONG(p) (ntohl(*(u_int32_t *)p))
-#else
-#define USBPF_EXTRACT_SHORT(p) \
- ((u_int16_t) \
- ((u_int16_t)*((u_char *)p+0)<<8| \
- (u_int16_t)*((u_char *)p+1)<<0))
-#define USBPF_EXTRACT_LONG(p) \
- ((u_int32_t)*((u_char *)p+0)<<24| \
- (u_int32_t)*((u_char *)p+1)<<16| \
- (u_int32_t)*((u_char *)p+2)<<8| \
- (u_int32_t)*((u_char *)p+3)<<0)
-#endif
-
-/*
- * Number of scratch memory words (for USBPF_LD|USBPF_MEM and USBPF_ST).
- */
-#define USBPF_MEMWORDS 16
-
-/* Values for ud_state */
-#define USBPF_IDLE 0 /* no select in progress */
-#define USBPF_WAITING 1 /* waiting for read timeout in select */
-#define USBPF_TIMED_OUT 2 /* read timeout has expired in select */
-
-#define PRIUSB 26 /* interruptible */
-
-/* Frame directions */
-enum usbpf_direction {
- USBPF_D_IN, /* See incoming frames */
- USBPF_D_INOUT, /* See incoming and outgoing frames */
- USBPF_D_OUT /* See outgoing frames */
-};
-
-static void usbpf_append_bytes(struct usbpf_d *, caddr_t, u_int, void *,
- u_int);
-static void usbpf_attachd(struct usbpf_d *, struct usbpf_if *);
-static void usbpf_detachd(struct usbpf_d *);
-static int usbpf_canfreebuf(struct usbpf_d *);
-static void usbpf_buf_reclaimed(struct usbpf_d *);
-static int usbpf_canwritebuf(struct usbpf_d *);
-
-static d_open_t usbpf_open;
-static d_read_t usbpf_read;
-static d_write_t usbpf_write;
-static d_ioctl_t usbpf_ioctl;
-static d_poll_t usbpf_poll;
-static d_kqfilter_t usbpf_kqfilter;
-
-static struct cdevsw usbpf_cdevsw = {
- .d_version = D_VERSION,
- .d_open = usbpf_open,
- .d_read = usbpf_read,
- .d_write = usbpf_write,
- .d_ioctl = usbpf_ioctl,
- .d_poll = usbpf_poll,
- .d_name = "usbpf",
- .d_kqfilter = usbpf_kqfilter,
-};
-
-static struct cdev *usbpf_cdev;
-static LIST_HEAD(, usbpf_if) usbpf_iflist;
-static struct mtx usbpf_mtx; /* global lock */
-static int usbpf_uifd_cnt;
-
-static int usbpf_bufsize = 4096;
-#define USBPF_MINBUFSIZE 32
-#define USBPF_MAXBUFSIZE 0x80000
-static int usbpf_maxbufsize = USBPF_MAXBUFSIZE;
-#define USBPF_MAXINSNS 512
-static int usbpf_maxinsns = USBPF_MAXINSNS;
-
-static void
-usbpf_buffer_init(struct usbpf_d *ud)
-{
-
- ud->ud_bufsize = usbpf_bufsize;
-}
-
-/*
- * Free USBPF kernel buffers on device close.
- */
-static void
-usbpf_buffer_free(struct usbpf_d *ud)
-{
-
- if (ud->ud_sbuf != NULL)
- free(ud->ud_sbuf, M_USBPF);
- if (ud->ud_hbuf != NULL)
- free(ud->ud_hbuf, M_USBPF);
- if (ud->ud_fbuf != NULL)
- free(ud->ud_fbuf, M_USBPF);
-
-#ifdef INVARIANTS
- ud->ud_sbuf = ud->ud_hbuf = ud->ud_fbuf = (caddr_t)~0;
-#endif
-}
-
-static void
-usbpf_buffer_alloc(struct usbpf_d *ud)
-{
-
- KASSERT(ud->ud_fbuf == NULL, ("%s: ud_fbuf != NULL", __func__));
- KASSERT(ud->ud_sbuf == NULL, ("%s: ud_sbuf != NULL", __func__));
- KASSERT(ud->ud_hbuf == NULL, ("%s: ud_hbuf != NULL", __func__));
-
- ud->ud_fbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
- ud->ud_sbuf = (caddr_t)malloc(ud->ud_bufsize, M_USBPF, M_WAITOK);
- ud->ud_hbuf = NULL;
- ud->ud_slen = 0;
- ud->ud_hlen = 0;
-}
-
-/*
- * Copy buffer storage to user space in read().
- */
-static int
-usbpf_buffer_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len,
- struct uio *uio)
-{
-
- return (uiomove(buf, len, uio));
-}
-
-/*
- * Simple data copy to the current kernel buffer.
- */
-static void
-usbpf_buffer_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset,
- void *src, u_int len)
-{
- u_char *src_bytes;
-
- src_bytes = (u_char *)src;
- bcopy(src_bytes, buf + offset, len);
-}
-
-/*
- * Allocate or resize buffers.
- */
-static int
-usbpf_buffer_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
- u_int size;
-
- USBPFD_LOCK(ud);
- if (ud->ud_bif != NULL) {
- USBPFD_UNLOCK(ud);
- return (EINVAL);
- }
- size = *i;
- if (size > usbpf_maxbufsize)
- *i = size = usbpf_maxbufsize;
- else if (size < USBPF_MINBUFSIZE)
- *i = size = USBPF_MINBUFSIZE;
- ud->ud_bufsize = size;
- USBPFD_UNLOCK(ud);
- return (0);
-}
-
-static const u_short usbpf_code_map[] = {
- 0x10ff, /* 0x00-0x0f: 1111111100001000 */
- 0x3070, /* 0x10-0x1f: 0000111000001100 */
- 0x3131, /* 0x20-0x2f: 1000110010001100 */
- 0x3031, /* 0x30-0x3f: 1000110000001100 */
- 0x3131, /* 0x40-0x4f: 1000110010001100 */
- 0x1011, /* 0x50-0x5f: 1000100000001000 */
- 0x1013, /* 0x60-0x6f: 1100100000001000 */
- 0x1010, /* 0x70-0x7f: 0000100000001000 */
- 0x0093, /* 0x80-0x8f: 1100100100000000 */
- 0x0000, /* 0x90-0x9f: 0000000000000000 */
- 0x0000, /* 0xa0-0xaf: 0000000000000000 */
- 0x0002, /* 0xb0-0xbf: 0100000000000000 */
- 0x0000, /* 0xc0-0xcf: 0000000000000000 */
- 0x0000, /* 0xd0-0xdf: 0000000000000000 */
- 0x0000, /* 0xe0-0xef: 0000000000000000 */
- 0x0000 /* 0xf0-0xff: 0000000000000000 */
-};
-
-#define USBPF_VALIDATE_CODE(c) \
- ((c) <= 0xff && (usbpf_code_map[(c) >> 4] & (1 << ((c) & 0xf))) != 0)
-
-/*
- * Return true if the 'fcode' is a valid filter program.
- * The constraints are that each jump be forward and to a valid
- * code. The code must terminate with either an accept or reject.
- *
- * The kernel needs to be able to verify an application's filter code.
- * Otherwise, a bogus program could easily crash the system.
- */
-static int
-usbpf_validate(const struct usbpf_insn *f, int len)
-{
- register int i;
- register const struct usbpf_insn *p;
-
- /* Do not accept negative length filter. */
- if (len < 0)
- return (0);
-
- /* An empty filter means accept all. */
- if (len == 0)
- return (1);
-
- for (i = 0; i < len; ++i) {
- p = &f[i];
- /*
- * Check that the code is valid.
- */
- if (!USBPF_VALIDATE_CODE(p->code))
- return (0);
- /*
- * Check that that jumps are forward, and within
- * the code block.
- */
- if (USBPF_CLASS(p->code) == USBPF_JMP) {
- register u_int offset;
-
- if (p->code == (USBPF_JMP|USBPF_JA))
- offset = p->k;
- else
- offset = p->jt > p->jf ? p->jt : p->jf;
- if (offset >= (u_int)(len - i) - 1)
- return (0);
- continue;
- }
- /*
- * Check that memory operations use valid addresses.
- */
- if (p->code == USBPF_ST || p->code == USBPF_STX ||
- p->code == (USBPF_LD|USBPF_MEM) ||
- p->code == (USBPF_LDX|USBPF_MEM)) {
- if (p->k >= USBPF_MEMWORDS)
- return (0);
- continue;
- }
- /*
- * Check for constant division by 0.
- */
- if (p->code == (USBPF_ALU|USBPF_DIV|USBPF_K) && p->k == 0)
- return (0);
- }
- return (USBPF_CLASS(f[len - 1].code) == USBPF_RET);
-}
-
-#ifdef _KERNEL
-#define MINDEX(m, k) \
-{ \
- register int len = m->m_len; \
- \
- while (k >= len) { \
- k -= len; \
- m = m->m_next; \
- if (m == 0) \
- return (0); \
- len = m->m_len; \
- } \
-}
-
-static u_int16_t m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err);
-static u_int32_t m_xword(struct mbuf *m, usbpf_u_int32 k, int *err);
-
-static u_int32_t
-m_xword(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
- size_t len;
- u_char *cp, *np;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == 0)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 4) {
- *err = 0;
- return (USBPF_EXTRACT_LONG(cp));
- }
- m0 = m->m_next;
- if (m0 == 0 || m0->m_len + len - k < 4)
- goto bad;
- *err = 0;
- np = mtod(m0, u_char *);
- switch (len - k) {
- case 1:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)np[0] << 16) |
- ((u_int32_t)np[1] << 8) |
- (u_int32_t)np[2]);
-
- case 2:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)np[0] << 8) |
- (u_int32_t)np[1]);
-
- default:
- return (((u_int32_t)cp[0] << 24) |
- ((u_int32_t)cp[1] << 16) |
- ((u_int32_t)cp[2] << 8) |
- (u_int32_t)np[0]);
- }
- bad:
- *err = 1;
- return (0);
-}
-
-static u_int16_t
-m_xhalf(struct mbuf *m, usbpf_u_int32 k, int *err)
-{
- size_t len;
- u_char *cp;
- struct mbuf *m0;
-
- len = m->m_len;
- while (k >= len) {
- k -= len;
- m = m->m_next;
- if (m == 0)
- goto bad;
- len = m->m_len;
- }
- cp = mtod(m, u_char *) + k;
- if (len - k >= 2) {
- *err = 0;
- return (USBPF_EXTRACT_SHORT(cp));
- }
- m0 = m->m_next;
- if (m0 == 0)
- goto bad;
- *err = 0;
- return ((cp[0] << 8) | mtod(m0, u_char *)[0]);
- bad:
- *err = 1;
- return (0);
-}
-#endif
-
-/*
- * Execute the filter program starting at pc on the packet p
- * wirelen is the length of the original packet
- * buflen is the amount of data present
- */
-static u_int
-usbpf_filter(const struct usbpf_insn *pc, u_char *p, u_int wirelen,
- u_int buflen)
-{
- u_int32_t A = 0, X = 0;
- usbpf_u_int32 k;
- u_int32_t mem[USBPF_MEMWORDS];
-
- /*
- * XXX temporarily the filter system is disabled because currently it
- * could not handle the some machine code properly that leads to
- * kernel crash by invalid usage.
- */
- return ((u_int)-1);
-
- if (pc == NULL)
- /*
- * No filter means accept all.
- */
- return ((u_int)-1);
-
- --pc;
- while (1) {
- ++pc;
- switch (pc->code) {
- default:
-#ifdef _KERNEL
- return (0);
-#else
- abort();
-#endif
-
- case USBPF_RET|USBPF_K:
- return ((u_int)pc->k);
-
- case USBPF_RET|USBPF_A:
- return ((u_int)A);
-
- case USBPF_LD|USBPF_W|USBPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
-#ifdef USBPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = USBPF_EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
- continue;
-
- case USBPF_LD|USBPF_H|USBPF_ABS:
- k = pc->k;
- if (k > buflen || sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- continue;
-#else
- return (0);
-#endif
- }
- A = USBPF_EXTRACT_SHORT(&p[k]);
- continue;
-
- case USBPF_LD|USBPF_B|USBPF_ABS:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
- return (0);
-#endif
- }
- A = p[k];
- continue;
-
- case USBPF_LD|USBPF_W|USBPF_LEN:
- A = wirelen;
- continue;
-
- case USBPF_LDX|USBPF_W|USBPF_LEN:
- X = wirelen;
- continue;
-
- case USBPF_LD|USBPF_W|USBPF_IND:
- k = X + pc->k;
- if (pc->k > buflen || X > buflen - pc->k ||
- sizeof(int32_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xword((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
-#ifdef USBPF_ALIGN
- if (((intptr_t)(p + k) & 3) != 0)
- A = USBPF_EXTRACT_LONG(&p[k]);
- else
-#endif
- A = ntohl(*(int32_t *)(p + k));
- continue;
-
- case USBPF_LD|USBPF_H|USBPF_IND:
- k = X + pc->k;
- if (X > buflen || pc->k > buflen - X ||
- sizeof(int16_t) > buflen - k) {
-#ifdef _KERNEL
- int merr;
-
- if (buflen != 0)
- return (0);
- A = m_xhalf((struct mbuf *)p, k, &merr);
- if (merr != 0)
- return (0);
- continue;
-#else
- return (0);
-#endif
- }
- A = USBPF_EXTRACT_SHORT(&p[k]);
- continue;
-
- case USBPF_LD|USBPF_B|USBPF_IND:
- k = X + pc->k;
- if (pc->k >= buflen || X >= buflen - pc->k) {
-#ifdef _KERNEL
- struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- A = mtod(m, u_char *)[k];
- continue;
-#else
- return (0);
-#endif
- }
- A = p[k];
- continue;
-
- case USBPF_LDX|USBPF_MSH|USBPF_B:
- k = pc->k;
- if (k >= buflen) {
-#ifdef _KERNEL
- register struct mbuf *m;
-
- if (buflen != 0)
- return (0);
- m = (struct mbuf *)p;
- MINDEX(m, k);
- X = (mtod(m, u_char *)[k] & 0xf) << 2;
- continue;
-#else
- return (0);
-#endif
- }
- X = (p[pc->k] & 0xf) << 2;
- continue;
-
- case USBPF_LD|USBPF_IMM:
- A = pc->k;
- continue;
-
- case USBPF_LDX|USBPF_IMM:
- X = pc->k;
- continue;
-
- case USBPF_LD|USBPF_MEM:
- A = mem[pc->k];
- continue;
-
- case USBPF_LDX|USBPF_MEM:
- X = mem[pc->k];
- continue;
-
- case USBPF_ST:
- mem[pc->k] = A;
- continue;
-
- case USBPF_STX:
- mem[pc->k] = X;
- continue;
-
- case USBPF_JMP|USBPF_JA:
- pc += pc->k;
- continue;
-
- case USBPF_JMP|USBPF_JGT|USBPF_K:
- pc += (A > pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGE|USBPF_K:
- pc += (A >= pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JEQ|USBPF_K:
- pc += (A == pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JSET|USBPF_K:
- pc += (A & pc->k) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGT|USBPF_X:
- pc += (A > X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JGE|USBPF_X:
- pc += (A >= X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JEQ|USBPF_X:
- pc += (A == X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_JMP|USBPF_JSET|USBPF_X:
- pc += (A & X) ? pc->jt : pc->jf;
- continue;
-
- case USBPF_ALU|USBPF_ADD|USBPF_X:
- A += X;
- continue;
-
- case USBPF_ALU|USBPF_SUB|USBPF_X:
- A -= X;
- continue;
-
- case USBPF_ALU|USBPF_MUL|USBPF_X:
- A *= X;
- continue;
-
- case USBPF_ALU|USBPF_DIV|USBPF_X:
- if (X == 0)
- return (0);
- A /= X;
- continue;
-
- case USBPF_ALU|USBPF_AND|USBPF_X:
- A &= X;
- continue;
-
- case USBPF_ALU|USBPF_OR|USBPF_X:
- A |= X;
- continue;
-
- case USBPF_ALU|USBPF_LSH|USBPF_X:
- A <<= X;
- continue;
-
- case USBPF_ALU|USBPF_RSH|USBPF_X:
- A >>= X;
- continue;
-
- case USBPF_ALU|USBPF_ADD|USBPF_K:
- A += pc->k;
- continue;
-
- case USBPF_ALU|USBPF_SUB|USBPF_K:
- A -= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_MUL|USBPF_K:
- A *= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_DIV|USBPF_K:
- A /= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_AND|USBPF_K:
- A &= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_OR|USBPF_K:
- A |= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_LSH|USBPF_K:
- A <<= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_RSH|USBPF_K:
- A >>= pc->k;
- continue;
-
- case USBPF_ALU|USBPF_NEG:
- A = -A;
- continue;
-
- case USBPF_MISC|USBPF_TAX:
- X = A;
- continue;
-
- case USBPF_MISC|USBPF_TXA:
- A = X;
- continue;
- }
- }
-}
-
-static void
-usbpf_free(struct usbpf_d *ud)
-{
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return (usbpf_buffer_free(ud));
- default:
- panic("usbpf_buf_free");
- }
-}
-
-/*
- * Notify the buffer model that a buffer has moved into the hold position.
- */
-static void
-usbpf_bufheld(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-}
-
-/*
- * Free buffers currently in use by a descriptor.
- * Called on close.
- */
-static void
-usbpf_freed(struct usbpf_d *ud)
-{
-
- /*
- * We don't need to lock out interrupts since this descriptor has
- * been detached from its interface and it yet hasn't been marked
- * free.
- */
- usbpf_free(ud);
- if (ud->ud_rfilter != NULL)
- free((caddr_t)ud->ud_rfilter, M_USBPF);
- if (ud->ud_wfilter != NULL)
- free((caddr_t)ud->ud_wfilter, M_USBPF);
- mtx_destroy(&ud->ud_mtx);
-}
-
-/*
- * Close the descriptor by detaching it from its interface,
- * deallocating its buffers, and marking it free.
- */
-static void
-usbpf_dtor(void *data)
-{
- struct usbpf_d *ud = data;
-
- USBPFD_LOCK(ud);
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- USBPFD_UNLOCK(ud);
- funsetown(&ud->ud_sigio);
- mtx_lock(&usbpf_mtx);
- if (ud->ud_bif)
- usbpf_detachd(ud);
- mtx_unlock(&usbpf_mtx);
- selwakeuppri(&ud->ud_sel, PRIUSB);
- knlist_destroy(&ud->ud_sel.si_note);
- callout_drain(&ud->ud_callout);
- usbpf_freed(ud);
- free(ud, M_USBPF);
-}
-
-/*
- * Open device. Returns ENXIO for illegal minor device number,
- * EBUSY if file is open by another process.
- */
-/* ARGSUSED */
-static int
-usbpf_open(struct cdev *dev, int flags, int fmt, struct thread *td)
-{
- struct usbpf_d *ud;
- int error;
-
- ud = malloc(sizeof(*ud), M_USBPF, M_WAITOK | M_ZERO);
- error = devfs_set_cdevpriv(ud, usbpf_dtor);
- if (error != 0) {
- free(ud, M_USBPF);
- return (error);
- }
-
- usbpf_buffer_init(ud);
- ud->ud_bufmode = USBPF_BUFMODE_BUFFER;
- ud->ud_sig = SIGIO;
- ud->ud_direction = USBPF_D_INOUT;
- ud->ud_pid = td->td_proc->p_pid;
- mtx_init(&ud->ud_mtx, devtoname(dev), "usbpf cdev lock", MTX_DEF);
- callout_init_mtx(&ud->ud_callout, &ud->ud_mtx, 0);
- knlist_init_mtx(&ud->ud_sel.si_note, &ud->ud_mtx);
-
- return (0);
-}
-
-static int
-usbpf_uiomove(struct usbpf_d *ud, caddr_t buf, u_int len, struct uio *uio)
-{
-
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
- return (EOPNOTSUPP);
- return (usbpf_buffer_uiomove(ud, buf, len, uio));
-}
-
-/*
- * usbpf_read - read next chunk of packets from buffers
- */
-static int
-usbpf_read(struct cdev *dev, struct uio *uio, int ioflag)
-{
- struct usbpf_d *ud;
- int error;
- int non_block;
- int timed_out;
-
- error = devfs_get_cdevpriv((void **)&ud);
- if (error != 0)
- return (error);
-
- /*
- * Restrict application to use a buffer the same size as
- * as kernel buffers.
- */
- if (uio->uio_resid != ud->ud_bufsize)
- return (EINVAL);
-
- non_block = ((ioflag & O_NONBLOCK) != 0);
-
- USBPFD_LOCK(ud);
- ud->ud_pid = curthread->td_proc->p_pid;
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER) {
- USBPFD_UNLOCK(ud);
- return (EOPNOTSUPP);
- }
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- timed_out = (ud->ud_state == USBPF_TIMED_OUT);
- ud->ud_state = USBPF_IDLE;
- /*
- * 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 (ud->ud_hbuf == NULL) {
- if (ud->ud_slen != 0) {
- /*
- * A packet(s) either arrived since the previous
- * read or arrived while we were asleep.
- */
- if (ud->ud_immediate || non_block || timed_out) {
- /*
- * Rotate the buffers and return what's here
- * if we are in immediate mode, non-blocking
- * flag is set, or this descriptor timed out.
- */
- USBPF_ROTATE_BUFFERS(ud);
- break;
- }
- }
-
- /*
- * No data is available, check to see if the usbpf device
- * is still pointed at a real interface. If not, return
- * ENXIO so that the userland process knows to rebind
- * it before using it again.
- */
- if (ud->ud_bif == NULL) {
- USBPFD_UNLOCK(ud);
- return (ENXIO);
- }
-
- if (non_block) {
- USBPFD_UNLOCK(ud);
- return (EWOULDBLOCK);
- }
- error = msleep(ud, &ud->ud_mtx, PRIUSB|PCATCH,
- "uff", ud->ud_rtout);
- if (error == EINTR || error == ERESTART) {
- USBPFD_UNLOCK(ud);
- 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 (ud->ud_hbuf)
- /*
- * We filled up the buffer in between
- * getting the timeout and arriving
- * here, so we don't need to rotate.
- */
- break;
-
- if (ud->ud_slen == 0) {
- USBPFD_UNLOCK(ud);
- return (0);
- }
- USBPF_ROTATE_BUFFERS(ud);
- break;
- }
- }
- /*
- * At this point, we know we have something in the hold slot.
- */
- USBPFD_UNLOCK(ud);
-
- /*
- * Move data from hold buffer into user space.
- * We know the entire buffer is transferred since
- * we checked above that the read buffer is usbpf_bufsize bytes.
- *
- * XXXRW: More synchronization needed here: what if a second thread
- * issues a read on the same fd at the same time? Don't want this
- * getting invalidated.
- */
- error = usbpf_uiomove(ud, ud->ud_hbuf, ud->ud_hlen, uio);
-
- USBPFD_LOCK(ud);
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- USBPFD_UNLOCK(ud);
-
- return (error);
-}
-
-static int
-usbpf_write(struct cdev *dev, struct uio *uio, int ioflag)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-static int
-usbpf_ioctl_sblen(struct usbpf_d *ud, u_int *i)
-{
-
- if (ud->ud_bufmode != USBPF_BUFMODE_BUFFER)
- return (EOPNOTSUPP);
- return (usbpf_buffer_ioctl_sblen(ud, i));
-}
-
-/*
- * Reset a descriptor by flushing its packet buffer and clearing the receive
- * and drop counts. This is doable for kernel-only buffers, but with
- * zero-copy buffers, we can't write to (or rotate) buffers that are
- * currently owned by userspace. It would be nice if we could encapsulate
- * this logic in the buffer code rather than here.
- */
-static void
-usbpf_reset_d(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- if ((ud->ud_hbuf != NULL) &&
- (ud->ud_bufmode != USBPF_BUFMODE_ZBUF || usbpf_canfreebuf(ud))) {
- /* Free the hold buffer. */
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- }
- if (usbpf_canwritebuf(ud))
- ud->ud_slen = 0;
- ud->ud_rcount = 0;
- ud->ud_dcount = 0;
- ud->ud_fcount = 0;
- ud->ud_wcount = 0;
- ud->ud_wfcount = 0;
- ud->ud_wdcount = 0;
- ud->ud_zcopy = 0;
-}
-
-static int
-usbpf_setif(struct usbpf_d *ud, struct usbpf_ifreq *ufr)
-{
- struct usbpf_if *uif;
- struct usb_bus *theywant;
-
- theywant = usb_bus_find(ufr->ufr_name);
- if (theywant == NULL || theywant->uif == NULL)
- return (ENXIO);
-
- uif = theywant->uif;
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- if (ud->ud_sbuf == NULL)
- usbpf_buffer_alloc(ud);
- KASSERT(ud->ud_sbuf != NULL, ("%s: ud_sbuf == NULL", __func__));
- break;
-
- default:
- panic("usbpf_setif: bufmode %d", ud->ud_bufmode);
- }
- if (uif != ud->ud_bif) {
- if (ud->ud_bif)
- /*
- * Detach if attached to something else.
- */
- usbpf_detachd(ud);
-
- usbpf_attachd(ud, uif);
- }
- USBPFD_LOCK(ud);
- usbpf_reset_d(ud);
- USBPFD_UNLOCK(ud);
- return (0);
-}
-
-/*
- * Set d's packet filter program to fp. If this file already has a filter,
- * free it and replace it. Returns EINVAL for bogus requests.
- */
-static int
-usbpf_setf(struct usbpf_d *ud, struct usbpf_program *fp, u_long cmd)
-{
- struct usbpf_insn *fcode, *old;
- u_int wfilter, flen, size;
-
- if (cmd == UIOCSETWF) {
- old = ud->ud_wfilter;
- wfilter = 1;
- } else {
- wfilter = 0;
- old = ud->ud_rfilter;
- }
- if (fp->uf_insns == NULL) {
- if (fp->uf_len != 0)
- return (EINVAL);
- USBPFD_LOCK(ud);
- if (wfilter)
- ud->ud_wfilter = NULL;
- else {
- ud->ud_rfilter = NULL;
- if (cmd == UIOCSETF)
- usbpf_reset_d(ud);
- }
- USBPFD_UNLOCK(ud);
- if (old != NULL)
- free((caddr_t)old, M_USBPF);
- return (0);
- }
- flen = fp->uf_len;
- if (flen > usbpf_maxinsns)
- return (EINVAL);
-
- size = flen * sizeof(*fp->uf_insns);
- fcode = (struct usbpf_insn *)malloc(size, M_USBPF, M_WAITOK);
- if (copyin((caddr_t)fp->uf_insns, (caddr_t)fcode, size) == 0 &&
- usbpf_validate(fcode, (int)flen)) {
- USBPFD_LOCK(ud);
- if (wfilter)
- ud->ud_wfilter = fcode;
- else {
- ud->ud_rfilter = fcode;
- if (cmd == UIOCSETF)
- usbpf_reset_d(ud);
- }
- USBPFD_UNLOCK(ud);
- if (old != NULL)
- free((caddr_t)old, M_USBPF);
-
- return (0);
- }
- free((caddr_t)fcode, M_USBPF);
- return (EINVAL);
-}
-
-static int
-usbpf_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
- struct thread *td)
-{
- struct usbpf_d *ud;
- int error;
-
- error = devfs_get_cdevpriv((void **)&ud);
- if (error != 0)
- return (error);
-
- /*
- * Refresh PID associated with this descriptor.
- */
- USBPFD_LOCK(ud);
- ud->ud_pid = td->td_proc->p_pid;
- if (ud->ud_state == USBPF_WAITING)
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- USBPFD_UNLOCK(ud);
-
- if (ud->ud_locked == 1) {
- switch (cmd) {
- case UIOCGBLEN:
- case UIOCSBLEN:
- case UIOCVERSION:
- break;
- default:
- return (EPERM);
- }
- }
-
- switch (cmd) {
-
- default:
- error = EINVAL;
- break;
-
- /*
- * Get buffer len [for read()].
- */
- case UIOCGBLEN:
- *(u_int *)addr = ud->ud_bufsize;
- break;
-
- /*
- * Set buffer length.
- */
- case UIOCSBLEN:
- error = usbpf_ioctl_sblen(ud, (u_int *)addr);
- break;
-
- /*
- * Set read filter.
- */
- case UIOCSETF:
- error = usbpf_setf(ud, (struct usbpf_program *)addr, cmd);
- break;
-
- /*
- * Set read timeout.
- */
- case UIOCSRTIMEOUT:
- {
- struct timeval *tv = (struct timeval *)addr;
-
- /*
- * Subtract 1 tick from tvtohz() since this isn't
- * a one-shot timer.
- */
- if ((error = itimerfix(tv)) == 0)
- ud->ud_rtout = tvtohz(tv) - 1;
- break;
- }
-
- /*
- * Get read timeout.
- */
- case UIOCGRTIMEOUT:
- {
- struct timeval *tv = (struct timeval *)addr;
-
- tv->tv_sec = ud->ud_rtout / hz;
- tv->tv_usec = (ud->ud_rtout % hz) * tick;
- break;
- }
-
- /*
- * Get packet stats.
- */
- case UIOCGSTATS:
- {
- struct usbpf_stat *us = (struct usbpf_stat *)addr;
-
- /* XXXCSJP overflow */
- us->us_recv = ud->ud_rcount;
- us->us_drop = ud->ud_dcount;
- break;
- }
-
- case UIOCVERSION:
- {
- struct usbpf_version *uv = (struct usbpf_version *)addr;
-
- uv->uv_major = USBPF_MAJOR_VERSION;
- uv->uv_minor = USBPF_MINOR_VERSION;
- break;
- }
-
- /*
- * Set interface.
- */
- case UIOCSETIF:
- error = usbpf_setif(ud, (struct usbpf_ifreq *)addr);
- break;
-
- }
- return (error);
-}
-
-/*
- * Support for select() and poll() system calls
- *
- * Return true iff the specific operation will not block indefinitely.
- * Otherwise, return false but make a note that a selwakeup() must be done.
- */
-static int
-usbpf_poll(struct cdev *dev, int events, struct thread *td)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-/*
- * Support for kevent() system call. Register EVFILT_READ filters and
- * reject all others.
- */
-int
-usbpf_kqfilter(struct cdev *dev, struct knote *kn)
-{
-
- /* NOT IMPLEMENTED */
- return (ENOSYS);
-}
-
-/*
- * Attach file to the usbpf interface, i.e. make d listen on bp.
- */
-static void
-usbpf_attachd(struct usbpf_d *ud, struct usbpf_if *uif)
+void
+usbpf_attach(struct usb_bus *ubus)
{
+ struct ifnet *ifp;
- USBPFIF_LOCK(uif);
- ud->ud_bif = uif;
- LIST_INSERT_HEAD(&uif->uif_dlist, ud, ud_next);
+ ifp = ubus->ifp = if_alloc(IFT_USB);
+ if_initname(ifp, "usbus", device_get_unit(ubus->parent));
+ if_attach(ifp);
- usbpf_uifd_cnt++;
- USBPFIF_UNLOCK(uif);
-}
-
-/*
- * Detach a file from its interface.
- */
-static void
-usbpf_detachd(struct usbpf_d *ud)
-{
- struct usbpf_if *uif;
- struct usb_bus *ubus;
-
- uif = ud->ud_bif;
- USBPFIF_LOCK(uif);
- USBPFD_LOCK(ud);
- ubus = ud->ud_bif->uif_ubus;
+ KASSERT(sizeof(struct usbpf_pkthdr) == USBPF_HDR_LEN,
+ ("wrong USB pf header length (%d)", sizeof(struct usbpf_pkthdr)));
/*
- * Remove d from the interface's descriptor list.
+ * XXX According to the specification of DLT_USB, it indicates packets
+ * beginning with USB setup header. But not sure all packets would be.
*/
- LIST_REMOVE(ud, ud_next);
-
- usbpf_uifd_cnt--;
- ud->ud_bif = NULL;
- USBPFD_UNLOCK(ud);
- USBPFIF_UNLOCK(uif);
-}
-
-void
-usbpf_attach(struct usb_bus *ubus, struct usbpf_if **driverp)
-{
- struct usbpf_if *uif;
-
- uif = malloc(sizeof(*uif), M_USBPF, M_WAITOK | M_ZERO);
- LIST_INIT(&uif->uif_dlist);
- uif->uif_ubus = ubus;
- mtx_init(&uif->uif_mtx, "usbpf interface lock", NULL, MTX_DEF);
- KASSERT(*driverp == NULL,
- ("usbpf_attach: driverp already initialized"));
- *driverp = uif;
-
- mtx_lock(&usbpf_mtx);
- LIST_INSERT_HEAD(&usbpf_iflist, uif, uif_next);
- mtx_unlock(&usbpf_mtx);
+ bpfattach(ifp, DLT_USB, USBPF_HDR_LEN);
if (bootverbose)
device_printf(ubus->parent, "usbpf attached\n");
}
-/*
- * If there are processes sleeping on this descriptor, wake them up.
- */
-static __inline void
-usbpf_wakeup(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
- if (ud->ud_state == USBPF_WAITING) {
- callout_stop(&ud->ud_callout);
- ud->ud_state = USBPF_IDLE;
- }
- wakeup(ud);
- if (ud->ud_async && ud->ud_sig && ud->ud_sigio)
- pgsigio(&ud->ud_sigio, ud->ud_sig, 0);
-
- selwakeuppri(&ud->ud_sel, PRIUSB);
- KNOTE_LOCKED(&ud->ud_sel.si_note, 0);
-}
-
void
usbpf_detach(struct usb_bus *ubus)
{
- struct usbpf_if *uif;
- struct usbpf_d *ud;
+ struct ifnet *ifp = ubus->ifp;
- /* Locate USBPF interface information */
- mtx_lock(&usbpf_mtx);
- LIST_FOREACH(uif, &usbpf_iflist, uif_next) {
- if (ubus == uif->uif_ubus)
- break;
+ if (ifp != NULL) {
+ bpfdetach(ifp);
+ if_detach(ifp);
+ if_free(ifp);
}
-
- /* Interface wasn't attached */
- if ((uif == NULL) || (uif->uif_ubus == NULL)) {
- mtx_unlock(&usbpf_mtx);
- printf("usbpf_detach: not attached\n"); /* XXX */
- return;
- }
-
- LIST_REMOVE(uif, uif_next);
- mtx_unlock(&usbpf_mtx);
-
- while ((ud = LIST_FIRST(&uif->uif_dlist)) != NULL) {
- usbpf_detachd(ud);
- USBPFD_LOCK(ud);
- usbpf_wakeup(ud);
- USBPFD_UNLOCK(ud);
- }
-
- mtx_destroy(&uif->uif_mtx);
- free(uif, M_USBPF);
-}
-
-/* Time stamping functions */
-#define USBPF_T_MICROTIME 0x0000
-#define USBPF_T_NANOTIME 0x0001
-#define USBPF_T_BINTIME 0x0002
-#define USBPF_T_NONE 0x0003
-#define USBPF_T_FORMAT_MASK 0x0003
-#define USBPF_T_NORMAL 0x0000
-#define USBPF_T_FAST 0x0100
-#define USBPF_T_MONOTONIC 0x0200
-#define USBPF_T_FORMAT(t) ((t) & USBPF_T_FORMAT_MASK)
-
-#define USBPF_TSTAMP_NONE 0
-#define USBPF_TSTAMP_FAST 1
-#define USBPF_TSTAMP_NORMAL 2
-
-static int
-usbpf_ts_quality(int tstype)
-{
-
- if (tstype == USBPF_T_NONE)
- return (USBPF_TSTAMP_NONE);
- if ((tstype & USBPF_T_FAST) != 0)
- return (USBPF_TSTAMP_FAST);
-
- return (USBPF_TSTAMP_NORMAL);
-}
-
-static int
-usbpf_gettime(struct bintime *bt, int tstype)
-{
- int quality;
-
- quality = usbpf_ts_quality(tstype);
- if (quality == USBPF_TSTAMP_NONE)
- return (quality);
- if (quality == USBPF_TSTAMP_NORMAL)
- binuptime(bt);
- else
- getbinuptime(bt);
-
- return (quality);
-}
-
-/*
- * If the buffer mechanism has a way to decide that a held buffer can be made
- * free, then it is exposed via the usbpf_canfreebuf() interface. (1) is
- * returned if the buffer can be discarded, (0) is returned if it cannot.
- */
-static int
-usbpf_canfreebuf(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- return (0);
-}
-
-/*
- * Allow the buffer model to indicate that the current store buffer is
- * immutable, regardless of the appearance of space. Return (1) if the
- * buffer is writable, and (0) if not.
- */
-static int
-usbpf_canwritebuf(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
- return (1);
-}
-
-/*
- * Notify buffer model that an attempt to write to the store buffer has
- * resulted in a dropped packet, in which case the buffer may be considered
- * full.
- */
-static void
-usbpf_buffull(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-}
-
-/*
- * This function gets called when the free buffer is re-assigned.
- */
-static void
-usbpf_buf_reclaimed(struct usbpf_d *ud)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return;
-
- default:
- panic("usbpf_buf_reclaimed");
- }
-}
-
-#define SIZEOF_USBPF_HDR(type) \
- (offsetof(type, uh_hdrlen) + sizeof(((type *)0)->uh_hdrlen))
-
-static int
-usbpf_hdrlen(struct usbpf_d *ud)
-{
- int hdrlen;
-
- hdrlen = ud->ud_bif->uif_hdrlen;
- hdrlen += SIZEOF_USBPF_HDR(struct usbpf_xhdr);
- hdrlen = USBPF_WORDALIGN(hdrlen);
-
- return (hdrlen - ud->ud_bif->uif_hdrlen);
-}
-
-static void
-usbpf_bintime2ts(struct bintime *bt, struct usbpf_ts *ts, int tstype)
-{
- struct bintime bt2;
- struct timeval tsm;
- struct timespec tsn;
-
- if ((tstype & USBPF_T_MONOTONIC) == 0) {
- bt2 = *bt;
- bintime_add(&bt2, &boottimebin);
- bt = &bt2;
- }
- switch (USBPF_T_FORMAT(tstype)) {
- case USBPF_T_MICROTIME:
- bintime2timeval(bt, &tsm);
- ts->ut_sec = tsm.tv_sec;
- ts->ut_frac = tsm.tv_usec;
- break;
- case USBPF_T_NANOTIME:
- bintime2timespec(bt, &tsn);
- ts->ut_sec = tsn.tv_sec;
- ts->ut_frac = tsn.tv_nsec;
- break;
- case USBPF_T_BINTIME:
- ts->ut_sec = bt->sec;
- ts->ut_frac = bt->frac;
- break;
- }
-}
-
-/*
- * Move the packet data from interface memory (pkt) into the
- * store buffer. "cpfn" is the routine called to do the actual data
- * transfer. bcopy is passed in to copy contiguous chunks, while
- * usbpf_append_mbuf is passed in to copy mbuf chains. In the latter case,
- * pkt is really an mbuf.
- */
-static void
-catchpacket(struct usbpf_d *ud, u_char *pkt, u_int pktlen, u_int snaplen,
- void (*cpfn)(struct usbpf_d *, caddr_t, u_int, void *, u_int),
- struct bintime *bt)
-{
- struct usbpf_xhdr hdr;
- int caplen, curlen, hdrlen, totlen;
- int do_wakeup = 0;
- int do_timestamp;
- int tstype;
-
- USBPFD_LOCK_ASSERT(ud);
-
- /*
- * Detect whether user space has released a buffer back to us, and if
- * so, move it from being a hold buffer to a free buffer. This may
- * not be the best place to do it (for example, we might only want to
- * run this check if we need the space), but for now it's a reliable
- * spot to do it.
- */
- if (ud->ud_fbuf == NULL && usbpf_canfreebuf(ud)) {
- ud->ud_fbuf = ud->ud_hbuf;
- ud->ud_hbuf = NULL;
- ud->ud_hlen = 0;
- usbpf_buf_reclaimed(ud);
- }
-
- /*
- * Figure out how many bytes to move. If the packet is
- * greater or equal to the snapshot length, transfer that
- * much. Otherwise, transfer the whole packet (unless
- * we hit the buffer size limit).
- */
- hdrlen = usbpf_hdrlen(ud);
- totlen = hdrlen + min(snaplen, pktlen);
- if (totlen > ud->ud_bufsize)
- totlen = ud->ud_bufsize;
-
- /*
- * Round up the end of the previous packet to the next longword.
- *
- * Drop the packet if there's no room and no hope of room
- * If the packet would overflow the storage buffer or the storage
- * buffer is considered immutable by the buffer model, try to rotate
- * the buffer and wakeup pending processes.
- */
- curlen = USBPF_WORDALIGN(ud->ud_slen);
- if (curlen + totlen > ud->ud_bufsize || !usbpf_canwritebuf(ud)) {
- if (ud->ud_fbuf == NULL) {
- /*
- * There's no room in the store buffer, and no
- * prospect of room, so drop the packet. Notify the
- * buffer model.
- */
- usbpf_buffull(ud);
- ++ud->ud_dcount;
- return;
- }
- USBPF_ROTATE_BUFFERS(ud);
- do_wakeup = 1;
- curlen = 0;
- } else if (ud->ud_immediate || ud->ud_state == USBPF_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;
- caplen = totlen - hdrlen;
- tstype = ud->ud_tstamp;
- do_timestamp = tstype != USBPF_T_NONE;
-
- /*
- * Append the usbpf header. Note we append the actual header size, but
- * move forward the length of the header plus padding.
- */
- bzero(&hdr, sizeof(hdr));
- if (do_timestamp)
- usbpf_bintime2ts(bt, &hdr.uh_tstamp, tstype);
- hdr.uh_datalen = pktlen;
- hdr.uh_hdrlen = hdrlen;
- hdr.uh_caplen = caplen;
- usbpf_append_bytes(ud, ud->ud_sbuf, curlen, &hdr, sizeof(hdr));
-
- /*
- * Copy the packet data into the store buffer and update its length.
- */
- (*cpfn)(ud, ud->ud_sbuf, curlen + hdrlen, pkt, caplen);
- ud->ud_slen = curlen + totlen;
-
- if (do_wakeup)
- usbpf_wakeup(ud);
-}
-
-/*
- * Incoming linkage from device drivers. Process the packet pkt, of length
- * pktlen, which is stored in a contiguous buffer. The packet is parsed
- * by each process' filter, and if accepted, stashed into the corresponding
- * buffer.
- */
-static void
-usbpf_tap(struct usbpf_if *uif, u_char *pkt, u_int pktlen)
-{
- struct bintime bt;
- struct usbpf_d *ud;
- u_int slen;
- int gottime;
-
- gottime = USBPF_TSTAMP_NONE;
- USBPFIF_LOCK(uif);
- LIST_FOREACH(ud, &uif->uif_dlist, ud_next) {
- USBPFD_LOCK(ud);
- ++ud->ud_rcount;
- slen = usbpf_filter(ud->ud_rfilter, pkt, pktlen, pktlen);
- if (slen != 0) {
- ud->ud_fcount++;
- if (gottime < usbpf_ts_quality(ud->ud_tstamp))
- gottime = usbpf_gettime(&bt, ud->ud_tstamp);
- catchpacket(ud, pkt, pktlen, slen,
- usbpf_append_bytes, &bt);
- }
- USBPFD_UNLOCK(ud);
- }
- USBPFIF_UNLOCK(uif);
+ ubus->ifp = NULL;
}
static uint32_t
@@ -1764,11 +181,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
int i;
char *buf, *ptr, *end;
- /*
- * NB: usbpf_uifd_cnt isn't protected by USBPFIF_LOCK() because it's
- * not harmful.
- */
- if (usbpf_uifd_cnt == 0)
+ if (!bpf_peers_present(bus->ifp->if_bpf))
return;
/*
@@ -1778,7 +191,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
* read filter to pass a virtually linear buffer.
*/
buf = ptr = malloc(sizeof(struct usbpf_pkthdr) + (USB_PAGE_SIZE * 5),
- M_USBPF, M_NOWAIT);
+ M_TEMP, M_NOWAIT);
if (buf == NULL) {
printf("usbpf_xfertap: out of memory\n"); /* XXX */
return;
@@ -1828,49 +241,7 @@ usbpf_xfertap(struct usb_xfer *xfer, int type)
ptr += xfer->frlengths[i];
}
- usbpf_tap(bus->uif, buf, ptr - buf);
+ bpf_tap(bus->ifp->if_bpf, buf, ptr - buf);
done:
- free(buf, M_USBPF);
+ free(buf, M_TEMP);
}
-
-static void
-usbpf_append_bytes(struct usbpf_d *ud, caddr_t buf, u_int offset, void *src,
- u_int len)
-{
-
- USBPFD_LOCK_ASSERT(ud);
-
- switch (ud->ud_bufmode) {
- case USBPF_BUFMODE_BUFFER:
- return (usbpf_buffer_append_bytes(ud, buf, offset, src, len));
- default:
- panic("usbpf_buf_append_bytes");
- }
-}
-
-static void
-usbpf_drvinit(void *unused)
-{
-
- mtx_init(&usbpf_mtx, "USB packet filter global lock", NULL,
- MTX_DEF);
- LIST_INIT(&usbpf_iflist);
-
- usbpf_cdev = make_dev(&usbpf_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
- "usbpf");
-}
-
-static void
-usbpf_drvuninit(void)
-{
-
- if (usbpf_cdev != NULL) {
- destroy_dev(usbpf_cdev);
- usbpf_cdev = NULL;
- }
- mtx_destroy(&usbpf_mtx);
-}
-
-SYSINIT(usbpf_dev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, usbpf_drvinit, NULL);
-SYSUNINIT(usbpf_undev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE, usbpf_drvuninit, NULL);
-
diff --git a/sys/dev/usb/usb_pf.h b/sys/dev/usb/usb_pf.h
index f5ed9a0..58b9ce9 100644
--- a/sys/dev/usb/usb_pf.h
+++ b/sys/dev/usb/usb_pf.h
@@ -37,190 +37,6 @@
#ifndef _DEV_USB_PF_H
#define _DEV_USB_PF_H
-#ifdef _KERNEL
-#include <sys/callout.h>
-#include <sys/selinfo.h>
-#include <sys/queue.h>
-#include <sys/conf.h>
-#endif
-
-typedef int32_t usbpf_int32;
-typedef u_int32_t usbpf_u_int32;
-typedef int64_t usbpf_int64;
-typedef u_int64_t usbpf_u_int64;
-
-struct usbpf_if;
-
-/*
- * Alignment macros. USBPF_WORDALIGN rounds up to the next
- * even multiple of USBPF_ALIGNMENT.
- */
-#define USBPF_ALIGNMENT sizeof(long)
-#define USBPF_WORDALIGN(x) (((x)+(USBPF_ALIGNMENT-1))&~(USBPF_ALIGNMENT-1))
-
-/*
- * The instruction encodings.
- */
-
-/* instruction classes */
-#define USBPF_CLASS(code) ((code) & 0x07)
-#define USBPF_LD 0x00
-#define USBPF_LDX 0x01
-#define USBPF_ST 0x02
-#define USBPF_STX 0x03
-#define USBPF_ALU 0x04
-#define USBPF_JMP 0x05
-#define USBPF_RET 0x06
-#define USBPF_MISC 0x07
-
-/* ld/ldx fields */
-#define USBPF_SIZE(code) ((code) & 0x18)
-#define USBPF_W 0x00
-#define USBPF_H 0x08
-#define USBPF_B 0x10
-#define USBPF_MODE(code) ((code) & 0xe0)
-#define USBPF_IMM 0x00
-#define USBPF_ABS 0x20
-#define USBPF_IND 0x40
-#define USBPF_MEM 0x60
-#define USBPF_LEN 0x80
-#define USBPF_MSH 0xa0
-
-/* alu/jmp fields */
-#define USBPF_OP(code) ((code) & 0xf0)
-#define USBPF_ADD 0x00
-#define USBPF_SUB 0x10
-#define USBPF_MUL 0x20
-#define USBPF_DIV 0x30
-#define USBPF_OR 0x40
-#define USBPF_AND 0x50
-#define USBPF_LSH 0x60
-#define USBPF_RSH 0x70
-#define USBPF_NEG 0x80
-#define USBPF_JA 0x00
-#define USBPF_JEQ 0x10
-#define USBPF_JGT 0x20
-#define USBPF_JGE 0x30
-#define USBPF_JSET 0x40
-#define USBPF_SRC(code) ((code) & 0x08)
-#define USBPF_K 0x00
-#define USBPF_X 0x08
-
-/* ret - USBPF_K and USBPF_X also apply */
-#define USBPF_RVAL(code) ((code) & 0x18)
-#define USBPF_A 0x10
-
-/* misc */
-#define USBPF_MISCOP(code) ((code) & 0xf8)
-#define USBPF_TAX 0x00
-#define USBPF_TXA 0x80
-
-/*
- * The instruction data structure.
- */
-struct usbpf_insn {
- u_short code;
- u_char jt;
- u_char jf;
- usbpf_u_int32 k;
-};
-
-#ifdef _KERNEL
-
-/*
- * Descriptor associated with each open uff file.
- */
-
-struct usbpf_d {
- LIST_ENTRY(usbpf_d) ud_next; /* Linked list of descriptors */
- /*
- * Buffer slots: two memory buffers store the incoming packets.
- * The model has three slots. Sbuf is always occupied.
- * sbuf (store) - Receive interrupt puts packets here.
- * hbuf (hold) - When sbuf is full, put buffer here and
- * wakeup read (replace sbuf with fbuf).
- * fbuf (free) - When read is done, put buffer here.
- * On receiving, if sbuf is full and fbuf is 0, packet is dropped.
- */
- caddr_t ud_sbuf; /* store slot */
- caddr_t ud_hbuf; /* hold slot */
- caddr_t ud_fbuf; /* free slot */
- int ud_slen; /* current length of store buffer */
- int ud_hlen; /* current length of hold buffer */
-
- int ud_bufsize; /* absolute length of buffers */
-
- struct usbpf_if *ud_bif; /* interface descriptor */
- u_long ud_rtout; /* Read timeout in 'ticks' */
- struct usbpf_insn *ud_rfilter; /* read filter code */
- struct usbpf_insn *ud_wfilter; /* write filter code */
- void *ud_bfilter; /* binary filter code */
- u_int64_t ud_rcount; /* number of packets received */
- u_int64_t ud_dcount; /* number of packets dropped */
-
- u_char ud_promisc; /* true if listening promiscuously */
- u_char ud_state; /* idle, waiting, or timed out */
- u_char ud_immediate; /* true to return on packet arrival */
- int ud_hdrcmplt; /* false to fill in src lladdr automatically */
- int ud_direction; /* select packet direction */
- int ud_tstamp; /* select time stamping function */
- int ud_feedback; /* true to feed back sent packets */
- int ud_async; /* non-zero if packet reception should generate signal */
- int ud_sig; /* signal to send upon packet reception */
- struct sigio * ud_sigio; /* information for async I/O */
- struct selinfo ud_sel; /* bsd select info */
- struct mtx ud_mtx; /* mutex for this descriptor */
- struct callout ud_callout; /* for USBPF timeouts with select */
- struct label *ud_label; /* MAC label for descriptor */
- u_int64_t ud_fcount; /* number of packets which matched filter */
- pid_t ud_pid; /* PID which created descriptor */
- int ud_locked; /* true if descriptor is locked */
- u_int ud_bufmode; /* Current buffer mode. */
- u_int64_t ud_wcount; /* number of packets written */
- u_int64_t ud_wfcount; /* number of packets that matched write filter */
- u_int64_t ud_wdcount; /* number of packets dropped during a write */
- u_int64_t ud_zcopy; /* number of zero copy operations */
- u_char ud_compat32; /* 32-bit stream on LP64 system */
-};
-
-#define USBPFD_LOCK(ud) mtx_lock(&(ud)->ud_mtx)
-#define USBPFD_UNLOCK(ud) mtx_unlock(&(ud)->ud_mtx)
-#define USBPFD_LOCK_ASSERT(ud) mtx_assert(&(ud)->ud_mtx, MA_OWNED)
-
-/*
- * Descriptor associated with each attached hardware interface.
- */
-struct usbpf_if {
- LIST_ENTRY(usbpf_if) uif_next; /* list of all interfaces */
- LIST_HEAD(, usbpf_d) uif_dlist; /* descriptor list */
- u_int uif_hdrlen; /* length of link header */
- struct usb_bus *uif_ubus; /* corresponding interface */
- struct mtx uif_mtx; /* mutex for interface */
-};
-
-#define USBPFIF_LOCK(uif) mtx_lock(&(uif)->uif_mtx)
-#define USBPFIF_UNLOCK(uif) mtx_unlock(&(uif)->uif_mtx)
-
-#endif
-
-/*
- * Structure prepended to each packet.
- */
-struct usbpf_ts {
- usbpf_int64 ut_sec; /* seconds */
- usbpf_u_int64 ut_frac; /* fraction */
-};
-struct usbpf_xhdr {
- struct usbpf_ts uh_tstamp; /* time stamp */
- usbpf_u_int32 uh_caplen; /* length of captured portion */
- usbpf_u_int32 uh_datalen; /* original length of packet */
- u_short uh_hdrlen; /* length of uff header (this struct
- plus alignment padding) */
-};
-
-#define USBPF_BUFMODE_BUFFER 1 /* Kernel buffers with read(). */
-#define USBPF_BUFMODE_ZBUF 2 /* Zero-copy buffers. */
-
struct usbpf_pkthdr {
int up_busunit; /* Host controller unit number */
u_char up_address; /* USB device address */
@@ -268,50 +84,13 @@ struct usbpf_pkthdr {
u_char up_reserved[96];
};
-struct usbpf_version {
- u_short uv_major;
- u_short uv_minor;
-};
-#define USBPF_MAJOR_VERSION 1
-#define USBPF_MINOR_VERSION 1
-
-#define USBPF_IFNAMSIZ 32
-struct usbpf_ifreq {
- /* bus name, e.g. "usbus0" */
- char ufr_name[USBPF_IFNAMSIZ];
-};
-
-/*
- * Structure for UIOCSETF.
- */
-struct usbpf_program {
- u_int uf_len;
- struct usbpf_insn *uf_insns;
-};
-
-/*
- * Struct returned by UIOCGSTATS.
- */
-struct usbpf_stat {
- u_int us_recv; /* number of packets received */
- u_int us_drop; /* number of packets dropped */
-};
-
-#define UIOCGBLEN _IOR('U', 102, u_int)
-#define UIOCSBLEN _IOWR('U', 102, u_int)
-#define UIOCSETF _IOW('U', 103, struct usbpf_program)
-#define UIOCSETIF _IOW('U', 108, struct usbpf_ifreq)
-#define UIOCSRTIMEOUT _IOW('U', 109, struct timeval)
-#define UIOCGRTIMEOUT _IOR('U', 110, struct timeval)
-#define UIOCGSTATS _IOR('U', 111, struct usbpf_stat)
-#define UIOCVERSION _IOR('U', 113, struct usbpf_version)
-#define UIOCSETWF _IOW('U', 123, struct usbpf_program)
+#define USBPF_HDR_LEN 128
#define USBPF_XFERTAP_SUBMIT 0
#define USBPF_XFERTAP_DONE 1
#ifdef _KERNEL
-void usbpf_attach(struct usb_bus *, struct usbpf_if **);
+void usbpf_attach(struct usb_bus *);
void usbpf_detach(struct usb_bus *);
void usbpf_xfertap(struct usb_xfer *, int);
#endif
OpenPOWER on IntegriCloud