aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Dunwoodie <ncon@noconroy.net>2020-05-18 22:31:01 +1000
committerMatt Dunwoodie <ncon@noconroy.net>2020-05-18 23:57:03 +1000
commit48eb55efef14523916b1c9f27d36d3a9ea48d621 (patch)
treed1b25c660ac42abb995129255d1aae13b8066cc5
parentLine up constants with Linux (diff)
downloadwireguard-openbsd-48eb55efef14523916b1c9f27d36d3a9ea48d621.tar.xz
wireguard-openbsd-48eb55efef14523916b1c9f27d36d3a9ea48d621.zip
Use distinct hashtables for rate limiting v4/v6
-rw-r--r--src/wg_cookie.c57
-rw-r--r--src/wg_cookie.h3
2 files changed, 43 insertions, 17 deletions
diff --git a/src/wg_cookie.c b/src/wg_cookie.c
index e451ecc..2761ff9 100644
--- a/src/wg_cookie.c
+++ b/src/wg_cookie.c
@@ -35,6 +35,8 @@ static void cookie_macs_mac2(struct cookie_macs *, const void *, size_t,
static int cookie_timer_expired(struct timespec *, time_t, long);
static void cookie_checker_make_cookie(struct cookie_checker *,
uint8_t[COOKIE_COOKIE_SIZE], struct sockaddr *);
+static int ratelimit_init(struct ratelimit *, struct pool *pool);
+static void ratelimit_deinit(struct ratelimit *);
static void ratelimit_gc(struct ratelimit *, int);
static int ratelimit_allow(struct ratelimit *, struct sockaddr *);
@@ -51,19 +53,19 @@ cookie_maker_init(struct cookie_maker *cp, uint8_t key[COOKIE_INPUT_SIZE])
int
cookie_checker_init(struct cookie_checker *cc, struct pool *pool)
{
- struct ratelimit *rl = &cc->cc_ratelimit;
+ int res = 0;
bzero(cc, sizeof(*cc));
rw_init(&cc->cc_key_lock, "cookie_checker_key");
rw_init(&cc->cc_secret_lock, "cookie_checker_secret");
- rw_init(&rl->rl_lock, "ratelimit_lock");
- arc4random_buf(&rl->rl_secret, sizeof(rl->rl_secret));
- rl->rl_table = hashinit(RATELIMIT_SIZE, M_DEVBUF, M_NOWAIT,
- &rl->rl_table_mask);
- rl->rl_pool = pool;
+ res = ratelimit_init(&cc->cc_ratelimit_v4, pool);
+ res = ratelimit_init(&cc->cc_ratelimit_v6, pool);
- return rl->rl_table == NULL ? ENOBUFS : 0;
+ if (res != 0)
+ cookie_checker_deinit(cc);
+
+ return res != 0 ? ENOBUFS : 0;
}
void
@@ -84,12 +86,8 @@ cookie_checker_update(struct cookie_checker *cc,
void
cookie_checker_deinit(struct cookie_checker *cc)
{
- struct ratelimit *rl = &cc->cc_ratelimit;
-
- rw_enter_write(&rl->rl_lock);
- ratelimit_gc(rl, 1);
- hashfree(rl->rl_table, RATELIMIT_SIZE, M_DEVBUF);
- rw_exit_write(&rl->rl_lock);
+ ratelimit_deinit(&cc->cc_ratelimit_v4);
+ ratelimit_deinit(&cc->cc_ratelimit_v6);
}
void
@@ -183,11 +181,16 @@ cookie_checker_validate_macs(struct cookie_checker *cc, struct cookie_macs *cm,
if (timingsafe_bcmp(our_cm.mac2, cm->mac2, COOKIE_MAC_SIZE) != 0)
return EAGAIN;
- /* If the mac2 is valid, we may want rate limit the peer.
+ /* If the mac2 is valid, we may want rate limit the peer.
* ratelimit_allow will return either 0 or ECONNREFUSED,
* implying there is no ratelimiting, or we should ratelimit
* (refuse) respectively. */
- return ratelimit_allow(&cc->cc_ratelimit, sa);
+ if (sa->sa_family == AF_INET)
+ return ratelimit_allow(&cc->cc_ratelimit_v4, sa);
+ else if (sa->sa_family == AF_INET6)
+ return ratelimit_allow(&cc->cc_ratelimit_v6, sa);
+ else
+ return EAFNOSUPPORT;
}
return 0;
}
@@ -259,7 +262,7 @@ cookie_checker_make_cookie(struct cookie_checker *cc,
if (sa->sa_family == AF_INET) {
blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_addr,
sizeof(struct in_addr));
- blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port,
+ blake2s_update(&state, (uint8_t *)&satosin(sa)->sin_port,
sizeof(in_port_t));
blake2s_final(&state, cookie, COOKIE_COOKIE_SIZE);
} else if (sa->sa_family == AF_INET6) {
@@ -273,6 +276,28 @@ cookie_checker_make_cookie(struct cookie_checker *cc,
}
}
+static int
+ratelimit_init(struct ratelimit *rl, struct pool *pool)
+{
+ rw_init(&rl->rl_lock, "ratelimit_lock");
+ arc4random_buf(&rl->rl_secret, sizeof(rl->rl_secret));
+ rl->rl_table = hashinit(RATELIMIT_SIZE, M_DEVBUF, M_NOWAIT,
+ &rl->rl_table_mask);
+ rl->rl_pool = pool;
+ return rl->rl_table == NULL ? ENOBUFS : 0;
+}
+
+static void
+ratelimit_deinit(struct ratelimit *rl)
+{
+ rw_enter_write(&rl->rl_lock);
+ if (rl->rl_table != NULL) {
+ ratelimit_gc(rl, 1);
+ hashfree(rl->rl_table, RATELIMIT_SIZE, M_DEVBUF);
+ }
+ rw_exit_write(&rl->rl_lock);
+}
+
static void
ratelimit_gc(struct ratelimit *rl, int force)
{
diff --git a/src/wg_cookie.h b/src/wg_cookie.h
index 88cd00d..2318062 100644
--- a/src/wg_cookie.h
+++ b/src/wg_cookie.h
@@ -144,7 +144,8 @@ struct cookie_maker {
};
struct cookie_checker {
- struct ratelimit cc_ratelimit;
+ struct ratelimit cc_ratelimit_v4;
+ struct ratelimit cc_ratelimit_v6;
struct rwlock cc_key_lock;
uint8_t cc_mac1_key[COOKIE_KEY_SIZE];