From owner-freebsd-net@FreeBSD.ORG Fri Sep 9 06:20:57 2005 Return-Path: X-Original-To: freebsd-net@freebsd.org Delivered-To: freebsd-net@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D127516A41F for ; Fri, 9 Sep 2005 06:20:57 +0000 (GMT) (envelope-from vys@renet.ru) Received: from mail.renet.ru (mail-local.renet.ru [82.116.32.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 9EDC343D48 for ; Fri, 9 Sep 2005 06:20:56 +0000 (GMT) (envelope-from vys@renet.ru) Received: from [82.116.32.17] (fox.renet.ru [82.116.32.17]) by mail.renet.ru (8.13.3/8.13.1) with ESMTP id j896KoNg028451 for ; Fri, 9 Sep 2005 10:20:50 +0400 (MSD) Message-ID: <432129C2.8090405@renet.ru> Date: Fri, 09 Sep 2005 10:20:50 +0400 From: "Vladimir Yu. Stepanov" User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050616) X-Accept-Language: en-us, en MIME-Version: 1.0 To: freebsd-net@freebsd.org Content-Type: multipart/mixed; boundary="------------050009020007020700010608" X-Virus-Scanned: ClamAV version 0.86.2, clamav-milter version 0.86 on mail.renet.ru X-Virus-Status: Clean X-Spam-Status: No, score=-102.6 required=2.2 tests=BAYES_00, USER_IN_WHITELIST autolearn=no version=3.0.1 X-Spam-Checker-Version: SpamAssassin 3.0.1 (2004-10-22) on mail.renet.ru X-Content-Filtered-By: Mailman/MimeDel 2.1.5 Subject: BPF patch for addition of good feature linux packet (7) (see attachment) X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Sep 2005 06:20:57 -0000 This is a multi-part message in MIME format. --------------050009020007020700010608 Content-Type: text/plain; charset=KOI8-R; format=flowed Content-Transfer-Encoding: 7bit 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) */ --------------050009020007020700010608 Content-Type: text/plain; name="freebsd-5.1-bpf-2.0-r4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="freebsd-5.1-bpf-2.0-r4.patch" 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. --------------050009020007020700010608 Content-Type: text/plain; name="freebsd-5.2.1-bpf-2.0-r4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="freebsd-5.2.1-bpf-2.0-r4.patch" 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. --------------050009020007020700010608 Content-Type: text/plain; name="freebsd-5.3-bpf-2.0-r4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="freebsd-5.3-bpf-2.0-r4.patch" 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. --------------050009020007020700010608 Content-Type: text/plain; name="freebsd-5.4-bpf-2.0-r4.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="freebsd-5.4-bpf-2.0-r4.patch" 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. --------------050009020007020700010608--