summaryrefslogtreecommitdiffstats
path: root/sys/net/bridge.c
diff options
context:
space:
mode:
authorarchie <archie@FreeBSD.org>2000-05-14 02:18:43 +0000
committerarchie <archie@FreeBSD.org>2000-05-14 02:18:43 +0000
commitfa21035b4e2f11d2c8f90174690853600b670e2d (patch)
tree9afb8dacfff6d7607064d8aa2bbf2da5069e8be6 /sys/net/bridge.c
parentd066b073153b986a54fd18a31d6bcc5d697933a2 (diff)
downloadFreeBSD-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.c58
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)
OpenPOWER on IntegriCloud