diff options
author | archie <archie@FreeBSD.org> | 2000-05-14 02:18:43 +0000 |
---|---|---|
committer | archie <archie@FreeBSD.org> | 2000-05-14 02:18:43 +0000 |
commit | fa21035b4e2f11d2c8f90174690853600b670e2d (patch) | |
tree | 9afb8dacfff6d7607064d8aa2bbf2da5069e8be6 /sys/net/bridge.c | |
parent | d066b073153b986a54fd18a31d6bcc5d697933a2 (diff) | |
download | FreeBSD-src-fa21035b4e2f11d2c8f90174690853600b670e2d.zip FreeBSD-src-fa21035b4e2f11d2c8f90174690853600b670e2d.tar.gz |
Move code to handle BPF and bridging for incoming Ethernet packets out
of the individual drivers and into the common routine ether_input().
Also, remove the (incomplete) hack for matching ethernet headers
in the ip_fw code.
The good news: net result of 1016 lines removed, and this should make
bridging now work with *all* Ethernet drivers.
The bad news: it's nearly impossible to test every driver, especially
for bridging, and I was unable to get much testing help on the mailing
lists.
Reviewed by: freebsd-net
Diffstat (limited to 'sys/net/bridge.c')
-rw-r--r-- | sys/net/bridge.c | 58 |
1 files changed, 23 insertions, 35 deletions
diff --git a/sys/net/bridge.c b/sys/net/bridge.c index e3fcc3f..83b711e 100644 --- a/sys/net/bridge.c +++ b/sys/net/bridge.c @@ -31,9 +31,8 @@ * A bridging table holds the source MAC address/dest. interface for each * known node. The table is indexed using an hash of the source address. * - * Input packets are tapped near the end of the input routine in each - * driver (near the call to bpf_mtap, or before the call to ether_input) - * and analysed calling bridge_in(). Depending on the result, the packet + * Input packets are tapped near the beginning of ether_input(), and + * analysed by calling bridge_in(). Depending on the result, the packet * can be forwarded to one or more output interfaces using bdg_forward(), * and/or sent to the upper layer (e.g. in case of multicast). * @@ -163,7 +162,7 @@ static struct bdg_softc *ifp2sc = NULL ; #define IFP_CHK(ifp, x) \ if (ifp2sc[ifp->if_index].magic != 0xDEADBEEF) { x ; } -#define SAMECLUSTER(ifp,src,eh) \ +#define SAMECLUSTER(ifp,src) \ (src == NULL || CLUSTER(ifp) == CLUSTER(src) ) /* @@ -473,11 +472,9 @@ bdginit(void *dummy) /* * bridge_in() is invoked to perform bridging decision on input packets. + * * On Input: - * m packet to be bridged. The mbuf need not to hold the - * whole packet, only the first 14 bytes suffice. We - * assume them to be contiguous. No alignment assumptions - * because they are not a problem on i386 class machines. + * eh Ethernet header of the incoming packet. * * On Return: destination of packet, one of * BDG_BCAST broadcast @@ -490,16 +487,12 @@ bdginit(void *dummy) * to fetch more of the packet, or simply drop it completely. */ - struct ifnet * -bridge_in(struct mbuf *m) +bridge_in(struct ifnet *ifp, struct ether_header *eh) { int index; - struct ifnet *ifp = m->m_pkthdr.rcvif, *dst , *old ; + struct ifnet *dst , *old ; int dropit = MUTED(ifp) ; - struct ether_header *eh; - - eh = mtod(m, struct ether_header *); /* * hash the source address @@ -545,7 +538,7 @@ bridge_in(struct mbuf *m) bcopy(eh->ether_shost, bdg_table[index].etheraddr, 6); bdg_table[index].name = ifp ; } - dst = bridge_dst_lookup(m); + dst = bridge_dst_lookup(eh); /* Return values: * BDG_BCAST, BDG_MCAST, BDG_LOCAL, BDG_UNKNOWN, BDG_DROP, ifp. * For muted interfaces, the first 3 are changed in BDG_LOCAL, @@ -599,7 +592,7 @@ bridge_in(struct mbuf *m) * *m0 -- pointer to the packet (NULL if still existent) */ int -bdg_forward (struct mbuf **m0, struct ifnet *dst) +bdg_forward(struct mbuf **m0, struct ether_header *const eh, struct ifnet *dst) { struct ifnet *src = (*m0)->m_pkthdr.rcvif; /* could be NULL in output */ struct ifnet *ifp, *last = NULL ; @@ -608,8 +601,6 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) int once = 0; /* loop only once */ struct mbuf *m ; - struct ether_header *eh = mtod(*m0, struct ether_header *); /* XXX */ - if (dst == BDG_DROP) { /* this should not happen */ printf("xx bdg_forward for BDG_DROP\n"); m_freem(*m0) ; @@ -642,7 +633,6 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) * ethernet header. */ if (ip_fw_chk_ptr) { - u_int16_t dummy = 0 ; struct ip_fw_chain *rule = NULL ; int off; struct ip *ip ; @@ -658,7 +648,6 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) (*m0) = m = m->m_next ; src = m->m_pkthdr.rcvif; /* could be NULL in output */ - eh = mtod(m, struct ether_header *); /* XXX */ canfree = 1 ; /* for sure, a copy is not needed later. */ goto forward; /* HACK! I should obey the fw_one_pass */ } @@ -680,7 +669,7 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) * Need to make a copy (and for good measure, make sure that * the header is contiguous). The original is still in *m0 */ - int needed = min(MHLEN, 14+max_protohdr) ; + int needed = min(MHLEN, max_protohdr) ; needed = min(needed, (*m0)->m_len ) ; m = m_copypacket( (*m0), M_DONTWAIT); @@ -688,8 +677,7 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) printf("-- bdg: m_copypacket failed.\n") ; return ENOBUFS ; } - m = m_pullup(m, needed) ; - if ( m == NULL ) { + if (m->m_len < needed && (m = m_pullup(m, needed)) == NULL) { printf("-- bdg: pullup failed.\n") ; return ENOBUFS ; } @@ -699,8 +687,7 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) * before calling the firewall, swap fields the same as IP does. * here we assume the pkt is an IP one and the header is contiguous */ - eh = mtod(m, struct ether_header *); - ip = (struct ip *)(eh + 1 ) ; + ip = mtod(m, struct ip *); NTOHS(ip->ip_len); NTOHS(ip->ip_id); NTOHS(ip->ip_off); @@ -709,7 +696,7 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) * The third parameter to the firewall code is the dst. interface. * Since we apply checks only on input pkts we use NULL. */ - off = (*ip_fw_chk_ptr)(NULL, 0, NULL, &dummy, &m, &rule, NULL) ; + off = (*ip_fw_chk_ptr)(&ip, 0, NULL, NULL, &m, &rule, NULL); if (m == NULL) { /* pkt discarded by firewall */ /* @@ -724,11 +711,9 @@ bdg_forward (struct mbuf **m0, struct ifnet *dst) /* * If we get here, the firewall has passed the pkt, but the - * mbuf pointer might have changed. Restore eh, ip, and the - * fields NTOHS()'d. Then, if canfree==1, also restore *m0. + * mbuf pointer might have changed. Restore the fields NTOHS()'d. + * Then, if canfree==1, also restore *m0. */ - eh = mtod(m, struct ether_header *); - ip = (struct ip *)(eh + 1 ) ; HTONS(ip->ip_len); HTONS(ip->ip_id); HTONS(ip->ip_off); @@ -774,11 +759,10 @@ forward: * but better than having packets corrupt! */ if (canfree == 0 ) { - int needed = min(MHLEN, 14+max_protohdr) ; + int needed = min(MHLEN, max_protohdr) ; needed = min(needed, (*m0)->m_len ) ; - *m0 = m_pullup( *m0, needed) ; - if ( *m0 == NULL ) { + if ((*m0)->m_len < needed && (*m0 = m_pullup(*m0, needed)) == NULL) { printf("-- bdg: pullup failed.\n") ; return ENOBUFS ; } @@ -795,9 +779,13 @@ forward: return ENOBUFS ; /* the original is still there... */ } /* - * Last part of ether_output: queue pkt and start + * Last part of ether_output: add header, queue pkt and start * output if interface not yet active. */ + M_PREPEND(m, ETHER_HDR_LEN, M_DONTWAIT); + if (m == NULL) + return ENOBUFS; + bcopy(eh, mtod(m, struct ether_header *), ETHER_HDR_LEN); s = splimp(); if (IF_QFULL(&last->if_snd)) { IF_DROP(&last->if_snd); @@ -828,7 +816,7 @@ forward: ! IF_QFULL(&ifp->if_snd) && (ifp->if_flags & (IFF_UP|IFF_RUNNING)) == (IFF_UP|IFF_RUNNING) && - SAMECLUSTER(ifp, src, eh) && !MUTED(ifp) ) + SAMECLUSTER(ifp, src) && !MUTED(ifp) ) last = ifp ; ifp = ifp->if_link.tqe_next ; if (ifp == NULL) |