162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2015-2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * This contains some basic static unit tests for the allowedips data structure. 662306a36Sopenharmony_ci * It also has two additional modes that are disabled and meant to be used by 762306a36Sopenharmony_ci * folks directly playing with this file. If you define the macro 862306a36Sopenharmony_ci * DEBUG_PRINT_TRIE_GRAPHVIZ to be 1, then every time there's a full tree in 962306a36Sopenharmony_ci * memory, it will be printed out as KERN_DEBUG in a format that can be passed 1062306a36Sopenharmony_ci * to graphviz (the dot command) to visualize it. If you define the macro 1162306a36Sopenharmony_ci * DEBUG_RANDOM_TRIE to be 1, then there will be an extremely costly set of 1262306a36Sopenharmony_ci * randomized tests done against a trivial implementation, which may take 1362306a36Sopenharmony_ci * upwards of a half-hour to complete. There's no set of users who should be 1462306a36Sopenharmony_ci * enabling these, and the only developers that should go anywhere near these 1562306a36Sopenharmony_ci * nobs are the ones who are reading this comment. 1662306a36Sopenharmony_ci */ 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#ifdef DEBUG 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#include <linux/siphash.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic __init void print_node(struct allowedips_node *node, u8 bits) 2362306a36Sopenharmony_ci{ 2462306a36Sopenharmony_ci char *fmt_connection = KERN_DEBUG "\t\"%p/%d\" -> \"%p/%d\";\n"; 2562306a36Sopenharmony_ci char *fmt_declaration = KERN_DEBUG "\t\"%p/%d\"[style=%s, color=\"#%06x\"];\n"; 2662306a36Sopenharmony_ci u8 ip1[16], ip2[16], cidr1, cidr2; 2762306a36Sopenharmony_ci char *style = "dotted"; 2862306a36Sopenharmony_ci u32 color = 0; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci if (node == NULL) 3162306a36Sopenharmony_ci return; 3262306a36Sopenharmony_ci if (bits == 32) { 3362306a36Sopenharmony_ci fmt_connection = KERN_DEBUG "\t\"%pI4/%d\" -> \"%pI4/%d\";\n"; 3462306a36Sopenharmony_ci fmt_declaration = KERN_DEBUG "\t\"%pI4/%d\"[style=%s, color=\"#%06x\"];\n"; 3562306a36Sopenharmony_ci } else if (bits == 128) { 3662306a36Sopenharmony_ci fmt_connection = KERN_DEBUG "\t\"%pI6/%d\" -> \"%pI6/%d\";\n"; 3762306a36Sopenharmony_ci fmt_declaration = KERN_DEBUG "\t\"%pI6/%d\"[style=%s, color=\"#%06x\"];\n"; 3862306a36Sopenharmony_ci } 3962306a36Sopenharmony_ci if (node->peer) { 4062306a36Sopenharmony_ci hsiphash_key_t key = { { 0 } }; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci memcpy(&key, &node->peer, sizeof(node->peer)); 4362306a36Sopenharmony_ci color = hsiphash_1u32(0xdeadbeef, &key) % 200 << 16 | 4462306a36Sopenharmony_ci hsiphash_1u32(0xbabecafe, &key) % 200 << 8 | 4562306a36Sopenharmony_ci hsiphash_1u32(0xabad1dea, &key) % 200; 4662306a36Sopenharmony_ci style = "bold"; 4762306a36Sopenharmony_ci } 4862306a36Sopenharmony_ci wg_allowedips_read_node(node, ip1, &cidr1); 4962306a36Sopenharmony_ci printk(fmt_declaration, ip1, cidr1, style, color); 5062306a36Sopenharmony_ci if (node->bit[0]) { 5162306a36Sopenharmony_ci wg_allowedips_read_node(rcu_dereference_raw(node->bit[0]), ip2, &cidr2); 5262306a36Sopenharmony_ci printk(fmt_connection, ip1, cidr1, ip2, cidr2); 5362306a36Sopenharmony_ci } 5462306a36Sopenharmony_ci if (node->bit[1]) { 5562306a36Sopenharmony_ci wg_allowedips_read_node(rcu_dereference_raw(node->bit[1]), ip2, &cidr2); 5662306a36Sopenharmony_ci printk(fmt_connection, ip1, cidr1, ip2, cidr2); 5762306a36Sopenharmony_ci } 5862306a36Sopenharmony_ci if (node->bit[0]) 5962306a36Sopenharmony_ci print_node(rcu_dereference_raw(node->bit[0]), bits); 6062306a36Sopenharmony_ci if (node->bit[1]) 6162306a36Sopenharmony_ci print_node(rcu_dereference_raw(node->bit[1]), bits); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic __init void print_tree(struct allowedips_node __rcu *top, u8 bits) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci printk(KERN_DEBUG "digraph trie {\n"); 6762306a36Sopenharmony_ci print_node(rcu_dereference_raw(top), bits); 6862306a36Sopenharmony_ci printk(KERN_DEBUG "}\n"); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cienum { 7262306a36Sopenharmony_ci NUM_PEERS = 2000, 7362306a36Sopenharmony_ci NUM_RAND_ROUTES = 400, 7462306a36Sopenharmony_ci NUM_MUTATED_ROUTES = 100, 7562306a36Sopenharmony_ci NUM_QUERIES = NUM_RAND_ROUTES * NUM_MUTATED_ROUTES * 30 7662306a36Sopenharmony_ci}; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistruct horrible_allowedips { 7962306a36Sopenharmony_ci struct hlist_head head; 8062306a36Sopenharmony_ci}; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_cistruct horrible_allowedips_node { 8362306a36Sopenharmony_ci struct hlist_node table; 8462306a36Sopenharmony_ci union nf_inet_addr ip; 8562306a36Sopenharmony_ci union nf_inet_addr mask; 8662306a36Sopenharmony_ci u8 ip_version; 8762306a36Sopenharmony_ci void *value; 8862306a36Sopenharmony_ci}; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_cistatic __init void horrible_allowedips_init(struct horrible_allowedips *table) 9162306a36Sopenharmony_ci{ 9262306a36Sopenharmony_ci INIT_HLIST_HEAD(&table->head); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_cistatic __init void horrible_allowedips_free(struct horrible_allowedips *table) 9662306a36Sopenharmony_ci{ 9762306a36Sopenharmony_ci struct horrible_allowedips_node *node; 9862306a36Sopenharmony_ci struct hlist_node *h; 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci hlist_for_each_entry_safe(node, h, &table->head, table) { 10162306a36Sopenharmony_ci hlist_del(&node->table); 10262306a36Sopenharmony_ci kfree(node); 10362306a36Sopenharmony_ci } 10462306a36Sopenharmony_ci} 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_cistatic __init inline union nf_inet_addr horrible_cidr_to_mask(u8 cidr) 10762306a36Sopenharmony_ci{ 10862306a36Sopenharmony_ci union nf_inet_addr mask; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci memset(&mask, 0, sizeof(mask)); 11162306a36Sopenharmony_ci memset(&mask.all, 0xff, cidr / 8); 11262306a36Sopenharmony_ci if (cidr % 32) 11362306a36Sopenharmony_ci mask.all[cidr / 32] = (__force u32)htonl( 11462306a36Sopenharmony_ci (0xFFFFFFFFUL << (32 - (cidr % 32))) & 0xFFFFFFFFUL); 11562306a36Sopenharmony_ci return mask; 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistatic __init inline u8 horrible_mask_to_cidr(union nf_inet_addr subnet) 11962306a36Sopenharmony_ci{ 12062306a36Sopenharmony_ci return hweight32(subnet.all[0]) + hweight32(subnet.all[1]) + 12162306a36Sopenharmony_ci hweight32(subnet.all[2]) + hweight32(subnet.all[3]); 12262306a36Sopenharmony_ci} 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_cistatic __init inline void 12562306a36Sopenharmony_cihorrible_mask_self(struct horrible_allowedips_node *node) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci if (node->ip_version == 4) { 12862306a36Sopenharmony_ci node->ip.ip &= node->mask.ip; 12962306a36Sopenharmony_ci } else if (node->ip_version == 6) { 13062306a36Sopenharmony_ci node->ip.ip6[0] &= node->mask.ip6[0]; 13162306a36Sopenharmony_ci node->ip.ip6[1] &= node->mask.ip6[1]; 13262306a36Sopenharmony_ci node->ip.ip6[2] &= node->mask.ip6[2]; 13362306a36Sopenharmony_ci node->ip.ip6[3] &= node->mask.ip6[3]; 13462306a36Sopenharmony_ci } 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_cistatic __init inline bool 13862306a36Sopenharmony_cihorrible_match_v4(const struct horrible_allowedips_node *node, struct in_addr *ip) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci return (ip->s_addr & node->mask.ip) == node->ip.ip; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic __init inline bool 14462306a36Sopenharmony_cihorrible_match_v6(const struct horrible_allowedips_node *node, struct in6_addr *ip) 14562306a36Sopenharmony_ci{ 14662306a36Sopenharmony_ci return (ip->in6_u.u6_addr32[0] & node->mask.ip6[0]) == node->ip.ip6[0] && 14762306a36Sopenharmony_ci (ip->in6_u.u6_addr32[1] & node->mask.ip6[1]) == node->ip.ip6[1] && 14862306a36Sopenharmony_ci (ip->in6_u.u6_addr32[2] & node->mask.ip6[2]) == node->ip.ip6[2] && 14962306a36Sopenharmony_ci (ip->in6_u.u6_addr32[3] & node->mask.ip6[3]) == node->ip.ip6[3]; 15062306a36Sopenharmony_ci} 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_cistatic __init void 15362306a36Sopenharmony_cihorrible_insert_ordered(struct horrible_allowedips *table, struct horrible_allowedips_node *node) 15462306a36Sopenharmony_ci{ 15562306a36Sopenharmony_ci struct horrible_allowedips_node *other = NULL, *where = NULL; 15662306a36Sopenharmony_ci u8 my_cidr = horrible_mask_to_cidr(node->mask); 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci hlist_for_each_entry(other, &table->head, table) { 15962306a36Sopenharmony_ci if (other->ip_version == node->ip_version && 16062306a36Sopenharmony_ci !memcmp(&other->mask, &node->mask, sizeof(union nf_inet_addr)) && 16162306a36Sopenharmony_ci !memcmp(&other->ip, &node->ip, sizeof(union nf_inet_addr))) { 16262306a36Sopenharmony_ci other->value = node->value; 16362306a36Sopenharmony_ci kfree(node); 16462306a36Sopenharmony_ci return; 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci } 16762306a36Sopenharmony_ci hlist_for_each_entry(other, &table->head, table) { 16862306a36Sopenharmony_ci where = other; 16962306a36Sopenharmony_ci if (horrible_mask_to_cidr(other->mask) <= my_cidr) 17062306a36Sopenharmony_ci break; 17162306a36Sopenharmony_ci } 17262306a36Sopenharmony_ci if (!other && !where) 17362306a36Sopenharmony_ci hlist_add_head(&node->table, &table->head); 17462306a36Sopenharmony_ci else if (!other) 17562306a36Sopenharmony_ci hlist_add_behind(&node->table, &where->table); 17662306a36Sopenharmony_ci else 17762306a36Sopenharmony_ci hlist_add_before(&node->table, &where->table); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_cistatic __init int 18162306a36Sopenharmony_cihorrible_allowedips_insert_v4(struct horrible_allowedips *table, 18262306a36Sopenharmony_ci struct in_addr *ip, u8 cidr, void *value) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci if (unlikely(!node)) 18762306a36Sopenharmony_ci return -ENOMEM; 18862306a36Sopenharmony_ci node->ip.in = *ip; 18962306a36Sopenharmony_ci node->mask = horrible_cidr_to_mask(cidr); 19062306a36Sopenharmony_ci node->ip_version = 4; 19162306a36Sopenharmony_ci node->value = value; 19262306a36Sopenharmony_ci horrible_mask_self(node); 19362306a36Sopenharmony_ci horrible_insert_ordered(table, node); 19462306a36Sopenharmony_ci return 0; 19562306a36Sopenharmony_ci} 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_cistatic __init int 19862306a36Sopenharmony_cihorrible_allowedips_insert_v6(struct horrible_allowedips *table, 19962306a36Sopenharmony_ci struct in6_addr *ip, u8 cidr, void *value) 20062306a36Sopenharmony_ci{ 20162306a36Sopenharmony_ci struct horrible_allowedips_node *node = kzalloc(sizeof(*node), GFP_KERNEL); 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci if (unlikely(!node)) 20462306a36Sopenharmony_ci return -ENOMEM; 20562306a36Sopenharmony_ci node->ip.in6 = *ip; 20662306a36Sopenharmony_ci node->mask = horrible_cidr_to_mask(cidr); 20762306a36Sopenharmony_ci node->ip_version = 6; 20862306a36Sopenharmony_ci node->value = value; 20962306a36Sopenharmony_ci horrible_mask_self(node); 21062306a36Sopenharmony_ci horrible_insert_ordered(table, node); 21162306a36Sopenharmony_ci return 0; 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_cistatic __init void * 21562306a36Sopenharmony_cihorrible_allowedips_lookup_v4(struct horrible_allowedips *table, struct in_addr *ip) 21662306a36Sopenharmony_ci{ 21762306a36Sopenharmony_ci struct horrible_allowedips_node *node; 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci hlist_for_each_entry(node, &table->head, table) { 22062306a36Sopenharmony_ci if (node->ip_version == 4 && horrible_match_v4(node, ip)) 22162306a36Sopenharmony_ci return node->value; 22262306a36Sopenharmony_ci } 22362306a36Sopenharmony_ci return NULL; 22462306a36Sopenharmony_ci} 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic __init void * 22762306a36Sopenharmony_cihorrible_allowedips_lookup_v6(struct horrible_allowedips *table, struct in6_addr *ip) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci struct horrible_allowedips_node *node; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci hlist_for_each_entry(node, &table->head, table) { 23262306a36Sopenharmony_ci if (node->ip_version == 6 && horrible_match_v6(node, ip)) 23362306a36Sopenharmony_ci return node->value; 23462306a36Sopenharmony_ci } 23562306a36Sopenharmony_ci return NULL; 23662306a36Sopenharmony_ci} 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic __init void 24062306a36Sopenharmony_cihorrible_allowedips_remove_by_value(struct horrible_allowedips *table, void *value) 24162306a36Sopenharmony_ci{ 24262306a36Sopenharmony_ci struct horrible_allowedips_node *node; 24362306a36Sopenharmony_ci struct hlist_node *h; 24462306a36Sopenharmony_ci 24562306a36Sopenharmony_ci hlist_for_each_entry_safe(node, h, &table->head, table) { 24662306a36Sopenharmony_ci if (node->value != value) 24762306a36Sopenharmony_ci continue; 24862306a36Sopenharmony_ci hlist_del(&node->table); 24962306a36Sopenharmony_ci kfree(node); 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic __init bool randomized_test(void) 25562306a36Sopenharmony_ci{ 25662306a36Sopenharmony_ci unsigned int i, j, k, mutate_amount, cidr; 25762306a36Sopenharmony_ci u8 ip[16], mutate_mask[16], mutated[16]; 25862306a36Sopenharmony_ci struct wg_peer **peers, *peer; 25962306a36Sopenharmony_ci struct horrible_allowedips h; 26062306a36Sopenharmony_ci DEFINE_MUTEX(mutex); 26162306a36Sopenharmony_ci struct allowedips t; 26262306a36Sopenharmony_ci bool ret = false; 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci mutex_init(&mutex); 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci wg_allowedips_init(&t); 26762306a36Sopenharmony_ci horrible_allowedips_init(&h); 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_ci peers = kcalloc(NUM_PEERS, sizeof(*peers), GFP_KERNEL); 27062306a36Sopenharmony_ci if (unlikely(!peers)) { 27162306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 27262306a36Sopenharmony_ci goto free; 27362306a36Sopenharmony_ci } 27462306a36Sopenharmony_ci for (i = 0; i < NUM_PEERS; ++i) { 27562306a36Sopenharmony_ci peers[i] = kzalloc(sizeof(*peers[i]), GFP_KERNEL); 27662306a36Sopenharmony_ci if (unlikely(!peers[i])) { 27762306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 27862306a36Sopenharmony_ci goto free; 27962306a36Sopenharmony_ci } 28062306a36Sopenharmony_ci kref_init(&peers[i]->refcount); 28162306a36Sopenharmony_ci INIT_LIST_HEAD(&peers[i]->allowedips_list); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_ci mutex_lock(&mutex); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci for (i = 0; i < NUM_RAND_ROUTES; ++i) { 28762306a36Sopenharmony_ci get_random_bytes(ip, 4); 28862306a36Sopenharmony_ci cidr = get_random_u32_inclusive(1, 32); 28962306a36Sopenharmony_ci peer = peers[get_random_u32_below(NUM_PEERS)]; 29062306a36Sopenharmony_ci if (wg_allowedips_insert_v4(&t, (struct in_addr *)ip, cidr, 29162306a36Sopenharmony_ci peer, &mutex) < 0) { 29262306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 29362306a36Sopenharmony_ci goto free_locked; 29462306a36Sopenharmony_ci } 29562306a36Sopenharmony_ci if (horrible_allowedips_insert_v4(&h, (struct in_addr *)ip, 29662306a36Sopenharmony_ci cidr, peer) < 0) { 29762306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 29862306a36Sopenharmony_ci goto free_locked; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci for (j = 0; j < NUM_MUTATED_ROUTES; ++j) { 30162306a36Sopenharmony_ci memcpy(mutated, ip, 4); 30262306a36Sopenharmony_ci get_random_bytes(mutate_mask, 4); 30362306a36Sopenharmony_ci mutate_amount = get_random_u32_below(32); 30462306a36Sopenharmony_ci for (k = 0; k < mutate_amount / 8; ++k) 30562306a36Sopenharmony_ci mutate_mask[k] = 0xff; 30662306a36Sopenharmony_ci mutate_mask[k] = 0xff 30762306a36Sopenharmony_ci << ((8 - (mutate_amount % 8)) % 8); 30862306a36Sopenharmony_ci for (; k < 4; ++k) 30962306a36Sopenharmony_ci mutate_mask[k] = 0; 31062306a36Sopenharmony_ci for (k = 0; k < 4; ++k) 31162306a36Sopenharmony_ci mutated[k] = (mutated[k] & mutate_mask[k]) | 31262306a36Sopenharmony_ci (~mutate_mask[k] & 31362306a36Sopenharmony_ci get_random_u8()); 31462306a36Sopenharmony_ci cidr = get_random_u32_inclusive(1, 32); 31562306a36Sopenharmony_ci peer = peers[get_random_u32_below(NUM_PEERS)]; 31662306a36Sopenharmony_ci if (wg_allowedips_insert_v4(&t, 31762306a36Sopenharmony_ci (struct in_addr *)mutated, 31862306a36Sopenharmony_ci cidr, peer, &mutex) < 0) { 31962306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 32062306a36Sopenharmony_ci goto free_locked; 32162306a36Sopenharmony_ci } 32262306a36Sopenharmony_ci if (horrible_allowedips_insert_v4(&h, 32362306a36Sopenharmony_ci (struct in_addr *)mutated, cidr, peer)) { 32462306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 32562306a36Sopenharmony_ci goto free_locked; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci } 32862306a36Sopenharmony_ci } 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci for (i = 0; i < NUM_RAND_ROUTES; ++i) { 33162306a36Sopenharmony_ci get_random_bytes(ip, 16); 33262306a36Sopenharmony_ci cidr = get_random_u32_inclusive(1, 128); 33362306a36Sopenharmony_ci peer = peers[get_random_u32_below(NUM_PEERS)]; 33462306a36Sopenharmony_ci if (wg_allowedips_insert_v6(&t, (struct in6_addr *)ip, cidr, 33562306a36Sopenharmony_ci peer, &mutex) < 0) { 33662306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 33762306a36Sopenharmony_ci goto free_locked; 33862306a36Sopenharmony_ci } 33962306a36Sopenharmony_ci if (horrible_allowedips_insert_v6(&h, (struct in6_addr *)ip, 34062306a36Sopenharmony_ci cidr, peer) < 0) { 34162306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 34262306a36Sopenharmony_ci goto free_locked; 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci for (j = 0; j < NUM_MUTATED_ROUTES; ++j) { 34562306a36Sopenharmony_ci memcpy(mutated, ip, 16); 34662306a36Sopenharmony_ci get_random_bytes(mutate_mask, 16); 34762306a36Sopenharmony_ci mutate_amount = get_random_u32_below(128); 34862306a36Sopenharmony_ci for (k = 0; k < mutate_amount / 8; ++k) 34962306a36Sopenharmony_ci mutate_mask[k] = 0xff; 35062306a36Sopenharmony_ci mutate_mask[k] = 0xff 35162306a36Sopenharmony_ci << ((8 - (mutate_amount % 8)) % 8); 35262306a36Sopenharmony_ci for (; k < 4; ++k) 35362306a36Sopenharmony_ci mutate_mask[k] = 0; 35462306a36Sopenharmony_ci for (k = 0; k < 4; ++k) 35562306a36Sopenharmony_ci mutated[k] = (mutated[k] & mutate_mask[k]) | 35662306a36Sopenharmony_ci (~mutate_mask[k] & 35762306a36Sopenharmony_ci get_random_u8()); 35862306a36Sopenharmony_ci cidr = get_random_u32_inclusive(1, 128); 35962306a36Sopenharmony_ci peer = peers[get_random_u32_below(NUM_PEERS)]; 36062306a36Sopenharmony_ci if (wg_allowedips_insert_v6(&t, 36162306a36Sopenharmony_ci (struct in6_addr *)mutated, 36262306a36Sopenharmony_ci cidr, peer, &mutex) < 0) { 36362306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 36462306a36Sopenharmony_ci goto free_locked; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci if (horrible_allowedips_insert_v6( 36762306a36Sopenharmony_ci &h, (struct in6_addr *)mutated, cidr, 36862306a36Sopenharmony_ci peer)) { 36962306a36Sopenharmony_ci pr_err("allowedips random self-test malloc: FAIL\n"); 37062306a36Sopenharmony_ci goto free_locked; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci } 37362306a36Sopenharmony_ci } 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci mutex_unlock(&mutex); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci if (IS_ENABLED(DEBUG_PRINT_TRIE_GRAPHVIZ)) { 37862306a36Sopenharmony_ci print_tree(t.root4, 32); 37962306a36Sopenharmony_ci print_tree(t.root6, 128); 38062306a36Sopenharmony_ci } 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci for (j = 0;; ++j) { 38362306a36Sopenharmony_ci for (i = 0; i < NUM_QUERIES; ++i) { 38462306a36Sopenharmony_ci get_random_bytes(ip, 4); 38562306a36Sopenharmony_ci if (lookup(t.root4, 32, ip) != horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip)) { 38662306a36Sopenharmony_ci horrible_allowedips_lookup_v4(&h, (struct in_addr *)ip); 38762306a36Sopenharmony_ci pr_err("allowedips random v4 self-test: FAIL\n"); 38862306a36Sopenharmony_ci goto free; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci get_random_bytes(ip, 16); 39162306a36Sopenharmony_ci if (lookup(t.root6, 128, ip) != horrible_allowedips_lookup_v6(&h, (struct in6_addr *)ip)) { 39262306a36Sopenharmony_ci pr_err("allowedips random v6 self-test: FAIL\n"); 39362306a36Sopenharmony_ci goto free; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci } 39662306a36Sopenharmony_ci if (j >= NUM_PEERS) 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci mutex_lock(&mutex); 39962306a36Sopenharmony_ci wg_allowedips_remove_by_peer(&t, peers[j], &mutex); 40062306a36Sopenharmony_ci mutex_unlock(&mutex); 40162306a36Sopenharmony_ci horrible_allowedips_remove_by_value(&h, peers[j]); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci if (t.root4 || t.root6) { 40562306a36Sopenharmony_ci pr_err("allowedips random self-test removal: FAIL\n"); 40662306a36Sopenharmony_ci goto free; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ret = true; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cifree: 41262306a36Sopenharmony_ci mutex_lock(&mutex); 41362306a36Sopenharmony_cifree_locked: 41462306a36Sopenharmony_ci wg_allowedips_free(&t, &mutex); 41562306a36Sopenharmony_ci mutex_unlock(&mutex); 41662306a36Sopenharmony_ci horrible_allowedips_free(&h); 41762306a36Sopenharmony_ci if (peers) { 41862306a36Sopenharmony_ci for (i = 0; i < NUM_PEERS; ++i) 41962306a36Sopenharmony_ci kfree(peers[i]); 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci kfree(peers); 42262306a36Sopenharmony_ci return ret; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic __init inline struct in_addr *ip4(u8 a, u8 b, u8 c, u8 d) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci static struct in_addr ip; 42862306a36Sopenharmony_ci u8 *split = (u8 *)&ip; 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_ci split[0] = a; 43162306a36Sopenharmony_ci split[1] = b; 43262306a36Sopenharmony_ci split[2] = c; 43362306a36Sopenharmony_ci split[3] = d; 43462306a36Sopenharmony_ci return &ip; 43562306a36Sopenharmony_ci} 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_cistatic __init inline struct in6_addr *ip6(u32 a, u32 b, u32 c, u32 d) 43862306a36Sopenharmony_ci{ 43962306a36Sopenharmony_ci static struct in6_addr ip; 44062306a36Sopenharmony_ci __be32 *split = (__be32 *)&ip; 44162306a36Sopenharmony_ci 44262306a36Sopenharmony_ci split[0] = cpu_to_be32(a); 44362306a36Sopenharmony_ci split[1] = cpu_to_be32(b); 44462306a36Sopenharmony_ci split[2] = cpu_to_be32(c); 44562306a36Sopenharmony_ci split[3] = cpu_to_be32(d); 44662306a36Sopenharmony_ci return &ip; 44762306a36Sopenharmony_ci} 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic __init struct wg_peer *init_peer(void) 45062306a36Sopenharmony_ci{ 45162306a36Sopenharmony_ci struct wg_peer *peer = kzalloc(sizeof(*peer), GFP_KERNEL); 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci if (!peer) 45462306a36Sopenharmony_ci return NULL; 45562306a36Sopenharmony_ci kref_init(&peer->refcount); 45662306a36Sopenharmony_ci INIT_LIST_HEAD(&peer->allowedips_list); 45762306a36Sopenharmony_ci return peer; 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci#define insert(version, mem, ipa, ipb, ipc, ipd, cidr) \ 46162306a36Sopenharmony_ci wg_allowedips_insert_v##version(&t, ip##version(ipa, ipb, ipc, ipd), \ 46262306a36Sopenharmony_ci cidr, mem, &mutex) 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci#define maybe_fail() do { \ 46562306a36Sopenharmony_ci ++i; \ 46662306a36Sopenharmony_ci if (!_s) { \ 46762306a36Sopenharmony_ci pr_info("allowedips self-test %zu: FAIL\n", i); \ 46862306a36Sopenharmony_ci success = false; \ 46962306a36Sopenharmony_ci } \ 47062306a36Sopenharmony_ci } while (0) 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_ci#define test(version, mem, ipa, ipb, ipc, ipd) do { \ 47362306a36Sopenharmony_ci bool _s = lookup(t.root##version, (version) == 4 ? 32 : 128, \ 47462306a36Sopenharmony_ci ip##version(ipa, ipb, ipc, ipd)) == (mem); \ 47562306a36Sopenharmony_ci maybe_fail(); \ 47662306a36Sopenharmony_ci } while (0) 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci#define test_negative(version, mem, ipa, ipb, ipc, ipd) do { \ 47962306a36Sopenharmony_ci bool _s = lookup(t.root##version, (version) == 4 ? 32 : 128, \ 48062306a36Sopenharmony_ci ip##version(ipa, ipb, ipc, ipd)) != (mem); \ 48162306a36Sopenharmony_ci maybe_fail(); \ 48262306a36Sopenharmony_ci } while (0) 48362306a36Sopenharmony_ci 48462306a36Sopenharmony_ci#define test_boolean(cond) do { \ 48562306a36Sopenharmony_ci bool _s = (cond); \ 48662306a36Sopenharmony_ci maybe_fail(); \ 48762306a36Sopenharmony_ci } while (0) 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_cibool __init wg_allowedips_selftest(void) 49062306a36Sopenharmony_ci{ 49162306a36Sopenharmony_ci bool found_a = false, found_b = false, found_c = false, found_d = false, 49262306a36Sopenharmony_ci found_e = false, found_other = false; 49362306a36Sopenharmony_ci struct wg_peer *a = init_peer(), *b = init_peer(), *c = init_peer(), 49462306a36Sopenharmony_ci *d = init_peer(), *e = init_peer(), *f = init_peer(), 49562306a36Sopenharmony_ci *g = init_peer(), *h = init_peer(); 49662306a36Sopenharmony_ci struct allowedips_node *iter_node; 49762306a36Sopenharmony_ci bool success = false; 49862306a36Sopenharmony_ci struct allowedips t; 49962306a36Sopenharmony_ci DEFINE_MUTEX(mutex); 50062306a36Sopenharmony_ci struct in6_addr ip; 50162306a36Sopenharmony_ci size_t i = 0, count = 0; 50262306a36Sopenharmony_ci __be64 part; 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci mutex_init(&mutex); 50562306a36Sopenharmony_ci mutex_lock(&mutex); 50662306a36Sopenharmony_ci wg_allowedips_init(&t); 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci if (!a || !b || !c || !d || !e || !f || !g || !h) { 50962306a36Sopenharmony_ci pr_err("allowedips self-test malloc: FAIL\n"); 51062306a36Sopenharmony_ci goto free; 51162306a36Sopenharmony_ci } 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci insert(4, a, 192, 168, 4, 0, 24); 51462306a36Sopenharmony_ci insert(4, b, 192, 168, 4, 4, 32); 51562306a36Sopenharmony_ci insert(4, c, 192, 168, 0, 0, 16); 51662306a36Sopenharmony_ci insert(4, d, 192, 95, 5, 64, 27); 51762306a36Sopenharmony_ci /* replaces previous entry, and maskself is required */ 51862306a36Sopenharmony_ci insert(4, c, 192, 95, 5, 65, 27); 51962306a36Sopenharmony_ci insert(6, d, 0x26075300, 0x60006b00, 0, 0xc05f0543, 128); 52062306a36Sopenharmony_ci insert(6, c, 0x26075300, 0x60006b00, 0, 0, 64); 52162306a36Sopenharmony_ci insert(4, e, 0, 0, 0, 0, 0); 52262306a36Sopenharmony_ci insert(6, e, 0, 0, 0, 0, 0); 52362306a36Sopenharmony_ci /* replaces previous entry */ 52462306a36Sopenharmony_ci insert(6, f, 0, 0, 0, 0, 0); 52562306a36Sopenharmony_ci insert(6, g, 0x24046800, 0, 0, 0, 32); 52662306a36Sopenharmony_ci /* maskself is required */ 52762306a36Sopenharmony_ci insert(6, h, 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 64); 52862306a36Sopenharmony_ci insert(6, a, 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef, 128); 52962306a36Sopenharmony_ci insert(6, c, 0x24446800, 0x40e40800, 0xdeaebeef, 0xdefbeef, 128); 53062306a36Sopenharmony_ci insert(6, b, 0x24446800, 0xf0e40800, 0xeeaebeef, 0, 98); 53162306a36Sopenharmony_ci insert(4, g, 64, 15, 112, 0, 20); 53262306a36Sopenharmony_ci /* maskself is required */ 53362306a36Sopenharmony_ci insert(4, h, 64, 15, 123, 211, 25); 53462306a36Sopenharmony_ci insert(4, a, 10, 0, 0, 0, 25); 53562306a36Sopenharmony_ci insert(4, b, 10, 0, 0, 128, 25); 53662306a36Sopenharmony_ci insert(4, a, 10, 1, 0, 0, 30); 53762306a36Sopenharmony_ci insert(4, b, 10, 1, 0, 4, 30); 53862306a36Sopenharmony_ci insert(4, c, 10, 1, 0, 8, 29); 53962306a36Sopenharmony_ci insert(4, d, 10, 1, 0, 16, 29); 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci if (IS_ENABLED(DEBUG_PRINT_TRIE_GRAPHVIZ)) { 54262306a36Sopenharmony_ci print_tree(t.root4, 32); 54362306a36Sopenharmony_ci print_tree(t.root6, 128); 54462306a36Sopenharmony_ci } 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci success = true; 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci test(4, a, 192, 168, 4, 20); 54962306a36Sopenharmony_ci test(4, a, 192, 168, 4, 0); 55062306a36Sopenharmony_ci test(4, b, 192, 168, 4, 4); 55162306a36Sopenharmony_ci test(4, c, 192, 168, 200, 182); 55262306a36Sopenharmony_ci test(4, c, 192, 95, 5, 68); 55362306a36Sopenharmony_ci test(4, e, 192, 95, 5, 96); 55462306a36Sopenharmony_ci test(6, d, 0x26075300, 0x60006b00, 0, 0xc05f0543); 55562306a36Sopenharmony_ci test(6, c, 0x26075300, 0x60006b00, 0, 0xc02e01ee); 55662306a36Sopenharmony_ci test(6, f, 0x26075300, 0x60006b01, 0, 0); 55762306a36Sopenharmony_ci test(6, g, 0x24046800, 0x40040806, 0, 0x1006); 55862306a36Sopenharmony_ci test(6, g, 0x24046800, 0x40040806, 0x1234, 0x5678); 55962306a36Sopenharmony_ci test(6, f, 0x240467ff, 0x40040806, 0x1234, 0x5678); 56062306a36Sopenharmony_ci test(6, f, 0x24046801, 0x40040806, 0x1234, 0x5678); 56162306a36Sopenharmony_ci test(6, h, 0x24046800, 0x40040800, 0x1234, 0x5678); 56262306a36Sopenharmony_ci test(6, h, 0x24046800, 0x40040800, 0, 0); 56362306a36Sopenharmony_ci test(6, h, 0x24046800, 0x40040800, 0x10101010, 0x10101010); 56462306a36Sopenharmony_ci test(6, a, 0x24046800, 0x40040800, 0xdeadbeef, 0xdeadbeef); 56562306a36Sopenharmony_ci test(4, g, 64, 15, 116, 26); 56662306a36Sopenharmony_ci test(4, g, 64, 15, 127, 3); 56762306a36Sopenharmony_ci test(4, g, 64, 15, 123, 1); 56862306a36Sopenharmony_ci test(4, h, 64, 15, 123, 128); 56962306a36Sopenharmony_ci test(4, h, 64, 15, 123, 129); 57062306a36Sopenharmony_ci test(4, a, 10, 0, 0, 52); 57162306a36Sopenharmony_ci test(4, b, 10, 0, 0, 220); 57262306a36Sopenharmony_ci test(4, a, 10, 1, 0, 2); 57362306a36Sopenharmony_ci test(4, b, 10, 1, 0, 6); 57462306a36Sopenharmony_ci test(4, c, 10, 1, 0, 10); 57562306a36Sopenharmony_ci test(4, d, 10, 1, 0, 20); 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci insert(4, a, 1, 0, 0, 0, 32); 57862306a36Sopenharmony_ci insert(4, a, 64, 0, 0, 0, 32); 57962306a36Sopenharmony_ci insert(4, a, 128, 0, 0, 0, 32); 58062306a36Sopenharmony_ci insert(4, a, 192, 0, 0, 0, 32); 58162306a36Sopenharmony_ci insert(4, a, 255, 0, 0, 0, 32); 58262306a36Sopenharmony_ci wg_allowedips_remove_by_peer(&t, a, &mutex); 58362306a36Sopenharmony_ci test_negative(4, a, 1, 0, 0, 0); 58462306a36Sopenharmony_ci test_negative(4, a, 64, 0, 0, 0); 58562306a36Sopenharmony_ci test_negative(4, a, 128, 0, 0, 0); 58662306a36Sopenharmony_ci test_negative(4, a, 192, 0, 0, 0); 58762306a36Sopenharmony_ci test_negative(4, a, 255, 0, 0, 0); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci wg_allowedips_free(&t, &mutex); 59062306a36Sopenharmony_ci wg_allowedips_init(&t); 59162306a36Sopenharmony_ci insert(4, a, 192, 168, 0, 0, 16); 59262306a36Sopenharmony_ci insert(4, a, 192, 168, 0, 0, 24); 59362306a36Sopenharmony_ci wg_allowedips_remove_by_peer(&t, a, &mutex); 59462306a36Sopenharmony_ci test_negative(4, a, 192, 168, 0, 1); 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci /* These will hit the WARN_ON(len >= MAX_ALLOWEDIPS_DEPTH) in free_node 59762306a36Sopenharmony_ci * if something goes wrong. 59862306a36Sopenharmony_ci */ 59962306a36Sopenharmony_ci for (i = 0; i < 64; ++i) { 60062306a36Sopenharmony_ci part = cpu_to_be64(~0LLU << i); 60162306a36Sopenharmony_ci memset(&ip, 0xff, 8); 60262306a36Sopenharmony_ci memcpy((u8 *)&ip + 8, &part, 8); 60362306a36Sopenharmony_ci wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); 60462306a36Sopenharmony_ci memcpy(&ip, &part, 8); 60562306a36Sopenharmony_ci memset((u8 *)&ip + 8, 0, 8); 60662306a36Sopenharmony_ci wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci memset(&ip, 0, 16); 60962306a36Sopenharmony_ci wg_allowedips_insert_v6(&t, &ip, 128, a, &mutex); 61062306a36Sopenharmony_ci wg_allowedips_free(&t, &mutex); 61162306a36Sopenharmony_ci 61262306a36Sopenharmony_ci wg_allowedips_init(&t); 61362306a36Sopenharmony_ci insert(4, a, 192, 95, 5, 93, 27); 61462306a36Sopenharmony_ci insert(6, a, 0x26075300, 0x60006b00, 0, 0xc05f0543, 128); 61562306a36Sopenharmony_ci insert(4, a, 10, 1, 0, 20, 29); 61662306a36Sopenharmony_ci insert(6, a, 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 83); 61762306a36Sopenharmony_ci insert(6, a, 0x26075300, 0x6d8a6bf8, 0xdab1f1df, 0xc05f1523, 21); 61862306a36Sopenharmony_ci list_for_each_entry(iter_node, &a->allowedips_list, peer_list) { 61962306a36Sopenharmony_ci u8 cidr, ip[16] __aligned(__alignof(u64)); 62062306a36Sopenharmony_ci int family = wg_allowedips_read_node(iter_node, ip, &cidr); 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci count++; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci if (cidr == 27 && family == AF_INET && 62562306a36Sopenharmony_ci !memcmp(ip, ip4(192, 95, 5, 64), sizeof(struct in_addr))) 62662306a36Sopenharmony_ci found_a = true; 62762306a36Sopenharmony_ci else if (cidr == 128 && family == AF_INET6 && 62862306a36Sopenharmony_ci !memcmp(ip, ip6(0x26075300, 0x60006b00, 0, 0xc05f0543), 62962306a36Sopenharmony_ci sizeof(struct in6_addr))) 63062306a36Sopenharmony_ci found_b = true; 63162306a36Sopenharmony_ci else if (cidr == 29 && family == AF_INET && 63262306a36Sopenharmony_ci !memcmp(ip, ip4(10, 1, 0, 16), sizeof(struct in_addr))) 63362306a36Sopenharmony_ci found_c = true; 63462306a36Sopenharmony_ci else if (cidr == 83 && family == AF_INET6 && 63562306a36Sopenharmony_ci !memcmp(ip, ip6(0x26075300, 0x6d8a6bf8, 0xdab1e000, 0), 63662306a36Sopenharmony_ci sizeof(struct in6_addr))) 63762306a36Sopenharmony_ci found_d = true; 63862306a36Sopenharmony_ci else if (cidr == 21 && family == AF_INET6 && 63962306a36Sopenharmony_ci !memcmp(ip, ip6(0x26075000, 0, 0, 0), 64062306a36Sopenharmony_ci sizeof(struct in6_addr))) 64162306a36Sopenharmony_ci found_e = true; 64262306a36Sopenharmony_ci else 64362306a36Sopenharmony_ci found_other = true; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci test_boolean(count == 5); 64662306a36Sopenharmony_ci test_boolean(found_a); 64762306a36Sopenharmony_ci test_boolean(found_b); 64862306a36Sopenharmony_ci test_boolean(found_c); 64962306a36Sopenharmony_ci test_boolean(found_d); 65062306a36Sopenharmony_ci test_boolean(found_e); 65162306a36Sopenharmony_ci test_boolean(!found_other); 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci if (IS_ENABLED(DEBUG_RANDOM_TRIE) && success) 65462306a36Sopenharmony_ci success = randomized_test(); 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (success) 65762306a36Sopenharmony_ci pr_info("allowedips self-tests: pass\n"); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_cifree: 66062306a36Sopenharmony_ci wg_allowedips_free(&t, &mutex); 66162306a36Sopenharmony_ci kfree(a); 66262306a36Sopenharmony_ci kfree(b); 66362306a36Sopenharmony_ci kfree(c); 66462306a36Sopenharmony_ci kfree(d); 66562306a36Sopenharmony_ci kfree(e); 66662306a36Sopenharmony_ci kfree(f); 66762306a36Sopenharmony_ci kfree(g); 66862306a36Sopenharmony_ci kfree(h); 66962306a36Sopenharmony_ci mutex_unlock(&mutex); 67062306a36Sopenharmony_ci 67162306a36Sopenharmony_ci return success; 67262306a36Sopenharmony_ci} 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci#undef test_negative 67562306a36Sopenharmony_ci#undef test 67662306a36Sopenharmony_ci#undef remove 67762306a36Sopenharmony_ci#undef insert 67862306a36Sopenharmony_ci#undef init_peer 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci#endif 681