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