summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2015-12-19 11:19:36 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2015-12-19 11:19:36 +0000
commit4c2727996705e64f00782bc5750444dc1fca824e (patch)
tree1faded5327c9644e544f053968eb412738c9dd8e /sys
parent9269c92c0f0c789524cc22e5a7299a00a304712e (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.c17
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);
}