xref: /dragonfly/sys/net/wg/selftest/allowedips.c (revision 350efd1c)
14c074b47SAaron LI /*-
24c074b47SAaron LI  * SPDX-License-Identifier: MIT
382c705f0SAaron LI  *
482c705f0SAaron LI  * Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
54c074b47SAaron LI  * Copyright (c) 2024 Aaron LI <aly@aaronly.me>
64c074b47SAaron LI  *
74c074b47SAaron LI  * Permission is hereby granted, free of charge, to any person obtaining
84c074b47SAaron LI  * a copy of this software and associated documentation files (the
94c074b47SAaron LI  * "Software"), to deal in the Software without restriction, including
104c074b47SAaron LI  * without limitation the rights to use, copy, modify, merge, publish,
114c074b47SAaron LI  * distribute, sublicense, and/or sell copies of the Software, and to
124c074b47SAaron LI  * permit persons to whom the Software is furnished to do so, subject
134c074b47SAaron LI  * to the following conditions:
144c074b47SAaron LI  *
154c074b47SAaron LI  * The above copyright notice and this permission notice shall be
164c074b47SAaron LI  * included in all copies or substantial portions of the Software.
174c074b47SAaron LI  *
184c074b47SAaron LI  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
194c074b47SAaron LI  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
204c074b47SAaron LI  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
214c074b47SAaron LI  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
224c074b47SAaron LI  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
234c074b47SAaron LI  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
244c074b47SAaron LI  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2582c705f0SAaron LI  */
2682c705f0SAaron LI 
274c074b47SAaron LI static bool
test_aip_init(struct wg_softc * sc)284c074b47SAaron LI test_aip_init(struct wg_softc *sc)
2982c705f0SAaron LI {
304c074b47SAaron LI 	memset(sc, 0, sizeof(*sc));
314c074b47SAaron LI 
324c074b47SAaron LI 	lockinit(&sc->sc_aip_lock, "aip_lock (test)", 0, 0);
334c074b47SAaron LI 
34cf257a5cSAaron LI 	if (!rn_inithead(&sc->sc_aip4, wg_maskhead,
35cf257a5cSAaron LI 			 offsetof(struct aip_addr, in)))
364c074b47SAaron LI 		return (false);
37cf257a5cSAaron LI 	if (!rn_inithead(&sc->sc_aip6, wg_maskhead,
38cf257a5cSAaron LI 			 offsetof(struct aip_addr, in6)))
394c074b47SAaron LI 		return (false);
404c074b47SAaron LI 
414c074b47SAaron LI 	return (true);
4282c705f0SAaron LI }
4382c705f0SAaron LI 
444c074b47SAaron LI static void
test_aip_deinit(struct wg_softc * sc)454c074b47SAaron LI test_aip_deinit(struct wg_softc *sc)
4682c705f0SAaron LI {
474c074b47SAaron LI 	if (sc->sc_aip4 != NULL) {
48cf257a5cSAaron LI 		rn_freehead(sc->sc_aip4);
49cf257a5cSAaron LI 		sc->sc_aip4 = NULL;
5082c705f0SAaron LI 	}
514c074b47SAaron LI 	if (sc->sc_aip6 != NULL) {
52cf257a5cSAaron LI 		rn_freehead(sc->sc_aip6);
53cf257a5cSAaron LI 		sc->sc_aip6 = NULL;
5482c705f0SAaron LI 	}
554c074b47SAaron LI 
564c074b47SAaron LI 	lockuninit(&sc->sc_aip_lock);
574c074b47SAaron LI }
584c074b47SAaron LI 
594c074b47SAaron LI static struct wg_peer *
test_aip_peer_new(struct wg_softc * sc)604c074b47SAaron LI test_aip_peer_new(struct wg_softc *sc)
614c074b47SAaron LI {
624c074b47SAaron LI 	struct wg_peer *peer;
634c074b47SAaron LI 
644c074b47SAaron LI 	peer = kmalloc(sizeof(*peer), M_WG, M_NOWAIT | M_ZERO);
654c074b47SAaron LI 	if (peer == NULL)
664c074b47SAaron LI 		return (NULL);
674c074b47SAaron LI 
684c074b47SAaron LI 	peer->p_sc = sc;
694c074b47SAaron LI 	LIST_INIT(&peer->p_aips);
704c074b47SAaron LI 	peer->p_aips_num = 0;
714c074b47SAaron LI 	/*
724c074b47SAaron LI 	 * WARNING:
734c074b47SAaron LI 	 * wg_aip_lookup() will reference 'peer->p_remote', so this member
744c074b47SAaron LI 	 * cannot be NULL.  Do a hack and just assign itself to it, so as
754c074b47SAaron LI 	 * no need to bother with creating noise_local and noise_remote.
764c074b47SAaron LI 	 * This is kind of dangerous, but probably fine.
774c074b47SAaron LI 	 */
784c074b47SAaron LI 	peer->p_remote = (struct noise_remote *)peer;
794c074b47SAaron LI 
804c074b47SAaron LI 	return (peer);
8182c705f0SAaron LI }
8282c705f0SAaron LI 
8382c705f0SAaron LI #ifdef WG_ALLOWEDIPS_RANDOMIZED_TEST
8482c705f0SAaron LI 
8582c705f0SAaron LI struct horrible_allowedips {
8682c705f0SAaron LI 	LIST_HEAD(, horrible_allowedips_node)	head;
8782c705f0SAaron LI };
8882c705f0SAaron LI 
8982c705f0SAaron LI struct horrible_allowedips_node {
904c074b47SAaron LI 	LIST_ENTRY(horrible_allowedips_node)	entry;
9182c705f0SAaron LI 	struct aip_addr				ip;
9282c705f0SAaron LI 	struct aip_addr				mask;
9382c705f0SAaron LI 	uint8_t					ip_version;
9482c705f0SAaron LI 	void					*value;
9582c705f0SAaron LI };
9682c705f0SAaron LI 
974c074b47SAaron LI static void
horrible_allowedips_init(struct horrible_allowedips * table)984c074b47SAaron LI horrible_allowedips_init(struct horrible_allowedips *table)
9982c705f0SAaron LI {
10082c705f0SAaron LI 	LIST_INIT(&table->head);
10182c705f0SAaron LI }
10282c705f0SAaron LI 
1034c074b47SAaron LI static void
horrible_allowedips_flush(struct horrible_allowedips * table)104*350efd1cSAaron LI horrible_allowedips_flush(struct horrible_allowedips *table)
10582c705f0SAaron LI {
1064c074b47SAaron LI 	struct horrible_allowedips_node *node, *node_;
10782c705f0SAaron LI 
1084c074b47SAaron LI 	LIST_FOREACH_MUTABLE(node, &table->head, entry, node_) {
1094c074b47SAaron LI 		LIST_REMOVE(node, entry);
110cf257a5cSAaron LI 		kfree(node, M_WG);
11182c705f0SAaron LI 	}
11282c705f0SAaron LI }
11382c705f0SAaron LI 
1144c074b47SAaron LI static inline void
horrible_cidr_to_mask(uint8_t cidr,struct aip_addr * mask)1154c074b47SAaron LI horrible_cidr_to_mask(uint8_t cidr, struct aip_addr *mask)
11682c705f0SAaron LI {
1174c074b47SAaron LI 	uint8_t n;
11882c705f0SAaron LI 
1194c074b47SAaron LI 	memset(&mask->in6, 0x00, sizeof(mask->in6));
1204c074b47SAaron LI 	memset(&mask->in6, 0xff, cidr / 8);
1214c074b47SAaron LI 	if ((n = cidr % 32) != 0)
1224c074b47SAaron LI 		mask->ip6[cidr / 32] =
1234c074b47SAaron LI 		    (uint32_t)htonl((0xFFFFFFFFUL << (32 - n)) & 0xFFFFFFFFUL);
12482c705f0SAaron LI }
12582c705f0SAaron LI 
1264c074b47SAaron LI static inline uint8_t
horrible_mask_to_cidr(const struct aip_addr * mask)1274c074b47SAaron LI horrible_mask_to_cidr(const struct aip_addr *mask)
12882c705f0SAaron LI {
1294c074b47SAaron LI 	return (bitcount32(mask->ip6[0]) +
1304c074b47SAaron LI 		bitcount32(mask->ip6[1]) +
1314c074b47SAaron LI 		bitcount32(mask->ip6[2]) +
1324c074b47SAaron LI 		bitcount32(mask->ip6[3]));
13382c705f0SAaron LI }
13482c705f0SAaron LI 
13582c705f0SAaron LI static inline void
horrible_mask_self(struct horrible_allowedips_node * node)13682c705f0SAaron LI horrible_mask_self(struct horrible_allowedips_node *node)
13782c705f0SAaron LI {
1384c074b47SAaron LI 	KKASSERT(node->ip_version == 4 || node->ip_version == 6);
1394c074b47SAaron LI 
14082c705f0SAaron LI 	if (node->ip_version == 4) {
14182c705f0SAaron LI 		node->ip.ip &= node->mask.ip;
1424c074b47SAaron LI 	} else {
14382c705f0SAaron LI 		node->ip.ip6[0] &= node->mask.ip6[0];
14482c705f0SAaron LI 		node->ip.ip6[1] &= node->mask.ip6[1];
14582c705f0SAaron LI 		node->ip.ip6[2] &= node->mask.ip6[2];
14682c705f0SAaron LI 		node->ip.ip6[3] &= node->mask.ip6[3];
14782c705f0SAaron LI 	}
14882c705f0SAaron LI }
14982c705f0SAaron LI 
15082c705f0SAaron LI static inline bool
horrible_match_v4(const struct horrible_allowedips_node * node,const struct in_addr * ip)15182c705f0SAaron LI horrible_match_v4(const struct horrible_allowedips_node *node,
1524c074b47SAaron LI 		  const struct in_addr *ip)
15382c705f0SAaron LI {
1544c074b47SAaron LI 	return ((ip->s_addr & node->mask.ip) == node->ip.ip);
15582c705f0SAaron LI }
15682c705f0SAaron LI 
15782c705f0SAaron LI static inline bool
horrible_match_v6(const struct horrible_allowedips_node * node,const struct in6_addr * ip)15882c705f0SAaron LI horrible_match_v6(const struct horrible_allowedips_node *node,
1594c074b47SAaron LI 		  const struct in6_addr *ip)
16082c705f0SAaron LI {
1614c074b47SAaron LI #define IP6MATCH_SEG(ip, node, n) \
1624c074b47SAaron LI 	((ip->__u6_addr.__u6_addr32[n] & node->mask.ip6[n]) \
1634c074b47SAaron LI 	 == node->ip.ip6[n])
1644c074b47SAaron LI 
1654c074b47SAaron LI 	return (IP6MATCH_SEG(ip, node, 0) &&
1664c074b47SAaron LI 		IP6MATCH_SEG(ip, node, 1) &&
1674c074b47SAaron LI 		IP6MATCH_SEG(ip, node, 2) &&
1684c074b47SAaron LI 		IP6MATCH_SEG(ip, node, 3));
1694c074b47SAaron LI 
1704c074b47SAaron LI #undef IP6MATCH_SEG
17182c705f0SAaron LI }
17282c705f0SAaron LI 
17382c705f0SAaron LI static void
horrible_insert_ordered(struct horrible_allowedips * table,struct horrible_allowedips_node * node)17482c705f0SAaron LI horrible_insert_ordered(struct horrible_allowedips *table,
17582c705f0SAaron LI 			struct horrible_allowedips_node *node)
17682c705f0SAaron LI {
1774c074b47SAaron LI 	struct horrible_allowedips_node *other, *where;
1784c074b47SAaron LI 	uint8_t my_cidr;
17982c705f0SAaron LI 
1804c074b47SAaron LI 	other = where = NULL;
1814c074b47SAaron LI 	my_cidr = horrible_mask_to_cidr(&node->mask);
1824c074b47SAaron LI 
1834c074b47SAaron LI 	LIST_FOREACH(other, &table->head, entry) {
18482c705f0SAaron LI 		if (!memcmp(&other->mask, &node->mask,
18582c705f0SAaron LI 			    sizeof(struct aip_addr)) &&
18682c705f0SAaron LI 		    !memcmp(&other->ip, &node->ip,
18782c705f0SAaron LI 			    sizeof(struct aip_addr)) &&
1884c074b47SAaron LI 		    other->ip_version == node->ip_version)
1894c074b47SAaron LI 		{
19082c705f0SAaron LI 			other->value = node->value;
191cf257a5cSAaron LI 			kfree(node, M_WG);
19282c705f0SAaron LI 			return;
19382c705f0SAaron LI 		}
19482c705f0SAaron LI 		where = other;
1954c074b47SAaron LI 		if (horrible_mask_to_cidr(&other->mask) <= my_cidr)
19682c705f0SAaron LI 			break;
19782c705f0SAaron LI 	}
1984c074b47SAaron LI 
1994c074b47SAaron LI 	if (other == NULL && where == NULL)
2004c074b47SAaron LI 		LIST_INSERT_HEAD(&table->head, node, entry);
2014c074b47SAaron LI 	else if (other == NULL)
2024c074b47SAaron LI 		LIST_INSERT_AFTER(where, node, entry);
20382c705f0SAaron LI 	else
2044c074b47SAaron LI 		LIST_INSERT_BEFORE(where, node, entry);
20582c705f0SAaron LI }
20682c705f0SAaron LI 
20782c705f0SAaron LI static int
horrible_allowedips_insert_v4(struct horrible_allowedips * table,const void * ip,uint8_t cidr,void * value)20882c705f0SAaron LI horrible_allowedips_insert_v4(struct horrible_allowedips *table,
2094c074b47SAaron LI 			      const void *ip, uint8_t cidr, void *value)
21082c705f0SAaron LI {
2114c074b47SAaron LI 	struct horrible_allowedips_node *node;
21282c705f0SAaron LI 
2134c074b47SAaron LI 	node = kmalloc(sizeof(*node), M_WG, M_NOWAIT | M_ZERO);
2144c074b47SAaron LI 	if (node == NULL)
2154c074b47SAaron LI 		return (ENOMEM);
2164c074b47SAaron LI 
2174c074b47SAaron LI 	node->ip.in = *(const struct in_addr *)ip;
2184c074b47SAaron LI 	horrible_cidr_to_mask(cidr, &node->mask);
21982c705f0SAaron LI 	node->ip_version = 4;
22082c705f0SAaron LI 	node->value = value;
2214c074b47SAaron LI 
22282c705f0SAaron LI 	horrible_mask_self(node);
22382c705f0SAaron LI 	horrible_insert_ordered(table, node);
2244c074b47SAaron LI 
2254c074b47SAaron LI 	return (0);
22682c705f0SAaron LI }
22782c705f0SAaron LI 
22882c705f0SAaron LI static int
horrible_allowedips_insert_v6(struct horrible_allowedips * table,const void * ip,uint8_t cidr,void * value)22982c705f0SAaron LI horrible_allowedips_insert_v6(struct horrible_allowedips *table,
2304c074b47SAaron LI 			      const void *ip, uint8_t cidr, void *value)
23182c705f0SAaron LI {
2324c074b47SAaron LI 	struct horrible_allowedips_node *node;
23382c705f0SAaron LI 
2344c074b47SAaron LI 	node = kmalloc(sizeof(*node), M_WG, M_NOWAIT | M_ZERO);
2354c074b47SAaron LI 	if (node == NULL)
2364c074b47SAaron LI 		return (ENOMEM);
2374c074b47SAaron LI 
2384c074b47SAaron LI 	node->ip.in6 = *(const struct in6_addr *)ip;
2394c074b47SAaron LI 	horrible_cidr_to_mask(cidr, &node->mask);
24082c705f0SAaron LI 	node->ip_version = 6;
24182c705f0SAaron LI 	node->value = value;
2424c074b47SAaron LI 
24382c705f0SAaron LI 	horrible_mask_self(node);
24482c705f0SAaron LI 	horrible_insert_ordered(table, node);
2454c074b47SAaron LI 
2464c074b47SAaron LI 	return (0);
24782c705f0SAaron LI }
24882c705f0SAaron LI 
24982c705f0SAaron LI static void *
horrible_allowedips_lookup_v4(const struct horrible_allowedips * table,const void * ip)2504c074b47SAaron LI horrible_allowedips_lookup_v4(const struct horrible_allowedips *table,
2514c074b47SAaron LI 			      const void *ip)
25282c705f0SAaron LI {
25382c705f0SAaron LI 	struct horrible_allowedips_node *node;
25482c705f0SAaron LI 	void *ret = NULL;
25582c705f0SAaron LI 
2564c074b47SAaron LI 	LIST_FOREACH(node, &table->head, entry) {
25782c705f0SAaron LI 		if (node->ip_version != 4)
25882c705f0SAaron LI 			continue;
2594c074b47SAaron LI 		if (horrible_match_v4(node, (const struct in_addr *)ip)) {
26082c705f0SAaron LI 			ret = node->value;
26182c705f0SAaron LI 			break;
26282c705f0SAaron LI 		}
26382c705f0SAaron LI 	}
2644c074b47SAaron LI 
2654c074b47SAaron LI 	return (ret);
26682c705f0SAaron LI }
26782c705f0SAaron LI 
26882c705f0SAaron LI static void *
horrible_allowedips_lookup_v6(const struct horrible_allowedips * table,const void * ip)2694c074b47SAaron LI horrible_allowedips_lookup_v6(const struct horrible_allowedips *table,
2704c074b47SAaron LI 			      const void *ip)
27182c705f0SAaron LI {
27282c705f0SAaron LI 	struct horrible_allowedips_node *node;
27382c705f0SAaron LI 	void *ret = NULL;
27482c705f0SAaron LI 
2754c074b47SAaron LI 	LIST_FOREACH(node, &table->head, entry) {
27682c705f0SAaron LI 		if (node->ip_version != 6)
27782c705f0SAaron LI 			continue;
2784c074b47SAaron LI 		if (horrible_match_v6(node, (const struct in6_addr *)ip)) {
27982c705f0SAaron LI 			ret = node->value;
28082c705f0SAaron LI 			break;
28182c705f0SAaron LI 		}
28282c705f0SAaron LI 	}
2834c074b47SAaron LI 
2844c074b47SAaron LI 	return (ret);
28582c705f0SAaron LI }
28682c705f0SAaron LI 
2874c074b47SAaron LI #define T_NUM_PEERS		2000
2884c074b47SAaron LI #define T_NUM_RAND_ROUTES	400
2894c074b47SAaron LI #define T_NUM_MUTATED_ROUTES	100
2904c074b47SAaron LI #define T_NUM_QUERIES		(T_NUM_RAND_ROUTES * T_NUM_MUTATED_ROUTES * 30)
2914c074b47SAaron LI 
2924c074b47SAaron LI static bool
wg_allowedips_randomized_test(void)2934c074b47SAaron LI wg_allowedips_randomized_test(void)
29482c705f0SAaron LI {
29582c705f0SAaron LI 	struct horrible_allowedips h;
2964c074b47SAaron LI 	struct wg_softc sc;
2974c074b47SAaron LI 	struct wg_peer **peers, *peer;
2984c074b47SAaron LI 	unsigned int i, j, k, p, nextp, mutate_amount;
2994c074b47SAaron LI 	uint8_t ip[16], mutated[16], mutate_mask[16], cidr;
30082c705f0SAaron LI 	bool ret = false;
30182c705f0SAaron LI 
3024c074b47SAaron LI 	peers = NULL;
3034c074b47SAaron LI 
30482c705f0SAaron LI 	horrible_allowedips_init(&h);
3054c074b47SAaron LI 	if (!test_aip_init(&sc)) {
3064c074b47SAaron LI 		kprintf("%s: FAIL: test_aip_init\n", __func__);
3074c074b47SAaron LI 		goto error;
3084c074b47SAaron LI 	}
3094c074b47SAaron LI 	peers = kmalloc(T_NUM_PEERS * sizeof(*peers), M_WG, M_NOWAIT | M_ZERO);
3104c074b47SAaron LI 	if (peers == NULL) {
3114c074b47SAaron LI 		kprintf("%s: FAIL: peers malloc\n", __func__);
3124c074b47SAaron LI 		goto error;
3134c074b47SAaron LI 	}
3144c074b47SAaron LI 	for (i = 0; i < T_NUM_PEERS; ++i) {
3154c074b47SAaron LI 		peers[i] = test_aip_peer_new(&sc);
3164c074b47SAaron LI 		if (peers[i] == NULL) {
3174c074b47SAaron LI 			kprintf("%s: FAIL: peer_new\n", __func__);
3184c074b47SAaron LI 			goto error;
3194c074b47SAaron LI 		}
3204c074b47SAaron LI 	}
32182c705f0SAaron LI 
3224c074b47SAaron LI 	kprintf("%s: inserting v4 routes: ", __func__);
3234c074b47SAaron LI 	for (i = 0, nextp = 0; i < T_NUM_RAND_ROUTES; ++i) {
3244c074b47SAaron LI 		if ((p = i * 100 / T_NUM_RAND_ROUTES) == nextp) {
3254c074b47SAaron LI 			kprintf("%d%%...", p);
3264c074b47SAaron LI 			nextp += 10;
3274c074b47SAaron LI 		}
328cf257a5cSAaron LI 		karc4random_buf(ip, 4);
329cf257a5cSAaron LI 		cidr = karc4random_uniform(32) + 1;
3304c074b47SAaron LI 		peer = peers[karc4random_uniform(T_NUM_PEERS)];
33182c705f0SAaron LI 		if (wg_aip_add(&sc, peer, AF_INET, ip, cidr)) {
3324c074b47SAaron LI 			kprintf("%s: FAIL: wg_aip_add(v4)\n", __func__);
3334c074b47SAaron LI 			goto error;
33482c705f0SAaron LI 		}
3354c074b47SAaron LI 		if (horrible_allowedips_insert_v4(&h, ip, cidr, peer)) {
3364c074b47SAaron LI 			kprintf("%s: FAIL: insert_v4\n", __func__);
3374c074b47SAaron LI 			goto error;
33882c705f0SAaron LI 		}
3394c074b47SAaron LI 		for (j = 0; j < T_NUM_MUTATED_ROUTES; ++j) {
34082c705f0SAaron LI 			memcpy(mutated, ip, 4);
341cf257a5cSAaron LI 			karc4random_buf(mutate_mask, 4);
342cf257a5cSAaron LI 			mutate_amount = karc4random_uniform(32);
34382c705f0SAaron LI 			for (k = 0; k < mutate_amount / 8; ++k)
34482c705f0SAaron LI 				mutate_mask[k] = 0xff;
3454c074b47SAaron LI 			mutate_mask[k] =
3464c074b47SAaron LI 			    0xff << ((8 - (mutate_amount % 8)) % 8);
34782c705f0SAaron LI 			for (; k < 4; ++k)
34882c705f0SAaron LI 				mutate_mask[k] = 0;
3494c074b47SAaron LI 			for (k = 0; k < 4; ++k) {
35082c705f0SAaron LI 				mutated[k] = (mutated[k] & mutate_mask[k]) |
35182c705f0SAaron LI 					     (~mutate_mask[k] &
352cf257a5cSAaron LI 					      karc4random_uniform(256));
3534c074b47SAaron LI 			}
354cf257a5cSAaron LI 			cidr = karc4random_uniform(32) + 1;
3554c074b47SAaron LI 			peer = peers[karc4random_uniform(T_NUM_PEERS)];
35682c705f0SAaron LI 			if (wg_aip_add(&sc, peer, AF_INET, mutated, cidr)) {
3574c074b47SAaron LI 				kprintf("%s: FAIL: wg_aip_add(v4)\n", __func__);
3584c074b47SAaron LI 				goto error;
35982c705f0SAaron LI 			}
3604c074b47SAaron LI 			if (horrible_allowedips_insert_v4(&h, mutated, cidr,
3614c074b47SAaron LI 							  peer)) {
3624c074b47SAaron LI 				kprintf("%s: FAIL: insert_v4\n", __func__);
3634c074b47SAaron LI 				goto error;
36482c705f0SAaron LI 			}
36582c705f0SAaron LI 		}
36682c705f0SAaron LI 	}
3674c074b47SAaron LI 	kprintf("done\n");
36882c705f0SAaron LI 
369*350efd1cSAaron LI 	kprintf("%s: v4 looking up: ", __func__);
370*350efd1cSAaron LI 	for (i = 0, nextp = 0; i < T_NUM_QUERIES; ++i) {
371*350efd1cSAaron LI 		if ((p = i * 100 / T_NUM_QUERIES) == nextp) {
372*350efd1cSAaron LI 			kprintf("%d%%...", p);
373*350efd1cSAaron LI 			nextp += 5;
374*350efd1cSAaron LI 		}
375*350efd1cSAaron LI 		karc4random_buf(ip, 4);
376*350efd1cSAaron LI 		if (wg_aip_lookup(&sc, AF_INET, ip) !=
377*350efd1cSAaron LI 		    horrible_allowedips_lookup_v4(&h, ip)) {
378*350efd1cSAaron LI 			kprintf("%s: FAIL: lookup_v4\n", __func__);
379*350efd1cSAaron LI 			goto error;
380*350efd1cSAaron LI 		}
381*350efd1cSAaron LI 	}
382*350efd1cSAaron LI 	kprintf("pass\n");
383*350efd1cSAaron LI 
384*350efd1cSAaron LI 	/*
385*350efd1cSAaron LI 	 * Flush existing v4 routes for the following v6 test so as to
386*350efd1cSAaron LI 	 * significantly reduce the test time.
387*350efd1cSAaron LI 	 */
388*350efd1cSAaron LI 	horrible_allowedips_flush(&h);
389*350efd1cSAaron LI 
3904c074b47SAaron LI 	kprintf("%s: inserting v6 routes: ", __func__);
3914c074b47SAaron LI 	for (i = 0, nextp = 0; i < T_NUM_RAND_ROUTES; ++i) {
3924c074b47SAaron LI 		if ((p = i * 100 / T_NUM_RAND_ROUTES) == nextp) {
3934c074b47SAaron LI 			kprintf("%d%%...", p);
3944c074b47SAaron LI 			nextp += 10;
3954c074b47SAaron LI 		}
396cf257a5cSAaron LI 		karc4random_buf(ip, 16);
397cf257a5cSAaron LI 		cidr = karc4random_uniform(128) + 1;
3984c074b47SAaron LI 		peer = peers[karc4random_uniform(T_NUM_PEERS)];
39982c705f0SAaron LI 		if (wg_aip_add(&sc, peer, AF_INET6, ip, cidr)) {
4004c074b47SAaron LI 			kprintf("%s: FAIL: wg_aip_add(v6)\n", __func__);
4014c074b47SAaron LI 			goto error;
40282c705f0SAaron LI 		}
4034c074b47SAaron LI 		if (horrible_allowedips_insert_v6(&h, ip, cidr, peer)) {
4044c074b47SAaron LI 			kprintf("%s: FAIL: insert_v6\n", __func__);
4054c074b47SAaron LI 			goto error;
40682c705f0SAaron LI 		}
4074c074b47SAaron LI 		for (j = 0; j < T_NUM_MUTATED_ROUTES; ++j) {
40882c705f0SAaron LI 			memcpy(mutated, ip, 16);
409cf257a5cSAaron LI 			karc4random_buf(mutate_mask, 16);
410cf257a5cSAaron LI 			mutate_amount = karc4random_uniform(128);
41182c705f0SAaron LI 			for (k = 0; k < mutate_amount / 8; ++k)
41282c705f0SAaron LI 				mutate_mask[k] = 0xff;
4134c074b47SAaron LI 			mutate_mask[k] =
4144c074b47SAaron LI 			    0xff << ((8 - (mutate_amount % 8)) % 8);
41582c705f0SAaron LI 			for (; k < 4; ++k)
41682c705f0SAaron LI 				mutate_mask[k] = 0;
4174c074b47SAaron LI 			for (k = 0; k < 4; ++k) {
41882c705f0SAaron LI 				mutated[k] = (mutated[k] & mutate_mask[k]) |
41982c705f0SAaron LI 					     (~mutate_mask[k] &
420cf257a5cSAaron LI 					      karc4random_uniform(256));
4214c074b47SAaron LI 			}
422cf257a5cSAaron LI 			cidr = karc4random_uniform(128) + 1;
4234c074b47SAaron LI 			peer = peers[karc4random_uniform(T_NUM_PEERS)];
42482c705f0SAaron LI 			if (wg_aip_add(&sc, peer, AF_INET6, mutated, cidr)) {
4254c074b47SAaron LI 				kprintf("%s: FAIL: wg_aip_add(v6)\n", __func__);
4264c074b47SAaron LI 				goto error;
42782c705f0SAaron LI 			}
4284c074b47SAaron LI 			if (horrible_allowedips_insert_v6(&h, mutated, cidr,
42982c705f0SAaron LI 							  peer)) {
4304c074b47SAaron LI 				kprintf("%s: FAIL: insert_v6\n", __func__);
4314c074b47SAaron LI 				goto error;
43282c705f0SAaron LI 			}
43382c705f0SAaron LI 		}
43482c705f0SAaron LI 	}
4354c074b47SAaron LI 	kprintf("done\n");
43682c705f0SAaron LI 
4374c074b47SAaron LI 	kprintf("%s: v6 looking up: ", __func__);
4384c074b47SAaron LI 	for (i = 0, nextp = 0; i < T_NUM_QUERIES; ++i) {
4394c074b47SAaron LI 		if ((p = i * 100 / T_NUM_QUERIES) == nextp) {
4404c074b47SAaron LI 			kprintf("%d%%...", p);
4414c074b47SAaron LI 			nextp += 5;
4424c074b47SAaron LI 		}
443cf257a5cSAaron LI 		karc4random_buf(ip, 16);
44482c705f0SAaron LI 		if (wg_aip_lookup(&sc, AF_INET6, ip) !=
4454c074b47SAaron LI 		    horrible_allowedips_lookup_v6(&h, ip)) {
4464c074b47SAaron LI 			kprintf("%s: FAIL: lookup_v6\n", __func__);
4474c074b47SAaron LI 			goto error;
44882c705f0SAaron LI 		}
44982c705f0SAaron LI 	}
4504c074b47SAaron LI 	kprintf("pass\n");
45182c705f0SAaron LI 
4524c074b47SAaron LI 	ret = true;
4534c074b47SAaron LI 	kprintf("%s: pass\n", __func__);
4544c074b47SAaron LI 
4554c074b47SAaron LI error:
456*350efd1cSAaron LI 	horrible_allowedips_flush(&h);
4574c074b47SAaron LI 	if (peers != NULL) {
4584c074b47SAaron LI 		for (i = 0; i < T_NUM_PEERS; ++i) {
4594c074b47SAaron LI 			if (peers[i] != NULL) {
46082c705f0SAaron LI 				wg_aip_remove_all(&sc, peers[i]);
461cf257a5cSAaron LI 				kfree(peers[i], M_WG);
46282c705f0SAaron LI 			}
46382c705f0SAaron LI 		}
4644c074b47SAaron LI 		kfree(peers, M_WG);
4654c074b47SAaron LI 	}
4664c074b47SAaron LI 	test_aip_deinit(&sc);
46782c705f0SAaron LI 
4684c074b47SAaron LI 	return (ret);
4694c074b47SAaron LI }
4704c074b47SAaron LI 
4714c074b47SAaron LI #else /* !WG_ALLOWEDIPS_RANDOMIZED_TEST */
4724c074b47SAaron LI 
4734c074b47SAaron LI static inline bool
wg_allowedips_randomized_test(void)4744c074b47SAaron LI wg_allowedips_randomized_test(void)
4754c074b47SAaron LI {
4764c074b47SAaron LI 	return (true);
4774c074b47SAaron LI }
4784c074b47SAaron LI 
4794c074b47SAaron LI #endif /* WG_ALLOWEDIPS_RANDOMIZED_TEST */
4804c074b47SAaron LI 
4814c074b47SAaron LI static inline void *
ip_make_v4(uint8_t a,uint8_t b,uint8_t c,uint8_t d)4824c074b47SAaron LI ip_make_v4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
48382c705f0SAaron LI {
48482c705f0SAaron LI 	static struct in_addr ip;
48582c705f0SAaron LI 	uint8_t *split = (uint8_t *)&ip;
48682c705f0SAaron LI 
48782c705f0SAaron LI 	split[0] = a;
48882c705f0SAaron LI 	split[1] = b;
48982c705f0SAaron LI 	split[2] = c;
49082c705f0SAaron LI 	split[3] = d;
4914c074b47SAaron LI 
4924c074b47SAaron LI 	return (void *)&ip;
49382c705f0SAaron LI }
49482c705f0SAaron LI 
4954c074b47SAaron LI static inline void *
ip_make_v6(uint32_t a,uint32_t b,uint32_t c,uint32_t d)4964c074b47SAaron LI ip_make_v6(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
49782c705f0SAaron LI {
49882c705f0SAaron LI 	static struct in6_addr ip;
49982c705f0SAaron LI 	uint32_t *split = ip.__u6_addr.__u6_addr32;
50082c705f0SAaron LI 
50182c705f0SAaron LI 	split[0] = htobe32(a);
50282c705f0SAaron LI 	split[1] = htobe32(b);
50382c705f0SAaron LI 	split[2] = htobe32(c);
50482c705f0SAaron LI 	split[3] = htobe32(d);
5054c074b47SAaron LI 
5064c074b47SAaron LI 	return (void *)&ip;
50782c705f0SAaron LI }
50882c705f0SAaron LI 
5094c074b47SAaron LI static inline bool
ip_equal_v4(const void * ip,uint8_t a,uint8_t b,uint8_t c,uint8_t d)5104c074b47SAaron LI ip_equal_v4(const void *ip, uint8_t a, uint8_t b, uint8_t c, uint8_t d)
51182c705f0SAaron LI {
5124c074b47SAaron LI 	return (memcmp(ip, ip_make_v4(a, b, c, d), 4) == 0);
51382c705f0SAaron LI }
51482c705f0SAaron LI 
5154c074b47SAaron LI static inline bool
ip_equal_v6(const void * ip,uint32_t a,uint32_t b,uint32_t c,uint32_t d)5164c074b47SAaron LI ip_equal_v6(const void *ip, uint32_t a, uint32_t b, uint32_t c, uint32_t d)
5174c074b47SAaron LI {
5184c074b47SAaron LI 	return (memcmp(ip, ip_make_v6(a, b, c, d), 16) == 0);
5194c074b47SAaron LI }
5204c074b47SAaron LI 
5214c074b47SAaron LI #define T_INSERT(n, peer, af, ipa, ipb, ipc, ipd, cidr) do {		\
5224c074b47SAaron LI 	const void *_ip = (af == AF_INET) ?				\
5234c074b47SAaron LI 			  ip_make_v4(ipa, ipb, ipc, ipd) :		\
5244c074b47SAaron LI 			  ip_make_v6(ipa, ipb, ipc, ipd);		\
5254c074b47SAaron LI 	if (wg_aip_add(&sc, peer, af, _ip, cidr)) {			\
5264c074b47SAaron LI 		kprintf("%s: insert #%d: FAIL\n", __func__, n);		\
52782c705f0SAaron LI 		success = false;					\
52882c705f0SAaron LI 	}								\
52982c705f0SAaron LI } while (0)
53082c705f0SAaron LI 
5314c074b47SAaron LI #define T_LOOKUP(n, op, peer, af, ipa, ipb, ipc, ipd) do {		\
5324c074b47SAaron LI 	const void *_ip = (af == AF_INET) ?				\
5334c074b47SAaron LI 			  ip_make_v4(ipa, ipb, ipc, ipd) :		\
5344c074b47SAaron LI 			  ip_make_v6(ipa, ipb, ipc, ipd);		\
5354c074b47SAaron LI 	if (!(wg_aip_lookup(&sc, af, _ip) op peer)) {			\
5364c074b47SAaron LI 		kprintf("%s: lookup #%d: FAIL\n", __func__, n);		\
53782c705f0SAaron LI 		success = false;					\
53882c705f0SAaron LI 	}								\
53982c705f0SAaron LI } while (0)
54082c705f0SAaron LI 
5414c074b47SAaron LI #define T_NEW_PEER(p) do { 						\
5424c074b47SAaron LI 	if ((p = test_aip_peer_new(&sc)) == NULL) {			\
5434c074b47SAaron LI 		kprintf("%s: FAIL: peer_new(%s)\n", __func__, #p);	\
5444c074b47SAaron LI 		goto error;						\
5454c074b47SAaron LI 	}								\
54682c705f0SAaron LI } while (0)
54782c705f0SAaron LI 
5484c074b47SAaron LI #define T_NEW_PEERS() do {						\
5494c074b47SAaron LI 	T_NEW_PEER(a);							\
5504c074b47SAaron LI 	T_NEW_PEER(b);							\
5514c074b47SAaron LI 	T_NEW_PEER(c);							\
5524c074b47SAaron LI 	T_NEW_PEER(d);							\
5534c074b47SAaron LI 	T_NEW_PEER(e);							\
5544c074b47SAaron LI 	T_NEW_PEER(f);							\
5554c074b47SAaron LI 	T_NEW_PEER(g);							\
5564c074b47SAaron LI 	T_NEW_PEER(h);							\
55782c705f0SAaron LI } while (0)
55882c705f0SAaron LI 
5594c074b47SAaron LI #define T_CLEAR_PEERS() do {						\
5604c074b47SAaron LI 	if (a != NULL)							\
5614c074b47SAaron LI 		wg_aip_remove_all(&sc, a);				\
5624c074b47SAaron LI 	if (b != NULL)							\
5634c074b47SAaron LI 		wg_aip_remove_all(&sc, b);				\
5644c074b47SAaron LI 	if (c != NULL)							\
5654c074b47SAaron LI 		wg_aip_remove_all(&sc, c);				\
5664c074b47SAaron LI 	if (d != NULL)							\
5674c074b47SAaron LI 		wg_aip_remove_all(&sc, d);				\
5684c074b47SAaron LI 	if (e != NULL)							\
5694c074b47SAaron LI 		wg_aip_remove_all(&sc, e);				\
5704c074b47SAaron LI 	if (f != NULL)							\
5714c074b47SAaron LI 		wg_aip_remove_all(&sc, f);				\
5724c074b47SAaron LI 	if (g != NULL)							\
5734c074b47SAaron LI 		wg_aip_remove_all(&sc, g);				\
5744c074b47SAaron LI 	if (h != NULL)							\
5754c074b47SAaron LI 		wg_aip_remove_all(&sc, h);				\
57682c705f0SAaron LI } while (0)
57782c705f0SAaron LI 
5784c074b47SAaron LI #define T_FREE_PEERS() do {						\
5794c074b47SAaron LI 	T_CLEAR_PEERS();						\
5804c074b47SAaron LI 	if (a != NULL)							\
5814c074b47SAaron LI 		kfree(a, M_WG);						\
5824c074b47SAaron LI 	if (b != NULL)							\
5834c074b47SAaron LI 		kfree(b, M_WG);						\
5844c074b47SAaron LI 	if (c != NULL)							\
5854c074b47SAaron LI 		kfree(c, M_WG);						\
5864c074b47SAaron LI 	if (d != NULL)							\
5874c074b47SAaron LI 		kfree(d, M_WG);						\
5884c074b47SAaron LI 	if (e != NULL)							\
5894c074b47SAaron LI 		kfree(e, M_WG);						\
5904c074b47SAaron LI 	if (f != NULL)							\
5914c074b47SAaron LI 		kfree(f, M_WG);						\
5924c074b47SAaron LI 	if (g != NULL)							\
5934c074b47SAaron LI 		kfree(g, M_WG);						\
5944c074b47SAaron LI 	if (h != NULL)							\
5954c074b47SAaron LI 		kfree(h, M_WG);						\
59682c705f0SAaron LI } while (0)
59782c705f0SAaron LI 
5984c074b47SAaron LI static bool
wg_allowedips_lookup_test(void)5994c074b47SAaron LI wg_allowedips_lookup_test(void)
60082c705f0SAaron LI {
6014c074b47SAaron LI 	struct wg_softc sc;
6024c074b47SAaron LI 	struct wg_peer *a = NULL, *b = NULL, *c = NULL, *d = NULL;
6034c074b47SAaron LI 	struct wg_peer *e = NULL, *f = NULL, *g = NULL, *h = NULL;
6044c074b47SAaron LI 	struct wg_aip *aip;
6054c074b47SAaron LI 	size_t i, count;
6064c074b47SAaron LI 	bool found_a, found_b, found_c, found_d, found_e, found_other;
60782c705f0SAaron LI 	bool success = false;
60882c705f0SAaron LI 
60982c705f0SAaron LI 	if (!test_aip_init(&sc)) {
6104c074b47SAaron LI 		kprintf("%s: FAIL: test_aip_init\n", __func__);
6114c074b47SAaron LI 		goto error;
61282c705f0SAaron LI 	}
61382c705f0SAaron LI 
6144c074b47SAaron LI 	T_NEW_PEERS();
61582c705f0SAaron LI 
6164c074b47SAaron LI 	T_INSERT( 1, a, AF_INET, 192, 168, 4, 0, 24);
6174c074b47SAaron LI 	T_INSERT( 2, b, AF_INET, 192, 168, 4, 4, 32);
6184c074b47SAaron LI 	T_INSERT( 3, c, AF_INET, 192, 168, 0, 0, 16);
6194c074b47SAaron LI 	T_INSERT( 4, d, AF_INET, 192, 95, 5, 64, 27);
62082c705f0SAaron LI 	/* replaces previous entry, and maskself is required */
6214c074b47SAaron LI 	T_INSERT( 5, c, AF_INET, 192, 95, 5, 65, 27);
6224c074b47SAaron LI 	T_INSERT( 6, d, AF_INET6,
6234c074b47SAaron LI 		 0x26075300, 0x60006b00, 0, 0xc05f0543, 128);
6244c074b47SAaron LI 	T_INSERT( 7, c, AF_INET6,
6254c074b47SAaron LI 		 0x26075300, 0x60006b00, 0, 0, 64);
6264c074b47SAaron LI 	T_INSERT( 8, e, AF_INET, 0, 0, 0, 0, 0);
6274c074b47SAaron LI 	T_INSERT( 9, e, AF_INET6, 0, 0, 0, 0, 0);
62882c705f0SAaron LI 	/* replaces previous entry */
6294c074b47SAaron LI 	T_INSERT(10, f, AF_INET6, 0, 0, 0, 0, 0);
6304c074b47SAaron LI 	T_INSERT(11, g, AF_INET6, 0x24046800, 0, 0, 0, 32);
63182c705f0SAaron LI 	/* maskself is required */
6324c074b47SAaron LI 	T_INSERT(12, h, AF_INET6,
6334c074b47SAaron LI 		 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 64);
6344c074b47SAaron LI 	T_INSERT(13, a, AF_INET6,
6354c074b47SAaron LI 		 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 128);
6364c074b47SAaron LI 	T_INSERT(14, c, AF_INET6,
6374c074b47SAaron LI 		0x24446800, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128);
6384c074b47SAaron LI 	T_INSERT(15, b, AF_INET6,
6394c074b47SAaron LI 		 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98);
6404c074b47SAaron LI 	T_INSERT(16, g, AF_INET, 64, 15, 112, 0, 20);
64182c705f0SAaron LI 	/* maskself is required */
6424c074b47SAaron LI 	T_INSERT(17, h, AF_INET, 64, 15, 123, 211, 25);
6434c074b47SAaron LI 	T_INSERT(18, a, AF_INET, 10, 0, 0, 0, 25);
6444c074b47SAaron LI 	T_INSERT(19, b, AF_INET, 10, 0, 0, 128, 25);
6454c074b47SAaron LI 	T_INSERT(20, a, AF_INET, 10, 1, 0, 0, 30);
6464c074b47SAaron LI 	T_INSERT(21, b, AF_INET, 10, 1, 0, 4, 30);
6474c074b47SAaron LI 	T_INSERT(22, c, AF_INET, 10, 1, 0, 8, 29);
6484c074b47SAaron LI 	T_INSERT(23, d, AF_INET, 10, 1, 0, 16, 29);
64982c705f0SAaron LI 
65082c705f0SAaron LI 	success = true;
65182c705f0SAaron LI 
6524c074b47SAaron LI 	T_LOOKUP( 1, ==, a, AF_INET, 192, 168, 4, 20);
6534c074b47SAaron LI 	T_LOOKUP( 2, ==, a, AF_INET, 192, 168, 4, 0);
6544c074b47SAaron LI 	T_LOOKUP( 3, ==, b, AF_INET, 192, 168, 4, 4);
6554c074b47SAaron LI 	T_LOOKUP( 4, ==, c, AF_INET, 192, 168, 200, 182);
6564c074b47SAaron LI 	T_LOOKUP( 5, ==, c, AF_INET, 192, 95, 5, 68);
6574c074b47SAaron LI 	T_LOOKUP( 6, ==, e, AF_INET, 192, 95, 5, 96);
6584c074b47SAaron LI 	T_LOOKUP( 7, ==, d, AF_INET6,
6594c074b47SAaron LI 		 0x26075300, 0x60006b00, 0, 0xc05f0543);
6604c074b47SAaron LI 	T_LOOKUP( 8, ==, c, AF_INET6,
6614c074b47SAaron LI 		 0x26075300, 0x60006b00, 0, 0xc02e01ee);
6624c074b47SAaron LI 	T_LOOKUP( 9, ==, f, AF_INET6,
6634c074b47SAaron LI 		 0x26075300, 0x60006b01, 0, 0);
6644c074b47SAaron LI 	T_LOOKUP(10, ==, g, AF_INET6,
6654c074b47SAaron LI 		 0x24046800, 0x40040806, 0, 0x1006);
6664c074b47SAaron LI 	T_LOOKUP(11, ==, g, AF_INET6,
6674c074b47SAaron LI 		 0x24046800, 0x40040806, 0x1234, 0x5678);
6684c074b47SAaron LI 	T_LOOKUP(12, ==, f, AF_INET6,
6694c074b47SAaron LI 		 0x240467ff, 0x40040806, 0x1234, 0x5678);
6704c074b47SAaron LI 	T_LOOKUP(13, ==, f, AF_INET6,
6714c074b47SAaron LI 		 0x24046801, 0x40040806, 0x1234, 0x5678);
6724c074b47SAaron LI 	T_LOOKUP(14, ==, h, AF_INET6,
6734c074b47SAaron LI 		 0x24046800, 0x40040800, 0x1234, 0x5678);
6744c074b47SAaron LI 	T_LOOKUP(15, ==, h, AF_INET6,
6754c074b47SAaron LI 		 0x24046800, 0x40040800, 0, 0);
6764c074b47SAaron LI 	T_LOOKUP(16, ==, h, AF_INET6,
6774c074b47SAaron LI 		 0x24046800, 0x40040800, 0x10101010, 0x10101010);
6784c074b47SAaron LI 	T_LOOKUP(17, ==, a, AF_INET6,
6794c074b47SAaron LI 		 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef);
6804c074b47SAaron LI 	T_LOOKUP(18, ==, g, AF_INET, 64, 15, 116, 26);
6814c074b47SAaron LI 	T_LOOKUP(19, ==, g, AF_INET, 64, 15, 127, 3);
6824c074b47SAaron LI 	T_LOOKUP(20, ==, g, AF_INET, 64, 15, 123, 1);
6834c074b47SAaron LI 	T_LOOKUP(21, ==, h, AF_INET, 64, 15, 123, 128);
6844c074b47SAaron LI 	T_LOOKUP(22, ==, h, AF_INET, 64, 15, 123, 129);
6854c074b47SAaron LI 	T_LOOKUP(23, ==, a, AF_INET, 10, 0, 0, 52);
6864c074b47SAaron LI 	T_LOOKUP(24, ==, b, AF_INET, 10, 0, 0, 220);
6874c074b47SAaron LI 	T_LOOKUP(25, ==, a, AF_INET, 10, 1, 0, 2);
6884c074b47SAaron LI 	T_LOOKUP(26, ==, b, AF_INET, 10, 1, 0, 6);
6894c074b47SAaron LI 	T_LOOKUP(27, ==, c, AF_INET, 10, 1, 0, 10);
6904c074b47SAaron LI 	T_LOOKUP(28, ==, d, AF_INET, 10, 1, 0, 20);
69182c705f0SAaron LI 
6924c074b47SAaron LI 	T_INSERT(24, a, AF_INET, 1, 0, 0, 0, 32);
6934c074b47SAaron LI 	T_INSERT(25, a, AF_INET, 64, 0, 0, 0, 32);
6944c074b47SAaron LI 	T_INSERT(26, a, AF_INET, 128, 0, 0, 0, 32);
6954c074b47SAaron LI 	T_INSERT(27, a, AF_INET, 192, 0, 0, 0, 32);
6964c074b47SAaron LI 	T_INSERT(28, a, AF_INET, 255, 0, 0, 0, 32);
69782c705f0SAaron LI 	wg_aip_remove_all(&sc, a);
6984c074b47SAaron LI 	T_LOOKUP(29, !=, a, AF_INET, 1, 0, 0, 0);
6994c074b47SAaron LI 	T_LOOKUP(30, !=, a, AF_INET, 64, 0, 0, 0);
7004c074b47SAaron LI 	T_LOOKUP(31, !=, a, AF_INET, 128, 0, 0, 0);
7014c074b47SAaron LI 	T_LOOKUP(32, !=, a, AF_INET, 192, 0, 0, 0);
7024c074b47SAaron LI 	T_LOOKUP(33, !=, a, AF_INET, 255, 0, 0, 0);
70382c705f0SAaron LI 
7044c074b47SAaron LI 	T_CLEAR_PEERS();
7054c074b47SAaron LI 	T_INSERT(29, a, AF_INET, 192, 168, 0, 0, 16);
7064c074b47SAaron LI 	T_INSERT(30, a, AF_INET, 192, 168, 0, 0, 24);
70782c705f0SAaron LI 	wg_aip_remove_all(&sc, a);
7084c074b47SAaron LI 	T_LOOKUP(34, !=, a, AF_INET, 192, 168, 0, 1);
70982c705f0SAaron LI 
71082c705f0SAaron LI 	for (i = 0; i < 128; ++i) {
7114c074b47SAaron LI 		uint64_t part = htobe64(~(1LLU << (i % 64)));
7124c074b47SAaron LI 		struct in6_addr addr;
7134c074b47SAaron LI 		memset(&addr, 0xff, 16);
7144c074b47SAaron LI 		memcpy((uint8_t *)&addr + (i < 64) * 8, &part, 8);
7154c074b47SAaron LI 		wg_aip_add(&sc, a, AF_INET6, &addr, 128);
71682c705f0SAaron LI 	}
71782c705f0SAaron LI 
7184c074b47SAaron LI 	T_CLEAR_PEERS();
7194c074b47SAaron LI 	T_INSERT(31, a, AF_INET, 192, 95, 5, 93, 27);
7204c074b47SAaron LI 	T_INSERT(32, a, AF_INET6,
7214c074b47SAaron LI 		 0x26075300, 0x60006b00, 0, 0xc05f0543, 128);
7224c074b47SAaron LI 	T_INSERT(33, a, AF_INET, 10, 1, 0, 20, 29);
7234c074b47SAaron LI 	T_INSERT(34, a, AF_INET6,
7244c074b47SAaron LI 		 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 83);
7254c074b47SAaron LI 	T_INSERT(35, a, AF_INET6,
7264c074b47SAaron LI 		 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 21);
7274c074b47SAaron LI 	count = 0;
7284c074b47SAaron LI 	found_a = found_b = found_c = found_d = found_e = found_other = false;
7294c074b47SAaron LI 	LIST_FOREACH(aip, &a->p_aips, a_entry) {
7304c074b47SAaron LI 		sa_family_t family = aip->a_af;
7314c074b47SAaron LI 		uint8_t *ip = aip->a_addr.bytes;
7324c074b47SAaron LI 		uint8_t cidr;
7334c074b47SAaron LI 
73482c705f0SAaron LI 		if (family == AF_INET)
7354c074b47SAaron LI 			cidr = bitcount32(aip->a_mask.ip);
73682c705f0SAaron LI 		else if (family == AF_INET6)
7374c074b47SAaron LI 			cidr = in6_mask2len(&aip->a_mask.in6, NULL);
73882c705f0SAaron LI 		else
73982c705f0SAaron LI 			continue;
74082c705f0SAaron LI 
74182c705f0SAaron LI 		count++;
74282c705f0SAaron LI 
74382c705f0SAaron LI 		if (cidr == 27 && family == AF_INET &&
7444c074b47SAaron LI 		    ip_equal_v4(ip, 192, 95, 5, 64))
74582c705f0SAaron LI 			found_a = true;
74682c705f0SAaron LI 		else if (cidr == 128 && family == AF_INET6 &&
7474c074b47SAaron LI 			 ip_equal_v6(ip, 0x26075300, 0x60006b00, 0, 0xc05f0543))
74882c705f0SAaron LI 			found_b = true;
74982c705f0SAaron LI 		else if (cidr == 29 && family == AF_INET &&
7504c074b47SAaron LI 			 ip_equal_v4(ip, 10, 1, 0, 16))
75182c705f0SAaron LI 			found_c = true;
75282c705f0SAaron LI 		else if (cidr == 83 && family == AF_INET6 &&
7534c074b47SAaron LI 			 ip_equal_v6(ip, 0x26075300, 0x6d8a6bf8, 0xdab1e000, 0))
75482c705f0SAaron LI 			found_d = true;
75582c705f0SAaron LI 		else if (cidr == 21 && family == AF_INET6 &&
7564c074b47SAaron LI 			 ip_equal_v6(ip, 0x26075000, 0, 0, 0))
75782c705f0SAaron LI 			found_e = true;
75882c705f0SAaron LI 		else
75982c705f0SAaron LI 			found_other = true;
76082c705f0SAaron LI 	}
7614c074b47SAaron LI 	if (!(count == 5 &&
7624c074b47SAaron LI 	      found_a && found_b && found_c && found_d && found_e &&
7634c074b47SAaron LI 	      !found_other)) {
7644c074b47SAaron LI 		kprintf("%s: aips lookup: FAIL\n", __func__);
7654c074b47SAaron LI 		success = false;
76682c705f0SAaron LI 	}
76782c705f0SAaron LI 
7684c074b47SAaron LI 	kprintf("%s: %s\n", __func__, success ? "pass" : "FAIL");
7694c074b47SAaron LI 
7704c074b47SAaron LI error:
7714c074b47SAaron LI 	T_FREE_PEERS();
7724c074b47SAaron LI 	test_aip_deinit(&sc);
7734c074b47SAaron LI 	return (success);
7744c074b47SAaron LI }
7754c074b47SAaron LI 
7764c074b47SAaron LI #undef T_INSERT
7774c074b47SAaron LI #undef T_LOOKUP
7784c074b47SAaron LI #undef T_NEW_PEER
7794c074b47SAaron LI #undef T_NEW_PEERS
7804c074b47SAaron LI #undef T_CLEAR_PEERS
7814c074b47SAaron LI #undef T_FREE_PEERS
7824c074b47SAaron LI 
7834c074b47SAaron LI static bool
wg_allowedips_selftest(void)7844c074b47SAaron LI wg_allowedips_selftest(void)
7854c074b47SAaron LI {
7864c074b47SAaron LI 	bool ret = true;
7874c074b47SAaron LI 
7884c074b47SAaron LI 	ret &= wg_allowedips_lookup_test();
7894c074b47SAaron LI 	ret &= wg_allowedips_randomized_test();
7904c074b47SAaron LI 
7914c074b47SAaron LI 	kprintf("%s: %s\n", __func__, ret ? "pass" : "FAIL");
7924c074b47SAaron LI 	return (ret);
7934c074b47SAaron LI }
794