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