Hello!

I made a modernization of bpf realization. It have a mind when we are trying to use bpf to account network statistic. When packets is catching by filter thereis imposible to determine the direction of packets flows. Due to this problem statistic accounts two times when packets is routes by the same interface, because this packets counts as incoming and outgoing traffic. The prototype of this patch is packet(7) on linux.

This patch is fully compatible with all program uses the bpf. It adds
the tags means traffic direction to the struct bpf_hdr.


struct bpf_hdr {
        struct timeval  bh_tstamp;      /* time stamp */
        bpf_u_int32     bh_caplen;      /* length of captured portion */
        bpf_u_int32     bh_datalen;     /* original length of packet */
u_short bh_hdrlen; /* length of bpf header (this struct
                                           plus alignment padding) */
        u_short         bh_pkttype;     /* packet type */
};
/*
 * Packet types.
 * For help to get some extra information.
 * It is taken from the description packet(7) in Linux system.
 */
#define BPFPKTTYPE_HOST         0       /* To us */
#define BPFPKTTYPE_BROADCAST    1       /* To all */
#define BPFPKTTYPE_MULTICAST    2       /* To group */
#define BPFPKTTYPE_OTHERHOST    3       /* To someone else */
#define BPFPKTTYPE_OUTGOING     4       /* Outgoing of any type */
#define BPFPKTTYPE_LOOPBACK     5       /* MC/BRD frame looped back */
#define BPFPKTTYPE_FASTROUTE 6 /* Fastrouted frame (if cannot detect MC/BRD type) */

diff -ruN sys.orig/net/bpf.c sys/net/bpf.c
--- sys.orig/net/bpf.c  Fri Dec 12 17:43:55 2003
+++ sys/net/bpf.c       Fri Apr 15 20:40:31 2005
@@ -106,7 +106,7 @@
 static __inline void
                bpf_wakeup(struct bpf_d *);
 static void    catchpacket(struct bpf_d *, u_char *, u_int,
-                   u_int, void (*)(const void *, void *, size_t));
+                   u_int, u_int, void (*)(const void *, void *, size_t));
 static void    reset_d(struct bpf_d *);
 static int      bpf_setf(struct bpf_d *, struct bpf_program *);
 static int     bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1094,7 +1094,7 @@
 #ifdef MAC
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
-                               catchpacket(d, pkt, pktlen, slen, bcopy);
+                               catchpacket(d, pkt, pktlen, slen, 
BPFPKTTYPE_FASTROUTE, bcopy);
                }
                BPFD_UNLOCK(d);
        }
@@ -1137,15 +1137,32 @@
        struct mbuf *m;
 {
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        pktlen = m_length(m, NULL);
-       if (pktlen == m->m_len) {
-               bpf_tap(bp, mtod(m, u_char *), pktlen);
-               return;
-       }
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1157,7 +1174,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)m, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1172,10 +1189,10 @@
  * pkt is really an mbuf.
  */
 static void
-catchpacket(d, pkt, pktlen, snaplen, cpfn)
+catchpacket(d, pkt, pktlen, snaplen, pkttype, cpfn)
        struct bpf_d *d;
        u_char *pkt;
-       u_int pktlen, snaplen;
+       u_int pktlen, snaplen, pkttype;
        void (*cpfn)(const void *, void *, size_t);
 {
        struct bpf_hdr *hp;
@@ -1228,6 +1245,7 @@
        microtime(&hp->bh_tstamp);
        hp->bh_datalen = pktlen;
        hp->bh_hdrlen = hdrlen;
+       hp->bh_pkttype = pkttype;
        /*
         * Copy the packet data into the store buffer and update its length.
         */
@@ -1326,11 +1344,11 @@
 
        /*
         * Compute the length of the bpf header.  This is not necessarily
-        * equal to SIZEOF_BPF_HDR because we want to insert spacing such
-        * that the network layer header begins on a longword boundary (for
-        * performance reasons and to alleviate alignment restrictions).
+        * equal to sizeof(struct bpf_hdr) because we want to insert spacing
+        * such that the network layer header begins on a longword boundary
+        * (for performance reasons and to alleviate alignment restrictions).
         */
-       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
+       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + sizeof(struct bpf_hdr)) - 
hdrlen;
 
        if (bootverbose)
                if_printf(ifp, "bpf attached\n");
diff -ruN sys.orig/net/bpf.h sys/net/bpf.h
--- sys.orig/net/bpf.h  Fri Dec 12 17:43:55 2003
+++ sys/net/bpf.h       Fri Apr 15 20:40:31 2005
@@ -94,7 +94,7 @@
 };
 /* Current version number of filter architecture. */
 #define BPF_MAJOR_VERSION 1
-#define BPF_MINOR_VERSION 1
+#define BPF_MINOR_VERSION 2
 
 #define        BIOCGBLEN       _IOR('B',102, u_int)
 #define        BIOCSBLEN       _IOWR('B',102, u_int)
@@ -127,16 +127,21 @@
        bpf_u_int32     bh_datalen;     /* original length of packet */
        u_short         bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
+       u_short         bh_pkttype;     /* packet type */
 };
+
 /*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
+ * Packet types.
+ * For help to get some extra information.
+ * It is taken from the description packet(7) in Linux system.
  */
-#ifdef _KERNEL
-#define        SIZEOF_BPF_HDR  (sizeof(struct bpf_hdr) <= 20 ? 18 : \
-    sizeof(struct bpf_hdr))
-#endif
+#define BPFPKTTYPE_HOST                0       /* To us */
+#define BPFPKTTYPE_BROADCAST   1       /* To all */
+#define BPFPKTTYPE_MULTICAST   2       /* To group */
+#define BPFPKTTYPE_OTHERHOST   3       /* To someone else */
+#define BPFPKTTYPE_OUTGOING    4       /* Outgoing of any type */
+#define BPFPKTTYPE_LOOPBACK    5       /* MC/BRD frame looped back */
+#define BPFPKTTYPE_FASTROUTE   6       /* Fastrouted frame (if cannot detect 
MC/BRD type) */
 
 /*
  * Data-link level type codes.
diff -ruN sys.orig/sys/mbuf.h sys/sys/mbuf.h
--- sys.orig/sys/mbuf.h Fri Dec 12 17:43:59 2003
+++ sys/sys/mbuf.h      Fri Apr 15 20:40:31 2005
@@ -163,6 +163,7 @@
 #define        M_FRAG          0x0800  /* packet is a fragment of a larger 
packet */
 #define        M_FIRSTFRAG     0x1000  /* packet is first fragment */
 #define        M_LASTFRAG      0x2000  /* packet is last fragment */
+#define        M_BPF_TAGGED    0x400000
 
 /*
  * External buffer types: identify ext_buf type.
diff -ruN sys.orig/net/bpf.c sys/net/bpf.c
--- sys.orig/net/bpf.c  Thu Dec  2 19:07:36 2004
+++ sys/net/bpf.c       Fri Apr 15 16:39:39 2005
@@ -110,7 +110,7 @@
 static __inline void
                bpf_wakeup(struct bpf_d *);
 static void    catchpacket(struct bpf_d *, u_char *, u_int,
-                   u_int, void (*)(const void *, void *, size_t));
+                   u_int, u_int, void (*)(const void *, void *, size_t));
 static void    reset_d(struct bpf_d *);
 static int      bpf_setf(struct bpf_d *, struct bpf_program *);
 static int     bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1157,7 +1157,7 @@
 #ifdef MAC
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
-                               catchpacket(d, pkt, pktlen, slen, bcopy);
+                               catchpacket(d, pkt, pktlen, slen, 
BPFPKTTYPE_FASTROUTE, bcopy);
                }
                BPFD_UNLOCK(d);
        }
@@ -1200,15 +1200,32 @@
        struct mbuf *m;
 {
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        pktlen = m_length(m, NULL);
-       if (pktlen == m->m_len) {
-               bpf_tap(bp, mtod(m, u_char *), pktlen);
-               return;
-       }
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1220,7 +1237,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)m, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1235,10 +1252,10 @@
  * pkt is really an mbuf.
  */
 static void
-catchpacket(d, pkt, pktlen, snaplen, cpfn)
+catchpacket(d, pkt, pktlen, snaplen, pkttype, cpfn)
        struct bpf_d *d;
        u_char *pkt;
-       u_int pktlen, snaplen;
+       u_int pktlen, snaplen, pkttype;
        void (*cpfn)(const void *, void *, size_t);
 {
        struct bpf_hdr *hp;
@@ -1291,6 +1308,7 @@
        microtime(&hp->bh_tstamp);
        hp->bh_datalen = pktlen;
        hp->bh_hdrlen = hdrlen;
+       hp->bh_pkttype = pkttype;
        /*
         * Copy the packet data into the store buffer and update its length.
         */
@@ -1389,11 +1407,11 @@
 
        /*
         * Compute the length of the bpf header.  This is not necessarily
-        * equal to SIZEOF_BPF_HDR because we want to insert spacing such
-        * that the network layer header begins on a longword boundary (for
-        * performance reasons and to alleviate alignment restrictions).
+        * equal to sizeof(struct bpf_hdr) because we want to insert spacing
+        * such that the network layer header begins on a longword boundary
+        * (for performance reasons and to alleviate alignment restrictions).
         */
-       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
+       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + sizeof(struct bpf_hdr)) - 
hdrlen;
 
        if (bootverbose)
                if_printf(ifp, "bpf attached\n");
diff -ruN sys.orig/net/bpf.h sys/net/bpf.h
--- sys.orig/net/bpf.h  Thu Dec  2 19:07:35 2004
+++ sys/net/bpf.h       Fri Apr 15 16:35:24 2005
@@ -94,7 +94,7 @@
 };
 /* Current version number of filter architecture. */
 #define BPF_MAJOR_VERSION 1
-#define BPF_MINOR_VERSION 1
+#define BPF_MINOR_VERSION 2
 
 #define        BIOCGBLEN       _IOR('B',102, u_int)
 #define        BIOCSBLEN       _IOWR('B',102, u_int)
@@ -127,16 +127,21 @@
        bpf_u_int32     bh_datalen;     /* original length of packet */
        u_short         bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
+       u_short         bh_pkttype;     /* packet type */
 };
+
 /*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
+ * Packet types.
+ * For help to get some extra information.
+ * It is taken from the description packet(7) in Linux system.
  */
-#ifdef _KERNEL
-#define        SIZEOF_BPF_HDR  (sizeof(struct bpf_hdr) <= 20 ? 18 : \
-    sizeof(struct bpf_hdr))
-#endif
+#define BPFPKTTYPE_HOST                0       /* To us */
+#define BPFPKTTYPE_BROADCAST   1       /* To all */
+#define BPFPKTTYPE_MULTICAST   2       /* To group */
+#define BPFPKTTYPE_OTHERHOST   3       /* To someone else */
+#define BPFPKTTYPE_OUTGOING    4       /* Outgoing of any type */
+#define BPFPKTTYPE_LOOPBACK    5       /* MC/BRD frame looped back */
+#define BPFPKTTYPE_FASTROUTE   6       /* Fastrouted frame (if cannot detect 
MC/BRD type) */
 
 /*
  * Data-link level type codes.
diff -ruN sys.orig/sys/mbuf.h sys/sys/mbuf.h
--- sys.orig/sys/mbuf.h Thu Dec  2 19:07:43 2004
+++ sys/sys/mbuf.h      Fri Apr 15 16:40:55 2005
@@ -164,6 +164,7 @@
 #define        M_FRAG          0x0800  /* packet is a fragment of a larger 
packet */
 #define        M_FIRSTFRAG     0x1000  /* packet is first fragment */
 #define        M_LASTFRAG      0x2000  /* packet is last fragment */
+#define        M_BPF_TAGGED    0x400000
 
 /*
  * External buffer types: identify ext_buf type.
diff -ruN sys.orig/net/bpf.c sys/net/bpf.c
--- sys.orig/net/bpf.c  Mon Oct 11 07:45:21 2004
+++ sys/net/bpf.c       Fri Apr 15 10:31:39 2005
@@ -106,7 +106,7 @@
 static __inline void
                bpf_wakeup(struct bpf_d *);
 static void    catchpacket(struct bpf_d *, u_char *, u_int,
-                   u_int, void (*)(const void *, void *, size_t));
+                   u_int, u_int, void (*)(const void *, void *, size_t));
 static void    reset_d(struct bpf_d *);
 static int      bpf_setf(struct bpf_d *, struct bpf_program *);
 static int     bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1162,7 +1162,7 @@
 #ifdef MAC
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
-                               catchpacket(d, pkt, pktlen, slen, bcopy);
+                               catchpacket(d, pkt, pktlen, slen, 
BPFPKTTYPE_FASTROUTE, bcopy);
                }
                BPFD_UNLOCK(d);
        }
@@ -1205,7 +1205,7 @@
        struct mbuf *m;
 {
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        /*
         * Lockless read to avoid cost of locking the interface if there are
@@ -1215,12 +1215,29 @@
                return;
 
        pktlen = m_length(m, NULL);
-       if (pktlen == m->m_len) {
-               bpf_tap(bp, mtod(m, u_char *), pktlen);
-               return;
-       }
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1232,7 +1249,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)m, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1251,7 +1268,7 @@
 {
        struct mbuf mb;
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        /*
         * Lockless read to avoid cost of locking the interface if there are
@@ -1272,6 +1289,27 @@
        pktlen += dlen;
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1283,7 +1321,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)&mb, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1297,10 +1335,10 @@
  * pkt is really an mbuf.
  */
 static void
-catchpacket(d, pkt, pktlen, snaplen, cpfn)
+catchpacket(d, pkt, pktlen, snaplen, pkttype, cpfn)
        struct bpf_d *d;
        u_char *pkt;
-       u_int pktlen, snaplen;
+       u_int pktlen, snaplen, pkttype;
        void (*cpfn)(const void *, void *, size_t);
 {
        struct bpf_hdr *hp;
@@ -1354,6 +1392,7 @@
        microtime(&hp->bh_tstamp);
        hp->bh_datalen = pktlen;
        hp->bh_hdrlen = hdrlen;
+       hp->bh_pkttype = pkttype;
        /*
         * Copy the packet data into the store buffer and update its length.
         */
@@ -1451,11 +1490,11 @@
 
        /*
         * Compute the length of the bpf header.  This is not necessarily
-        * equal to SIZEOF_BPF_HDR because we want to insert spacing such
-        * that the network layer header begins on a longword boundary (for
-        * performance reasons and to alleviate alignment restrictions).
+        * equal to sizeof(struct bpf_hdr) because we want to insert spacing
+        * such that the network layer header begins on a longword boundary
+        * (for performance reasons and to alleviate alignment restrictions).
         */
-       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
+       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + sizeof(struct bpf_hdr)) - 
hdrlen;
 
        if (bootverbose)
                if_printf(ifp, "bpf attached\n");
diff -ruN sys.orig/net/bpf.h sys/net/bpf.h
--- sys.orig/net/bpf.h  Sun May 30 21:03:48 2004
+++ sys/net/bpf.h       Fri Apr 15 09:28:16 2005
@@ -90,7 +90,7 @@
 };
 /* Current version number of filter architecture. */
 #define BPF_MAJOR_VERSION 1
-#define BPF_MINOR_VERSION 1
+#define BPF_MINOR_VERSION 2
 
 #define        BIOCGBLEN       _IOR('B',102, u_int)
 #define        BIOCSBLEN       _IOWR('B',102, u_int)
@@ -123,16 +123,21 @@
        bpf_u_int32     bh_datalen;     /* original length of packet */
        u_short         bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
+       u_short         bh_pkttype;     /* packet type */
 };
+
 /*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
+ * Packet types.
+ * For help to get some extra information.
+ * It is taken from the description packet(7) in Linux system.
  */
-#ifdef _KERNEL
-#define        SIZEOF_BPF_HDR  (sizeof(struct bpf_hdr) <= 20 ? 18 : \
-    sizeof(struct bpf_hdr))
-#endif
+#define BPFPKTTYPE_HOST                0       /* To us */
+#define BPFPKTTYPE_BROADCAST   1       /* To all */
+#define BPFPKTTYPE_MULTICAST   2       /* To group */
+#define BPFPKTTYPE_OTHERHOST   3       /* To someone else */
+#define BPFPKTTYPE_OUTGOING    4       /* Outgoing of any type */
+#define BPFPKTTYPE_LOOPBACK    5       /* MC/BRD frame looped back */
+#define BPFPKTTYPE_FASTROUTE   6       /* Fastrouted frame (if cannot detect 
MC/BRD type) */
 
 /*
  * Data-link level type codes.
diff -ruN sys.orig/sys/mbuf.h sys/sys/mbuf.h
--- sys.orig/sys/mbuf.h Sat Oct 16 01:45:13 2004
+++ sys/sys/mbuf.h      Fri Apr 15 09:42:31 2005
@@ -178,6 +178,7 @@
 #define        M_FRAG          0x0800  /* packet is a fragment of a larger 
packet */
 #define        M_FIRSTFRAG     0x1000  /* packet is first fragment */
 #define        M_LASTFRAG      0x2000  /* packet is last fragment */
+#define        M_BPF_TAGGED    0x400000
 
 /*
  * External buffer types: identify ext_buf type.
diff -ruN sys.orig/net/bpf.c sys/net/bpf.c
--- sys.orig/net/bpf.c  Thu Jun 16 14:41:15 2005
+++ sys/net/bpf.c       Thu Jun 16 14:45:59 2005
@@ -109,7 +109,7 @@
 static __inline void
                bpf_wakeup(struct bpf_d *);
 static void    catchpacket(struct bpf_d *, u_char *, u_int,
-                   u_int, void (*)(const void *, void *, size_t));
+                   u_int, u_int, void (*)(const void *, void *, size_t));
 static void    reset_d(struct bpf_d *);
 static int      bpf_setf(struct bpf_d *, struct bpf_program *);
 static int     bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
@@ -1168,7 +1168,7 @@
 #ifdef MAC
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
-                               catchpacket(d, pkt, pktlen, slen, bcopy);
+                               catchpacket(d, pkt, pktlen, slen, 
BPFPKTTYPE_FASTROUTE, bcopy);
                }
                BPFD_UNLOCK(d);
        }
@@ -1211,7 +1211,7 @@
        struct mbuf *m;
 {
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        /*
         * Lockless read to avoid cost of locking the interface if there are
@@ -1221,12 +1221,29 @@
                return;
 
        pktlen = m_length(m, NULL);
-       if (pktlen == m->m_len) {
-               bpf_tap(bp, mtod(m, u_char *), pktlen);
-               return;
-       }
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1238,7 +1255,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)m, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1257,7 +1274,7 @@
 {
        struct mbuf mb;
        struct bpf_d *d;
-       u_int pktlen, slen;
+       u_int pktlen, slen, pkttype;
 
        /*
         * Lockless read to avoid cost of locking the interface if there are
@@ -1278,6 +1295,27 @@
        pktlen += dlen;
 
        BPFIF_LOCK(bp);
+       if (m->m_pkthdr.rcvif == NULL)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if (m->m_pkthdr.rcvif != bp->bif_ifp)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else
+       if ((m->m_flags&M_BPF_TAGGED) == M_BPF_TAGGED)
+               pkttype = BPFPKTTYPE_OUTGOING;
+       else {
+               if ((m->m_flags&M_BCAST) != 0)
+                       pkttype = BPFPKTTYPE_BROADCAST;
+               else
+               if ((m->m_flags&M_MCAST) != 0)
+                       pkttype = BPFPKTTYPE_MULTICAST;
+               else
+                       /* How to detect if packet may received
+                        * only in promiscuous mode ? */
+                       pkttype = BPFPKTTYPE_HOST;
+       }
+       if (m->m_pkthdr.rcvif != NULL && (m->m_flags&M_RDONLY) != M_RDONLY)
+               m->m_flags |= M_BPF_TAGGED;
        LIST_FOREACH(d, &bp->bif_dlist, bd_next) {
                if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
                        continue;
@@ -1289,7 +1327,7 @@
                        if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0)
 #endif
                                catchpacket(d, (u_char *)&mb, pktlen, slen,
-                                   bpf_mcopy);
+                                   pkttype, bpf_mcopy);
                BPFD_UNLOCK(d);
        }
        BPFIF_UNLOCK(bp);
@@ -1303,10 +1341,10 @@
  * pkt is really an mbuf.
  */
 static void
-catchpacket(d, pkt, pktlen, snaplen, cpfn)
+catchpacket(d, pkt, pktlen, snaplen, pkttype, cpfn)
        struct bpf_d *d;
        u_char *pkt;
-       u_int pktlen, snaplen;
+       u_int pktlen, snaplen, pkttype;
        void (*cpfn)(const void *, void *, size_t);
 {
        struct bpf_hdr *hp;
@@ -1361,6 +1399,7 @@
        microtime(&hp->bh_tstamp);
        hp->bh_datalen = pktlen;
        hp->bh_hdrlen = hdrlen;
+       hp->bh_pkttype = pkttype;
        /*
         * Copy the packet data into the store buffer and update its length.
         */
@@ -1461,11 +1500,11 @@
 
        /*
         * Compute the length of the bpf header.  This is not necessarily
-        * equal to SIZEOF_BPF_HDR because we want to insert spacing such
-        * that the network layer header begins on a longword boundary (for
-        * performance reasons and to alleviate alignment restrictions).
+        * equal to sizeof(struct bpf_hdr) because we want to insert spacing
+        * such that the network layer header begins on a longword boundary
+        * (for performance reasons and to alleviate alignment restrictions).
         */
-       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
+       bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + sizeof(struct bpf_hdr)) - 
hdrlen;
 
        if (bootverbose)
                if_printf(ifp, "bpf attached\n");
diff -ruN sys.orig/net/bpf.h sys/net/bpf.h
--- sys.orig/net/bpf.h  Thu Jun 16 14:41:15 2005
+++ sys/net/bpf.h       Thu Jun 16 14:45:59 2005
@@ -90,7 +90,7 @@
 };
 /* Current version number of filter architecture. */
 #define BPF_MAJOR_VERSION 1
-#define BPF_MINOR_VERSION 1
+#define BPF_MINOR_VERSION 2
 
 #define        BIOCGBLEN       _IOR('B',102, u_int)
 #define        BIOCSBLEN       _IOWR('B',102, u_int)
@@ -123,16 +123,21 @@
        bpf_u_int32     bh_datalen;     /* original length of packet */
        u_short         bh_hdrlen;      /* length of bpf header (this struct
                                           plus alignment padding) */
+       u_short         bh_pkttype;     /* packet type */
 };
+
 /*
- * Because the structure above is not a multiple of 4 bytes, some compilers
- * will insist on inserting padding; hence, sizeof(struct bpf_hdr) won't work.
- * Only the kernel needs to know about it; applications use bh_hdrlen.
+ * Packet types.
+ * For help to get some extra information.
+ * It is taken from the description packet(7) in Linux system.
  */
-#ifdef _KERNEL
-#define        SIZEOF_BPF_HDR  (sizeof(struct bpf_hdr) <= 20 ? 18 : \
-    sizeof(struct bpf_hdr))
-#endif
+#define BPFPKTTYPE_HOST                0       /* To us */
+#define BPFPKTTYPE_BROADCAST   1       /* To all */
+#define BPFPKTTYPE_MULTICAST   2       /* To group */
+#define BPFPKTTYPE_OTHERHOST   3       /* To someone else */
+#define BPFPKTTYPE_OUTGOING    4       /* Outgoing of any type */
+#define BPFPKTTYPE_LOOPBACK    5       /* MC/BRD frame looped back */
+#define BPFPKTTYPE_FASTROUTE   6       /* Fastrouted frame (if cannot detect 
MC/BRD type) */
 
 /*
  * Data-link level type codes.
diff -ruN sys.orig/sys/mbuf.h sys/sys/mbuf.h
--- sys.orig/sys/mbuf.h Thu Jun 16 14:41:19 2005
+++ sys/sys/mbuf.h      Thu Jun 16 14:45:59 2005
@@ -178,6 +178,7 @@
 #define        M_FRAG          0x0800  /* packet is a fragment of a larger 
packet */
 #define        M_FIRSTFRAG     0x1000  /* packet is first fragment */
 #define        M_LASTFRAG      0x2000  /* packet is last fragment */
+#define        M_BPF_TAGGED    0x400000
 
 /*
  * External buffer types: identify ext_buf type.
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to