diff options
author | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2011-03-08 22:53:29 +0000 |
---|---|---|
committer | Marco Pfatschbacher <mpf@cvs.openbsd.org> | 2011-03-08 22:53:29 +0000 |
commit | 68557265eccf8f10e3f16c3b904be70e744e3d74 (patch) | |
tree | 8c0c9a33203f784e11a95f6bb78989eba2ddf386 | |
parent | 7975e243374cebcb360a74289feb1cca514a6897 (diff) |
Fix a subtle carp reconfiguration problem.
Updating the HMAC from the carp_ioctl call does not see the newly
set IP address in the if_addrlist. The only chance for carp to see
the new address is via the address-hook callback. This change moves
the detection of address changes entirely into carp_addr_updated.
Furthermore, only call carp_hmac_prepare for the SIOCSVH case. This
second bug was the reason why the first one went unnoticed for such
a long time.
Problem found and debugging help by camield@.
OK camield@
-rw-r--r-- | sys/netinet/ip_carp.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 90e8295e309..ef67977f270 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.180 2010/12/21 14:59:14 claudio Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.181 2011/03/08 22:53:28 mpf Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -1941,11 +1941,11 @@ carp_addr_updated(void *v) new_naddrs++; else if (ifa->ifa_addr->sa_family == AF_INET6 && !IN6_IS_ADDR_LINKLOCAL(&ifatoia6(ifa)->ia_addr.sin6_addr)) - new_naddrs6++; + new_naddrs6++; } - /* Handle a callback after SIOCDIFADDR */ - if (new_naddrs < sc->sc_naddrs || new_naddrs6 < sc->sc_naddrs6) { + /* We received address changes from if_addrhooks callback */ + if (new_naddrs != sc->sc_naddrs || new_naddrs6 != sc->sc_naddrs6) { struct in_addr mc_addr; struct in_multi *inm; @@ -1988,6 +1988,7 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) struct in_ifaddr *ia, *ia_if; int error = 0; + /* XXX is this necessary? */ if (sin->sin_addr.s_addr == 0) { if (!(sc->sc_if.if_flags & IFF_UP)) carp_set_state_all(sc, INIT); @@ -2033,7 +2034,6 @@ carp_set_addr(struct carp_softc *sc, struct sockaddr_in *sin) if (sc->sc_naddrs == 0 && (error = carp_join_multicast(sc)) != 0) return (error); - sc->sc_naddrs++; if (sc->sc_carpdev != NULL) sc->sc_if.if_flags |= IFF_UP; @@ -2131,8 +2131,6 @@ carp_set_addr6(struct carp_softc *sc, struct sockaddr_in6 *sin6) if (sc->sc_naddrs6 == 0 && (error = carp_join_multicast6(sc)) != 0) return (error); - if (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) - sc->sc_naddrs6++; if (sc->sc_carpdev != NULL && sc->sc_naddrs6) sc->sc_if.if_flags |= IFF_UP; carp_set_state_all(sc, INIT); @@ -2313,6 +2311,7 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) error = EINVAL; else { error = 0; + carp_hmac_prepare(sc); carp_setrun_all(sc, 0); } break; @@ -2359,7 +2358,6 @@ carp_ioctl(struct ifnet *ifp, u_long cmd, caddr_t addr) if (bcmp(sc->sc_ac.ac_enaddr, sc->sc_curlladdr, ETHER_ADDR_LEN) != 0) carp_set_enaddr(sc); - carp_hmac_prepare(sc); return (error); } |