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