aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-03 21:35:44 +0100
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-03 21:35:44 +0100
commite4b1ddee83baa30a659107b92ff2953104b674e0 (patch)
tree8f99aa24299ae4279a8bd70e7db3d7be7b9d42fd
parentFurther simplify the wireguard.h interface (diff)
downloadwireguard-openbsd-e4b1ddee83baa30a659107b92ff2953104b674e0.tar.xz
wireguard-openbsd-e4b1ddee83baa30a659107b92ff2953104b674e0.zip
A few small bugfixes
* Make sure peer sessions are removed when dropping peer * Free correct size in wg_softc_route_delete * Extract softc_peer_{add,delete} * Delete all peers when destroying interface We probably want a free function so we can delete all peers while dropping the wg_device.
-rw-r--r--src/if_wg.c97
-rw-r--r--src/wireguard.c5
2 files changed, 69 insertions, 33 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index 51d7b32..a5c2d7f 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -145,6 +145,10 @@ struct mbuf *wg_input(void *, struct mbuf *, struct sockaddr *, int);
void wg_input_deliver(struct mbuf *);
void wg_output_deliver(struct mbuf *);
+struct wg_peer *wg_softc_peer_add(struct wg_softc *, struct wg_pubkey *);
+void wg_softc_peer_delete(struct wg_softc *, struct wg_peer *);
+void wg_softc_peer_route_delete(struct wg_softc *, struct wg_peer *);
+
void wgattach(int);
int wg_clone_create(struct if_clone *, int);
int wg_clone_destroy(struct ifnet *);
@@ -218,7 +222,7 @@ wg_softc_route_delete(struct wg_softc *sc, struct wg_cidr *cidr)
srp_leave(&sr);
route = (struct wg_route_entry *) node->an_gc;
SLIST_REMOVE(&route->r_dst->r_aip, route, wg_route_entry, r_entry);
- free(route, M_DEVBUF, sizeof(struct wg_route));
+ free(route, M_DEVBUF, sizeof(struct wg_route_entry));
free(node, M_DEVBUF, sizeof(*node));
rw_exit_write(&root->ar_lock);
@@ -951,11 +955,15 @@ wg_clone_create(struct if_clone * ifc, int unit)
int
wg_clone_destroy(struct ifnet * ifp)
{
+ struct map_item *item;
struct wg_softc *sc = ifp->if_softc;
CLR(sc->sc_if.if_flags, IFF_RUNNING);
- /* TODO cleanup device */
+ /* TODO lock device */
+ /* For the time being, no lock as we hold kernel lock in ioctl */
+ FM_FOREACH_FILLED(item, &sc->sc_dev.d_peers)
+ wg_softc_peer_delete(sc, item->value);
taskq_destroy(sc->sc_taskq);
@@ -966,12 +974,13 @@ wg_clone_destroy(struct ifnet * ifp)
if_detach(ifp);
+ DPRINTF(sc, "destroyed interface: %s\n", ifp->if_xname);
+
#if NBPFILTER > 0
bpfdetach(ifp);
#endif
- DPRINTF(sc, "destroyed interface: %s\n", ifp->if_xname);
-
+ /* Free structures */
free(sc->sc_ip_rt, M_RTABLE, sizeof(*sc->sc_ip_rt));
#ifdef INET6
free(sc->sc_ip6_rt, M_RTABLE, sizeof(*sc->sc_ip6_rt));
@@ -1034,13 +1043,57 @@ wg_bind_port(struct wg_softc *sc)
return 0;
}
+void
+wg_softc_peer_route_delete(struct wg_softc *sc, struct wg_peer *peer)
+{
+ struct wg_route_entry *raip, *traip;
+ struct wg_route *route = peer->p_arg;
+ SLIST_FOREACH_SAFE(raip, &route->r_aip, r_entry, traip)
+ wg_softc_route_delete(sc, &raip->r_cidr);
+}
+
+struct wg_peer *
+wg_softc_peer_add(struct wg_softc *sc, struct wg_pubkey *key)
+{
+ struct wg_peer *peer;
+ struct wg_route *route;
+
+ route = malloc(sizeof(*route), M_DEVBUF, M_WAITOK | M_ZERO);
+ peer = wg_device_new_peer(&sc->sc_dev, key, route);
+
+ route->r_sc = sc;
+ route->r_peer = peer;
+ mq_init(&route->r_outgoing, IFQ_MAXLEN, IPL_NET);
+ SLIST_INIT(&route->r_aip);
+
+ wg_timer_setup(&peer->p_timers, route,
+ (void (*)(void *)) wg_route_send_keepalive,
+ (void (*)(void *)) wg_route_broken,
+ (void (*)(void *)) wg_route_send_initiation,
+ (void (*)(void *)) wg_route_clean);
+
+ DPRINTF(sc, "added peer: %x\n", peer->p_id);
+
+ return peer;
+}
+
+void
+wg_softc_peer_delete(struct wg_softc *sc, struct wg_peer *peer)
+{
+ DPRINTF(sc, "deleted peer: %x\n", peer->p_id);
+ wg_timer_stop(&peer->p_timers);
+ wg_softc_peer_route_delete(sc, peer);
+ free(peer->p_arg, M_DEVBUF, sizeof(struct wg_route));
+ wg_peer_drop(peer);
+}
+
+/* TODO flip set_peer -> peer_set */
int
wg_ioctl_set_peer(struct wg_softc *sc, u_long cmd, struct wg_set_peer *wsp)
{
int ret = 0;
struct wg_peer *peer;
struct wg_route *route;
- struct wg_route_entry *raip, *traip;
struct wg_pubkey pub;
struct wg_privkey shared;
@@ -1056,25 +1109,10 @@ wg_ioctl_set_peer(struct wg_softc *sc, u_long cmd, struct wg_set_peer *wsp)
/* TODO compat with byte key */
memcpy(pub.k, wsp->sp_pubkey, sizeof(pub.k));
- if ((peer = wg_device_ref_peerkey(&sc->sc_dev, &pub)) == NULL) {
- route = malloc(sizeof(*route), M_DEVBUF, M_WAITOK | M_ZERO);
- peer = wg_device_new_peer(&sc->sc_dev, &pub, route);
-
- route->r_sc = sc;
- route->r_peer = peer;
- mq_init(&route->r_outgoing, IFQ_MAXLEN, IPL_NET);
- SLIST_INIT(&route->r_aip);
-
- wg_timer_setup(&peer->p_timers, route,
- (void (*)(void *)) wg_route_send_keepalive,
- (void (*)(void *)) wg_route_broken,
- (void (*)(void *)) wg_route_send_initiation,
- (void (*)(void *)) wg_route_clean);
-
- DPRINTF(sc, "added peer: %x\n", peer->p_id);
- } else {
- route = peer->p_arg;
- }
+ if ((peer = wg_device_ref_peerkey(&sc->sc_dev, &pub)) == NULL)
+ peer = wg_softc_peer_add(sc, &pub);
+
+ route = peer->p_arg;
switch (cmd) {
case SIOCSWGPEERIP:
@@ -1091,13 +1129,9 @@ wg_ioctl_set_peer(struct wg_softc *sc, u_long cmd, struct wg_set_peer *wsp)
wg_timer_persistent_keepalive_set(&peer->p_timers, wsp->sp_pka);
break;
case SIOCDWGPEER:
- DPRINTF(sc, "deleted peer: %x\n", peer->p_id);
- SLIST_FOREACH_SAFE(raip, &route->r_aip, r_entry, traip)
- wg_softc_route_delete(sc, &raip->r_cidr);
wg_peer_put(peer);
- free(peer->p_arg, M_DEVBUF, sizeof(struct wg_route));
- wg_peer_drop(peer);
- break;
+ wg_softc_peer_delete(sc, peer);
+ return WG_OK;
case SIOCSWGPEERAIP:
ret = wg_softc_route_add(sc, &wsp->sp_aip, route);
break;
@@ -1105,8 +1139,7 @@ wg_ioctl_set_peer(struct wg_softc *sc, u_long cmd, struct wg_set_peer *wsp)
ret = wg_softc_route_delete(sc, &wsp->sp_aip);
break;
case SIOCCWGPEERAIP:
- SLIST_FOREACH_SAFE(raip, &route->r_aip, r_entry, traip)
- wg_softc_route_delete(sc, &raip->r_cidr);
+ wg_softc_peer_route_delete(sc, peer);
break;
}
diff --git a/src/wireguard.c b/src/wireguard.c
index b2f9b63..d1df72e 100644
--- a/src/wireguard.c
+++ b/src/wireguard.c
@@ -210,6 +210,9 @@ wg_peer_put(struct wg_peer *peer)
void
wg_peer_drop(struct wg_peer *peer)
{
+ /* TODO prevent lock gap */
+ wg_peer_clean(peer);
+
rw_enter_write(&peer->p_device->d_lock);
fm_remove(&peer->p_device->d_peers, peer->p_id);
rw_exit_write(&peer->p_device->d_lock);
@@ -225,7 +228,7 @@ wg_device_ref_session(struct wg_device *dev, uint32_t id)
rw_enter_read(&dev->d_lock);
session = fm_lookup(&dev->d_sessions, id);
if (session)
- refcnt_take(&session->s_refcnt);
+ wg_session_ref(session);
rw_exit_read(&dev->d_lock);
return session;
}