1 /* $NetBSD: ip_htable.c,v 1.8 2026/01/11 15:54:52 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2012 by Darren Reed. 5 * 6 * See the IPFILTER.LICENCE file for details on licencing. 7 */ 8 #if defined(KERNEL) || defined(_KERNEL) 9 # undef KERNEL 10 # undef _KERNEL 11 # define KERNEL 1 12 # define _KERNEL 1 13 #endif 14 #include <sys/param.h> 15 #if defined(__NetBSD__) 16 # if (NetBSD >= 199905) && !defined(IPFILTER_LKM) && defined(_KERNEL) 17 # if (__NetBSD_Version__ >= 799003000) 18 # if defined(_KERNEL_OPT) 19 # include "opt_ipfilter.h" 20 # endif 21 # else 22 # include "opt_ipfilter.h" 23 # endif 24 # endif 25 #endif 26 #include <sys/types.h> 27 #include <sys/errno.h> 28 #include <sys/time.h> 29 #include <sys/file.h> 30 #if !defined(_KERNEL) 31 # include <stdlib.h> 32 # include <string.h> 33 # define _KERNEL 34 # ifdef __OpenBSD__ 35 struct file; 36 # endif 37 # include <sys/uio.h> 38 # undef _KERNEL 39 #endif 40 #include <sys/socket.h> 41 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 42 # include <sys/malloc.h> 43 #endif 44 #if defined(__FreeBSD__) 45 # include <sys/cdefs.h> 46 # include <sys/proc.h> 47 #endif 48 #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \ 49 !defined(linux) 50 # include <sys/mbuf.h> 51 #endif 52 #if defined(_KERNEL) 53 # include <sys/systm.h> 54 #else 55 # include "ipf.h" 56 #endif 57 #include <netinet/in.h> 58 #include <net/if.h> 59 60 #include "netinet/ip_compat.h" 61 #include "netinet/ip_fil.h" 62 #include "netinet/ip_lookup.h" 63 #include "netinet/ip_htable.h" 64 /* END OF INCLUDES */ 65 66 #if !defined(lint) 67 #if defined(__NetBSD__) 68 #include <sys/cdefs.h> 69 __KERNEL_RCSID(0, "$NetBSD: ip_htable.c,v 1.8 2026/01/11 15:54:52 christos Exp $"); 70 #else 71 static const char rcsid[] = "@(#)Id: ip_htable.c,v 1.1.1.2 2012/07/22 13:45:19 darrenr Exp"; 72 #endif 73 #endif 74 75 # ifdef USE_INET6 76 static iphtent_t *ipf_iphmfind6(iphtable_t *, i6addr_t *); 77 # endif 78 static iphtent_t *ipf_iphmfind(iphtable_t *, struct in_addr *); 79 static int ipf_iphmfindip(ipf_main_softc_t *, void *, int, void *, u_int); 80 static int ipf_htable_clear(ipf_main_softc_t *, void *, iphtable_t *); 81 static int ipf_htable_create(ipf_main_softc_t *, void *, iplookupop_t *); 82 static int ipf_htable_deref(ipf_main_softc_t *, void *, void *); 83 static int ipf_htable_destroy(ipf_main_softc_t *, void *, int, char *); 84 static void *ipf_htable_exists(void *, int, char *); 85 static size_t ipf_htable_flush(ipf_main_softc_t *, void *, 86 iplookupflush_t *); 87 static void ipf_htable_free(void *, iphtable_t *); 88 static int ipf_htable_iter_deref(ipf_main_softc_t *, void *, int, 89 int, void *); 90 static int ipf_htable_iter_next(ipf_main_softc_t *, void *, ipftoken_t *, 91 ipflookupiter_t *); 92 static int ipf_htable_node_add(ipf_main_softc_t *, void *, 93 iplookupop_t *, int); 94 static int ipf_htable_node_del(ipf_main_softc_t *, void *, 95 iplookupop_t *, int); 96 static int ipf_htable_remove(ipf_main_softc_t *, void *, iphtable_t *); 97 static void *ipf_htable_soft_create(ipf_main_softc_t *); 98 static void ipf_htable_soft_destroy(ipf_main_softc_t *, void *); 99 static int ipf_htable_soft_init(ipf_main_softc_t *, void *); 100 static void ipf_htable_soft_fini(ipf_main_softc_t *, void *); 101 static int ipf_htable_stats_get(ipf_main_softc_t *, void *, 102 iplookupop_t *); 103 static int ipf_htable_table_add(ipf_main_softc_t *, void *, 104 iplookupop_t *); 105 static int ipf_htable_table_del(ipf_main_softc_t *, void *, 106 iplookupop_t *); 107 static int ipf_htent_deref(void *, iphtent_t *); 108 static iphtent_t *ipf_htent_find(iphtable_t *, iphtent_t *); 109 static int ipf_htent_insert(ipf_main_softc_t *, void *, iphtable_t *, 110 iphtent_t *); 111 static int ipf_htent_remove(ipf_main_softc_t *, void *, iphtable_t *, 112 iphtent_t *); 113 static void *ipf_htable_select_add_ref(void *, int, char *); 114 static void ipf_htable_expire(ipf_main_softc_t *, void *); 115 116 117 typedef struct ipf_htable_softc_s { 118 u_long ipht_nomem[LOOKUP_POOL_SZ]; 119 u_long ipf_nhtables[LOOKUP_POOL_SZ]; 120 u_long ipf_nhtnodes[LOOKUP_POOL_SZ]; 121 iphtable_t *ipf_htables[LOOKUP_POOL_SZ]; 122 iphtent_t *ipf_node_explist; 123 } ipf_htable_softc_t; 124 125 ipf_lookup_t ipf_htable_backend = { 126 IPLT_HASH, 127 ipf_htable_soft_create, 128 ipf_htable_soft_destroy, 129 ipf_htable_soft_init, 130 ipf_htable_soft_fini, 131 ipf_iphmfindip, 132 ipf_htable_flush, 133 ipf_htable_iter_deref, 134 ipf_htable_iter_next, 135 ipf_htable_node_add, 136 ipf_htable_node_del, 137 ipf_htable_stats_get, 138 ipf_htable_table_add, 139 ipf_htable_table_del, 140 ipf_htable_deref, 141 ipf_htable_exists, 142 ipf_htable_select_add_ref, 143 NULL, 144 ipf_htable_expire, 145 NULL 146 }; 147 148 149 /* ------------------------------------------------------------------------ */ 150 /* Function: ipf_htable_soft_create */ 151 /* Returns: void * - NULL = failure, else pointer to local context */ 152 /* Parameters: softc(I) - pointer to soft context main structure */ 153 /* */ 154 /* Initialise the routing table data structures where required. */ 155 /* ------------------------------------------------------------------------ */ 156 static void * 157 ipf_htable_soft_create(ipf_main_softc_t *softc) 158 { 159 ipf_htable_softc_t *softh; 160 161 KMALLOC(softh, ipf_htable_softc_t *); 162 if (softh == NULL) { 163 IPFERROR(30026); 164 return NULL; 165 } 166 167 bzero((char *)softh, sizeof(*softh)); 168 169 return softh; 170 } 171 172 173 /* ------------------------------------------------------------------------ */ 174 /* Function: ipf_htable_soft_destroy */ 175 /* Returns: Nil */ 176 /* Parameters: softc(I) - pointer to soft context main structure */ 177 /* arg(I) - pointer to local context to use */ 178 /* */ 179 /* Clean up the pool by free'ing the radix tree associated with it and free */ 180 /* up the pool context too. */ 181 /* ------------------------------------------------------------------------ */ 182 static void 183 ipf_htable_soft_destroy(ipf_main_softc_t *softc, void *arg) 184 { 185 ipf_htable_softc_t *softh = arg; 186 187 KFREE(softh); 188 } 189 190 191 /* ------------------------------------------------------------------------ */ 192 /* Function: ipf_htable_soft_init */ 193 /* Returns: int - 0 = success, else error */ 194 /* Parameters: softc(I) - pointer to soft context main structure */ 195 /* arg(I) - pointer to local context to use */ 196 /* */ 197 /* Initialise the hash table ready for use. */ 198 /* ------------------------------------------------------------------------ */ 199 static int 200 ipf_htable_soft_init(ipf_main_softc_t *softc, void *arg) 201 { 202 ipf_htable_softc_t *softh = arg; 203 204 bzero((char *)softh, sizeof(*softh)); 205 206 return 0; 207 } 208 209 210 /* ------------------------------------------------------------------------ */ 211 /* Function: ipf_htable_soft_fini */ 212 /* Returns: Nil */ 213 /* Parameters: softc(I) - pointer to soft context main structure */ 214 /* arg(I) - pointer to local context to use */ 215 /* Locks: WRITE(ipf_global) */ 216 /* */ 217 /* Clean up all the pool data structures allocated and call the cleanup */ 218 /* function for the radix tree that supports the pools. ipf_pool_destroy is */ 219 /* used to delete the pools one by one to ensure they're properly freed up. */ 220 /* ------------------------------------------------------------------------ */ 221 static void 222 ipf_htable_soft_fini(ipf_main_softc_t *softc, void *arg) 223 { 224 iplookupflush_t fop; 225 226 fop.iplf_type = IPLT_HASH; 227 fop.iplf_unit = IPL_LOGALL; 228 fop.iplf_arg = 0; 229 fop.iplf_count = 0; 230 *fop.iplf_name = '\0'; 231 ipf_htable_flush(softc, arg, &fop); 232 } 233 234 235 /* ------------------------------------------------------------------------ */ 236 /* Function: ipf_htable_stats_get */ 237 /* Returns: int - 0 = success, else error */ 238 /* Parameters: softc(I) - pointer to soft context main structure */ 239 /* arg(I) - pointer to local context to use */ 240 /* op(I) - pointer to lookup operation data */ 241 /* */ 242 /* Copy the relevant statistics out of internal structures and into the */ 243 /* structure used to export statistics. */ 244 /* ------------------------------------------------------------------------ */ 245 static int 246 ipf_htable_stats_get(ipf_main_softc_t *softc, void *arg, iplookupop_t *op) 247 { 248 ipf_htable_softc_t *softh = arg; 249 iphtstat_t stats; 250 int err; 251 252 if (op->iplo_size != sizeof(stats)) { 253 IPFERROR(30001); 254 return EINVAL; 255 } 256 257 bzero(&stats, sizeof(stats)); 258 stats.iphs_tables = softh->ipf_htables[op->iplo_unit + 1]; 259 stats.iphs_numtables = softh->ipf_nhtables[op->iplo_unit + 1]; 260 stats.iphs_numnodes = softh->ipf_nhtnodes[op->iplo_unit + 1]; 261 stats.iphs_nomem = softh->ipht_nomem[op->iplo_unit + 1]; 262 263 err = COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 264 if (err != 0) { 265 IPFERROR(30013); 266 return EFAULT; 267 } 268 return 0; 269 270 } 271 272 273 /* ------------------------------------------------------------------------ */ 274 /* Function: ipf_htable_create */ 275 /* Returns: int - 0 = success, else error */ 276 /* Parameters: softc(I) - pointer to soft context main structure */ 277 /* arg(I) - pointer to local context to use */ 278 /* op(I) - pointer to lookup operation data */ 279 /* */ 280 /* Create a new hash table using the template passed. */ 281 /* ------------------------------------------------------------------------ */ 282 static int 283 ipf_htable_create(ipf_main_softc_t *softc, void *arg, iplookupop_t *op) 284 { 285 ipf_htable_softc_t *softh = arg; 286 iphtable_t htab, *iph, *oiph; 287 char name[FR_GROUPLEN]; 288 int err, i, unit; 289 290 if (op->iplo_size != sizeof(htab)) { 291 IPFERROR(30024); 292 return EINVAL; 293 } 294 err = COPYIN(op->iplo_struct, &htab, sizeof(htab)); 295 if (err != 0) { 296 IPFERROR(30003); 297 return EFAULT; 298 } 299 300 unit = op->iplo_unit; 301 if (htab.iph_unit != unit) { 302 IPFERROR(30005); 303 return EINVAL; 304 } 305 if (htab.iph_size < 1) { 306 IPFERROR(30025); 307 return EINVAL; 308 } 309 310 311 if ((op->iplo_arg & IPHASH_ANON) == 0) { 312 iph = ipf_htable_exists(softh, unit, op->iplo_name); 313 if (iph != NULL) { 314 if ((iph->iph_flags & IPHASH_DELETE) == 0) { 315 IPFERROR(30004); 316 return EEXIST; 317 } 318 iph->iph_flags &= ~IPHASH_DELETE; 319 iph->iph_ref++; 320 return 0; 321 } 322 } 323 324 KMALLOC(iph, iphtable_t *); 325 if (iph == NULL) { 326 softh->ipht_nomem[op->iplo_unit + 1]++; 327 IPFERROR(30002); 328 return ENOMEM; 329 } 330 *iph = htab; 331 332 if ((op->iplo_arg & IPHASH_ANON) != 0) { 333 i = IPHASH_ANON; 334 do { 335 i++; 336 snprintf(name, sizeof(name), "%u", i); 337 for (oiph = softh->ipf_htables[unit + 1]; oiph != NULL; 338 oiph = oiph->iph_next) 339 if (strncmp(oiph->iph_name, name, 340 sizeof(oiph->iph_name)) == 0) 341 break; 342 } while (oiph != NULL); 343 344 (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name)); 345 (void)strncpy(op->iplo_name, name, sizeof(op->iplo_name)); 346 iph->iph_type |= IPHASH_ANON; 347 } else { 348 (void)strncpy(iph->iph_name, op->iplo_name, 349 sizeof(iph->iph_name)); 350 iph->iph_name[sizeof(iph->iph_name) - 1] = '\0'; 351 } 352 353 KMALLOCS(iph->iph_table, iphtent_t **, 354 iph->iph_size * sizeof(*iph->iph_table)); 355 if (iph->iph_table == NULL) { 356 KFREE(iph); 357 softh->ipht_nomem[unit + 1]++; 358 IPFERROR(30006); 359 return ENOMEM; 360 } 361 362 bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 363 iph->iph_maskset[0] = 0; 364 iph->iph_maskset[1] = 0; 365 iph->iph_maskset[2] = 0; 366 iph->iph_maskset[3] = 0; 367 368 iph->iph_ref = 1; 369 iph->iph_list = NULL; 370 iph->iph_tail = &iph->iph_list; 371 iph->iph_next = softh->ipf_htables[unit + 1]; 372 iph->iph_pnext = &softh->ipf_htables[unit + 1]; 373 if (softh->ipf_htables[unit + 1] != NULL) 374 softh->ipf_htables[unit + 1]->iph_pnext = &iph->iph_next; 375 softh->ipf_htables[unit + 1] = iph; 376 377 softh->ipf_nhtables[unit + 1]++; 378 379 return 0; 380 } 381 382 383 /* ------------------------------------------------------------------------ */ 384 /* Function: ipf_htable_table_del */ 385 /* Returns: int - 0 = success, else error */ 386 /* Parameters: softc(I) - pointer to soft context main structure */ 387 /* arg(I) - pointer to local context to use */ 388 /* op(I) - pointer to lookup operation data */ 389 /* */ 390 /* ------------------------------------------------------------------------ */ 391 static int 392 ipf_htable_table_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op) 393 { 394 return ipf_htable_destroy(softc, arg, op->iplo_unit, op->iplo_name); 395 } 396 397 398 /* ------------------------------------------------------------------------ */ 399 /* Function: ipf_htable_destroy */ 400 /* Returns: int - 0 = success, else error */ 401 /* Parameters: softc(I) - pointer to soft context main structure */ 402 /* arg(I) - pointer to local context to use */ 403 /* op(I) - pointer to lookup operation data */ 404 /* */ 405 /* Find the hash table that belongs to the relevant part of ipfilter with a */ 406 /* matching name and attempt to destroy it. If it is in use, empty it out */ 407 /* and mark it for deletion so that when all the references disappear, it */ 408 /* can be removed. */ 409 /* ------------------------------------------------------------------------ */ 410 static int 411 ipf_htable_destroy(ipf_main_softc_t *softc, void *arg, int unit, char *name) 412 { 413 iphtable_t *iph; 414 415 iph = ipf_htable_find(arg, unit, name); 416 if (iph == NULL) { 417 IPFERROR(30007); 418 return ESRCH; 419 } 420 421 if (iph->iph_unit != unit) { 422 IPFERROR(30008); 423 return EINVAL; 424 } 425 426 if (iph->iph_ref != 0) { 427 ipf_htable_clear(softc, arg, iph); 428 iph->iph_flags |= IPHASH_DELETE; 429 return 0; 430 } 431 432 ipf_htable_remove(softc, arg, iph); 433 434 return 0; 435 } 436 437 438 /* ------------------------------------------------------------------------ */ 439 /* Function: ipf_htable_clear */ 440 /* Returns: int - 0 = success, else error */ 441 /* Parameters: softc(I) - pointer to soft context main structure */ 442 /* arg(I) - pointer to local context to use */ 443 /* iph(I) - pointer to hash table to destroy */ 444 /* */ 445 /* Clean out the hash table by walking the list of entries and removing */ 446 /* each one, one by one. */ 447 /* ------------------------------------------------------------------------ */ 448 static int 449 ipf_htable_clear(ipf_main_softc_t *softc, void *arg, iphtable_t *iph) 450 { 451 iphtent_t *ipe; 452 453 while ((ipe = iph->iph_list) != NULL) 454 if (ipf_htent_remove(softc, arg, iph, ipe) != 0) 455 return 1; 456 return 0; 457 } 458 459 460 /* ------------------------------------------------------------------------ */ 461 /* Function: ipf_htable_free */ 462 /* Returns: Nil */ 463 /* Parameters: arg(I) - pointer to local context to use */ 464 /* iph(I) - pointer to hash table to destroy */ 465 /* */ 466 /* ------------------------------------------------------------------------ */ 467 static void 468 ipf_htable_free(void *arg, iphtable_t *iph) 469 { 470 ipf_htable_softc_t *softh = arg; 471 472 if (iph->iph_next != NULL) 473 iph->iph_next->iph_pnext = iph->iph_pnext; 474 if (iph->iph_pnext != NULL) 475 *iph->iph_pnext = iph->iph_next; 476 iph->iph_pnext = NULL; 477 iph->iph_next = NULL; 478 479 softh->ipf_nhtables[iph->iph_unit + 1]--; 480 481 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 482 KFREE(iph); 483 } 484 485 486 /* ------------------------------------------------------------------------ */ 487 /* Function: ipf_htable_remove */ 488 /* Returns: int - 0 = success, else error */ 489 /* Parameters: softc(I) - pointer to soft context main structure */ 490 /* arg(I) - pointer to local context to use */ 491 /* iph(I) - pointer to hash table to destroy */ 492 /* */ 493 /* It is necessary to unlink here as well as free (called by deref) so that */ 494 /* the while loop in ipf_htable_flush() functions properly. */ 495 /* ------------------------------------------------------------------------ */ 496 static int 497 ipf_htable_remove(ipf_main_softc_t *softc, void *arg, iphtable_t *iph) 498 { 499 500 if (ipf_htable_clear(softc, arg, iph) != 0) 501 return 1; 502 503 if (iph->iph_pnext != NULL) 504 *iph->iph_pnext = iph->iph_next; 505 if (iph->iph_next != NULL) 506 iph->iph_next->iph_pnext = iph->iph_pnext; 507 iph->iph_pnext = NULL; 508 iph->iph_next = NULL; 509 510 return ipf_htable_deref(softc, arg, iph); 511 } 512 513 514 /* ------------------------------------------------------------------------ */ 515 /* Function: ipf_htable_node_del */ 516 /* Returns: int - 0 = success, else error */ 517 /* Parameters: softc(I) - pointer to soft context main structure */ 518 /* arg(I) - pointer to local context to use */ 519 /* op(I) - pointer to lookup operation data */ 520 /* uid(I) - real uid of process doing operation */ 521 /* */ 522 /* ------------------------------------------------------------------------ */ 523 static int 524 ipf_htable_node_del(ipf_main_softc_t *softc, void *arg, iplookupop_t *op, 525 int uid) 526 { 527 iphtable_t *iph; 528 iphtent_t hte, *ent; 529 int err; 530 531 if (op->iplo_size != sizeof(hte)) { 532 IPFERROR(30014); 533 return EINVAL; 534 } 535 536 err = COPYIN(op->iplo_struct, &hte, sizeof(hte)); 537 if (err != 0) { 538 IPFERROR(30015); 539 return EFAULT; 540 } 541 542 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name); 543 if (iph == NULL) { 544 IPFERROR(30016); 545 return ESRCH; 546 } 547 548 ent = ipf_htent_find(iph, &hte); 549 if (ent == NULL) { 550 IPFERROR(30022); 551 return ESRCH; 552 } 553 554 if ((uid != 0) && (ent->ipe_uid != uid)) { 555 IPFERROR(30023); 556 return EACCES; 557 } 558 559 err = ipf_htent_remove(softc, arg, iph, ent); 560 561 return err; 562 } 563 564 565 /* ------------------------------------------------------------------------ */ 566 /* Function: ipf_htable_node_del */ 567 /* Returns: int - 0 = success, else error */ 568 /* Parameters: softc(I) - pointer to soft context main structure */ 569 /* arg(I) - pointer to local context to use */ 570 /* op(I) - pointer to lookup operation data */ 571 /* */ 572 /* ------------------------------------------------------------------------ */ 573 static int 574 ipf_htable_table_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op) 575 { 576 int err; 577 578 if (ipf_htable_find(arg, op->iplo_unit, op->iplo_name) != NULL) { 579 IPFERROR(30017); 580 err = EEXIST; 581 } else { 582 err = ipf_htable_create(softc, arg, op); 583 } 584 585 return err; 586 } 587 588 589 /* ------------------------------------------------------------------------ */ 590 /* Function: ipf_htent_remove */ 591 /* Returns: int - 0 = success, else error */ 592 /* Parameters: softc(I) - pointer to soft context main structure */ 593 /* arg(I) - pointer to local context to use */ 594 /* iph(I) - pointer to hash table */ 595 /* ipe(I) - pointer to hash table entry to remove */ 596 /* */ 597 /* Delete an entry from a hash table. */ 598 /* ------------------------------------------------------------------------ */ 599 static int 600 ipf_htent_remove(ipf_main_softc_t *softc, void *arg, iphtable_t *iph, 601 iphtent_t *ipe) 602 { 603 604 if (iph->iph_tail == &ipe->ipe_next) 605 iph->iph_tail = ipe->ipe_pnext; 606 607 if (ipe->ipe_hnext != NULL) 608 ipe->ipe_hnext->ipe_phnext = ipe->ipe_phnext; 609 if (ipe->ipe_phnext != NULL) 610 *ipe->ipe_phnext = ipe->ipe_hnext; 611 ipe->ipe_phnext = NULL; 612 ipe->ipe_hnext = NULL; 613 614 if (ipe->ipe_dnext != NULL) 615 ipe->ipe_dnext->ipe_pdnext = ipe->ipe_pdnext; 616 if (ipe->ipe_pdnext != NULL) 617 *ipe->ipe_pdnext = ipe->ipe_dnext; 618 ipe->ipe_pdnext = NULL; 619 ipe->ipe_dnext = NULL; 620 621 if (ipe->ipe_next != NULL) 622 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; 623 if (ipe->ipe_pnext != NULL) 624 *ipe->ipe_pnext = ipe->ipe_next; 625 ipe->ipe_pnext = NULL; 626 ipe->ipe_next = NULL; 627 628 switch (iph->iph_type & ~IPHASH_ANON) 629 { 630 case IPHASH_GROUPMAP : 631 ipf_group_del(softc, ipe->ipe_ptr, NULL); 632 break; 633 634 default : 635 ipe->ipe_ptr = NULL; 636 ipe->ipe_value = 0; 637 break; 638 } 639 640 return ipf_htent_deref(arg, ipe); 641 } 642 643 644 /* ------------------------------------------------------------------------ */ 645 /* Function: ipf_htable_deref */ 646 /* Returns: int - 0 = success, else error */ 647 /* Parameters: softc(I) - pointer to soft context main structure */ 648 /* arg(I) - pointer to local context to use */ 649 /* object(I) - pointer to hash table */ 650 /* */ 651 /* ------------------------------------------------------------------------ */ 652 static int 653 ipf_htable_deref(ipf_main_softc_t *softc, void *arg, void *object) 654 { 655 ipf_htable_softc_t *softh = arg; 656 iphtable_t *iph = object; 657 int refs; 658 659 iph->iph_ref--; 660 refs = iph->iph_ref; 661 662 if (iph->iph_ref == 0) { 663 ipf_htable_free(softh, iph); 664 } 665 666 return refs; 667 } 668 669 670 /* ------------------------------------------------------------------------ */ 671 /* Function: ipf_htent_deref */ 672 /* Parameters: arg(I) - pointer to local context to use */ 673 /* ipe(I) - */ 674 /* */ 675 /* ------------------------------------------------------------------------ */ 676 static int 677 ipf_htent_deref(void *arg, iphtent_t *ipe) 678 { 679 ipf_htable_softc_t *softh = arg; 680 681 ipe->ipe_ref--; 682 if (ipe->ipe_ref == 0) { 683 softh->ipf_nhtnodes[ipe->ipe_unit + 1]--; 684 KFREE(ipe); 685 686 return 0; 687 } 688 689 return ipe->ipe_ref; 690 } 691 692 693 /* ------------------------------------------------------------------------ */ 694 /* Function: ipf_htable_exists */ 695 /* Parameters: arg(I) - pointer to local context to use */ 696 /* */ 697 /* ------------------------------------------------------------------------ */ 698 static void * 699 ipf_htable_exists(void *arg, int unit, char *name) 700 { 701 ipf_htable_softc_t *softh = arg; 702 iphtable_t *iph; 703 704 if (unit == IPL_LOGALL) { 705 int i; 706 707 for (i = 0; i <= LOOKUP_POOL_MAX; i++) { 708 for (iph = softh->ipf_htables[i]; iph != NULL; 709 iph = iph->iph_next) { 710 if (strncmp(iph->iph_name, name, 711 sizeof(iph->iph_name)) == 0) 712 break; 713 } 714 if (iph != NULL) 715 break; 716 } 717 } else { 718 for (iph = softh->ipf_htables[unit + 1]; iph != NULL; 719 iph = iph->iph_next) { 720 if (strncmp(iph->iph_name, name, 721 sizeof(iph->iph_name)) == 0) 722 break; 723 } 724 } 725 return iph; 726 } 727 728 729 /* ------------------------------------------------------------------------ */ 730 /* Function: ipf_htable_select_add_ref */ 731 /* Returns: void * - NULL = failure, else pointer to the hash table */ 732 /* Parameters: arg(I) - pointer to local context to use */ 733 /* unit(I) - ipfilter device to which we are working on */ 734 /* name(I) - name of the hash table */ 735 /* */ 736 /* ------------------------------------------------------------------------ */ 737 static void * 738 ipf_htable_select_add_ref(void *arg, int unit, char *name) 739 { 740 iphtable_t *iph; 741 742 iph = ipf_htable_exists(arg, unit, name); 743 if (iph != NULL) { 744 ATOMIC_INC32(iph->iph_ref); 745 } 746 return iph; 747 } 748 749 750 /* ------------------------------------------------------------------------ */ 751 /* Function: ipf_htable_find */ 752 /* Returns: void * - NULL = failure, else pointer to the hash table */ 753 /* Parameters: arg(I) - pointer to local context to use */ 754 /* unit(I) - ipfilter device to which we are working on */ 755 /* name(I) - name of the hash table */ 756 /* */ 757 /* This function is exposed becaues it is used in the group-map feature. */ 758 /* ------------------------------------------------------------------------ */ 759 iphtable_t * 760 ipf_htable_find(void *arg, int unit, char *name) 761 { 762 iphtable_t *iph; 763 764 iph = ipf_htable_exists(arg, unit, name); 765 if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0) 766 return iph; 767 768 return NULL; 769 } 770 771 772 /* ------------------------------------------------------------------------ */ 773 /* Function: ipf_htable_flush */ 774 /* Returns: size_t - number of entries flushed */ 775 /* Parameters: softc(I) - pointer to soft context main structure */ 776 /* arg(I) - pointer to local context to use */ 777 /* op(I) - pointer to lookup operation data */ 778 /* */ 779 /* ------------------------------------------------------------------------ */ 780 static size_t 781 ipf_htable_flush(ipf_main_softc_t *softc, void *arg, iplookupflush_t *op) 782 { 783 ipf_htable_softc_t *softh = arg; 784 iphtable_t *iph; 785 size_t freed; 786 int i; 787 788 freed = 0; 789 790 for (i = -1; i <= IPL_LOGMAX; i++) { 791 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { 792 while ((iph = softh->ipf_htables[i + 1]) != NULL) { 793 if (ipf_htable_remove(softc, arg, iph) == 0) { 794 freed++; 795 } else { 796 iph->iph_flags |= IPHASH_DELETE; 797 } 798 } 799 } 800 } 801 802 return freed; 803 } 804 805 806 /* ------------------------------------------------------------------------ */ 807 /* Function: ipf_htable_node_add */ 808 /* Returns: int - 0 = success, else error */ 809 /* Parameters: softc(I) - pointer to soft context main structure */ 810 /* arg(I) - pointer to local context to use */ 811 /* op(I) - pointer to lookup operation data */ 812 /* uid(I) - real uid of process doing operation */ 813 /* */ 814 /* ------------------------------------------------------------------------ */ 815 static int 816 ipf_htable_node_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op, 817 int uid) 818 { 819 iphtable_t *iph; 820 iphtent_t hte; 821 int err; 822 823 if (op->iplo_size != sizeof(hte)) { 824 IPFERROR(30018); 825 return EINVAL; 826 } 827 828 err = COPYIN(op->iplo_struct, &hte, sizeof(hte)); 829 if (err != 0) { 830 IPFERROR(30019); 831 return EFAULT; 832 } 833 hte.ipe_uid = uid; 834 835 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name); 836 if (iph == NULL) { 837 IPFERROR(30020); 838 return ESRCH; 839 } 840 841 if (ipf_htent_find(iph, &hte) != NULL) { 842 IPFERROR(30021); 843 return EEXIST; 844 } 845 846 err = ipf_htent_insert(softc, arg, iph, &hte); 847 848 return err; 849 } 850 851 852 /* ------------------------------------------------------------------------ */ 853 /* Function: ipf_htent_insert */ 854 /* Returns: int - 0 = success, -1 = error */ 855 /* Parameters: softc(I) - pointer to soft context main structure */ 856 /* arg(I) - pointer to local context to use */ 857 /* op(I) - pointer to lookup operation data */ 858 /* ipeo(I) - */ 859 /* */ 860 /* Add an entry to a hash table. */ 861 /* ------------------------------------------------------------------------ */ 862 static int 863 ipf_htent_insert(ipf_main_softc_t *softc, void *arg, iphtable_t *iph, 864 iphtent_t *ipeo) 865 { 866 ipf_htable_softc_t *softh = arg; 867 iphtent_t *ipe; 868 u_int hv; 869 int bits; 870 871 KMALLOC(ipe, iphtent_t *); 872 if (ipe == NULL) 873 return -1; 874 875 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe)); 876 ipe->ipe_addr.i6[0] &= ipe->ipe_mask.i6[0]; 877 if (ipe->ipe_family == AF_INET) { 878 bits = count4bits(ipe->ipe_mask.in4_addr); 879 ipe->ipe_addr.i6[1] = 0; 880 ipe->ipe_addr.i6[2] = 0; 881 ipe->ipe_addr.i6[3] = 0; 882 ipe->ipe_mask.i6[1] = 0; 883 ipe->ipe_mask.i6[2] = 0; 884 ipe->ipe_mask.i6[3] = 0; 885 hv = IPE_V4_HASH_FN(ipe->ipe_addr.in4_addr, 886 ipe->ipe_mask.in4_addr, iph->iph_size); 887 } else 888 #ifdef USE_INET6 889 if (ipe->ipe_family == AF_INET6) { 890 ipe->ipe_addr.i6[1] &= ipe->ipe_mask.i6[1]; 891 ipe->ipe_addr.i6[2] &= ipe->ipe_mask.i6[2]; 892 ipe->ipe_addr.i6[3] &= ipe->ipe_mask.i6[3]; 893 894 bits = count6bits(ipe->ipe_mask.i6); 895 hv = IPE_V6_HASH_FN(ipe->ipe_addr.i6, 896 ipe->ipe_mask.i6, iph->iph_size); 897 } else 898 #endif 899 { 900 KFREE(ipe); 901 return -1; 902 } 903 904 ipe->ipe_owner = iph; 905 ipe->ipe_ref = 1; 906 ipe->ipe_hnext = iph->iph_table[hv]; 907 ipe->ipe_phnext = iph->iph_table + hv; 908 909 if (iph->iph_table[hv] != NULL) 910 iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext; 911 iph->iph_table[hv] = ipe; 912 913 ipe->ipe_pnext = iph->iph_tail; 914 *iph->iph_tail = ipe; 915 iph->iph_tail = &ipe->ipe_next; 916 ipe->ipe_next = NULL; 917 918 if (ipe->ipe_die != 0) { 919 /* 920 * If the new node has a given expiration time, insert it 921 * into the list of expiring nodes with the ones to be 922 * removed first added to the front of the list. The 923 * insertion is O(n) but it is kept sorted for quick scans 924 * at expiration interval checks. 925 */ 926 iphtent_t *n; 927 928 ipe->ipe_die = softc->ipf_ticks + IPF_TTLVAL(ipe->ipe_die); 929 for (n = softh->ipf_node_explist; n != NULL; n = n->ipe_dnext) { 930 if (ipe->ipe_die < n->ipe_die) 931 break; 932 if (n->ipe_dnext == NULL) { 933 /* 934 * We've got to the last node and everything 935 * wanted to be expired before this new node, 936 * so we have to tack it on the end... 937 */ 938 n->ipe_dnext = ipe; 939 ipe->ipe_pdnext = &n->ipe_dnext; 940 n = NULL; 941 break; 942 } 943 } 944 945 if (softh->ipf_node_explist == NULL) { 946 softh->ipf_node_explist = ipe; 947 ipe->ipe_pdnext = &softh->ipf_node_explist; 948 } else if (n != NULL) { 949 ipe->ipe_dnext = n; 950 ipe->ipe_pdnext = n->ipe_pdnext; 951 n->ipe_pdnext = &ipe->ipe_dnext; 952 } 953 } 954 955 if (ipe->ipe_family == AF_INET) { 956 ipf_inet_mask_add(bits, &iph->iph_v4_masks); 957 } 958 #ifdef USE_INET6 959 else if (ipe->ipe_family == AF_INET6) { 960 ipf_inet6_mask_add(bits, &ipe->ipe_mask, &iph->iph_v6_masks); 961 } 962 #endif 963 964 switch (iph->iph_type & ~IPHASH_ANON) 965 { 966 case IPHASH_GROUPMAP : 967 ipe->ipe_ptr = ipf_group_add(softc, ipe->ipe_group, NULL, 968 iph->iph_flags, IPL_LOGIPF, 969 softc->ipf_active); 970 break; 971 972 default : 973 ipe->ipe_ptr = NULL; 974 ipe->ipe_value = 0; 975 break; 976 } 977 978 ipe->ipe_unit = iph->iph_unit; 979 softh->ipf_nhtnodes[ipe->ipe_unit + 1]++; 980 981 return 0; 982 } 983 984 985 /* ------------------------------------------------------------------------ */ 986 /* Function: ipf_htent_find */ 987 /* Returns: int - 0 = success, else error */ 988 /* Parameters: iph(I) - pointer to table to search */ 989 /* ipeo(I) - pointer to entry to find */ 990 /* */ 991 /* While it isn't absolutely necessary to for the address and mask to be */ 992 /* passed in through an iphtent_t structure, one is always present when it */ 993 /* is time to call this function, so it is just more convenient. */ 994 /* ------------------------------------------------------------------------ */ 995 static iphtent_t * 996 ipf_htent_find(iphtable_t *iph, iphtent_t *ipeo) 997 { 998 iphtent_t ipe, *ent; 999 u_int hv; 1000 1001 bcopy((char *)ipeo, (char *)&ipe, sizeof(ipe)); 1002 ipe.ipe_addr.i6[0] &= ipe.ipe_mask.i6[0]; 1003 ipe.ipe_addr.i6[1] &= ipe.ipe_mask.i6[1]; 1004 ipe.ipe_addr.i6[2] &= ipe.ipe_mask.i6[2]; 1005 ipe.ipe_addr.i6[3] &= ipe.ipe_mask.i6[3]; 1006 if (ipe.ipe_family == AF_INET) { 1007 ipe.ipe_addr.i6[1] = 0; 1008 ipe.ipe_addr.i6[2] = 0; 1009 ipe.ipe_addr.i6[3] = 0; 1010 ipe.ipe_mask.i6[1] = 0; 1011 ipe.ipe_mask.i6[2] = 0; 1012 ipe.ipe_mask.i6[3] = 0; 1013 hv = IPE_V4_HASH_FN(ipe.ipe_addr.in4_addr, 1014 ipe.ipe_mask.in4_addr, iph->iph_size); 1015 } else 1016 #ifdef USE_INET6 1017 if (ipe.ipe_family == AF_INET6) { 1018 hv = IPE_V6_HASH_FN(ipe.ipe_addr.i6, 1019 ipe.ipe_mask.i6, iph->iph_size); 1020 } else 1021 #endif 1022 return NULL; 1023 1024 for (ent = iph->iph_table[hv]; ent != NULL; ent = ent->ipe_hnext) { 1025 if (ent->ipe_family != ipe.ipe_family) 1026 continue; 1027 if (IP6_NEQ(&ipe.ipe_addr, &ent->ipe_addr)) 1028 continue; 1029 if (IP6_NEQ(&ipe.ipe_mask, &ent->ipe_mask)) 1030 continue; 1031 break; 1032 } 1033 1034 return ent; 1035 } 1036 1037 1038 /* ------------------------------------------------------------------------ */ 1039 /* Function: ipf_iphmfindgroup */ 1040 /* Returns: int - 0 = success, else error */ 1041 /* Parameters: softc(I) - pointer to soft context main structure */ 1042 /* tptr(I) - */ 1043 /* aptr(I) - */ 1044 /* */ 1045 /* Search a hash table for a matching entry and return the pointer stored */ 1046 /* in it for use as the next group of rules to search. */ 1047 /* */ 1048 /* This function is exposed becaues it is used in the group-map feature. */ 1049 /* ------------------------------------------------------------------------ */ 1050 void * 1051 ipf_iphmfindgroup(ipf_main_softc_t *softc, void *tptr, void *aptr) 1052 { 1053 struct in_addr *addr; 1054 iphtable_t *iph; 1055 iphtent_t *ipe; 1056 void *rval; 1057 1058 READ_ENTER(&softc->ipf_poolrw); 1059 iph = tptr; 1060 addr = aptr; 1061 1062 ipe = ipf_iphmfind(iph, addr); 1063 if (ipe != NULL) 1064 rval = ipe->ipe_ptr; 1065 else 1066 rval = NULL; 1067 RWLOCK_EXIT(&softc->ipf_poolrw); 1068 return rval; 1069 } 1070 1071 1072 /* ------------------------------------------------------------------------ */ 1073 /* Function: ipf_iphmfindip */ 1074 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 1075 /* Parameters: softc(I) - pointer to soft context main structure */ 1076 /* tptr(I) - pointer to the pool to search */ 1077 /* ipversion(I) - IP protocol version (4 or 6) */ 1078 /* aptr(I) - pointer to address information */ 1079 /* bytes(I) - packet length */ 1080 /* */ 1081 /* Search the hash table for a given address and return a search result. */ 1082 /* ------------------------------------------------------------------------ */ 1083 static int 1084 ipf_iphmfindip(ipf_main_softc_t *softc, void *tptr, int ipversion, void *aptr, 1085 u_int bytes) 1086 { 1087 struct in_addr *addr; 1088 iphtable_t *iph; 1089 iphtent_t *ipe; 1090 int rval; 1091 1092 if (tptr == NULL || aptr == NULL) 1093 return -1; 1094 1095 iph = tptr; 1096 addr = aptr; 1097 1098 READ_ENTER(&softc->ipf_poolrw); 1099 if (ipversion == 4) { 1100 ipe = ipf_iphmfind(iph, addr); 1101 #ifdef USE_INET6 1102 } else if (ipversion == 6) { 1103 ipe = ipf_iphmfind6(iph, (i6addr_t *)addr); 1104 #endif 1105 } else { 1106 ipe = NULL; 1107 } 1108 1109 if (ipe != NULL) { 1110 rval = 0; 1111 ipe->ipe_hits++; 1112 ipe->ipe_bytes += bytes; 1113 } else { 1114 rval = 1; 1115 } 1116 RWLOCK_EXIT(&softc->ipf_poolrw); 1117 return rval; 1118 } 1119 1120 1121 /* ------------------------------------------------------------------------ */ 1122 /* Function: ipf_iphmfindip */ 1123 /* Parameters: iph(I) - pointer to hash table */ 1124 /* addr(I) - pointer to IPv4 address */ 1125 /* Locks: ipf_poolrw */ 1126 /* */ 1127 /* ------------------------------------------------------------------------ */ 1128 static iphtent_t * 1129 ipf_iphmfind(iphtable_t *iph, struct in_addr *addr) 1130 { 1131 u_32_t msk, ips; 1132 iphtent_t *ipe; 1133 u_int hv; 1134 int i; 1135 1136 i = 0; 1137 maskloop: 1138 msk = iph->iph_v4_masks.imt4_active[i]; 1139 ips = addr->s_addr & msk; 1140 hv = IPE_V4_HASH_FN(ips, msk, iph->iph_size); 1141 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) { 1142 if ((ipe->ipe_family != AF_INET) || 1143 (ipe->ipe_mask.in4_addr != msk) || 1144 (ipe->ipe_addr.in4_addr != ips)) { 1145 continue; 1146 } 1147 break; 1148 } 1149 1150 if (ipe == NULL) { 1151 i++; 1152 if (i < iph->iph_v4_masks.imt4_max) 1153 goto maskloop; 1154 } 1155 return ipe; 1156 } 1157 1158 1159 /* ------------------------------------------------------------------------ */ 1160 /* Function: ipf_htable_iter_next */ 1161 /* Returns: int - 0 = success, else error */ 1162 /* Parameters: softc(I) - pointer to soft context main structure */ 1163 /* arg(I) - pointer to local context to use */ 1164 /* token(I) - */ 1165 /* ilp(I) - */ 1166 /* */ 1167 /* ------------------------------------------------------------------------ */ 1168 static int 1169 ipf_htable_iter_next(ipf_main_softc_t *softc, void *arg, ipftoken_t *token, 1170 ipflookupiter_t *ilp) 1171 { 1172 ipf_htable_softc_t *softh = arg; 1173 iphtent_t *node, zn, *nextnode; 1174 iphtable_t *iph, zp, *nextiph; 1175 void *hnext; 1176 int err; 1177 1178 err = 0; 1179 iph = NULL; 1180 node = NULL; 1181 nextiph = NULL; 1182 nextnode = NULL; 1183 1184 READ_ENTER(&softc->ipf_poolrw); 1185 1186 switch (ilp->ili_otype) 1187 { 1188 case IPFLOOKUPITER_LIST : 1189 iph = token->ipt_data; 1190 if (iph == NULL) { 1191 nextiph = softh->ipf_htables[(int)ilp->ili_unit + 1]; 1192 } else { 1193 nextiph = iph->iph_next; 1194 } 1195 1196 if (nextiph != NULL) { 1197 ATOMIC_INC(nextiph->iph_ref); 1198 token->ipt_data = nextiph; 1199 } else { 1200 bzero((char *)&zp, sizeof(zp)); 1201 nextiph = &zp; 1202 token->ipt_data = NULL; 1203 } 1204 hnext = nextiph->iph_next; 1205 break; 1206 1207 case IPFLOOKUPITER_NODE : 1208 node = token->ipt_data; 1209 if (node == NULL) { 1210 iph = ipf_htable_find(arg, ilp->ili_unit, 1211 ilp->ili_name); 1212 if (iph == NULL) { 1213 IPFERROR(30009); 1214 err = ESRCH; 1215 } else { 1216 nextnode = iph->iph_list; 1217 } 1218 } else { 1219 nextnode = node->ipe_next; 1220 } 1221 1222 if (nextnode != NULL) { 1223 ATOMIC_INC(nextnode->ipe_ref); 1224 token->ipt_data = nextnode; 1225 } else { 1226 bzero((char *)&zn, sizeof(zn)); 1227 nextnode = &zn; 1228 token->ipt_data = NULL; 1229 } 1230 hnext = nextnode->ipe_next; 1231 break; 1232 1233 default : 1234 IPFERROR(30010); 1235 err = EINVAL; 1236 hnext = NULL; 1237 break; 1238 } 1239 1240 RWLOCK_EXIT(&softc->ipf_poolrw); 1241 if (err != 0) 1242 return err; 1243 1244 switch (ilp->ili_otype) 1245 { 1246 case IPFLOOKUPITER_LIST : 1247 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); 1248 if (err != 0) { 1249 IPFERROR(30011); 1250 err = EFAULT; 1251 } 1252 if (iph != NULL) { 1253 WRITE_ENTER(&softc->ipf_poolrw); 1254 ipf_htable_deref(softc, softh, iph); 1255 RWLOCK_EXIT(&softc->ipf_poolrw); 1256 } 1257 break; 1258 1259 case IPFLOOKUPITER_NODE : 1260 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 1261 if (err != 0) { 1262 IPFERROR(30012); 1263 err = EFAULT; 1264 } 1265 if (node != NULL) { 1266 WRITE_ENTER(&softc->ipf_poolrw); 1267 ipf_htent_deref(softc, node); 1268 RWLOCK_EXIT(&softc->ipf_poolrw); 1269 } 1270 break; 1271 } 1272 1273 if (hnext == NULL) 1274 ipf_token_mark_complete(token); 1275 1276 return err; 1277 } 1278 1279 1280 /* ------------------------------------------------------------------------ */ 1281 /* Function: ipf_htable_iter_deref */ 1282 /* Returns: int - 0 = success, else error */ 1283 /* Parameters: softc(I) - pointer to soft context main structure */ 1284 /* arg(I) - pointer to local context to use */ 1285 /* otype(I) - which data structure type is being walked */ 1286 /* unit(I) - ipfilter device to which we are working on */ 1287 /* data(I) - pointer to old data structure */ 1288 /* */ 1289 /* ------------------------------------------------------------------------ */ 1290 static int 1291 ipf_htable_iter_deref(ipf_main_softc_t *softc, void *arg, int otype, int unit, 1292 void *data) 1293 { 1294 1295 if (data == NULL) 1296 return EFAULT; 1297 1298 if (unit < -1 || unit > IPL_LOGMAX) 1299 return EINVAL; 1300 1301 switch (otype) 1302 { 1303 case IPFLOOKUPITER_LIST : 1304 ipf_htable_deref(softc, arg, (iphtable_t *)data); 1305 break; 1306 1307 case IPFLOOKUPITER_NODE : 1308 ipf_htent_deref(arg, (iphtent_t *)data); 1309 break; 1310 default : 1311 break; 1312 } 1313 1314 return 0; 1315 } 1316 1317 1318 #ifdef USE_INET6 1319 /* ------------------------------------------------------------------------ */ 1320 /* Function: ipf_iphmfind6 */ 1321 /* Parameters: iph(I) - pointer to hash table */ 1322 /* addr(I) - pointer to IPv6 address */ 1323 /* Locks: ipf_poolrw */ 1324 /* */ 1325 /* ------------------------------------------------------------------------ */ 1326 static iphtent_t * 1327 ipf_iphmfind6(iphtable_t *iph, i6addr_t *addr) 1328 { 1329 i6addr_t *msk, ips; 1330 iphtent_t *ipe; 1331 u_int hv; 1332 int i; 1333 1334 i = 0; 1335 maskloop: 1336 msk = iph->iph_v6_masks.imt6_active + i; 1337 ips.i6[0] = addr->i6[0] & msk->i6[0]; 1338 ips.i6[1] = addr->i6[1] & msk->i6[1]; 1339 ips.i6[2] = addr->i6[2] & msk->i6[2]; 1340 ips.i6[3] = addr->i6[3] & msk->i6[3]; 1341 hv = IPE_V6_HASH_FN(ips.i6, msk->i6, iph->iph_size); 1342 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 1343 if ((ipe->ipe_family != AF_INET6) || 1344 IP6_NEQ(&ipe->ipe_mask, msk) || 1345 IP6_NEQ(&ipe->ipe_addr, &ips)) { 1346 continue; 1347 } 1348 break; 1349 } 1350 1351 if (ipe == NULL) { 1352 i++; 1353 if (i < iph->iph_v6_masks.imt6_max) 1354 goto maskloop; 1355 } 1356 return ipe; 1357 } 1358 #endif 1359 1360 1361 static void 1362 ipf_htable_expire(ipf_main_softc_t *softc, void *arg) 1363 { 1364 ipf_htable_softc_t *softh = arg; 1365 iphtent_t *n; 1366 1367 while ((n = softh->ipf_node_explist) != NULL) { 1368 if (n->ipe_die > softc->ipf_ticks) 1369 break; 1370 1371 ipf_htent_remove(softc, softh, n->ipe_owner, n); 1372 } 1373 } 1374 1375 1376 #ifndef _KERNEL 1377 1378 /* ------------------------------------------------------------------------ */ 1379 /* */ 1380 /* ------------------------------------------------------------------------ */ 1381 void 1382 ipf_htable_dump(softc, arg) 1383 ipf_main_softc_t *softc; 1384 void *arg; 1385 { 1386 ipf_htable_softc_t *softh = arg; 1387 iphtable_t *iph; 1388 int i; 1389 1390 printf("List of configured hash tables\n"); 1391 for (i = 0; i < IPL_LOGSIZE; i++) 1392 for (iph = softh->ipf_htables[i]; iph != NULL; 1393 iph = iph->iph_next) 1394 printhash(iph, bcopywrap, NULL, opts, NULL); 1395 1396 } 1397 #endif 1398