umb(4) is currently the only user of DLT_RAW. The problem with this is
that it only works for IPv4 packets and that is less than ideal.
This diff switches umb(4) to DLT_LOOP like lo(4), tun(4), gif(4), ...

To make this work the driver injects the af header in umb_decap() when
pulling the packet of the ring and pops that header in umb_input() this
way the common interface input handling can still be used.
For the outbound packets umb_output() will now set ph_family header in the
mbuf so that umb_start() can use this in bpf_mtap_af().

With this tcpdump should be able to show also IPv6 packets. 
My provider does not do IPv6 (neither via umb MBIM_CID_IP_CONFIGURATION or
via slaac) but maybe someone else has a more tech competent provider than
me and is willing to make IPv6 go on umb(4).
-- 
:wq Claudio

Index: dev/usb/if_umb.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/if_umb.c,v
retrieving revision 1.26
diff -u -p -r1.26 if_umb.c
--- dev/usb/if_umb.c    29 Sep 2019 15:31:16 -0000      1.26
+++ dev/usb/if_umb.c    1 Oct 2019 11:00:10 -0000
@@ -516,7 +516,7 @@ umb_attach(struct device *parent, struct
        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 mbu
                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
                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 u
        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 u
 
                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:

Reply via email to