diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-12-19 11:19:36 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2015-12-19 11:19:36 +0000 |
commit | 4c2727996705e64f00782bc5750444dc1fca824e (patch) | |
tree | 1faded5327c9644e544f053968eb412738c9dd8e /sys | |
parent | 9269c92c0f0c789524cc22e5a7299a00a304712e (diff) |
Make carp_output() mpsafe.
This is needed in order to fully unlock ARP processing with carp(4)
interfaces as found the hardway by sthen@.
ok sthen@, dlg@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/netinet/ip_carp.c | 17 |
1 files changed, 12 insertions, 5 deletions
diff --git a/sys/netinet/ip_carp.c b/sys/netinet/ip_carp.c index 4dbb6e5616b..3cba5b6c2cc 100644 --- a/sys/netinet/ip_carp.c +++ b/sys/netinet/ip_carp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_carp.c,v 1.283 2015/12/03 16:27:32 mpi Exp $ */ +/* $OpenBSD: ip_carp.c,v 1.284 2015/12/19 11:19:35 mpi Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff. All rights reserved. @@ -2305,13 +2305,20 @@ carp_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa, { struct carp_softc *sc = ((struct carp_softc *)ifp->if_softc); struct carp_vhost_entry *vhe; + struct srpl_iter i; + int ismaster; - KERNEL_ASSERT_LOCKED(); /* touching carp_vhosts */ + KASSERT(sc->sc_carpdev != NULL); - vhe = sc->cur_vhe ? sc->cur_vhe : SRPL_FIRST_LOCKED(&sc->carp_vhosts); + if (sc->cur_vhe == NULL) { + vhe = SRPL_ENTER(&sc->carp_vhosts, &i); /* head */ + ismaster = (vhe->state == MASTER); + SRPL_LEAVE(&i, vhe); + } else { + ismaster = (sc->cur_vhe->state == MASTER); + } - if ((sc->sc_carpdev == NULL) || - (sc->sc_balancing == CARP_BAL_NONE && vhe->state != MASTER)) { + if ((sc->sc_balancing == CARP_BAL_NONE && !ismaster)) { m_freem(m); return (ENETUNREACH); } |