1 /*- 2 * SPDX-License-Identifier: MIT 3 * 4 * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 5 * Copyright (c) 2024 Aaron LI <aly@aaronly.me> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining 8 * a copy of this software and associated documentation files (the 9 * "Software"), to deal in the Software without restriction, including 10 * without limitation the rights to use, copy, modify, merge, publish, 11 * distribute, sublicense, and/or sell copies of the Software, and to 12 * permit persons to whom the Software is furnished to do so, subject 13 * to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be 16 * included in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 21 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 */ 26 27 static bool 28 test_aip_init(struct wg_softc *sc) 29 { 30 memset(sc, 0, sizeof(*sc)); 31 32 lockinit(&sc->sc_aip_lock, "aip_lock (test)", 0, 0); 33 34 if (!rn_inithead(&sc->sc_aip4, wg_maskhead, 35 offsetof(struct aip_addr, in))) 36 return (false); 37 if (!rn_inithead(&sc->sc_aip6, wg_maskhead, 38 offsetof(struct aip_addr, in6))) 39 return (false); 40 41 return (true); 42 } 43 44 static void 45 test_aip_deinit(struct wg_softc *sc) 46 { 47 if (sc->sc_aip4 != NULL) { 48 rn_freehead(sc->sc_aip4); 49 sc->sc_aip4 = NULL; 50 } 51 if (sc->sc_aip6 != NULL) { 52 rn_freehead(sc->sc_aip6); 53 sc->sc_aip6 = NULL; 54 } 55 56 lockuninit(&sc->sc_aip_lock); 57 } 58 59 static struct wg_peer * 60 test_aip_peer_new(struct wg_softc *sc) 61 { 62 struct wg_peer *peer; 63 64 peer = kmalloc(sizeof(*peer), M_WG, M_NOWAIT | M_ZERO); 65 if (peer == NULL) 66 return (NULL); 67 68 peer->p_sc = sc; 69 LIST_INIT(&peer->p_aips); 70 peer->p_aips_num = 0; 71 /* 72 * WARNING: 73 * wg_aip_lookup() will reference 'peer->p_remote', so this member 74 * cannot be NULL. Do a hack and just assign itself to it, so as 75 * no need to bother with creating noise_local and noise_remote. 76 * This is kind of dangerous, but probably fine. 77 */ 78 peer->p_remote = (struct noise_remote *)peer; 79 80 return (peer); 81 } 82 83 #ifdef WG_ALLOWEDIPS_RANDOMIZED_TEST 84 85 struct horrible_allowedips { 86 LIST_HEAD(, horrible_allowedips_node) head; 87 }; 88 89 struct horrible_allowedips_node { 90 LIST_ENTRY(horrible_allowedips_node) entry; 91 struct aip_addr ip; 92 struct aip_addr mask; 93 uint8_t ip_version; 94 void *value; 95 }; 96 97 static void 98 horrible_allowedips_init(struct horrible_allowedips *table) 99 { 100 LIST_INIT(&table->head); 101 } 102 103 static void 104 horrible_allowedips_flush(struct horrible_allowedips *table) 105 { 106 struct horrible_allowedips_node *node, *node_; 107 108 LIST_FOREACH_MUTABLE(node, &table->head, entry, node_) { 109 LIST_REMOVE(node, entry); 110 kfree(node, M_WG); 111 } 112 } 113 114 static inline void 115 horrible_cidr_to_mask(uint8_t cidr, struct aip_addr *mask) 116 { 117 uint8_t n; 118 119 memset(&mask->in6, 0x00, sizeof(mask->in6)); 120 memset(&mask->in6, 0xff, cidr / 8); 121 if ((n = cidr % 32) != 0) 122 mask->ip6[cidr / 32] = 123 (uint32_t)htonl((0xFFFFFFFFUL << (32 - n)) & 0xFFFFFFFFUL); 124 } 125 126 static inline uint8_t 127 horrible_mask_to_cidr(const struct aip_addr *mask) 128 { 129 return (bitcount32(mask->ip6[0]) + 130 bitcount32(mask->ip6[1]) + 131 bitcount32(mask->ip6[2]) + 132 bitcount32(mask->ip6[3])); 133 } 134 135 static inline void 136 horrible_mask_self(struct horrible_allowedips_node *node) 137 { 138 KKASSERT(node->ip_version == 4 || node->ip_version == 6); 139 140 if (node->ip_version == 4) { 141 node->ip.ip &= node->mask.ip; 142 } else { 143 node->ip.ip6[0] &= node->mask.ip6[0]; 144 node->ip.ip6[1] &= node->mask.ip6[1]; 145 node->ip.ip6[2] &= node->mask.ip6[2]; 146 node->ip.ip6[3] &= node->mask.ip6[3]; 147 } 148 } 149 150 static inline bool 151 horrible_match_v4(const struct horrible_allowedips_node *node, 152 const struct in_addr *ip) 153 { 154 return ((ip->s_addr & node->mask.ip) == node->ip.ip); 155 } 156 157 static inline bool 158 horrible_match_v6(const struct horrible_allowedips_node *node, 159 const struct in6_addr *ip) 160 { 161 #define IP6MATCH_SEG(ip, node, n) \ 162 ((ip->__u6_addr.__u6_addr32[n] & node->mask.ip6[n]) \ 163 == node->ip.ip6[n]) 164 165 return (IP6MATCH_SEG(ip, node, 0) && 166 IP6MATCH_SEG(ip, node, 1) && 167 IP6MATCH_SEG(ip, node, 2) && 168 IP6MATCH_SEG(ip, node, 3)); 169 170 #undef IP6MATCH_SEG 171 } 172 173 static void 174 horrible_insert_ordered(struct horrible_allowedips *table, 175 struct horrible_allowedips_node *node) 176 { 177 struct horrible_allowedips_node *other, *where; 178 uint8_t my_cidr; 179 180 other = where = NULL; 181 my_cidr = horrible_mask_to_cidr(&node->mask); 182 183 LIST_FOREACH(other, &table->head, entry) { 184 if (!memcmp(&other->mask, &node->mask, 185 sizeof(struct aip_addr)) && 186 !memcmp(&other->ip, &node->ip, 187 sizeof(struct aip_addr)) && 188 other->ip_version == node->ip_version) 189 { 190 other->value = node->value; 191 kfree(node, M_WG); 192 return; 193 } 194 where = other; 195 if (horrible_mask_to_cidr(&other->mask) <= my_cidr) 196 break; 197 } 198 199 if (other == NULL && where == NULL) 200 LIST_INSERT_HEAD(&table->head, node, entry); 201 else if (other == NULL) 202 LIST_INSERT_AFTER(where, node, entry); 203 else 204 LIST_INSERT_BEFORE(where, node, entry); 205 } 206 207 static int 208 horrible_allowedips_insert_v4(struct horrible_allowedips *table, 209 const void *ip, uint8_t cidr, void *value) 210 { 211 struct horrible_allowedips_node *node; 212 213 node = kmalloc(sizeof(*node), M_WG, M_NOWAIT | M_ZERO); 214 if (node == NULL) 215 return (ENOMEM); 216 217 node->ip.in = *(const struct in_addr *)ip; 218 horrible_cidr_to_mask(cidr, &node->mask); 219 node->ip_version = 4; 220 node->value = value; 221 222 horrible_mask_self(node); 223 horrible_insert_ordered(table, node); 224 225 return (0); 226 } 227 228 static int 229 horrible_allowedips_insert_v6(struct horrible_allowedips *table, 230 const void *ip, uint8_t cidr, void *value) 231 { 232 struct horrible_allowedips_node *node; 233 234 node = kmalloc(sizeof(*node), M_WG, M_NOWAIT | M_ZERO); 235 if (node == NULL) 236 return (ENOMEM); 237 238 node->ip.in6 = *(const struct in6_addr *)ip; 239 horrible_cidr_to_mask(cidr, &node->mask); 240 node->ip_version = 6; 241 node->value = value; 242 243 horrible_mask_self(node); 244 horrible_insert_ordered(table, node); 245 246 return (0); 247 } 248 249 static void * 250 horrible_allowedips_lookup_v4(const struct horrible_allowedips *table, 251 const void *ip) 252 { 253 struct horrible_allowedips_node *node; 254 void *ret = NULL; 255 256 LIST_FOREACH(node, &table->head, entry) { 257 if (node->ip_version != 4) 258 continue; 259 if (horrible_match_v4(node, (const struct in_addr *)ip)) { 260 ret = node->value; 261 break; 262 } 263 } 264 265 return (ret); 266 } 267 268 static void * 269 horrible_allowedips_lookup_v6(const struct horrible_allowedips *table, 270 const void *ip) 271 { 272 struct horrible_allowedips_node *node; 273 void *ret = NULL; 274 275 LIST_FOREACH(node, &table->head, entry) { 276 if (node->ip_version != 6) 277 continue; 278 if (horrible_match_v6(node, (const struct in6_addr *)ip)) { 279 ret = node->value; 280 break; 281 } 282 } 283 284 return (ret); 285 } 286 287 #define T_NUM_PEERS 2000 288 #define T_NUM_RAND_ROUTES 400 289 #define T_NUM_MUTATED_ROUTES 100 290 #define T_NUM_QUERIES (T_NUM_RAND_ROUTES * T_NUM_MUTATED_ROUTES * 30) 291 292 static bool 293 wg_allowedips_randomized_test(void) 294 { 295 struct horrible_allowedips h; 296 struct wg_softc sc; 297 struct wg_peer **peers, *peer; 298 unsigned int i, j, k, p, nextp, mutate_amount; 299 uint8_t ip[16], mutated[16], mutate_mask[16], cidr; 300 bool ret = false; 301 302 peers = NULL; 303 304 horrible_allowedips_init(&h); 305 if (!test_aip_init(&sc)) { 306 kprintf("%s: FAIL: test_aip_init\n", __func__); 307 goto error; 308 } 309 peers = kmalloc(T_NUM_PEERS * sizeof(*peers), M_WG, M_NOWAIT | M_ZERO); 310 if (peers == NULL) { 311 kprintf("%s: FAIL: peers malloc\n", __func__); 312 goto error; 313 } 314 for (i = 0; i < T_NUM_PEERS; ++i) { 315 peers[i] = test_aip_peer_new(&sc); 316 if (peers[i] == NULL) { 317 kprintf("%s: FAIL: peer_new\n", __func__); 318 goto error; 319 } 320 } 321 322 kprintf("%s: inserting v4 routes: ", __func__); 323 for (i = 0, nextp = 0; i < T_NUM_RAND_ROUTES; ++i) { 324 if ((p = i * 100 / T_NUM_RAND_ROUTES) == nextp) { 325 kprintf("%d%%...", p); 326 nextp += 10; 327 } 328 karc4random_buf(ip, 4); 329 cidr = karc4random_uniform(32) + 1; 330 peer = peers[karc4random_uniform(T_NUM_PEERS)]; 331 if (wg_aip_add(&sc, peer, AF_INET, ip, cidr)) { 332 kprintf("%s: FAIL: wg_aip_add(v4)\n", __func__); 333 goto error; 334 } 335 if (horrible_allowedips_insert_v4(&h, ip, cidr, peer)) { 336 kprintf("%s: FAIL: insert_v4\n", __func__); 337 goto error; 338 } 339 for (j = 0; j < T_NUM_MUTATED_ROUTES; ++j) { 340 memcpy(mutated, ip, 4); 341 karc4random_buf(mutate_mask, 4); 342 mutate_amount = karc4random_uniform(32); 343 for (k = 0; k < mutate_amount / 8; ++k) 344 mutate_mask[k] = 0xff; 345 mutate_mask[k] = 346 0xff << ((8 - (mutate_amount % 8)) % 8); 347 for (; k < 4; ++k) 348 mutate_mask[k] = 0; 349 for (k = 0; k < 4; ++k) { 350 mutated[k] = (mutated[k] & mutate_mask[k]) | 351 (~mutate_mask[k] & 352 karc4random_uniform(256)); 353 } 354 cidr = karc4random_uniform(32) + 1; 355 peer = peers[karc4random_uniform(T_NUM_PEERS)]; 356 if (wg_aip_add(&sc, peer, AF_INET, mutated, cidr)) { 357 kprintf("%s: FAIL: wg_aip_add(v4)\n", __func__); 358 goto error; 359 } 360 if (horrible_allowedips_insert_v4(&h, mutated, cidr, 361 peer)) { 362 kprintf("%s: FAIL: insert_v4\n", __func__); 363 goto error; 364 } 365 } 366 } 367 kprintf("done\n"); 368 369 kprintf("%s: v4 looking up: ", __func__); 370 for (i = 0, nextp = 0; i < T_NUM_QUERIES; ++i) { 371 if ((p = i * 100 / T_NUM_QUERIES) == nextp) { 372 kprintf("%d%%...", p); 373 nextp += 5; 374 } 375 karc4random_buf(ip, 4); 376 if (wg_aip_lookup(&sc, AF_INET, ip) != 377 horrible_allowedips_lookup_v4(&h, ip)) { 378 kprintf("%s: FAIL: lookup_v4\n", __func__); 379 goto error; 380 } 381 } 382 kprintf("pass\n"); 383 384 /* 385 * Flush existing v4 routes for the following v6 test so as to 386 * significantly reduce the test time. 387 */ 388 horrible_allowedips_flush(&h); 389 390 kprintf("%s: inserting v6 routes: ", __func__); 391 for (i = 0, nextp = 0; i < T_NUM_RAND_ROUTES; ++i) { 392 if ((p = i * 100 / T_NUM_RAND_ROUTES) == nextp) { 393 kprintf("%d%%...", p); 394 nextp += 10; 395 } 396 karc4random_buf(ip, 16); 397 cidr = karc4random_uniform(128) + 1; 398 peer = peers[karc4random_uniform(T_NUM_PEERS)]; 399 if (wg_aip_add(&sc, peer, AF_INET6, ip, cidr)) { 400 kprintf("%s: FAIL: wg_aip_add(v6)\n", __func__); 401 goto error; 402 } 403 if (horrible_allowedips_insert_v6(&h, ip, cidr, peer)) { 404 kprintf("%s: FAIL: insert_v6\n", __func__); 405 goto error; 406 } 407 for (j = 0; j < T_NUM_MUTATED_ROUTES; ++j) { 408 memcpy(mutated, ip, 16); 409 karc4random_buf(mutate_mask, 16); 410 mutate_amount = karc4random_uniform(128); 411 for (k = 0; k < mutate_amount / 8; ++k) 412 mutate_mask[k] = 0xff; 413 mutate_mask[k] = 414 0xff << ((8 - (mutate_amount % 8)) % 8); 415 for (; k < 4; ++k) 416 mutate_mask[k] = 0; 417 for (k = 0; k < 4; ++k) { 418 mutated[k] = (mutated[k] & mutate_mask[k]) | 419 (~mutate_mask[k] & 420 karc4random_uniform(256)); 421 } 422 cidr = karc4random_uniform(128) + 1; 423 peer = peers[karc4random_uniform(T_NUM_PEERS)]; 424 if (wg_aip_add(&sc, peer, AF_INET6, mutated, cidr)) { 425 kprintf("%s: FAIL: wg_aip_add(v6)\n", __func__); 426 goto error; 427 } 428 if (horrible_allowedips_insert_v6(&h, mutated, cidr, 429 peer)) { 430 kprintf("%s: FAIL: insert_v6\n", __func__); 431 goto error; 432 } 433 } 434 } 435 kprintf("done\n"); 436 437 kprintf("%s: v6 looking up: ", __func__); 438 for (i = 0, nextp = 0; i < T_NUM_QUERIES; ++i) { 439 if ((p = i * 100 / T_NUM_QUERIES) == nextp) { 440 kprintf("%d%%...", p); 441 nextp += 5; 442 } 443 karc4random_buf(ip, 16); 444 if (wg_aip_lookup(&sc, AF_INET6, ip) != 445 horrible_allowedips_lookup_v6(&h, ip)) { 446 kprintf("%s: FAIL: lookup_v6\n", __func__); 447 goto error; 448 } 449 } 450 kprintf("pass\n"); 451 452 ret = true; 453 kprintf("%s: pass\n", __func__); 454 455 error: 456 horrible_allowedips_flush(&h); 457 if (peers != NULL) { 458 for (i = 0; i < T_NUM_PEERS; ++i) { 459 if (peers[i] != NULL) { 460 wg_aip_remove_all(&sc, peers[i]); 461 kfree(peers[i], M_WG); 462 } 463 } 464 kfree(peers, M_WG); 465 } 466 test_aip_deinit(&sc); 467 468 return (ret); 469 } 470 471 #else /* !WG_ALLOWEDIPS_RANDOMIZED_TEST */ 472 473 static inline bool 474 wg_allowedips_randomized_test(void) 475 { 476 return (true); 477 } 478 479 #endif /* WG_ALLOWEDIPS_RANDOMIZED_TEST */ 480 481 static inline void * 482 ip_make_v4(uint8_t a, uint8_t b, uint8_t c, uint8_t d) 483 { 484 static struct in_addr ip; 485 uint8_t *split = (uint8_t *)&ip; 486 487 split[0] = a; 488 split[1] = b; 489 split[2] = c; 490 split[3] = d; 491 492 return (void *)&ip; 493 } 494 495 static inline void * 496 ip_make_v6(uint32_t a, uint32_t b, uint32_t c, uint32_t d) 497 { 498 static struct in6_addr ip; 499 uint32_t *split = ip.__u6_addr.__u6_addr32; 500 501 split[0] = htobe32(a); 502 split[1] = htobe32(b); 503 split[2] = htobe32(c); 504 split[3] = htobe32(d); 505 506 return (void *)&ip; 507 } 508 509 static inline bool 510 ip_equal_v4(const void *ip, uint8_t a, uint8_t b, uint8_t c, uint8_t d) 511 { 512 return (memcmp(ip, ip_make_v4(a, b, c, d), 4) == 0); 513 } 514 515 static inline bool 516 ip_equal_v6(const void *ip, uint32_t a, uint32_t b, uint32_t c, uint32_t d) 517 { 518 return (memcmp(ip, ip_make_v6(a, b, c, d), 16) == 0); 519 } 520 521 #define T_INSERT(n, peer, af, ipa, ipb, ipc, ipd, cidr) do { \ 522 const void *_ip = (af == AF_INET) ? \ 523 ip_make_v4(ipa, ipb, ipc, ipd) : \ 524 ip_make_v6(ipa, ipb, ipc, ipd); \ 525 if (wg_aip_add(&sc, peer, af, _ip, cidr)) { \ 526 kprintf("%s: insert #%d: FAIL\n", __func__, n); \ 527 success = false; \ 528 } \ 529 } while (0) 530 531 #define T_LOOKUP(n, op, peer, af, ipa, ipb, ipc, ipd) do { \ 532 const void *_ip = (af == AF_INET) ? \ 533 ip_make_v4(ipa, ipb, ipc, ipd) : \ 534 ip_make_v6(ipa, ipb, ipc, ipd); \ 535 if (!(wg_aip_lookup(&sc, af, _ip) op peer)) { \ 536 kprintf("%s: lookup #%d: FAIL\n", __func__, n); \ 537 success = false; \ 538 } \ 539 } while (0) 540 541 #define T_NEW_PEER(p) do { \ 542 if ((p = test_aip_peer_new(&sc)) == NULL) { \ 543 kprintf("%s: FAIL: peer_new(%s)\n", __func__, #p); \ 544 goto error; \ 545 } \ 546 } while (0) 547 548 #define T_NEW_PEERS() do { \ 549 T_NEW_PEER(a); \ 550 T_NEW_PEER(b); \ 551 T_NEW_PEER(c); \ 552 T_NEW_PEER(d); \ 553 T_NEW_PEER(e); \ 554 T_NEW_PEER(f); \ 555 T_NEW_PEER(g); \ 556 T_NEW_PEER(h); \ 557 } while (0) 558 559 #define T_CLEAR_PEERS() do { \ 560 if (a != NULL) \ 561 wg_aip_remove_all(&sc, a); \ 562 if (b != NULL) \ 563 wg_aip_remove_all(&sc, b); \ 564 if (c != NULL) \ 565 wg_aip_remove_all(&sc, c); \ 566 if (d != NULL) \ 567 wg_aip_remove_all(&sc, d); \ 568 if (e != NULL) \ 569 wg_aip_remove_all(&sc, e); \ 570 if (f != NULL) \ 571 wg_aip_remove_all(&sc, f); \ 572 if (g != NULL) \ 573 wg_aip_remove_all(&sc, g); \ 574 if (h != NULL) \ 575 wg_aip_remove_all(&sc, h); \ 576 } while (0) 577 578 #define T_FREE_PEERS() do { \ 579 T_CLEAR_PEERS(); \ 580 if (a != NULL) \ 581 kfree(a, M_WG); \ 582 if (b != NULL) \ 583 kfree(b, M_WG); \ 584 if (c != NULL) \ 585 kfree(c, M_WG); \ 586 if (d != NULL) \ 587 kfree(d, M_WG); \ 588 if (e != NULL) \ 589 kfree(e, M_WG); \ 590 if (f != NULL) \ 591 kfree(f, M_WG); \ 592 if (g != NULL) \ 593 kfree(g, M_WG); \ 594 if (h != NULL) \ 595 kfree(h, M_WG); \ 596 } while (0) 597 598 static bool 599 wg_allowedips_lookup_test(void) 600 { 601 struct wg_softc sc; 602 struct wg_peer *a = NULL, *b = NULL, *c = NULL, *d = NULL; 603 struct wg_peer *e = NULL, *f = NULL, *g = NULL, *h = NULL; 604 struct wg_aip *aip; 605 size_t i, count; 606 bool found_a, found_b, found_c, found_d, found_e, found_other; 607 bool success = false; 608 609 if (!test_aip_init(&sc)) { 610 kprintf("%s: FAIL: test_aip_init\n", __func__); 611 goto error; 612 } 613 614 T_NEW_PEERS(); 615 616 T_INSERT( 1, a, AF_INET, 192, 168, 4, 0, 24); 617 T_INSERT( 2, b, AF_INET, 192, 168, 4, 4, 32); 618 T_INSERT( 3, c, AF_INET, 192, 168, 0, 0, 16); 619 T_INSERT( 4, d, AF_INET, 192, 95, 5, 64, 27); 620 /* replaces previous entry, and maskself is required */ 621 T_INSERT( 5, c, AF_INET, 192, 95, 5, 65, 27); 622 T_INSERT( 6, d, AF_INET6, 623 0x26075300, 0x60006b00, 0, 0xc05f0543, 128); 624 T_INSERT( 7, c, AF_INET6, 625 0x26075300, 0x60006b00, 0, 0, 64); 626 T_INSERT( 8, e, AF_INET, 0, 0, 0, 0, 0); 627 T_INSERT( 9, e, AF_INET6, 0, 0, 0, 0, 0); 628 /* replaces previous entry */ 629 T_INSERT(10, f, AF_INET6, 0, 0, 0, 0, 0); 630 T_INSERT(11, g, AF_INET6, 0x24046800, 0, 0, 0, 32); 631 /* maskself is required */ 632 T_INSERT(12, h, AF_INET6, 633 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 64); 634 T_INSERT(13, a, AF_INET6, 635 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 128); 636 T_INSERT(14, c, AF_INET6, 637 0x24446800, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128); 638 T_INSERT(15, b, AF_INET6, 639 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98); 640 T_INSERT(16, g, AF_INET, 64, 15, 112, 0, 20); 641 /* maskself is required */ 642 T_INSERT(17, h, AF_INET, 64, 15, 123, 211, 25); 643 T_INSERT(18, a, AF_INET, 10, 0, 0, 0, 25); 644 T_INSERT(19, b, AF_INET, 10, 0, 0, 128, 25); 645 T_INSERT(20, a, AF_INET, 10, 1, 0, 0, 30); 646 T_INSERT(21, b, AF_INET, 10, 1, 0, 4, 30); 647 T_INSERT(22, c, AF_INET, 10, 1, 0, 8, 29); 648 T_INSERT(23, d, AF_INET, 10, 1, 0, 16, 29); 649 650 success = true; 651 652 T_LOOKUP( 1, ==, a, AF_INET, 192, 168, 4, 20); 653 T_LOOKUP( 2, ==, a, AF_INET, 192, 168, 4, 0); 654 T_LOOKUP( 3, ==, b, AF_INET, 192, 168, 4, 4); 655 T_LOOKUP( 4, ==, c, AF_INET, 192, 168, 200, 182); 656 T_LOOKUP( 5, ==, c, AF_INET, 192, 95, 5, 68); 657 T_LOOKUP( 6, ==, e, AF_INET, 192, 95, 5, 96); 658 T_LOOKUP( 7, ==, d, AF_INET6, 659 0x26075300, 0x60006b00, 0, 0xc05f0543); 660 T_LOOKUP( 8, ==, c, AF_INET6, 661 0x26075300, 0x60006b00, 0, 0xc02e01ee); 662 T_LOOKUP( 9, ==, f, AF_INET6, 663 0x26075300, 0x60006b01, 0, 0); 664 T_LOOKUP(10, ==, g, AF_INET6, 665 0x24046800, 0x40040806, 0, 0x1006); 666 T_LOOKUP(11, ==, g, AF_INET6, 667 0x24046800, 0x40040806, 0x1234, 0x5678); 668 T_LOOKUP(12, ==, f, AF_INET6, 669 0x240467ff, 0x40040806, 0x1234, 0x5678); 670 T_LOOKUP(13, ==, f, AF_INET6, 671 0x24046801, 0x40040806, 0x1234, 0x5678); 672 T_LOOKUP(14, ==, h, AF_INET6, 673 0x24046800, 0x40040800, 0x1234, 0x5678); 674 T_LOOKUP(15, ==, h, AF_INET6, 675 0x24046800, 0x40040800, 0, 0); 676 T_LOOKUP(16, ==, h, AF_INET6, 677 0x24046800, 0x40040800, 0x10101010, 0x10101010); 678 T_LOOKUP(17, ==, a, AF_INET6, 679 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef); 680 T_LOOKUP(18, ==, g, AF_INET, 64, 15, 116, 26); 681 T_LOOKUP(19, ==, g, AF_INET, 64, 15, 127, 3); 682 T_LOOKUP(20, ==, g, AF_INET, 64, 15, 123, 1); 683 T_LOOKUP(21, ==, h, AF_INET, 64, 15, 123, 128); 684 T_LOOKUP(22, ==, h, AF_INET, 64, 15, 123, 129); 685 T_LOOKUP(23, ==, a, AF_INET, 10, 0, 0, 52); 686 T_LOOKUP(24, ==, b, AF_INET, 10, 0, 0, 220); 687 T_LOOKUP(25, ==, a, AF_INET, 10, 1, 0, 2); 688 T_LOOKUP(26, ==, b, AF_INET, 10, 1, 0, 6); 689 T_LOOKUP(27, ==, c, AF_INET, 10, 1, 0, 10); 690 T_LOOKUP(28, ==, d, AF_INET, 10, 1, 0, 20); 691 692 T_INSERT(24, a, AF_INET, 1, 0, 0, 0, 32); 693 T_INSERT(25, a, AF_INET, 64, 0, 0, 0, 32); 694 T_INSERT(26, a, AF_INET, 128, 0, 0, 0, 32); 695 T_INSERT(27, a, AF_INET, 192, 0, 0, 0, 32); 696 T_INSERT(28, a, AF_INET, 255, 0, 0, 0, 32); 697 wg_aip_remove_all(&sc, a); 698 T_LOOKUP(29, !=, a, AF_INET, 1, 0, 0, 0); 699 T_LOOKUP(30, !=, a, AF_INET, 64, 0, 0, 0); 700 T_LOOKUP(31, !=, a, AF_INET, 128, 0, 0, 0); 701 T_LOOKUP(32, !=, a, AF_INET, 192, 0, 0, 0); 702 T_LOOKUP(33, !=, a, AF_INET, 255, 0, 0, 0); 703 704 T_CLEAR_PEERS(); 705 T_INSERT(29, a, AF_INET, 192, 168, 0, 0, 16); 706 T_INSERT(30, a, AF_INET, 192, 168, 0, 0, 24); 707 wg_aip_remove_all(&sc, a); 708 T_LOOKUP(34, !=, a, AF_INET, 192, 168, 0, 1); 709 710 for (i = 0; i < 128; ++i) { 711 uint64_t part = htobe64(~(1LLU << (i % 64))); 712 struct in6_addr addr; 713 memset(&addr, 0xff, 16); 714 memcpy((uint8_t *)&addr + (i < 64) * 8, &part, 8); 715 wg_aip_add(&sc, a, AF_INET6, &addr, 128); 716 } 717 718 T_CLEAR_PEERS(); 719 T_INSERT(31, a, AF_INET, 192, 95, 5, 93, 27); 720 T_INSERT(32, a, AF_INET6, 721 0x26075300, 0x60006b00, 0, 0xc05f0543, 128); 722 T_INSERT(33, a, AF_INET, 10, 1, 0, 20, 29); 723 T_INSERT(34, a, AF_INET6, 724 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 83); 725 T_INSERT(35, a, AF_INET6, 726 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 21); 727 count = 0; 728 found_a = found_b = found_c = found_d = found_e = found_other = false; 729 LIST_FOREACH(aip, &a->p_aips, a_entry) { 730 sa_family_t family = aip->a_af; 731 uint8_t *ip = aip->a_addr.bytes; 732 uint8_t cidr; 733 734 if (family == AF_INET) 735 cidr = bitcount32(aip->a_mask.ip); 736 else if (family == AF_INET6) 737 cidr = in6_mask2len(&aip->a_mask.in6, NULL); 738 else 739 continue; 740 741 count++; 742 743 if (cidr == 27 && family == AF_INET && 744 ip_equal_v4(ip, 192, 95, 5, 64)) 745 found_a = true; 746 else if (cidr == 128 && family == AF_INET6 && 747 ip_equal_v6(ip, 0x26075300, 0x60006b00, 0, 0xc05f0543)) 748 found_b = true; 749 else if (cidr == 29 && family == AF_INET && 750 ip_equal_v4(ip, 10, 1, 0, 16)) 751 found_c = true; 752 else if (cidr == 83 && family == AF_INET6 && 753 ip_equal_v6(ip, 0x26075300, 0x6d8a6bf8, 0xdab1e000, 0)) 754 found_d = true; 755 else if (cidr == 21 && family == AF_INET6 && 756 ip_equal_v6(ip, 0x26075000, 0, 0, 0)) 757 found_e = true; 758 else 759 found_other = true; 760 } 761 if (!(count == 5 && 762 found_a && found_b && found_c && found_d && found_e && 763 !found_other)) { 764 kprintf("%s: aips lookup: FAIL\n", __func__); 765 success = false; 766 } 767 768 kprintf("%s: %s\n", __func__, success ? "pass" : "FAIL"); 769 770 error: 771 T_FREE_PEERS(); 772 test_aip_deinit(&sc); 773 return (success); 774 } 775 776 #undef T_INSERT 777 #undef T_LOOKUP 778 #undef T_NEW_PEER 779 #undef T_NEW_PEERS 780 #undef T_CLEAR_PEERS 781 #undef T_FREE_PEERS 782 783 static bool 784 wg_allowedips_selftest(void) 785 { 786 bool ret = true; 787 788 ret &= wg_allowedips_lookup_test(); 789 ret &= wg_allowedips_randomized_test(); 790 791 kprintf("%s: %s\n", __func__, ret ? "pass" : "FAIL"); 792 return (ret); 793 } 794