> On 11 Jan 2018, at 23:54, Martin Pieuchot <m...@openbsd.org> wrote:
> 
> On 11/01/18(Thu) 23:10, David Gwynne wrote:
>> 
>> 
>>> On 11 Jan 2018, at 9:11 pm, Martin Pieuchot <m...@openbsd.org> wrote:
>>> 
>>> On 11/01/18(Thu) 11:58, David Gwynne wrote:
>>>> im sending this out more as a backup than a serious diff.
>>> 
>>> I love this.  It's one of the steps to be able to use bpf(4) for USB.
>> 
>> oh yeah.
>> 
>>> 
>>> Is there an easy way to also remove the mbuf requirement?  For example
>>> I'd like to call bpf_mtap() or similar in usb_transfer_complete().
>> 
>> is the usb payload in one or two contig buffers? we could just fake it.
> 
> Yes, it's  KERNADDR(&xfer->dmabuf, 0) of size `xfer->actlen'.

if it's a single buffer, just use https://man.openbsd.org/bpf_filter.

if you want to put a header on it too, we'll need to a bit of extra code, but 
it's fairly trivial.

jono reminded me that i wanted bpf on sd(4) at one point too. or ttys. i dont 
think ttys was my idea though.

dlg

> 
>>>> this tweaks bpf so it can be used by subsystems, not just interfaces.
>>>> this is done by making bpf store and use names (eg, "pf" and "em0")
>>>> instead of just interfaces. interfaces get some special handling
>>>> so you can't bpfwrite or enable ifpromisc unless bif_ifp is set.
>>>> 
>>>> an example use of this is attaching bpf to pf. you can see all the
>>>> packets handed to pf_test with this diff and tcpdump -ni pf.
>>>> 
>>>> Index: bpf.c
>>>> ===================================================================
>>>> RCS file: /cvs/src/sys/net/bpf.c,v
>>>> retrieving revision 1.165
>>>> diff -u -p -r1.165 bpf.c
>>>> --- bpf.c  30 Dec 2017 23:08:29 -0000      1.165
>>>> +++ bpf.c  10 Jan 2018 07:27:45 -0000
>>>> @@ -93,7 +93,7 @@ struct bpf_if    *bpf_iflist;
>>>> LIST_HEAD(, bpf_d) bpf_d_list;
>>>> 
>>>> int        bpf_allocbufs(struct bpf_d *);
>>>> -void      bpf_ifname(struct ifnet *, struct ifreq *);
>>>> +void      bpf_ifname(struct bpf_if*, struct ifreq *);
>>>> int        _bpf_mtap(caddr_t, const struct mbuf *, u_int,
>>>>        void (*)(const void *, void *, size_t));
>>>> void       bpf_mcopy(const void *, void *, size_t);
>>>> @@ -320,6 +320,8 @@ bpf_detachd(struct bpf_d *d)
>>>>    if (d->bd_promisc) {
>>>>            int error;
>>>> 
>>>> +          KASSERT(bp->bif_ifp != NULL);
>>>> +
>>>>            d->bd_promisc = 0;
>>>> 
>>>>            bpf_get(d);
>>>> @@ -593,7 +595,7 @@ bpfwrite(dev_t dev, struct uio *uio, int
>>>>    bpf_get(d);
>>>>    ifp = d->bd_bif->bif_ifp;
>>>> 
>>>> -  if ((ifp->if_flags & IFF_UP) == 0) {
>>>> +  if (ifp == NULL || (ifp->if_flags & IFF_UP) == 0) {
>>>>            error = ENETDOWN;
>>>>            goto out;
>>>>    }
>>>> @@ -789,7 +791,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t 
>>>>                     * No interface attached yet.
>>>>                     */
>>>>                    error = EINVAL;
>>>> -          } else {
>>>> +          } else if (d->bd_bif->bif_ifp != NULL) { 
>>>>                    if (d->bd_promisc == 0) {
>>>>                            MUTEX_ASSERT_UNLOCKED(&d->bd_mtx);
>>>>                            error = ifpromisc(d->bd_bif->bif_ifp, 1);
>>>> @@ -839,7 +841,7 @@ bpfioctl(dev_t dev, u_long cmd, caddr_t 
>>>>            if (d->bd_bif == NULL)
>>>>                    error = EINVAL;
>>>>            else
>>>> -                  bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
>>>> +                  bpf_ifname(d->bd_bif, (struct ifreq *)addr);
>>>>            break;
>>>> 
>>>>    /*
>>>> @@ -1049,10 +1051,7 @@ bpf_setif(struct bpf_d *d, struct ifreq 
>>>>     * Look through attached interfaces for the named one.
>>>>     */
>>>>    for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
>>>> -          struct ifnet *ifp = bp->bif_ifp;
>>>> -
>>>> -          if (ifp == NULL ||
>>>> -              strcmp(ifp->if_xname, ifr->ifr_name) != 0)
>>>> +          if (strcmp(bp->bif_name, ifr->ifr_name) != 0)
>>>>                    continue;
>>>> 
>>>>            if (candidate == NULL || candidate->bif_dlt > bp->bif_dlt)
>>>> @@ -1090,9 +1089,9 @@ out:
>>>> * Copy the interface name to the ifreq.
>>>> */
>>>> void
>>>> -bpf_ifname(struct ifnet *ifp, struct ifreq *ifr)
>>>> +bpf_ifname(struct bpf_if *bif, struct ifreq *ifr)
>>>> {
>>>> -  bcopy(ifp->if_xname, ifr->ifr_name, IFNAMSIZ);
>>>> +  bcopy(bif->bif_name, ifr->ifr_name, sizeof(ifr->ifr_name));
>>>> }
>>>> 
>>>> /*
>>>> @@ -1538,21 +1537,17 @@ bpf_put(struct bpf_d *bd)
>>>>    free(bd, M_DEVBUF, sizeof(*bd));
>>>> }
>>>> 
>>>> -/*
>>>> - * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if 
>>>> *)
>>>> - * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
>>>> - * size of the link header (variable length headers not yet supported).
>>>> - */
>>>> -void
>>>> -bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
>>>> +void *
>>>> +bpfsattach(caddr_t *bpfp, const char *name, u_int dlt, u_int hdrlen)
>>>> {
>>>>    struct bpf_if *bp;
>>>> 
>>>>    if ((bp = malloc(sizeof(*bp), M_DEVBUF, M_NOWAIT)) == NULL)
>>>>            panic("bpfattach");
>>>>    SRPL_INIT(&bp->bif_dlist);
>>>> -  bp->bif_driverp = (struct bpf_if **)driverp;
>>>> -  bp->bif_ifp = ifp;
>>>> +  bp->bif_driverp = (struct bpf_if **)bpfp;
>>>> +  bp->bif_name = name;
>>>> +  bp->bif_ifp = NULL;
>>>>    bp->bif_dlt = dlt;
>>>> 
>>>>    bp->bif_next = bpf_iflist;
>>>> @@ -1567,6 +1562,17 @@ bpfattach(caddr_t *driverp, struct ifnet
>>>>     * performance reasons and to alleviate alignment restrictions).
>>>>     */
>>>>    bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
>>>> +
>>>> +  return (bp);
>>>> +}
>>>> +
>>>> +void
>>>> +bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
>>>> +{
>>>> +  struct bpf_if *bp;
>>>> +
>>>> +  bp = bpfsattach(driverp, ifp->if_xname, dlt, hdrlen);
>>>> +  bp->bif_ifp = ifp;
>>>> }
>>>> 
>>>> /* Detach an interface from its attached bpf device.  */
>>>> @@ -1574,31 +1580,39 @@ void
>>>> bpfdetach(struct ifnet *ifp)
>>>> {
>>>>    struct bpf_if *bp, *nbp, **pbp = &bpf_iflist;
>>>> -  struct bpf_d *bd;
>>>> -  int maj;
>>>> 
>>>>    KERNEL_ASSERT_LOCKED();
>>>> 
>>>>    for (bp = bpf_iflist; bp; bp = nbp) {
>>>> -          nbp= bp->bif_next;
>>>> +          nbp = bp->bif_next;
>>>>            if (bp->bif_ifp == ifp) {
>>>>                    *pbp = nbp;
>>>> 
>>>> -                  /* Locate the major number. */
>>>> -                  for (maj = 0; maj < nchrdev; maj++)
>>>> -                          if (cdevsw[maj].d_open == bpfopen)
>>>> -                                  break;
>>>> -
>>>> -                  while ((bd = SRPL_FIRST_LOCKED(&bp->bif_dlist)))
>>>> -                          vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR);
>>>> -
>>>> -                  free(bp, M_DEVBUF, sizeof *bp);
>>>> +                  bpfsdetach(bp);
>>>>            } else
>>>>                    pbp = &bp->bif_next;
>>>>    }
>>>>    ifp->if_bpf = NULL;
>>>> }
>>>> 
>>>> +void
>>>> +bpfsdetach(void *p)
>>>> +{
>>>> +  struct bpf_if *bp = p;
>>>> +  struct bpf_d *bd;
>>>> +  int maj;
>>>> +
>>>> +  /* Locate the major number. */
>>>> +  for (maj = 0; maj < nchrdev; maj++)
>>>> +          if (cdevsw[maj].d_open == bpfopen)
>>>> +                  break;
>>>> +
>>>> +  while ((bd = SRPL_FIRST_LOCKED(&bp->bif_dlist)))
>>>> +          vdevgone(maj, bd->bd_unit, bd->bd_unit, VCHR);
>>>> +
>>>> +  free(bp, M_DEVBUF, sizeof *bp);
>>>> +}
>>>> +
>>>> int
>>>> bpf_sysctl_locked(int *name, u_int namelen, void *oldp, size_t *oldlenp,
>>>>    void *newp, size_t newlen)
>>>> @@ -1674,14 +1688,14 @@ int
>>>> bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl)
>>>> {
>>>>    int n, error;
>>>> -  struct ifnet *ifp;
>>>>    struct bpf_if *bp;
>>>> +  const char *name;
>>>> 
>>>> -  ifp = d->bd_bif->bif_ifp;
>>>> +  name = d->bd_bif->bif_name;
>>>>    n = 0;
>>>>    error = 0;
>>>>    for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
>>>> -          if (bp->bif_ifp != ifp)
>>>> +          if (strcmp(name, bp->bif_name) != 0)
>>>>                    continue;
>>>>            if (bfl->bfl_list != NULL) {
>>>>                    if (n >= bfl->bfl_len)
>>>> @@ -1704,15 +1718,17 @@ bpf_getdltlist(struct bpf_d *d, struct b
>>>> int
>>>> bpf_setdlt(struct bpf_d *d, u_int dlt)
>>>> {
>>>> -  struct ifnet *ifp;
>>>> +  const char *name;
>>>>    struct bpf_if *bp;
>>>> 
>>>>    MUTEX_ASSERT_LOCKED(&d->bd_mtx);
>>>>    if (d->bd_bif->bif_dlt == dlt)
>>>>            return (0);
>>>> -  ifp = d->bd_bif->bif_ifp;
>>>> +  name = d->bd_bif->bif_name;
>>>>    for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
>>>> -          if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
>>>> +          if (strcmp(name, bp->bif_name) != 0)
>>>> +                  continue;
>>>> +          if (bp->bif_dlt == dlt)
>>>>                    break;
>>>>    }
>>>>    if (bp == NULL)
>>>> Index: bpf.h
>>>> ===================================================================
>>>> RCS file: /cvs/src/sys/net/bpf.h,v
>>>> retrieving revision 1.62
>>>> diff -u -p -r1.62 bpf.h
>>>> --- bpf.h  22 Feb 2017 09:56:03 -0000      1.62
>>>> +++ bpf.h  10 Jan 2018 07:27:45 -0000
>>>> @@ -313,6 +313,8 @@ int     bpf_mtap_af(caddr_t, u_int32_t, con
>>>> int         bpf_mtap_ether(caddr_t, const struct mbuf *, u_int);
>>>> void        bpfattach(caddr_t *, struct ifnet *, u_int, u_int);
>>>> void        bpfdetach(struct ifnet *);
>>>> +void      *bpfsattach(caddr_t *, const char *, u_int, u_int);
>>>> +void       bpfsdetach(void *);
>>>> void        bpfilterattach(int);
>>>> 
>>>> u_int       bpf_mfilter(const struct bpf_insn *, const struct mbuf *, 
>>>> u_int);
>>>> Index: bpfdesc.h
>>>> ===================================================================
>>>> RCS file: /cvs/src/sys/net/bpfdesc.h,v
>>>> retrieving revision 1.35
>>>> diff -u -p -r1.35 bpfdesc.h
>>>> --- bpfdesc.h      24 Jan 2017 10:08:30 -0000      1.35
>>>> +++ bpfdesc.h      10 Jan 2018 07:27:45 -0000
>>>> @@ -103,6 +103,7 @@ struct bpf_if {
>>>>    struct bpf_if **bif_driverp;    /* pointer into softc */
>>>>    u_int bif_dlt;                  /* link layer type */
>>>>    u_int bif_hdrlen;               /* length of header (with padding) */
>>>> +  const char *bif_name;           /* name of "subsystem" */
>>>>    struct ifnet *bif_ifp;          /* corresponding interface */
>>>> };
>>>> 
>>>> Index: pf.c
>>>> ===================================================================
>>>> RCS file: /cvs/src/sys/net/pf.c,v
>>>> retrieving revision 1.1054
>>>> diff -u -p -r1.1054 pf.c
>>>> --- pf.c   29 Dec 2017 23:55:22 -0000      1.1054
>>>> +++ pf.c   10 Jan 2018 07:27:45 -0000
>>>> @@ -104,6 +104,11 @@
>>>> #include <ddb/db_interface.h>
>>>> #endif
>>>> 
>>>> +#if NBPFILTER > 0
>>>> +#include <net/bpf.h>
>>>> +caddr_t pf_bpf;
>>>> +#endif
>>>> +
>>>> /*
>>>> * Global variables
>>>> */
>>>> @@ -6719,6 +6724,11 @@ pf_test(sa_family_t af, int fwdir, struc
>>>> 
>>>>    if (!pf_status.running)
>>>>            return (PF_PASS);
>>>> +
>>>> +#if NBPFILTER > 0
>>>> +  if (pf_bpf)
>>>> +          bpf_mtap_af(pf_bpf, af, *m0, BPF_DIRECTION_IN);
>>>> +#endif
>>>> 
>>>> #if NCARP > 0
>>>>    if (ifp->if_type == IFT_CARP && ifp->if_carpdev)
>>>> Index: pf_ioctl.c
>>>> ===================================================================
>>>> RCS file: /cvs/src/sys/net/pf_ioctl.c,v
>>>> retrieving revision 1.326
>>>> diff -u -p -r1.326 pf_ioctl.c
>>>> --- pf_ioctl.c     28 Nov 2017 16:05:46 -0000      1.326
>>>> +++ pf_ioctl.c     10 Jan 2018 07:27:45 -0000
>>>> @@ -35,6 +35,7 @@
>>>> *
>>>> */
>>>> 
>>>> +#include "bpfilter.h"
>>>> #include "pfsync.h"
>>>> #include "pflog.h"
>>>> 
>>>> @@ -84,6 +85,11 @@
>>>> #include <net/if_pfsync.h>
>>>> #endif /* NPFSYNC > 0 */
>>>> 
>>>> +#if NBPFILTER > 0
>>>> +#include <net/bpf.h>
>>>> +extern caddr_t pf_bpf;
>>>> +#endif
>>>> +
>>>> struct pool                 pf_tag_pl;
>>>> 
>>>> void                        pfattach(int);
>>>> @@ -231,6 +237,10 @@ pfattach(int num)
>>>> 
>>>>    /* XXX do our best to avoid a conflict */
>>>>    pf_status.hostid = arc4random();
>>>> +
>>>> +#if NBPFILTER > 0
>>>> +  bpfsattach(&pf_bpf, "pf", DLT_LOOP, sizeof(u_int32_t));
>>>> +#endif
>>>> }
>>>> 
>>>> int

Reply via email to