summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrzalamena <rzalamena@openbsd.org>2016-09-28 08:31:42 +0000
committerrzalamena <rzalamena@openbsd.org>2016-09-28 08:31:42 +0000
commit1bfa6094fbcd01d60c8a4f7c0f94d343d4ec22e4 (patch)
tree0a3601c58829eadbacec1e842130effa471b244e
parentRate limit TIOCSWINSZ on a timer to avoid programs getting hammered with (diff)
downloadwireguard-openbsd-1bfa6094fbcd01d60c8a4f7c0f94d343d4ec22e4.tar.xz
wireguard-openbsd-1bfa6094fbcd01d60c8a4f7c0f94d343d4ec22e4.zip
Fix a kernel panic that happened when destroying interfaces attached to
the switch(4) without prior removal. ok reyk@, goda@
-rw-r--r--sys/net/if.c11
-rw-r--r--sys/net/if_switch.c27
-rw-r--r--sys/net/if_switch.h3
3 files changed, 31 insertions, 10 deletions
diff --git a/sys/net/if.c b/sys/net/if.c
index 480f080d29b..5abe7516a51 100644
--- a/sys/net/if.c
+++ b/sys/net/if.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if.c,v 1.450 2016/09/22 14:50:11 mpi Exp $ */
+/* $OpenBSD: if.c,v 1.451 2016/09/28 08:31:42 rzalamena Exp $ */
/* $NetBSD: if.c,v 1.35 1996/05/07 05:26:04 thorpej Exp $ */
/*
@@ -130,6 +130,10 @@
#include <net/pfvar.h>
#endif
+#if NSWITCH > 0
+#include <net/if_switch.h>
+#endif
+
void if_attachsetup(struct ifnet *);
void if_attachdomain(struct ifnet *);
void if_attach_common(struct ifnet *);
@@ -897,6 +901,11 @@ if_deactivate(struct ifnet *ifp)
bridge_ifdetach(ifp);
#endif
+#if NSWITCH > 0
+ if (ifp->if_switchport)
+ switch_port_detach(ifp);
+#endif
+
#if NCARP > 0
/* Remove the interface from any carp group it is a part of. */
if (ifp->if_carp && ifp->if_type != IFT_CARP)
diff --git a/sys/net/if_switch.c b/sys/net/if_switch.c
index 6309d28f364..c8079cf32c3 100644
--- a/sys/net/if_switch.c
+++ b/sys/net/if_switch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_switch.c,v 1.5 2016/09/04 17:11:09 goda Exp $ */
+/* $OpenBSD: if_switch.c,v 1.6 2016/09/28 08:31:42 rzalamena Exp $ */
/*
* Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
@@ -629,6 +629,23 @@ done:
return (error);
}
+void
+switch_port_detach(struct ifnet *ifp)
+{
+ struct switch_softc *sc = ifp->if_softc;
+ struct switch_port *swpo;
+
+ swpo = (struct switch_port *)ifp->if_switchport;
+ if (swpo->swpo_flags & IFBIF_LOCAL)
+ switch_port_unset_local(sc, swpo);
+
+ ifp->if_switchport = NULL;
+ ifpromisc(ifp, 0);
+ if_ih_remove(ifp, switch_input, NULL);
+ TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
+ free(swpo, M_DEVBUF, sizeof(*swpo));
+}
+
int
switch_port_del(struct switch_softc *sc, struct ifbreq *req)
{
@@ -645,13 +662,7 @@ switch_port_del(struct switch_softc *sc, struct ifbreq *req)
}
if (swpo) {
- if (swpo->swpo_flags & IFBIF_LOCAL)
- switch_port_unset_local(sc, swpo);
- ifs->if_switchport = NULL;
- ifpromisc(ifs, 0);
- if_ih_remove(ifs, switch_input, NULL);
- TAILQ_REMOVE(&sc->sc_swpo_list, swpo, swpo_list_next);
- free(swpo, M_DEVBUF, sizeof(*swpo));
+ switch_port_detach(ifs);
if_put(ifs);
error = 0;
} else
diff --git a/sys/net/if_switch.h b/sys/net/if_switch.h
index 7765ac20e11..cb5a9f35b09 100644
--- a/sys/net/if_switch.h
+++ b/sys/net/if_switch.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_switch.h,v 1.2 2016/09/04 16:47:41 goda Exp $ */
+/* $OpenBSD: if_switch.h,v 1.3 2016/09/28 08:31:42 rzalamena Exp $ */
/*
* Copyright (c) 2016 Kazuya GODA <goda@openbsd.org>
@@ -215,6 +215,7 @@ void switch_port_egress(struct switch_softc *, struct switch_fwdp_queue *,
int switch_swfcl_dup(struct switch_flow_classify *,
struct switch_flow_classify *);
void switch_swfcl_free(struct switch_flow_classify *);
+void switch_port_detach(struct ifnet *);
/* switchctl.c */
void switch_dev_destroy(struct switch_softc *);