diff options
author | sam <sam@FreeBSD.org> | 2003-12-28 03:56:00 +0000 |
---|---|---|
committer | sam <sam@FreeBSD.org> | 2003-12-28 03:56:00 +0000 |
commit | c165a87f8dfc070bceb68d9c3ff183ec2135e060 (patch) | |
tree | f663da0db11fcecb5ff2d3e93732492fb4d7bd29 /sys/net | |
parent | 853a4ae85d691a2f3500efc16c2eab14e3c117b0 (diff) | |
download | FreeBSD-src-c165a87f8dfc070bceb68d9c3ff183ec2135e060.zip FreeBSD-src-c165a87f8dfc070bceb68d9c3ff183ec2135e060.tar.gz |
o eliminate widespread on-stack mbuf use for bpf by introducing
a new bpf_mtap2 routine that does the right thing for an mbuf
and a variable-length chunk of data that should be prepended.
o while we're sweeping the drivers, use u_int32_t uniformly when
when prepending the address family (several places were assuming
sizeof(int) was 4)
o return M_ASSERTVALID to BPF_MTAP* now that all stack-allocated
mbufs have been eliminated; this may better be moved to the bpf
routines
Reviewed by: arch@ and several others
Diffstat (limited to 'sys/net')
-rw-r--r-- | sys/net/bpf.c | 53 | ||||
-rw-r--r-- | sys/net/bpf.h | 11 | ||||
-rw-r--r-- | sys/net/if_disc.c | 15 | ||||
-rw-r--r-- | sys/net/if_ef.c | 8 | ||||
-rw-r--r-- | sys/net/if_faith.c | 15 | ||||
-rw-r--r-- | sys/net/if_gif.c | 30 | ||||
-rw-r--r-- | sys/net/if_gre.c | 9 | ||||
-rw-r--r-- | sys/net/if_loop.c | 18 | ||||
-rw-r--r-- | sys/net/if_stf.c | 12 | ||||
-rw-r--r-- | sys/net/if_tun.c | 50 |
10 files changed, 83 insertions, 138 deletions
diff --git a/sys/net/bpf.c b/sys/net/bpf.c index c282dcf..c06312e 100644 --- a/sys/net/bpf.c +++ b/sys/net/bpf.c @@ -1227,6 +1227,50 @@ bpf_mtap(bp, m) } /* + * Incoming linkage from device drivers, when packet is in + * an mbuf chain and to be prepended by a contiguous header. + */ +void +bpf_mtap2(bp, data, dlen, m) + struct bpf_if *bp; + void *data; + u_int dlen; + struct mbuf *m; +{ + struct mbuf mb; + struct bpf_d *d; + u_int pktlen, slen; + + pktlen = m_length(m, NULL); + /* + * Craft on-stack mbuf suitable for passing to bpf_filter. + * Note that we cut corners here; we only setup what's + * absolutely needed--this mbuf should never go anywhere else. + */ + mb.m_next = m; + mb.m_data = data; + mb.m_len = dlen; + pktlen += dlen; + + BPFIF_LOCK(bp); + for (d = bp->bif_dlist; d != 0; d = d->bd_next) { + if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL)) + continue; + BPFD_LOCK(d); + ++d->bd_rcount; + slen = bpf_filter(d->bd_filter, (u_char *)&mb, pktlen, 0); + if (slen != 0) +#ifdef MAC + if (mac_check_bpfdesc_receive(d, bp->bif_ifp) == 0) +#endif + catchpacket(d, (u_char *)&mb, pktlen, slen, + bpf_mcopy); + BPFD_UNLOCK(d); + } + BPFIF_UNLOCK(bp); +} + +/* * Move the packet data from interface memory (pkt) into the * store buffer. Return 1 if it's time to wakeup a listener (buffer full), * otherwise 0. "copy" is the routine called to do the actual data @@ -1580,6 +1624,15 @@ bpf_mtap(bp, m) } void +bpf_mtap2(bp, d, l, m) + struct bpf_if *bp; + const void *d; + u_int l; + struct mbuf *m; +{ +} + +void bpfattach(ifp, dlt, hdrlen) struct ifnet *ifp; u_int dlt, hdrlen; diff --git a/sys/net/bpf.h b/sys/net/bpf.h index 6d3e800..c4b31d4 100644 --- a/sys/net/bpf.h +++ b/sys/net/bpf.h @@ -354,6 +354,7 @@ struct bpf_if; int bpf_validate(const struct bpf_insn *, int); void bpf_tap(struct bpf_if *, u_char *, u_int); void bpf_mtap(struct bpf_if *, struct mbuf *); +void bpf_mtap2(struct bpf_if *, void *, u_int, struct mbuf *); void bpfattach(struct ifnet *, u_int, u_int); void bpfattach2(struct ifnet *, u_int, u_int, struct bpf_if **); void bpfdetach(struct ifnet *); @@ -366,8 +367,16 @@ u_int bpf_filter(const struct bpf_insn *, u_char *, u_int, u_int); bpf_tap((_ifp)->if_bpf, (_pkt), (_pktlen)); \ } while (0) #define BPF_MTAP(_ifp,_m) do { \ - if ((_ifp)->if_bpf) \ + if ((_ifp)->if_bpf) { \ + M_ASSERTVALID(_m); \ bpf_mtap((_ifp)->if_bpf, (_m)); \ + } \ +} while (0) +#define BPF_MTAP2(_ifp,_data,_dlen,_m) do { \ + if ((_ifp)->if_bpf) { \ + M_ASSERTVALID(_m); \ + bpf_mtap2((_ifp)->if_bpf,(_data),(_dlen),(_m)); \ + } \ } while (0) #endif diff --git a/sys/net/if_disc.c b/sys/net/if_disc.c index 48935b3..bc1f0ad 100644 --- a/sys/net/if_disc.c +++ b/sys/net/if_disc.c @@ -164,21 +164,8 @@ discoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, } if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). - */ - struct mbuf m0; u_int af = dst->sa_family; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); } m->m_pkthdr.rcvif = ifp; diff --git a/sys/net/if_ef.c b/sys/net/if_ef.c index a239613..f0440de 100644 --- a/sys/net/if_ef.c +++ b/sys/net/if_ef.c @@ -372,13 +372,7 @@ ef_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m) eifp->if_ibytes += m->m_pkthdr.len + sizeof (*eh); m->m_pkthdr.rcvif = eifp; - if (eifp->if_bpf) { - struct mbuf m0; - m0.m_next = m; - m0.m_len = ETHER_HDR_LEN; - m0.m_data = (char *)eh; - BPF_MTAP(eifp, &m0); - } + BPF_MTAP2(eifp, eh, ETHER_HDR_LEN, m); /* * Now we ready to adjust mbufs and pass them to protocol intr's */ diff --git a/sys/net/if_faith.c b/sys/net/if_faith.c index a8da4ad..06e60cd 100644 --- a/sys/net/if_faith.c +++ b/sys/net/if_faith.c @@ -213,21 +213,8 @@ faithoutput(ifp, m, dst, rt) } if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a faith header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). - */ - struct mbuf m0; u_int32_t af = dst->sa_family; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); } if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) { diff --git a/sys/net/if_gif.c b/sys/net/if_gif.c index d77a5a5..6bf538f 100644 --- a/sys/net/if_gif.c +++ b/sys/net/if_gif.c @@ -349,21 +349,8 @@ gif_output(ifp, m, dst, rt) } if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). - */ - struct mbuf m0; u_int32_t af = dst->sa_family; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); } ifp->if_opackets++; ifp->if_obytes += m->m_pkthdr.len; @@ -418,21 +405,8 @@ gif_input(m, af, ifp) #endif if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). - */ - struct mbuf m0; u_int32_t af1 = af; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)&af1; - - BPF_MTAP(ifp, &m0); + bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); } if (ng_gif_input_p != NULL) { diff --git a/sys/net/if_gre.c b/sys/net/if_gre.c index 3d1adad..9c41e71 100644 --- a/sys/net/if_gre.c +++ b/sys/net/if_gre.c @@ -240,15 +240,8 @@ gre_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, osrc = 0; if (ifp->if_bpf) { - /* see comment of other if_foo.c files */ - struct mbuf m0; u_int32_t af = dst->sa_family; - - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); } m->m_flags &= ~(M_BCAST|M_MCAST); diff --git a/sys/net/if_loop.c b/sys/net/if_loop.c index 9a54af4..38aae4e 100644 --- a/sys/net/if_loop.c +++ b/sys/net/if_loop.c @@ -252,22 +252,14 @@ if_simloop(ifp, m, af, hlen) /* Let BPF see incoming packet */ if (ifp->if_bpf) { - struct mbuf m0, *n = m; - if (ifp->if_bpf->bif_dlt == DLT_NULL) { + u_int32_t af1 = af; /* XXX beware sizeof(af) != 4 */ /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer a to it). + * We need to prepend the address family. */ - m0.m_next = m; - m0.m_len = 4; - m0.m_data = (char *)⁡ - n = &m0; - } - BPF_MTAP(ifp, n); + bpf_mtap2(ifp->if_bpf, &af1, sizeof(af1), m); + } else + bpf_mtap(ifp->if_bpf, m); } /* Strip away media header */ diff --git a/sys/net/if_stf.c b/sys/net/if_stf.c index 76b92ec..88214f9 100644 --- a/sys/net/if_stf.c +++ b/sys/net/if_stf.c @@ -430,17 +430,17 @@ stf_output(ifp, m, dst, rt) * will only read from the mbuf (i.e., it won't * try to free it or keep a pointer a to it). */ - struct mbuf m0; u_int32_t af = AF_INET6; +#ifdef HAVE_OLD_BPF + struct mbuf m0; m0.m_next = m; m0.m_len = 4; m0.m_data = (char *)⁡ -#ifdef HAVE_OLD_BPF BPF_MTAP(ifp, &m0); #else - bpf_mtap(ifp->if_bpf, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m); #endif } #endif /*NBPFILTER > 0*/ @@ -685,17 +685,17 @@ in_stf_input(m, off) * will only read from the mbuf (i.e., it won't * try to free it or keep a pointer a to it). */ - struct mbuf m0; u_int32_t af = AF_INET6; +#ifdef HAVE_OLD_BPF + struct mbuf m0; m0.m_next = m; m0.m_len = 4; m0.m_data = (char *)⁡ -#ifdef HAVE_OLD_BPF BPF_MTAP(ifp, &m0); #else - bpf_mtap(ifp->if_bpf, &m0); + bpf_mtap2(ifp->if_bpf, &af, sizeof(ah), m); #endif } diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c index e983a5b..516d299 100644 --- a/sys/net/if_tun.c +++ b/sys/net/if_tun.c @@ -456,21 +456,8 @@ tunoutput( } if (ifp->if_bpf) { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer to it). - */ - struct mbuf m; uint32_t af = dst->sa_family; - - m.m_next = m0; - m.m_len = 4; - m.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m); + bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0); } /* prepend sockaddr? this may abort if the mbuf allocation fails */ @@ -743,39 +730,6 @@ tunwrite(dev_t dev, struct uio *uio, int flag) mac_create_mbuf_from_ifnet(ifp, top); #endif - if (ifp->if_bpf) { - if (tp->tun_flags & TUN_IFHEAD) { - /* - * Conveniently, we already have a 4-byte address - * family prepended to our packet ! - * Inconveniently, it's in the wrong byte order ! - */ - if ((top = m_pullup(top, sizeof(family))) == NULL) - return (ENOBUFS); - *mtod(top, u_int32_t *) = - ntohl(*mtod(top, u_int32_t *)); - BPF_MTAP(ifp, top); - *mtod(top, u_int32_t *) = - htonl(*mtod(top, u_int32_t *)); - } else { - /* - * We need to prepend the address family as - * a four byte field. Cons up a dummy header - * to pacify bpf. This is safe because bpf - * will only read from the mbuf (i.e., it won't - * try to free it or keep a pointer to it). - */ - struct mbuf m; - uint32_t af = AF_INET; - - m.m_next = top; - m.m_len = 4; - m.m_data = (char *)⁡ - - BPF_MTAP(ifp, &m); - } - } - if (tp->tun_flags & TUN_IFHEAD) { if (top->m_len < sizeof(family) && (top = m_pullup(top, sizeof(family))) == NULL) @@ -785,6 +739,8 @@ tunwrite(dev_t dev, struct uio *uio, int flag) } else family = AF_INET; + BPF_MTAP2(ifp, &family, sizeof(family), top); + switch (family) { #ifdef INET case AF_INET: |