diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-05-21 09:17:54 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-05-21 09:17:54 +0000 |
commit | 42c3219ed782c5a1065ad5ca7c71d8734c4065e0 (patch) | |
tree | aaeeeb0dd4d4e0cca65edb7dd8cbdda933e7445c /sys/netinet/ip_carp.c | |
parent | 711af9c078183bfff233395a9db5a61c701313fe (diff) |
Correctly state the link state to INVALID when creating a carp interface.
Since vhe are allocated with M_ZERO and INIT is also defined to be 0,
carp_set_state() would result in a no-op because of the state check.
So explicitly initialize the state of a vhe to INIT and move the state
check in carp_set_state_all() to prevent similar issues in the future.
Problem and initial diff from Johan Ymerson, thanks!
ok henning@
Diffstat (limited to 'sys/netinet/ip_carp.c')
-rw-r--r-- | sys/netinet/ip_carp.c | 19 |
1 files changed, 11 insertions, 8 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 76185eb4d10..310b0ce8ffc 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.256 2015/05/15 11:53:06 claudio Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.257 2015/05/21 09:17:53 mpi Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -708,9 +708,7 @@ carpattach(int n) } int -carp_clone_create(ifc, unit) - struct if_clone *ifc; - int unit; +carp_clone_create(struct if_clone *ifc, int unit) { struct carp_softc *sc; struct ifnet *ifp; @@ -753,11 +751,11 @@ carp_clone_create(ifc, unit) ifp->if_sadl->sdl_type = IFT_CARP; ifp->if_output = carp_output; ifp->if_priority = IF_CARP_DEFAULT_PRIORITY; + ifp->if_link_state = LINK_STATE_INVALID; /* Hook carp_addr_updated to cope with address and route changes. */ sc->ah_cookie = hook_establish(sc->sc_if.if_addrhooks, 0, carp_addr_updated, sc); - carp_set_state_all(sc, INIT); return (0); } @@ -774,6 +772,7 @@ carp_new_vhost(struct carp_softc *sc, int vhid, int advskew) vhe->parent_sc = sc; vhe->vhid = vhid; vhe->advskew = advskew; + vhe->state = INIT; timeout_set(&vhe->ad_tmo, carp_send_ad, vhe); timeout_set(&vhe->md_tmo, carp_master_down, vhe); timeout_set(&vhe->md6_tmo, carp_master_down, vhe); @@ -2276,8 +2275,12 @@ carp_set_state_all(struct carp_softc *sc, int state) { struct carp_vhost_entry *vhe; - LIST_FOREACH(vhe, &sc->carp_vhosts, vhost_entries) + LIST_FOREACH(vhe, &sc->carp_vhosts, vhost_entries) { + if (vhe->state == state) + continue; + carp_set_state(vhe, state); + } } void @@ -2287,8 +2290,8 @@ carp_set_state(struct carp_vhost_entry *vhe, int state) static const char *carp_states[] = { CARP_STATES }; int loglevel; - if (vhe->state == state) - return; + KASSERT(vhe->state != state); + if (vhe->state == INIT || state == INIT) loglevel = LOG_WARNING; else |