1 /* $NetBSD: npf_table_test.c,v 1.9 2016/12/26 23:05:05 christos Exp $ */ 2 3 /* 4 * NPF tableset test. 5 * 6 * Public Domain. 7 */ 8 9 #ifdef _KERNEL 10 #include <sys/types.h> 11 #include <sys/malloc.h> 12 #endif 13 14 #ifdef __linux__ 15 #include <endian.h> 16 #else 17 #include <sys/endian.h> 18 #endif 19 20 #include "npf_impl.h" 21 #include "npf_test.h" 22 23 static const char *ip_list[] = { 24 "192.168.1.1", 25 "10.0.0.1", 26 "192.168.2.1", 27 "10.1.0.1", 28 "192.168.100.253", 29 "10.0.5.1", 30 "192.168.128.127", 31 "10.0.0.2", 32 }; 33 34 #if __BYTE_ORDER == __LITTLE_ENDIAN 35 #define U16_TO_LE(x) ((((x) & 0xff) << 8) | (((x) & 0xff00) >> 8)) 36 #else 37 #define U16_TO_LE(x) (x) 38 #endif 39 40 static const uint16_t ip6_list[][8] = { 41 { 42 U16_TO_LE(0xfe80), 0x0, 0x0, 0x0, 43 U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff), 44 U16_TO_LE(0xfe10), U16_TO_LE(0x1234) 45 }, 46 { 47 U16_TO_LE(0xfe80), 0x0, 0x0, 0x0, 48 U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff), 0x00, 0x0 49 }, 50 { 51 U16_TO_LE(0xfe80), 0x0, 0x0, 0x0, 52 0x0, 0x0, 0x0, 0x0 53 }, 54 { 55 U16_TO_LE(0xfe80), 0x0, 0x0, 0x0, 56 U16_TO_LE(0x2a0), U16_TO_LE(0xc0ff), 57 U16_TO_LE(0xfe10), U16_TO_LE(0x1230) 58 } 59 }; 60 61 #define check_ok(x) \ 62 ((x) ? true : (printf("fail at line %d\n", __LINE__), false)) 63 64 #define HASH_TID "hash-table" 65 #define TREE_TID "tree-table" 66 #define CDB_TID "cdb-table" 67 68 static bool 69 npf_table_test_fill4(npf_tableset_t *tblset, npf_addr_t *addr) 70 { 71 const int alen = sizeof(struct in_addr); 72 const int nm = NPF_NO_NETMASK; 73 bool fail = false; 74 75 /* Fill both tables with IP addresses. */ 76 for (unsigned i = 0; i < __arraycount(ip_list); i++) { 77 npf_table_t *t; 78 int error; 79 80 addr->word32[0] = inet_addr(ip_list[i]); 81 82 t = npf_tableset_getbyname(tblset, HASH_TID); 83 error = npf_table_insert(t, alen, addr, nm); 84 fail |= !check_ok(error == 0); 85 error = npf_table_insert(t, alen, addr, nm); 86 fail |= !check_ok(error != 0); 87 88 t = npf_tableset_getbyname(tblset, TREE_TID); 89 error = npf_table_insert(t, alen, addr, nm); 90 fail |= !check_ok(error == 0); 91 error = npf_table_insert(t, alen, addr, nm); 92 fail |= !check_ok(error != 0); 93 } 94 return fail; 95 } 96 97 bool 98 npf_table_test(bool verbose, void *blob, size_t size) 99 { 100 npf_addr_t addr_storage, *addr = &addr_storage; 101 const int nm = NPF_NO_NETMASK; 102 npf_table_t *t, *t1, *t2, *t3; 103 npf_tableset_t *tblset; 104 int error, alen; 105 bool fail = false; 106 void *cdb; 107 u_int i; 108 109 tblset = npf_tableset_create(3); 110 fail |= !check_ok(tblset != NULL); 111 112 /* Table ID 1, using hash table with 256 lists. */ 113 t1 = npf_table_create(HASH_TID, 0, NPF_TABLE_HASH, NULL, 256); 114 fail |= !check_ok(t1 != NULL); 115 error = npf_tableset_insert(tblset, t1); 116 fail |= !check_ok(error == 0); 117 118 /* Check for double-insert. */ 119 error = npf_tableset_insert(tblset, t1); 120 fail |= !check_ok(error != 0); 121 122 /* Table ID 2, using a prefix tree. */ 123 t2 = npf_table_create(TREE_TID, 1, NPF_TABLE_TREE, NULL, 0); 124 fail |= !(t2 != NULL); 125 error = npf_tableset_insert(tblset, t2); 126 fail |= !check_ok(error == 0); 127 128 /* Table ID 3, using a CDB. */ 129 cdb = malloc(size, M_TEMP, M_WAITOK); 130 memcpy(cdb, blob, size); 131 132 t3 = npf_table_create(CDB_TID, 2, NPF_TABLE_CDB, cdb, size); 133 fail |= !(t3 != NULL); 134 error = npf_tableset_insert(tblset, t3); 135 fail |= !check_ok(error == 0); 136 137 /* Attempt to match non-existing entries - should fail. */ 138 addr->word32[0] = inet_addr(ip_list[0]); 139 alen = sizeof(struct in_addr); 140 141 t = npf_tableset_getbyname(tblset, HASH_TID); 142 error = npf_table_lookup(t, alen, addr); 143 fail |= !check_ok(error != 0); 144 145 t = npf_tableset_getbyname(tblset, TREE_TID); 146 error = npf_table_lookup(t, alen, addr); 147 fail |= !check_ok(error != 0); 148 149 /* Fill both tables with IP addresses. */ 150 fail |= npf_table_test_fill4(tblset, addr); 151 152 /* Attempt to add duplicates - should fail. */ 153 addr->word32[0] = inet_addr(ip_list[0]); 154 alen = sizeof(struct in_addr); 155 156 t = npf_tableset_getbyname(tblset, HASH_TID); 157 error = npf_table_insert(t, alen, addr, nm); 158 fail |= !check_ok(error != 0); 159 160 t = npf_tableset_getbyname(tblset, TREE_TID); 161 error = npf_table_insert(t, alen, addr, nm); 162 fail |= !check_ok(error != 0); 163 164 /* Match (validate) each IP entry. */ 165 for (i = 0; i < __arraycount(ip_list); i++) { 166 addr->word32[0] = inet_addr(ip_list[i]); 167 168 t = npf_tableset_getbyname(tblset, HASH_TID); 169 error = npf_table_lookup(t, alen, addr); 170 fail |= !check_ok(error == 0); 171 172 t = npf_tableset_getbyname(tblset, TREE_TID); 173 error = npf_table_lookup(t, alen, addr); 174 fail |= !check_ok(error == 0); 175 } 176 177 /* IPv6 addresses. */ 178 memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); 179 alen = sizeof(struct in6_addr); 180 181 t = npf_tableset_getbyname(tblset, HASH_TID); 182 error = npf_table_insert(t, alen, addr, nm); 183 fail |= !check_ok(error == 0); 184 error = npf_table_lookup(t, alen, addr); 185 fail |= !check_ok(error == 0); 186 error = npf_table_remove(t, alen, addr, nm); 187 fail |= !check_ok(error == 0); 188 189 t = npf_tableset_getbyname(tblset, TREE_TID); 190 error = npf_table_insert(t, alen, addr, nm); 191 fail |= !check_ok(error == 0); 192 error = npf_table_lookup(t, alen, addr); 193 fail |= !check_ok(error == 0); 194 error = npf_table_remove(t, alen, addr, nm); 195 fail |= !check_ok(error == 0); 196 197 /* 198 * Masking: 96, 32, 127. 199 */ 200 201 memcpy(addr, ip6_list[1], sizeof(ip6_list[1])); 202 error = npf_table_insert(t, alen, addr, 96); 203 fail |= !check_ok(error == 0); 204 205 memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); 206 error = npf_table_lookup(t, alen, addr); 207 fail |= !check_ok(error == 0); 208 209 memcpy(addr, ip6_list[1], sizeof(ip6_list[1])); 210 error = npf_table_remove(t, alen, addr, 96); 211 fail |= !check_ok(error == 0); 212 213 214 memcpy(addr, ip6_list[2], sizeof(ip6_list[2])); 215 error = npf_table_insert(t, alen, addr, 32); 216 fail |= !check_ok(error == 0); 217 218 memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); 219 error = npf_table_lookup(t, alen, addr); 220 fail |= !check_ok(error == 0); 221 222 memcpy(addr, ip6_list[2], sizeof(ip6_list[2])); 223 error = npf_table_remove(t, alen, addr, 32); 224 fail |= !check_ok(error == 0); 225 226 227 memcpy(addr, ip6_list[3], sizeof(ip6_list[3])); 228 error = npf_table_insert(t, alen, addr, 126); 229 fail |= !check_ok(error == 0); 230 231 memcpy(addr, ip6_list[0], sizeof(ip6_list[0])); 232 error = npf_table_lookup(t, alen, addr); 233 fail |= !check_ok(error != 0); 234 235 memcpy(addr, ip6_list[3], sizeof(ip6_list[3])); 236 error = npf_table_remove(t, alen, addr, 126); 237 fail |= !check_ok(error == 0); 238 239 240 alen = sizeof(struct in_addr); 241 242 /* Remove all IPv4 entries. */ 243 for (i = 0; i < __arraycount(ip_list); i++) { 244 addr->word32[0] = inet_addr(ip_list[i]); 245 246 t = npf_tableset_getbyname(tblset, HASH_TID); 247 error = npf_table_remove(t, alen, addr, nm); 248 fail |= !check_ok(error == 0); 249 250 t = npf_tableset_getbyname(tblset, TREE_TID); 251 error = npf_table_remove(t, alen, addr, nm); 252 fail |= !check_ok(error == 0); 253 } 254 255 /* Test CDB. */ 256 addr->word32[0] = inet_addr(ip_list[0]); 257 alen = sizeof(struct in_addr); 258 error = npf_table_lookup(t3, alen, addr); 259 fail |= !check_ok(error == 0); 260 261 for (i = 1; i < __arraycount(ip_list) - 1; i++) { 262 addr->word32[0] = inet_addr(ip_list[i]); 263 alen = sizeof(struct in_addr); 264 error = npf_table_lookup(t3, alen, addr); 265 fail |= !check_ok(error != 0); 266 } 267 268 npf_tableset_destroy(tblset); 269 270 return !fail; 271 } 272