CARP doesn't send advertisements correctly when a virtual host's IP is on an interface that is participating in a bridge, because carp_output is called too late to set the virtual MAC address in ether_output. Moving the carp_output call to before bridge_output fixes this. Additionally, packets that are received on an interface participating in a bridge but destined for a local virtual host are not received locally and are always forwarded over the bridge. Add a check against carp_forus so we can handle these packets locally as required. Patch against -current + carp_icmpfix.diff. Chris Pascoe 2004/06/28 Index: net/if_ethersubr.c =================================================================== RCS file: /cvs/src/sys/net/if_ethersubr.c,v retrieving revision 1.78 diff -u -p -r1.78 if_ethersubr.c --- net/if_ethersubr.c 26 Jun 2004 06:01:14 -0000 1.78 +++ net/if_ethersubr.c 28 Jun 2004 08:07:50 -0000 @@ -519,6 +519,15 @@ ether_output(ifp, 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) { + int error; + error = carp_output(ifp, m, dst, NULL); + if (error) + goto bad; + } +#endif + #if NBRIDGE > 0 /* * Interfaces that are bridge members need special handling @@ -560,15 +569,6 @@ ether_output(ifp, m0, dst, rt0) } #endif -#if NCARP > 0 - if (ifp->if_carp) { - int error; - error = carp_output(ifp, m, dst, NULL); - if (error) - goto bad; - } -#endif - mflags = m->m_flags; len = m->m_pkthdr.len; s = splimp(); Index: net/if_bridge.c =================================================================== RCS file: /cvs/src/sys/net/if_bridge.c,v retrieving revision 1.136 diff -u -p -r1.136 if_bridge.c --- net/if_bridge.c 21 Jun 2004 23:50:36 -0000 1.136 +++ net/if_bridge.c 28 Jun 2004 08:07:51 -0000 @@ -82,6 +82,11 @@ #define BRIDGE_OUT 1 #endif +#include "carp.h" +#if NCARP > 0 +#include +#endif + #if NBPFILTER > 0 #include #endif @@ -1387,7 +1392,12 @@ bridge_input(struct ifnet *ifp, struct e 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 ( +#if NCARP > 0 + (ifl->ifp->if_carp && (m->m_pkthdr.carpif = + carp_forus(ifl->ifp->if_carp, eh->ether_dhost)) != NULL) || +#endif + bcmp(ac->ac_enaddr, eh->ether_dhost, ETHER_ADDR_LEN) == 0) { if (srcifl->bif_flags & IFBIF_LEARNING) bridge_rtupdate(sc, (struct ether_addr *)&eh->ether_shost,