aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-03 23:50:18 +0100
committerMatt Dunwoodie <ncon@mail.noconroy.net>2019-10-03 23:50:18 +0100
commit2ae00f8c6730a2a7342f099c5d40f44d138d46d2 (patch)
treec3bca0e5c0f7c4cb5964b35f57a9027aa46c3b75
parentA few small bugfixes (diff)
downloadwireguard-openbsd-2ae00f8c6730a2a7342f099c5d40f44d138d46d2.tar.xz
wireguard-openbsd-2ae00f8c6730a2a7342f099c5d40f44d138d46d2.zip
New idea again. Please bear with me
-rw-r--r--src/if_wg.c69
-rw-r--r--src/kern_wg.c4
-rw-r--r--src/wireguard.c65
-rw-r--r--src/wireguard.h11
4 files changed, 69 insertions, 80 deletions
diff --git a/src/if_wg.c b/src/if_wg.c
index a5c2d7f..092667c 100644
--- a/src/if_wg.c
+++ b/src/if_wg.c
@@ -66,7 +66,6 @@ struct wg_tag {
struct wg_route {
union wg_ip r_ip;
struct wg_peer *r_peer;
- /* TODO do we need r_sc? not used anywhere else */
struct wg_softc *r_sc;
struct mbuf_queue r_outgoing;
SLIST_HEAD(, wg_route_entry) r_aip;
@@ -145,9 +144,8 @@ 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 wg_softc_peer_clean(struct wg_peer *);
void wgattach(int);
int wg_clone_create(struct if_clone *, int);
@@ -162,6 +160,7 @@ void wg_ioctl_get_serv(struct wg_softc *, struct wg_get_serv *);
int wg_ioctl_get_peer(struct wg_softc *, struct wg_get_peer *);
int wg_ioctl(struct ifnet *, u_long, caddr_t);
+
MPQ_WORKER(wg_tx_slow_task_fn, wg_encrypt_hs, wg_output_deliver);
MPQ_WORKER(wg_tx_task_fn, wg_encrypt, wg_output_deliver);
MPQ_WORKER(wg_rx_slow_task_fn, wg_decrypt_hs, m_freem);
@@ -400,7 +399,7 @@ void
wg_route_send_keepalive(struct wg_route *route)
{
struct wg_session *session;
- if ((session = wg_peer_ks_session(route->r_peer)) != NULL) {
+ if ((session = wg_peer_last_session(route->r_peer)) != NULL) {
wg_route_queue(route, WG_PKT_TRANSPORT, session->s_local_id);
wg_session_put(session);
} else {
@@ -731,7 +730,7 @@ wg_output(struct ifnet *ifp, struct mbuf *m, struct sockaddr *sa,
BPF_DIRECTION_IN);
#endif
- if ((session = wg_peer_ks_session(route->r_peer)) == NULL) {
+ if ((session = wg_peer_last_session(route->r_peer)) == NULL) {
if (mq_push(&route->r_outgoing, m) != 0)
counters_inc(sc->sc_if.if_counters, ifc_oqdrops);
wg_peer_reset_attempts(route->r_peer);
@@ -904,7 +903,7 @@ wg_clone_create(struct if_clone * ifc, int unit)
inp->inp_upcall_arg = sc;
#endif
- wg_device_init(&sc->sc_dev, wg_peer_queue);
+ wg_device_init(&sc->sc_dev, wg_peer_queue, wg_softc_peer_clean, sc);
sc->sc_taskq = taskq_create("wg", ncpus, IPL_NET, TASKQ_MPSAFE);
task_set(&sc->sc_tx_task, wg_tx_task_fn, &sc->sc_tx_queue);
@@ -955,15 +954,11 @@ 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 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);
+ wg_device_destroy(&sc->sc_dev);
taskq_destroy(sc->sc_taskq);
@@ -1052,39 +1047,14 @@ wg_softc_peer_route_delete(struct wg_softc *sc, struct wg_peer *peer)
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)
+wg_softc_peer_clean(struct wg_peer *peer)
{
- DPRINTF(sc, "deleted peer: %x\n", peer->p_id);
+ struct wg_softc *sc = peer->p_device->d_arg;
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);
+ DPRINTF(sc, "deleted peer: %x\n", peer->p_id);
}
/* TODO flip set_peer -> peer_set */
@@ -1109,8 +1079,23 @@ 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)
- peer = wg_softc_peer_add(sc, &pub);
+ 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);
+ }
route = peer->p_arg;
@@ -1130,7 +1115,7 @@ wg_ioctl_set_peer(struct wg_softc *sc, u_long cmd, struct wg_set_peer *wsp)
break;
case SIOCDWGPEER:
wg_peer_put(peer);
- wg_softc_peer_delete(sc, peer);
+ wg_peer_drop(peer);
return WG_OK;
case SIOCSWGPEERAIP:
ret = wg_softc_route_add(sc, &wsp->sp_aip, route);
diff --git a/src/kern_wg.c b/src/kern_wg.c
index 8d3296f..185d2c6 100644
--- a/src/kern_wg.c
+++ b/src/kern_wg.c
@@ -195,6 +195,9 @@ fm_resize(struct fixed_map *fm, size_t size)
void
fm_destroy(struct fixed_map *fm)
{
+ struct map_item *item;
+ FM_FOREACH_FILLED(item, fm)
+ panic("non empty fixedmap");
free(fm->map, M_DEVBUF, 0);
}
@@ -243,6 +246,7 @@ fm_remove(struct fixed_map *fm, uint32_t k)
if (item->key == k) {
item->state = FM_ITEM_EMPTY;
item->value = NULL;
+ item->key = 0;
}
}
diff --git a/src/wireguard.c b/src/wireguard.c
index d1df72e..bd9e096 100644
--- a/src/wireguard.c
+++ b/src/wireguard.c
@@ -78,6 +78,9 @@ void wg_keypair_generate(struct wg_keypair *);
enum wg_error wg_msg_initiation_valid_mac2(struct wg_msg_initiation *, struct wg_cookie *);
enum wg_error wg_msg_response_valid_mac2(struct wg_msg_response *, struct wg_cookie *);
+struct wg_session *wg_peer_hs_session(struct wg_peer *);
+struct wg_session *wg_peer_ks_session(struct wg_peer *);
+
void wg_session_drop(struct wg_session *);
void wg_session_ref(struct wg_session *);
void wg_peer_ref(struct wg_peer *);
@@ -88,10 +91,13 @@ struct wg_session *wg_device_ref_session(struct wg_device *, uint32_t);
/* Some crappy API */
void
wg_device_init(struct wg_device *dev,
- void (*outq)(struct wg_peer *, enum wg_pkt_type, uint32_t))
+ void (*outq_fn)(struct wg_peer *, enum wg_pkt_type, uint32_t),
+ void (*cleanup_fn)(struct wg_peer *), void *arg)
{
bzero(dev, sizeof(*dev));
- dev->d_outq = outq;
+ dev->d_arg = arg;
+ dev->d_outq = outq_fn;
+ dev->d_cleanup = cleanup_fn;
fm_init(&dev->d_peers);
fm_init(&dev->d_sessions);
rw_init(&dev->d_lock, "wg_device");
@@ -109,7 +115,11 @@ wg_device_setkey(struct wg_device *dev, struct wg_privkey *key)
void
wg_device_destroy(struct wg_device *dev)
{
- /* TODO */
+ struct map_item *item;
+
+ FM_FOREACH_FILLED(item, &dev->d_peers)
+ wg_peer_drop(item->value);
+
fm_destroy(&dev->d_sessions);
fm_destroy(&dev->d_peers);
}
@@ -164,7 +174,7 @@ wg_device_ref_peerkey(struct wg_device *dev, struct wg_pubkey *key)
{
/* For the time being, we just iterate through peers to find the
* matching peer */
- struct wg_peer *peer;
+ struct wg_peer *peer = NULL;
struct map_item *item;
rw_enter_read(&dev->d_lock);
FM_FOREACH_FILLED(item, &dev->d_peers) {
@@ -211,6 +221,8 @@ void
wg_peer_drop(struct wg_peer *peer)
{
/* TODO prevent lock gap */
+ peer->p_device->d_cleanup(peer);
+
wg_peer_clean(peer);
rw_enter_write(&peer->p_device->d_lock);
@@ -352,35 +364,6 @@ wg_session_promote(struct wg_session *session)
wg_session_drop(old_session);
}
-struct wg_session *
-wg_peer_hs_session(struct wg_peer *peer)
-{
- struct wg_session *session;
-
- rw_enter_read(&peer->p_lock);
- session = peer->p_hs_session;
- if (session)
- wg_session_ref(session);
- rw_exit_read(&peer->p_lock);
- return session;
-}
-
-struct wg_session *
-wg_peer_ks_session(struct wg_peer *peer)
-{
- struct wg_session *session;
- rw_enter_read(&peer->p_lock);
- session = peer->p_ks_session;
- if (session != NULL &&
- (wg_timespec_timedout(&session->s_created, WG_REJECT_AFTER_TIME) ||
- session->s_keyset.k_txcounter > WG_REJECT_AFTER_MESSAGES))
- session = NULL;
- if (session != NULL)
- wg_session_ref(session);
- rw_exit_read(&peer->p_lock);
- return session;
-}
-
void
wg_peer_setshared(struct wg_peer *peer, struct wg_privkey *key)
{
@@ -408,6 +391,22 @@ wg_peer_last_handshake(struct wg_peer *peer)
return ret;
}
+struct wg_session *
+wg_peer_last_session(struct wg_peer *peer)
+{
+ struct wg_session *session;
+ rw_enter_read(&peer->p_lock);
+ session = peer->p_ks_session;
+ if (session != NULL &&
+ (wg_timespec_timedout(&session->s_created, WG_REJECT_AFTER_TIME) ||
+ session->s_keyset.k_txcounter > WG_REJECT_AFTER_MESSAGES))
+ session = NULL;
+ if (session != NULL)
+ wg_session_ref(session);
+ rw_exit_read(&peer->p_lock);
+ return session;
+}
+
/* Crypto */
enum wg_error
wg_device_rx_initiation(struct wg_device *dev, struct wg_msg_initiation *init,
diff --git a/src/wireguard.h b/src/wireguard.h
index 2add51d..8223d38 100644
--- a/src/wireguard.h
+++ b/src/wireguard.h
@@ -198,6 +198,8 @@ struct wg_peer {
};
struct wg_device {
+ void *d_arg;
+ void (*d_cleanup)(struct wg_peer *);
void (*d_outq)(struct wg_peer *, enum wg_pkt_type, uint32_t);
struct fixed_map d_peers;
struct fixed_map d_sessions;
@@ -243,7 +245,8 @@ static char *wg_error_str[] = {
/* WireGuard functions */
void wg_device_init(struct wg_device *,
- void (*)(struct wg_peer *, enum wg_pkt_type, uint32_t));
+ void (*)(struct wg_peer *, enum wg_pkt_type, uint32_t),
+ void (*)(struct wg_peer *), void *);
void wg_device_setkey(struct wg_device *, struct wg_privkey *);
void wg_device_destroy(struct wg_device *);
@@ -257,10 +260,9 @@ void wg_peer_reset_attempts(struct wg_peer *);
void wg_peer_clean(struct wg_peer *);
void wg_peer_setshared(struct wg_peer *, struct wg_privkey *);
void wg_peer_getshared(struct wg_peer *, struct wg_privkey *);
-struct timespec wg_peer_last_handshake(struct wg_peer *);
+struct timespec wg_peer_last_handshake(struct wg_peer *);
+struct wg_session *wg_peer_last_session(struct wg_peer *);
-struct wg_session *wg_peer_hs_session(struct wg_peer *);
-struct wg_session *wg_peer_ks_session(struct wg_peer *);
void wg_session_put(struct wg_session *);
enum wg_error wg_device_rx_initiation(struct wg_device *,
@@ -283,7 +285,6 @@ enum wg_error wg_device_tx_transport(struct wg_device *,
struct wg_msg_transport *, size_t, uint32_t,
struct wg_session **);
-
enum wg_error wg_msg_initiation_valid_mac2(struct wg_msg_initiation *,
struct wg_cookie *);
enum wg_error wg_msg_response_valid_mac2(struct wg_msg_response *,