diff options
author | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2004-12-17 12:42:03 +0000 |
---|---|---|
committer | Christopher Pascoe <pascoe@cvs.openbsd.org> | 2004-12-17 12:42:03 +0000 |
commit | 00cabea6fcdbcf8569fba0e1263ab451f1cdf325 (patch) | |
tree | af618745f40973d7af5d616f304616ed17c64d0e | |
parent | 4b8b00a64383f5942e6ec2170da2236e0ad29722 (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.c | 21 | ||||
-rw-r--r-- | sys/net/if_ethersubr.c | 18 | ||||
-rw-r--r-- | sys/netinet/ip_carp.c | 47 | ||||
-rw-r--r-- | sys/netinet/ip_carp.h | 3 |
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 */ |