diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2019-10-03 07:32:20 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2019-10-03 07:32:20 +0000 |
commit | 704e9ff2481bd1f20ab1e6e05bf3d76c48e4a4bb (patch) | |
tree | 2972e930e0616a9c3162990606533acd3fd7bb98 /sys/dev/usb/if_umb.c | |
parent | c4076cad3b40323b1f22e0c682186813618a4b32 (diff) |
Switch the bpf of umb(4) from DTL_RAW to DTL_LOOP. DTL_RAW is limited to
ip only whereas DTL_LOOP passes the address family of the packet and so
supports more address families.
To make this work umb_decap() prepends the AF to the packet and which is
consumed then by umb_input(). Similar umb_output() sets ph_family in the
mbuf header which is used by umb_start().
OK deraadt@ dlg@
Diffstat (limited to 'sys/dev/usb/if_umb.c')
-rw-r--r-- | sys/dev/usb/if_umb.c | 44 |
1 files changed, 31 insertions, 13 deletions
diff --git a/sys/dev/usb/if_umb.c b/sys/dev/usb/if_umb.c index a8ea64213e1..77f9c95c4d9 100644 --- a/sys/dev/usb/if_umb.c +++ b/sys/dev/usb/if_umb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_umb.c,v 1.26 2019/09/29 15:31:16 deraadt Exp $ */ +/* $OpenBSD: if_umb.c,v 1.27 2019/10/03 07:32:19 claudio Exp $ */ /* * Copyright (c) 2016 genua mbH @@ -516,7 +516,7 @@ umb_attach(struct device *parent, struct device *self, void *aux) if_alloc_sadl(ifp); ifp->if_softc = sc; #if NBPFILTER > 0 - bpfattach(&ifp->if_bpf, ifp, DLT_RAW, 0); + bpfattach(&ifp->if_bpf, ifp, DLT_LOOP, sizeof(uint32_t)); #endif /* * Open the device now so that we are able to query device information. @@ -759,19 +759,20 @@ umb_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, m_freem(m); return ENETDOWN; } + m->m_pkthdr.ph_family = dst->sa_family; return if_enqueue(ifp, m); } int umb_input(struct ifnet *ifp, struct mbuf *m, void *cookie) { - uint8_t ipv; + uint32_t af; if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return 1; } - if (m->m_pkthdr.len < sizeof (struct ip)) { + if (m->m_pkthdr.len < sizeof (struct ip) + sizeof(af)) { ifp->if_ierrors++; DPRINTFN(4, "%s: dropping short packet (len %d)\n", __func__, m->m_pkthdr.len); @@ -779,16 +780,19 @@ umb_input(struct ifnet *ifp, struct mbuf *m, void *cookie) return 1; } m->m_pkthdr.ph_rtableid = ifp->if_rdomain; - m_copydata(m, 0, sizeof (ipv), &ipv); - ipv >>= 4; + + /* pop of DLT_LOOP header, no longer needed */ + af = *mtod(m, uint32_t *); + m_adj(m, sizeof (af)); + af = ntohl(af); ifp->if_ibytes += m->m_pkthdr.len; - switch (ipv) { - case 4: + switch (af) { + case AF_INET: ipv4_input(ifp, m); return 1; #ifdef INET6 - case 6: + case AF_INET6: ipv6_input(ifp, m); return 1; #endif /* INET6 */ @@ -878,7 +882,8 @@ umb_start(struct ifnet *ifp) #if NBPFILTER > 0 if (ifp->if_bpf) - bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); + bpf_mtap_af(ifp->if_bpf, m->m_pkthdr.ph_family, m, + BPF_DIRECTION_OUT); #endif } if (ml_empty(&sc->sc_tx_ml)) @@ -1916,7 +1921,7 @@ umb_decap(struct umb_softc *sc, struct usbd_xfer *xfer) struct ifnet *ifp = GET_IFP(sc); int s; void *buf; - uint32_t len; + uint32_t len, af = 0; char *dp; struct ncm_header16 *hdr16; struct ncm_header32 *hdr32; @@ -2033,12 +2038,25 @@ umb_decap(struct umb_softc *sc, struct usbd_xfer *xfer) dp = buf + doff; DPRINTFN(3, "%s: decap %d bytes\n", DEVNAM(sc), dlen); - m = m_devget(dp, dlen, 0); + m = m_devget(dp, dlen, sizeof(uint32_t)); if (m == NULL) { ifp->if_iqdrops++; continue; } - + m = m_prepend(m, sizeof(uint32_t), M_DONTWAIT); + if (m == NULL) { + ifp->if_iqdrops++; + continue; + } + switch (*dp & 0xf0) { + case 4 << 4: + af = htonl(AF_INET); + break; + case 6 << 4: + af = htonl(AF_INET6); + break; + } + *mtod(m, uint32_t *) = af; ml_enqueue(&ml, m); } done: |