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