summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Pascoe <pascoe@cvs.openbsd.org>2004-12-17 12:42:03 +0000
committerChristopher Pascoe <pascoe@cvs.openbsd.org>2004-12-17 12:42:03 +0000
commit00cabea6fcdbcf8569fba0e1263ab451f1cdf325 (patch)
treeaf618745f40973d7af5d616f304616ed17c64d0e
parent4b8b00a64383f5942e6ec2170da2236e0ad29722 (diff)
Reorder code in the ethernet output path, and enhance unicast address
matching in the bridge receive path to make CARP operate correctly on physical interfaces that are participating in a bridge. ok mcbride@ henning@ dlg@
-rw-r--r--sys/net/if_bridge.c21
-rw-r--r--sys/net/if_ethersubr.c18
-rw-r--r--sys/netinet/ip_carp.c47
-rw-r--r--sys/netinet/ip_carp.h3
4 files changed, 60 insertions, 29 deletions
diff --git a/sys/net/if_bridge.c b/sys/net/if_bridge.c
index a99466c4d5c..8936febc198 100644
--- a/sys/net/if_bridge.c
+++ b/sys/net/if_bridge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bridge.c,v 1.138 2004/10/09 19:55:28 brad Exp $ */
+/* $OpenBSD: if_bridge.c,v 1.139 2004/12/17 12:42:02 pascoe Exp $ */
/*
* Copyright (c) 1999, 2000 Jason L. Wright (jason@thought.net)
@@ -35,6 +35,7 @@
#include "gif.h"
#include "pf.h"
#include "vlan.h"
+#include "carp.h"
#include <sys/param.h>
#include <sys/proc.h>
@@ -90,6 +91,10 @@
#include <net/if_vlan_var.h>
#endif
+#if NCARP > 0
+#include <netinet/ip_carp.h>
+#endif
+
#include <net/if_bridge.h>
#ifndef BRIDGE_RTABLE_SIZE
@@ -1387,7 +1392,12 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
if (ifl->ifp->if_type != IFT_ETHER)
continue;
ac = (struct arpcom *)ifl->ifp;
- if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) {
+ if (bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0
+#if NCARP > 0
+ || (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp,
+ eh, 0) != NULL)
+#endif
+ ) {
if (srcifl->bif_flags & IFBIF_LEARNING)
bridge_rtupdate(sc,
(struct ether_addr *)&eh->ether_shost,
@@ -1405,7 +1415,12 @@ bridge_input(struct ifnet *ifp, struct ether_header *eh, struct mbuf *m)
}
return (m);
}
- if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0) {
+ if (bcmp(ac->ac_enaddr, eh->ether_shost, ETHER_ADDR_LEN) == 0
+#if NCARP > 0
+ || (ifl->ifp->if_carp && carp_ourether(ifl->ifp->if_carp,
+ eh, 1) != NULL)
+#endif
+ ) {
m_freem(m);
return (NULL);
}
diff --git a/sys/net/if_ethersubr.c b/sys/net/if_ethersubr.c
index dee823be08c..cfc6fbc5cc5 100644
--- a/sys/net/if_ethersubr.c
+++ b/sys/net/if_ethersubr.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_ethersubr.c,v 1.85 2004/12/10 22:35:17 mcbride Exp $ */
+/* $OpenBSD: if_ethersubr.c,v 1.86 2004/12/17 12:42:02 pascoe Exp $ */
/* $NetBSD: if_ethersubr.c,v 1.19 1996/05/07 02:40:30 thorpej Exp $ */
/*
@@ -493,6 +493,14 @@ ether_output(ifp0, m0, dst, rt0)
bcopy((caddr_t)ac->ac_enaddr, (caddr_t)eh->ether_shost,
sizeof(eh->ether_shost));
+#if NCARP > 0
+ if (ifp->if_carp) {
+ error = carp_fix_lladdr(ifp0, m, dst, NULL);
+ if (error)
+ goto bad;
+ }
+#endif
+
#if NBRIDGE > 0
/*
* Interfaces that are bridge members need special handling
@@ -534,14 +542,6 @@ ether_output(ifp0, m0, dst, rt0)
}
#endif
-#if NCARP > 0
- if (ifp->if_carp) {
- error = carp_fix_lladdr(ifp0, m, dst, NULL);
- if (error)
- goto bad;
- }
-#endif
-
mflags = m->m_flags;
len = m->m_pkthdr.len;
s = splimp();
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c
index 9afae3af7cf..53c5cda4d07 100644
--- a/sys/netinet/ip_carp.c
+++ b/sys/netinet/ip_carp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.c,v 1.82 2004/12/17 06:47:00 mcbride Exp $ */
+/* $OpenBSD: ip_carp.c,v 1.83 2004/12/17 12:42:01 pascoe Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -1239,19 +1239,43 @@ carp_macmatch6(void *v, struct mbuf *m, struct in6_addr *taddr)
}
#endif /* INET6 */
+struct ifnet *
+carp_ourether(void *v, struct ether_header *eh, int src)
+{
+ struct carp_if *cif = (struct carp_if *)v;
+ struct carp_softc *vh;
+ u_int8_t *ena;
+
+ if (src)
+ ena = (u_int8_t *)&eh->ether_shost;
+ else
+ ena = (u_int8_t *)&eh->ether_dhost;
+
+ if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1)
+ return (NULL);
+
+ TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list)
+ if ((vh->sc_ac.ac_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
+ (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER &&
+ !bcmp(ena, vh->sc_ac.ac_enaddr,
+ ETHER_ADDR_LEN))
+ return (&vh->sc_ac.ac_if);
+
+ return (NULL);
+}
+
int
carp_input(struct ether_header *eh, struct mbuf *m)
{
struct carp_if *cif = (struct carp_if *)m->m_pkthdr.rcvif->if_carp;
- struct carp_softc *vh;
- u_int8_t *ena = (u_int8_t *)&eh->ether_dhost;
struct ifnet *ifp;
if (ETHER_IS_MULTICAST(eh->ether_dhost)) {
+ struct carp_softc *vh;
struct mbuf *m0;
/*
- * XXX Should reall check the list of multicast addresses
+ * XXX Should really check the list of multicast addresses
* for each CARP interface _before_ copying.
*/
TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list) {
@@ -1264,20 +1288,11 @@ carp_input(struct ether_header *eh, struct mbuf *m)
return (1);
}
- if (ena[0] || ena[1] || ena[2] != 0x5e || ena[3] || ena[4] != 1)
- return (1);
-
- TAILQ_FOREACH(vh, &cif->vhif_vrs, sc_list)
- if ((vh->sc_ac.ac_if.if_flags & (IFF_UP|IFF_RUNNING)) ==
- (IFF_UP|IFF_RUNNING) && vh->sc_state == MASTER &&
- !bcmp(ena, vh->sc_ac.ac_enaddr,
- ETHER_ADDR_LEN))
- break;
-
- if (vh == NULL)
+ ifp = carp_ourether(cif, eh, 0);
+ if (ifp == NULL)
return (1);
- m->m_pkthdr.rcvif = ifp = &vh->sc_ac.ac_if;
+ m->m_pkthdr.rcvif = ifp;
#if NBPFILTER > 0
if (ifp->if_bpf) {
diff --git a/sys/netinet/ip_carp.h b/sys/netinet/ip_carp.h
index 86cafdb5f7a..879e6f1cab6 100644
--- a/sys/netinet/ip_carp.h
+++ b/sys/netinet/ip_carp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ip_carp.h,v 1.13 2004/12/15 14:01:03 pat Exp $ */
+/* $OpenBSD: ip_carp.h,v 1.14 2004/12/17 12:42:01 pascoe Exp $ */
/*
* Copyright (c) 2002 Michael Shalayeff. All rights reserved.
@@ -162,6 +162,7 @@ int carp_iamatch(void *, struct in_ifaddr *, struct in_addr *,
u_int8_t **);
struct ifaddr *carp_iamatch6(void *, struct in6_addr *);
void *carp_macmatch6(void *, struct mbuf *, struct in6_addr *);
+struct ifnet *carp_ourether(void *, struct ether_header *, int);
int carp_input(struct ether_header *, struct mbuf *);
int carp_sysctl(int *, u_int, void *, size_t *, void *, size_t);
#endif /* _KERNEL */