1 /*-
2 * SPDX-License-Identifier: ISC
3 *
4 * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
5 * Copyright (C) 2019-2021 Matt Dunwoodie <ncon@noconroy.net>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20 #include "opt_inet6.h"
21
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/callout.h>
25 #include <sys/kernel.h>
26 #include <sys/lock.h>
27 #include <sys/malloc.h>
28 #include <sys/objcache.h>
29 #include <sys/queue.h>
30 #include <sys/socket.h>
31 #include <sys/time.h>
32 #include <netinet/in.h>
33
34 #include <crypto/chachapoly.h>
35 #include <crypto/blake2/blake2s.h>
36 #include <crypto/siphash/siphash.h>
37
38 #include "wg_cookie.h"
39
40 /* Constants for cookies */
41 #define COOKIE_KEY_SIZE BLAKE2S_KEY_SIZE
42 #define COOKIE_SECRET_SIZE 32
43 #define COOKIE_MAC1_KEY_LABEL "mac1----"
44 #define COOKIE_COOKIE_KEY_LABEL "cookie--"
45 #define COOKIE_SECRET_MAX_AGE 120
46 #define COOKIE_SECRET_LATENCY 5
47
48 /* Constants for initiation rate limiting */
49 #define RATELIMIT_SIZE (1 << 13)
50 #define RATELIMIT_MASK (RATELIMIT_SIZE - 1)
51 #define RATELIMIT_SIZE_MAX (RATELIMIT_SIZE * 8)
52 #define NSEC_PER_SEC 1000000000LL
53 #define INITIATIONS_PER_SECOND 20
54 #define INITIATIONS_BURSTABLE 5
55 #define INITIATION_COST (NSEC_PER_SEC / INITIATIONS_PER_SECOND)
56 #define TOKEN_MAX (INITIATION_COST * INITIATIONS_BURSTABLE)
57 #define ELEMENT_TIMEOUT 1 /* second */
58 #define IPV4_MASK_SIZE 4 /* Use all 4 bytes of IPv4 address */
59 #define IPV6_MASK_SIZE 8 /* Use top 8 bytes (/64) of IPv6 address */
60
61 struct cookie_maker {
62 uint8_t cm_mac1_key[COOKIE_KEY_SIZE];
63 uint8_t cm_cookie_key[COOKIE_KEY_SIZE];
64
65 struct lock cm_lock;
66 bool cm_cookie_valid;
67 uint8_t cm_cookie[COOKIE_COOKIE_SIZE];
68 struct timespec cm_cookie_birthdate; /* nanouptime */
69 bool cm_mac1_sent;
70 uint8_t cm_mac1_last[COOKIE_MAC_SIZE];
71 };
72
73 struct cookie_checker {
74 struct lock cc_key_lock;
75 uint8_t cc_mac1_key[COOKIE_KEY_SIZE];
76 uint8_t cc_cookie_key[COOKIE_KEY_SIZE];
77
78 struct lock cc_secret_mtx;
79 struct timespec cc_secret_birthdate; /* nanouptime */
80 uint8_t cc_secret[COOKIE_SECRET_SIZE];
81 };
82
83 struct ratelimit_key {
84 uint8_t ip[IPV6_MASK_SIZE];
85 };
86
87 struct ratelimit_entry {
88 LIST_ENTRY(ratelimit_entry) r_entry;
89 struct ratelimit_key r_key;
90 struct timespec r_last_time; /* nanouptime */
91 uint64_t r_tokens;
92 };
93
94 struct ratelimit {
95 uint8_t rl_secret[SIPHASH_KEY_LENGTH];
96 struct lock rl_mtx;
97 struct callout rl_gc;
98 LIST_HEAD(, ratelimit_entry) rl_table[RATELIMIT_SIZE];
99 size_t rl_table_num;
100 bool rl_initialized;
101 };
102
103
104 static void macs_mac1(struct cookie_macs *, const void *, size_t,
105 const uint8_t[COOKIE_KEY_SIZE]);
106 static void macs_mac2(struct cookie_macs *, const void *, size_t,
107 const uint8_t[COOKIE_COOKIE_SIZE]);
108 static void make_cookie(struct cookie_checker *,
109 uint8_t[COOKIE_COOKIE_SIZE],
110 const struct sockaddr *);
111 static void precompute_key(uint8_t[COOKIE_KEY_SIZE],
112 const uint8_t[COOKIE_INPUT_SIZE],
113 const uint8_t *, size_t);
114 static void ratelimit_init(struct ratelimit *);
115 static void ratelimit_deinit(struct ratelimit *);
116 static void ratelimit_gc_callout(void *);
117 static void ratelimit_gc_schedule(struct ratelimit *);
118 static void ratelimit_gc(struct ratelimit *, bool);
119 static int ratelimit_allow(struct ratelimit *, const struct sockaddr *);
120
121
122 static struct ratelimit ratelimit_v4;
123 #ifdef INET6
124 static struct ratelimit ratelimit_v6;
125 #endif
126
127 static struct objcache *ratelimit_zone;
128 static MALLOC_DEFINE(M_WG_RATELIMIT, "WG ratelimit", "wireguard ratelimit");
129 static MALLOC_DEFINE(M_WG_COOKIE, "WG cookie", "wireguard cookie");
130
131
132 static inline uint64_t
siphash13(const uint8_t key[SIPHASH_KEY_LENGTH],const void * src,size_t len)133 siphash13(const uint8_t key[SIPHASH_KEY_LENGTH], const void *src, size_t len)
134 {
135 SIPHASH_CTX ctx;
136 return SipHashX(&ctx, 1, 3, key, src, len);
137 }
138
139 static inline bool
timer_expired(const struct timespec * birthdate,time_t sec,long nsec)140 timer_expired(const struct timespec *birthdate, time_t sec, long nsec)
141 {
142 struct timespec uptime;
143 struct timespec expire = { .tv_sec = sec, .tv_nsec = nsec };
144
145 if (birthdate->tv_sec == 0 && birthdate->tv_nsec == 0)
146 return (true);
147
148 getnanouptime(&uptime);
149 timespecadd(birthdate, &expire, &expire);
150 return timespeccmp(&uptime, &expire, >);
151 }
152
153 /*----------------------------------------------------------------------------*/
154 /* Public Functions */
155
156 int
cookie_init(void)157 cookie_init(void)
158 {
159 ratelimit_zone = objcache_create_simple(
160 M_WG_RATELIMIT, sizeof(struct ratelimit_entry));
161 if (ratelimit_zone == NULL)
162 return (ENOMEM);
163
164 ratelimit_init(&ratelimit_v4);
165 #ifdef INET6
166 ratelimit_init(&ratelimit_v6);
167 #endif
168
169 return (0);
170 }
171
172 void
cookie_deinit(void)173 cookie_deinit(void)
174 {
175 ratelimit_deinit(&ratelimit_v4);
176 #ifdef INET6
177 ratelimit_deinit(&ratelimit_v6);
178 #endif
179 if (ratelimit_zone != NULL)
180 objcache_destroy(ratelimit_zone);
181 }
182
183 struct cookie_checker *
cookie_checker_alloc(void)184 cookie_checker_alloc(void)
185 {
186 struct cookie_checker *cc;
187
188 cc = kmalloc(sizeof(*cc), M_WG_COOKIE, M_WAITOK | M_ZERO);
189 lockinit(&cc->cc_key_lock, "cookie_checker_key", 0, 0);
190 lockinit(&cc->cc_secret_mtx, "cookie_checker_secret", 0, 0);
191
192 return (cc);
193 }
194
195 void
cookie_checker_free(struct cookie_checker * cc)196 cookie_checker_free(struct cookie_checker *cc)
197 {
198 lockuninit(&cc->cc_key_lock);
199 lockuninit(&cc->cc_secret_mtx);
200 explicit_bzero(cc, sizeof(*cc));
201 kfree(cc, M_WG_COOKIE);
202 }
203
204 void
cookie_checker_update(struct cookie_checker * cc,const uint8_t key[COOKIE_INPUT_SIZE])205 cookie_checker_update(struct cookie_checker *cc,
206 const uint8_t key[COOKIE_INPUT_SIZE])
207 {
208 lockmgr(&cc->cc_key_lock, LK_EXCLUSIVE);
209 if (key != NULL) {
210 precompute_key(cc->cc_mac1_key, key, COOKIE_MAC1_KEY_LABEL,
211 sizeof(COOKIE_MAC1_KEY_LABEL) - 1);
212 precompute_key(cc->cc_cookie_key, key, COOKIE_COOKIE_KEY_LABEL,
213 sizeof(COOKIE_COOKIE_KEY_LABEL) - 1);
214 } else {
215 bzero(cc->cc_mac1_key, sizeof(cc->cc_mac1_key));
216 bzero(cc->cc_cookie_key, sizeof(cc->cc_cookie_key));
217 }
218 lockmgr(&cc->cc_key_lock, LK_RELEASE);
219 }
220
221 void
cookie_checker_create_payload(struct cookie_checker * cc,const struct cookie_macs * macs,uint8_t nonce[COOKIE_NONCE_SIZE],uint8_t ecookie[COOKIE_ENCRYPTED_SIZE],const struct sockaddr * sa)222 cookie_checker_create_payload(struct cookie_checker *cc,
223 const struct cookie_macs *macs,
224 uint8_t nonce[COOKIE_NONCE_SIZE],
225 uint8_t ecookie[COOKIE_ENCRYPTED_SIZE],
226 const struct sockaddr *sa)
227 {
228 uint8_t cookie[COOKIE_COOKIE_SIZE];
229
230 make_cookie(cc, cookie, sa);
231 karc4random_buf(nonce, COOKIE_NONCE_SIZE);
232
233 lockmgr(&cc->cc_key_lock, LK_SHARED);
234 xchacha20poly1305_encrypt(ecookie, cookie, COOKIE_COOKIE_SIZE,
235 macs->mac1, COOKIE_MAC_SIZE, nonce,
236 cc->cc_cookie_key);
237 lockmgr(&cc->cc_key_lock, LK_RELEASE);
238
239 explicit_bzero(cookie, sizeof(cookie));
240 }
241
242 int
cookie_checker_validate_macs(struct cookie_checker * cc,const struct cookie_macs * macs,const void * buf,size_t len,bool check_cookie,const struct sockaddr * sa)243 cookie_checker_validate_macs(struct cookie_checker *cc,
244 const struct cookie_macs *macs,
245 const void *buf, size_t len, bool check_cookie,
246 const struct sockaddr *sa)
247 {
248 struct cookie_macs our_macs;
249 uint8_t cookie[COOKIE_COOKIE_SIZE];
250
251 /* Validate incoming MACs */
252 lockmgr(&cc->cc_key_lock, LK_SHARED);
253 macs_mac1(&our_macs, buf, len, cc->cc_mac1_key);
254 lockmgr(&cc->cc_key_lock, LK_RELEASE);
255
256 /* If mac1 is invald, we want to drop the packet */
257 if (timingsafe_bcmp(our_macs.mac1, macs->mac1, COOKIE_MAC_SIZE) != 0)
258 return (EINVAL);
259
260 if (check_cookie) {
261 make_cookie(cc, cookie, sa);
262 macs_mac2(&our_macs, buf, len, cookie);
263
264 /* If mac2 is invalid, we want to send a cookie response. */
265 if (timingsafe_bcmp(our_macs.mac2, macs->mac2, COOKIE_MAC_SIZE)
266 != 0)
267 return (EAGAIN);
268
269 /*
270 * If the mac2 is valid, we may want to rate limit the peer.
271 * ratelimit_allow() will return either 0 or ECONNREFUSED,
272 * implying there is no ratelimiting, or we should ratelimit
273 * (refuse), respectively.
274 */
275 if (sa->sa_family == AF_INET)
276 return ratelimit_allow(&ratelimit_v4, sa);
277 #ifdef INET6
278 else if (sa->sa_family == AF_INET6)
279 return ratelimit_allow(&ratelimit_v6, sa);
280 #endif
281 else
282 return (EAFNOSUPPORT);
283 }
284
285 return (0);
286 }
287
288 struct cookie_maker *
cookie_maker_alloc(const uint8_t key[COOKIE_INPUT_SIZE])289 cookie_maker_alloc(const uint8_t key[COOKIE_INPUT_SIZE])
290 {
291 struct cookie_maker *cm;
292
293 cm = kmalloc(sizeof(*cm), M_WG_COOKIE, M_WAITOK | M_ZERO);
294 precompute_key(cm->cm_mac1_key, key, COOKIE_MAC1_KEY_LABEL,
295 sizeof(COOKIE_MAC1_KEY_LABEL) - 1);
296 precompute_key(cm->cm_cookie_key, key, COOKIE_COOKIE_KEY_LABEL,
297 sizeof(COOKIE_COOKIE_KEY_LABEL) - 1);
298 lockinit(&cm->cm_lock, "cookie_maker", 0, 0);
299
300 return (cm);
301 }
302
303 void
cookie_maker_free(struct cookie_maker * cm)304 cookie_maker_free(struct cookie_maker *cm)
305 {
306 lockuninit(&cm->cm_lock);
307 explicit_bzero(cm, sizeof(*cm));
308 kfree(cm, M_WG_COOKIE);
309 }
310
311 int
cookie_maker_consume_payload(struct cookie_maker * cm,const uint8_t nonce[COOKIE_NONCE_SIZE],const uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])312 cookie_maker_consume_payload(struct cookie_maker *cm,
313 const uint8_t nonce[COOKIE_NONCE_SIZE],
314 const uint8_t ecookie[COOKIE_ENCRYPTED_SIZE])
315 {
316 uint8_t cookie[COOKIE_COOKIE_SIZE];
317 int ret = 0;
318
319 lockmgr(&cm->cm_lock, LK_SHARED);
320
321 if (!cm->cm_mac1_sent) {
322 ret = ETIMEDOUT;
323 goto out;
324 }
325
326 if (!xchacha20poly1305_decrypt(cookie, ecookie, COOKIE_ENCRYPTED_SIZE,
327 cm->cm_mac1_last, COOKIE_MAC_SIZE,
328 nonce, cm->cm_cookie_key)) {
329 ret = EINVAL;
330 goto out;
331 }
332
333 lockmgr(&cm->cm_lock, LK_RELEASE);
334 lockmgr(&cm->cm_lock, LK_EXCLUSIVE);
335
336 memcpy(cm->cm_cookie, cookie, COOKIE_COOKIE_SIZE);
337 getnanouptime(&cm->cm_cookie_birthdate);
338 cm->cm_cookie_valid = true;
339 cm->cm_mac1_sent = false;
340
341 out:
342 lockmgr(&cm->cm_lock, LK_RELEASE);
343 return (ret);
344 }
345
346 void
cookie_maker_mac(struct cookie_maker * cm,struct cookie_macs * macs,const void * buf,size_t len)347 cookie_maker_mac(struct cookie_maker *cm, struct cookie_macs *macs,
348 const void *buf, size_t len)
349 {
350 lockmgr(&cm->cm_lock, LK_EXCLUSIVE);
351
352 macs_mac1(macs, buf, len, cm->cm_mac1_key);
353 memcpy(cm->cm_mac1_last, macs->mac1, COOKIE_MAC_SIZE);
354 cm->cm_mac1_sent = true;
355
356 if (cm->cm_cookie_valid &&
357 !timer_expired(&cm->cm_cookie_birthdate,
358 COOKIE_SECRET_MAX_AGE - COOKIE_SECRET_LATENCY, 0)) {
359 macs_mac2(macs, buf, len, cm->cm_cookie);
360 } else {
361 bzero(macs->mac2, COOKIE_MAC_SIZE);
362 cm->cm_cookie_valid = false;
363 }
364
365 lockmgr(&cm->cm_lock, LK_RELEASE);
366 }
367
368 /*----------------------------------------------------------------------------*/
369 /* Private functions */
370
371 static void
precompute_key(uint8_t key[COOKIE_KEY_SIZE],const uint8_t input[COOKIE_INPUT_SIZE],const uint8_t * label,size_t label_len)372 precompute_key(uint8_t key[COOKIE_KEY_SIZE],
373 const uint8_t input[COOKIE_INPUT_SIZE],
374 const uint8_t *label, size_t label_len)
375 {
376 struct blake2s_state blake;
377
378 blake2s_init(&blake, COOKIE_KEY_SIZE);
379 blake2s_update(&blake, label, label_len);
380 blake2s_update(&blake, input, COOKIE_INPUT_SIZE);
381 blake2s_final(&blake, key);
382 }
383
384 static void
macs_mac1(struct cookie_macs * macs,const void * buf,size_t len,const uint8_t key[COOKIE_KEY_SIZE])385 macs_mac1(struct cookie_macs *macs, const void *buf, size_t len,
386 const uint8_t key[COOKIE_KEY_SIZE])
387 {
388 struct blake2s_state state;
389
390 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_KEY_SIZE);
391 blake2s_update(&state, buf, len);
392 blake2s_final(&state, macs->mac1);
393 }
394
395 static void
macs_mac2(struct cookie_macs * macs,const void * buf,size_t len,const uint8_t key[COOKIE_COOKIE_SIZE])396 macs_mac2(struct cookie_macs *macs, const void *buf, size_t len,
397 const uint8_t key[COOKIE_COOKIE_SIZE])
398 {
399 struct blake2s_state state;
400
401 blake2s_init_key(&state, COOKIE_MAC_SIZE, key, COOKIE_COOKIE_SIZE);
402 blake2s_update(&state, buf, len);
403 blake2s_update(&state, macs->mac1, COOKIE_MAC_SIZE);
404 blake2s_final(&state, macs->mac2);
405 }
406
407 static void
make_cookie(struct cookie_checker * cc,uint8_t cookie[COOKIE_COOKIE_SIZE],const struct sockaddr * sa)408 make_cookie(struct cookie_checker *cc, uint8_t cookie[COOKIE_COOKIE_SIZE],
409 const struct sockaddr *sa)
410 {
411 struct blake2s_state state;
412
413 lockmgr(&cc->cc_secret_mtx, LK_EXCLUSIVE);
414 if (timer_expired(&cc->cc_secret_birthdate,
415 COOKIE_SECRET_MAX_AGE, 0)) {
416 karc4random_buf(cc->cc_secret, COOKIE_SECRET_SIZE);
417 getnanouptime(&cc->cc_secret_birthdate);
418 }
419 blake2s_init_key(&state, COOKIE_COOKIE_SIZE, cc->cc_secret,
420 COOKIE_SECRET_SIZE);
421 lockmgr(&cc->cc_secret_mtx, LK_RELEASE);
422
423 if (sa->sa_family == AF_INET) {
424 const struct sockaddr_in *sin = (const void *)sa;
425 blake2s_update(&state, (const uint8_t *)&sin->sin_addr,
426 sizeof(sin->sin_addr));
427 blake2s_update(&state, (const uint8_t *)&sin->sin_port,
428 sizeof(sin->sin_port));
429 blake2s_final(&state, cookie);
430 #ifdef INET6
431 } else if (sa->sa_family == AF_INET6) {
432 const struct sockaddr_in6 *sin6 = (const void *)sa;
433 blake2s_update(&state, (const uint8_t *)&sin6->sin6_addr,
434 sizeof(sin6->sin6_addr));
435 blake2s_update(&state, (const uint8_t *)&sin6->sin6_port,
436 sizeof(sin6->sin6_port));
437 blake2s_final(&state, cookie);
438 #endif
439 } else {
440 karc4random_buf(cookie, COOKIE_COOKIE_SIZE);
441 }
442 }
443
444
445 static void
ratelimit_init(struct ratelimit * rl)446 ratelimit_init(struct ratelimit *rl)
447 {
448 size_t i;
449
450 bzero(rl, sizeof(*rl));
451 lockinit(&rl->rl_mtx, "ratelimit_lock", 0, 0);
452 callout_init_lk(&rl->rl_gc, &rl->rl_mtx);
453 karc4random_buf(rl->rl_secret, sizeof(rl->rl_secret));
454 for (i = 0; i < RATELIMIT_SIZE; i++)
455 LIST_INIT(&rl->rl_table[i]);
456 rl->rl_table_num = 0;
457
458 rl->rl_initialized = true;
459 }
460
461 static void
ratelimit_deinit(struct ratelimit * rl)462 ratelimit_deinit(struct ratelimit *rl)
463 {
464 if (!rl->rl_initialized)
465 return;
466
467 lockmgr(&rl->rl_mtx, LK_EXCLUSIVE);
468 callout_stop(&rl->rl_gc);
469 ratelimit_gc(rl, true);
470 lockmgr(&rl->rl_mtx, LK_RELEASE);
471 lockuninit(&rl->rl_mtx);
472
473 rl->rl_initialized = false;
474 }
475
476 static void
ratelimit_gc_callout(void * _rl)477 ratelimit_gc_callout(void *_rl)
478 {
479 /* callout will lock for us */
480 ratelimit_gc(_rl, false);
481 }
482
483 static void
ratelimit_gc_schedule(struct ratelimit * rl)484 ratelimit_gc_schedule(struct ratelimit *rl)
485 {
486 /*
487 * Trigger another GC if needed. There is no point calling GC if
488 * there are no entries in the table. We also want to ensure that
489 * GC occurs on a regular interval, so don't override a currently
490 * pending GC.
491 *
492 * In the case of a forced ratelimit_gc(), there will be no entries
493 * left so we will not schedule another GC.
494 */
495 if (rl->rl_table_num > 0 && !callout_pending(&rl->rl_gc))
496 callout_reset(&rl->rl_gc, ELEMENT_TIMEOUT * hz,
497 ratelimit_gc_callout, rl);
498 }
499
500 static void
ratelimit_gc(struct ratelimit * rl,bool force)501 ratelimit_gc(struct ratelimit *rl, bool force)
502 {
503 struct ratelimit_entry *r, *tr;
504 struct timespec expiry;
505 size_t i;
506
507 KKASSERT(lockstatus(&rl->rl_mtx, curthread) == LK_EXCLUSIVE);
508
509 if (rl->rl_table_num == 0)
510 return;
511
512 getnanouptime(&expiry);
513 expiry.tv_sec -= ELEMENT_TIMEOUT;
514
515 for (i = 0; i < RATELIMIT_SIZE; i++) {
516 LIST_FOREACH_MUTABLE(r, &rl->rl_table[i], r_entry, tr) {
517 if (force ||
518 timespeccmp(&r->r_last_time, &expiry, <)) {
519 rl->rl_table_num--;
520 LIST_REMOVE(r, r_entry);
521 objcache_put(ratelimit_zone, r);
522 }
523 }
524 }
525
526 ratelimit_gc_schedule(rl);
527 }
528
529 static int
ratelimit_allow(struct ratelimit * rl,const struct sockaddr * sa)530 ratelimit_allow(struct ratelimit *rl, const struct sockaddr *sa)
531 {
532 struct timespec diff;
533 struct ratelimit_entry *r;
534 struct ratelimit_key key = { 0 };
535 uint64_t bucket, tokens;
536 size_t len;
537 int ret = ECONNREFUSED;
538
539 if (sa->sa_family == AF_INET) {
540 len = IPV4_MASK_SIZE;
541 memcpy(key.ip, &((const struct sockaddr_in *)sa)->sin_addr,
542 len);
543 }
544 #ifdef INET6
545 else if (sa->sa_family == AF_INET6) {
546 len = IPV6_MASK_SIZE;
547 memcpy(key.ip, &((const struct sockaddr_in6 *)sa)->sin6_addr,
548 len);
549 }
550 #endif
551 else {
552 return (ret);
553 }
554
555 bucket = siphash13(rl->rl_secret, &key, len) & RATELIMIT_MASK;
556 lockmgr(&rl->rl_mtx, LK_EXCLUSIVE);
557
558 LIST_FOREACH(r, &rl->rl_table[bucket], r_entry) {
559 if (memcmp(&r->r_key, &key, len) != 0)
560 continue;
561
562 /*
563 * Found an entry for the endpoint. We apply standard token
564 * bucket, by calculating the time lapsed since last_time,
565 * adding that, ensuring that we cap the tokens at TOKEN_MAX.
566 * If the endpoint has no tokens left (i.e., tokens <
567 * INITIATION_COST) then we block the request. Otherwise, we
568 * subtract the INITITIATION_COST and return OK.
569 */
570 diff = r->r_last_time;
571 getnanouptime(&r->r_last_time);
572 timespecsub(&r->r_last_time, &diff, &diff);
573
574 tokens = r->r_tokens;
575 tokens += diff.tv_sec * NSEC_PER_SEC + diff.tv_nsec;
576 if (tokens > TOKEN_MAX)
577 tokens = TOKEN_MAX;
578
579 if (tokens >= INITIATION_COST) {
580 r->r_tokens = tokens - INITIATION_COST;
581 goto ok;
582 } else {
583 r->r_tokens = tokens;
584 goto error;
585 }
586 }
587
588 /*
589 * Didn't have an entry for the endpoint, so let's add one if we
590 * have space.
591 */
592 if (rl->rl_table_num >= RATELIMIT_SIZE_MAX)
593 goto error;
594
595 if ((r = objcache_get(ratelimit_zone, M_NOWAIT)) == NULL)
596 goto error;
597 bzero(r, sizeof(*r)); /* objcache_get() doesn't ensure M_ZERO. */
598
599 rl->rl_table_num++;
600
601 /* Insert the new entry and initialize it. */
602 LIST_INSERT_HEAD(&rl->rl_table[bucket], r, r_entry);
603 r->r_key = key;
604 r->r_tokens = TOKEN_MAX - INITIATION_COST;
605 getnanouptime(&r->r_last_time);
606
607 /* We've added a new entry; let's trigger GC. */
608 ratelimit_gc_schedule(rl);
609
610 ok:
611 ret = 0;
612 error:
613 lockmgr(&rl->rl_mtx, LK_RELEASE);
614 return (ret);
615 }
616
617
618 #ifdef WG_SELFTESTS
619 #include "selftest/cookie.c"
620 #endif /* WG_SELFTESTS */
621