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/if_ethersubr.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/if_ethersubr.c')
-rw-r--r-- | sys/net/if_ethersubr.c | 69 |
1 files changed, 61 insertions, 8 deletions
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c index f7a5158..1a5b0c9 100644 --- a/sys/net/if_ethersubr.c +++ b/sys/net/if_ethersubr.c @@ -56,6 +56,7 @@ #include <net/if_llc.h> #include <net/if_dl.h> #include <net/if_types.h> +#include <net/bpf.h> #if defined(INET) || defined(INET6) #include <netinet/in.h> @@ -365,19 +366,22 @@ ether_output(ifp, m, dst, rt0) return (0); /* XXX */ } } + #ifdef BRIDGE if (do_bridge) { - struct mbuf *m0 = m ; - - if (m->m_pkthdr.rcvif) - m->m_pkthdr.rcvif = NULL ; - ifp = bridge_dst_lookup(m); - bdg_forward(&m0, ifp); - if (m0) - m_freem(m0); + struct ether_header hdr; + + m->m_pkthdr.rcvif = NULL; + bcopy(mtod(m, struct ether_header *), &hdr, ETHER_HDR_LEN); + m_adj(m, ETHER_HDR_LEN); + ifp = bridge_dst_lookup(&hdr); + bdg_forward(&m, &hdr, ifp); + if (m != NULL) + m_freem(m); return (0); } #endif + s = splimp(); /* * Queue message on interface, and start output if interface @@ -421,6 +425,55 @@ ether_input(ifp, eh, m) register struct llc *l; #endif + /* Check for a BPF tap */ + if (ifp->if_bpf != NULL) { + struct m_hdr mh; + + /* This kludge is OK; BPF treats the "mbuf" as read-only */ + mh.mh_next = m; + mh.mh_data = (char *)eh; + mh.mh_len = ETHER_HDR_LEN; + bpf_mtap(ifp, (struct mbuf *)&mh); + } + +#ifdef BRIDGE + /* Check for bridging mode */ + if (do_bridge) { + struct ifnet *bif; + + /* Check with bridging code */ + if ((bif = bridge_in(ifp, eh)) == BDG_DROP) { + m_freem(m); + return; + } + if (bif != BDG_LOCAL) + bdg_forward(&m, eh, bif); /* needs forwarding */ + if (bif == BDG_LOCAL + || bif == BDG_BCAST + || bif == BDG_MCAST) + goto recvLocal; /* receive locally */ + + /* If not local and not multicast, just drop it */ + if (m != NULL) + m_freem(m); + return; + } +#endif + + /* Discard packet if upper layers shouldn't see it. This should + only happen when the interface is in promiscuous mode. */ + if ((ifp->if_flags & IFF_PROMISC) != 0 + && (eh->ether_dhost[0] & 1) == 0 + && bcmp(eh->ether_dhost, + IFP2AC(ifp)->ac_enaddr, ETHER_ADDR_LEN) != 0) { + m_freem(m); + return; + } + +#ifdef BRIDGE +recvLocal: +#endif + /* Discard packet if interface is not up */ if ((ifp->if_flags & IFF_UP) == 0) { m_freem(m); return; |