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