1 /* $NetBSD: ip_htable.c,v 1.4 2013/09/14 11:41:45 martin 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.4 2013/09/14 11:41:45 martin 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 if (ipe->ipe_group != NULL) 629 ipf_group_del(softc, ipe->ipe_ptr, NULL); 630 break; 631 632 default : 633 ipe->ipe_ptr = NULL; 634 ipe->ipe_value = 0; 635 break; 636 } 637 638 return ipf_htent_deref(arg, ipe); 639 } 640 641 642 /* ------------------------------------------------------------------------ */ 643 /* Function: ipf_htable_deref */ 644 /* Returns: int - 0 = success, else error */ 645 /* Parameters: softc(I) - pointer to soft context main structure */ 646 /* arg(I) - pointer to local context to use */ 647 /* object(I) - pointer to hash table */ 648 /* */ 649 /* ------------------------------------------------------------------------ */ 650 static int 651 ipf_htable_deref(ipf_main_softc_t *softc, void *arg, void *object) 652 { 653 ipf_htable_softc_t *softh = arg; 654 iphtable_t *iph = object; 655 int refs; 656 657 iph->iph_ref--; 658 refs = iph->iph_ref; 659 660 if (iph->iph_ref == 0) { 661 ipf_htable_free(softh, iph); 662 } 663 664 return refs; 665 } 666 667 668 /* ------------------------------------------------------------------------ */ 669 /* Function: ipf_htent_deref */ 670 /* Parameters: arg(I) - pointer to local context to use */ 671 /* ipe(I) - */ 672 /* */ 673 /* ------------------------------------------------------------------------ */ 674 static int 675 ipf_htent_deref(void *arg, iphtent_t *ipe) 676 { 677 ipf_htable_softc_t *softh = arg; 678 679 ipe->ipe_ref--; 680 if (ipe->ipe_ref == 0) { 681 softh->ipf_nhtnodes[ipe->ipe_unit + 1]--; 682 KFREE(ipe); 683 684 return 0; 685 } 686 687 return ipe->ipe_ref; 688 } 689 690 691 /* ------------------------------------------------------------------------ */ 692 /* Function: ipf_htable_exists */ 693 /* Parameters: arg(I) - pointer to local context to use */ 694 /* */ 695 /* ------------------------------------------------------------------------ */ 696 static void * 697 ipf_htable_exists(void *arg, int unit, char *name) 698 { 699 ipf_htable_softc_t *softh = arg; 700 iphtable_t *iph; 701 702 if (unit == IPL_LOGALL) { 703 int i; 704 705 for (i = 0; i <= LOOKUP_POOL_MAX; i++) { 706 for (iph = softh->ipf_htables[i]; iph != NULL; 707 iph = iph->iph_next) { 708 if (strncmp(iph->iph_name, name, 709 sizeof(iph->iph_name)) == 0) 710 break; 711 } 712 if (iph != NULL) 713 break; 714 } 715 } else { 716 for (iph = softh->ipf_htables[unit + 1]; iph != NULL; 717 iph = iph->iph_next) { 718 if (strncmp(iph->iph_name, name, 719 sizeof(iph->iph_name)) == 0) 720 break; 721 } 722 } 723 return iph; 724 } 725 726 727 /* ------------------------------------------------------------------------ */ 728 /* Function: ipf_htable_select_add_ref */ 729 /* Returns: void * - NULL = failure, else pointer to the hash table */ 730 /* Parameters: arg(I) - pointer to local context to use */ 731 /* unit(I) - ipfilter device to which we are working on */ 732 /* name(I) - name of the hash table */ 733 /* */ 734 /* ------------------------------------------------------------------------ */ 735 static void * 736 ipf_htable_select_add_ref(void *arg, int unit, char *name) 737 { 738 iphtable_t *iph; 739 740 iph = ipf_htable_exists(arg, unit, name); 741 if (iph != NULL) { 742 ATOMIC_INC32(iph->iph_ref); 743 } 744 return iph; 745 } 746 747 748 /* ------------------------------------------------------------------------ */ 749 /* Function: ipf_htable_find */ 750 /* Returns: void * - NULL = failure, else pointer to the hash table */ 751 /* Parameters: arg(I) - pointer to local context to use */ 752 /* unit(I) - ipfilter device to which we are working on */ 753 /* name(I) - name of the hash table */ 754 /* */ 755 /* This function is exposed becaues it is used in the group-map feature. */ 756 /* ------------------------------------------------------------------------ */ 757 iphtable_t * 758 ipf_htable_find(void *arg, int unit, char *name) 759 { 760 iphtable_t *iph; 761 762 iph = ipf_htable_exists(arg, unit, name); 763 if ((iph != NULL) && (iph->iph_flags & IPHASH_DELETE) == 0) 764 return iph; 765 766 return NULL; 767 } 768 769 770 /* ------------------------------------------------------------------------ */ 771 /* Function: ipf_htable_flush */ 772 /* Returns: size_t - number of entries flushed */ 773 /* Parameters: softc(I) - pointer to soft context main structure */ 774 /* arg(I) - pointer to local context to use */ 775 /* op(I) - pointer to lookup operation data */ 776 /* */ 777 /* ------------------------------------------------------------------------ */ 778 static size_t 779 ipf_htable_flush(ipf_main_softc_t *softc, void *arg, iplookupflush_t *op) 780 { 781 ipf_htable_softc_t *softh = arg; 782 iphtable_t *iph; 783 size_t freed; 784 int i; 785 786 freed = 0; 787 788 for (i = -1; i <= IPL_LOGMAX; i++) { 789 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { 790 while ((iph = softh->ipf_htables[i + 1]) != NULL) { 791 if (ipf_htable_remove(softc, arg, iph) == 0) { 792 freed++; 793 } else { 794 iph->iph_flags |= IPHASH_DELETE; 795 } 796 } 797 } 798 } 799 800 return freed; 801 } 802 803 804 /* ------------------------------------------------------------------------ */ 805 /* Function: ipf_htable_node_add */ 806 /* Returns: int - 0 = success, else error */ 807 /* Parameters: softc(I) - pointer to soft context main structure */ 808 /* arg(I) - pointer to local context to use */ 809 /* op(I) - pointer to lookup operation data */ 810 /* uid(I) - real uid of process doing operation */ 811 /* */ 812 /* ------------------------------------------------------------------------ */ 813 static int 814 ipf_htable_node_add(ipf_main_softc_t *softc, void *arg, iplookupop_t *op, 815 int uid) 816 { 817 iphtable_t *iph; 818 iphtent_t hte; 819 int err; 820 821 if (op->iplo_size != sizeof(hte)) { 822 IPFERROR(30018); 823 return EINVAL; 824 } 825 826 err = COPYIN(op->iplo_struct, &hte, sizeof(hte)); 827 if (err != 0) { 828 IPFERROR(30019); 829 return EFAULT; 830 } 831 hte.ipe_uid = uid; 832 833 iph = ipf_htable_find(arg, op->iplo_unit, op->iplo_name); 834 if (iph == NULL) { 835 IPFERROR(30020); 836 return ESRCH; 837 } 838 839 if (ipf_htent_find(iph, &hte) != NULL) { 840 IPFERROR(30021); 841 return EEXIST; 842 } 843 844 err = ipf_htent_insert(softc, arg, iph, &hte); 845 846 return err; 847 } 848 849 850 /* ------------------------------------------------------------------------ */ 851 /* Function: ipf_htent_insert */ 852 /* Returns: int - 0 = success, -1 = error */ 853 /* Parameters: softc(I) - pointer to soft context main structure */ 854 /* arg(I) - pointer to local context to use */ 855 /* op(I) - pointer to lookup operation data */ 856 /* ipeo(I) - */ 857 /* */ 858 /* Add an entry to a hash table. */ 859 /* ------------------------------------------------------------------------ */ 860 static int 861 ipf_htent_insert(ipf_main_softc_t *softc, void *arg, iphtable_t *iph, 862 iphtent_t *ipeo) 863 { 864 ipf_htable_softc_t *softh = arg; 865 iphtent_t *ipe; 866 u_int hv; 867 int bits; 868 869 KMALLOC(ipe, iphtent_t *); 870 if (ipe == NULL) 871 return -1; 872 873 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe)); 874 ipe->ipe_addr.i6[0] &= ipe->ipe_mask.i6[0]; 875 if (ipe->ipe_family == AF_INET) { 876 bits = count4bits(ipe->ipe_mask.in4_addr); 877 ipe->ipe_addr.i6[1] = 0; 878 ipe->ipe_addr.i6[2] = 0; 879 ipe->ipe_addr.i6[3] = 0; 880 ipe->ipe_mask.i6[1] = 0; 881 ipe->ipe_mask.i6[2] = 0; 882 ipe->ipe_mask.i6[3] = 0; 883 hv = IPE_V4_HASH_FN(ipe->ipe_addr.in4_addr, 884 ipe->ipe_mask.in4_addr, iph->iph_size); 885 } else 886 #ifdef USE_INET6 887 if (ipe->ipe_family == AF_INET6) { 888 ipe->ipe_addr.i6[1] &= ipe->ipe_mask.i6[1]; 889 ipe->ipe_addr.i6[2] &= ipe->ipe_mask.i6[2]; 890 ipe->ipe_addr.i6[3] &= ipe->ipe_mask.i6[3]; 891 892 bits = count6bits(ipe->ipe_mask.i6); 893 hv = IPE_V6_HASH_FN(ipe->ipe_addr.i6, 894 ipe->ipe_mask.i6, iph->iph_size); 895 } else 896 #endif 897 { 898 KFREE(ipe); 899 return -1; 900 } 901 902 ipe->ipe_owner = iph; 903 ipe->ipe_ref = 1; 904 ipe->ipe_hnext = iph->iph_table[hv]; 905 ipe->ipe_phnext = iph->iph_table + hv; 906 907 if (iph->iph_table[hv] != NULL) 908 iph->iph_table[hv]->ipe_phnext = &ipe->ipe_hnext; 909 iph->iph_table[hv] = ipe; 910 911 ipe->ipe_pnext = iph->iph_tail; 912 *iph->iph_tail = ipe; 913 iph->iph_tail = &ipe->ipe_next; 914 ipe->ipe_next = NULL; 915 916 if (ipe->ipe_die != 0) { 917 /* 918 * If the new node has a given expiration time, insert it 919 * into the list of expiring nodes with the ones to be 920 * removed first added to the front of the list. The 921 * insertion is O(n) but it is kept sorted for quick scans 922 * at expiration interval checks. 923 */ 924 iphtent_t *n; 925 926 ipe->ipe_die = softc->ipf_ticks + IPF_TTLVAL(ipe->ipe_die); 927 for (n = softh->ipf_node_explist; n != NULL; n = n->ipe_dnext) { 928 if (ipe->ipe_die < n->ipe_die) 929 break; 930 if (n->ipe_dnext == NULL) { 931 /* 932 * We've got to the last node and everything 933 * wanted to be expired before this new node, 934 * so we have to tack it on the end... 935 */ 936 n->ipe_dnext = ipe; 937 ipe->ipe_pdnext = &n->ipe_dnext; 938 n = NULL; 939 break; 940 } 941 } 942 943 if (softh->ipf_node_explist == NULL) { 944 softh->ipf_node_explist = ipe; 945 ipe->ipe_pdnext = &softh->ipf_node_explist; 946 } else if (n != NULL) { 947 ipe->ipe_dnext = n; 948 ipe->ipe_pdnext = n->ipe_pdnext; 949 n->ipe_pdnext = &ipe->ipe_dnext; 950 } 951 } 952 953 if (ipe->ipe_family == AF_INET) { 954 ipf_inet_mask_add(bits, &iph->iph_v4_masks); 955 } 956 #ifdef USE_INET6 957 else if (ipe->ipe_family == AF_INET6) { 958 ipf_inet6_mask_add(bits, &ipe->ipe_mask, &iph->iph_v6_masks); 959 } 960 #endif 961 962 switch (iph->iph_type & ~IPHASH_ANON) 963 { 964 case IPHASH_GROUPMAP : 965 ipe->ipe_ptr = ipf_group_add(softc, ipe->ipe_group, NULL, 966 iph->iph_flags, IPL_LOGIPF, 967 softc->ipf_active); 968 break; 969 970 default : 971 ipe->ipe_ptr = NULL; 972 ipe->ipe_value = 0; 973 break; 974 } 975 976 ipe->ipe_unit = iph->iph_unit; 977 softh->ipf_nhtnodes[ipe->ipe_unit + 1]++; 978 979 return 0; 980 } 981 982 983 /* ------------------------------------------------------------------------ */ 984 /* Function: ipf_htent_find */ 985 /* Returns: int - 0 = success, else error */ 986 /* Parameters: iph(I) - pointer to table to search */ 987 /* ipeo(I) - pointer to entry to find */ 988 /* */ 989 /* While it isn't absolutely necessary to for the address and mask to be */ 990 /* passed in through an iphtent_t structure, one is always present when it */ 991 /* is time to call this function, so it is just more convenient. */ 992 /* ------------------------------------------------------------------------ */ 993 static iphtent_t * 994 ipf_htent_find(iphtable_t *iph, iphtent_t *ipeo) 995 { 996 iphtent_t ipe, *ent; 997 u_int hv; 998 999 bcopy((char *)ipeo, (char *)&ipe, sizeof(ipe)); 1000 ipe.ipe_addr.i6[0] &= ipe.ipe_mask.i6[0]; 1001 ipe.ipe_addr.i6[1] &= ipe.ipe_mask.i6[1]; 1002 ipe.ipe_addr.i6[2] &= ipe.ipe_mask.i6[2]; 1003 ipe.ipe_addr.i6[3] &= ipe.ipe_mask.i6[3]; 1004 if (ipe.ipe_family == AF_INET) { 1005 ipe.ipe_addr.i6[1] = 0; 1006 ipe.ipe_addr.i6[2] = 0; 1007 ipe.ipe_addr.i6[3] = 0; 1008 ipe.ipe_mask.i6[1] = 0; 1009 ipe.ipe_mask.i6[2] = 0; 1010 ipe.ipe_mask.i6[3] = 0; 1011 hv = IPE_V4_HASH_FN(ipe.ipe_addr.in4_addr, 1012 ipe.ipe_mask.in4_addr, iph->iph_size); 1013 } else 1014 #ifdef USE_INET6 1015 if (ipe.ipe_family == AF_INET6) { 1016 hv = IPE_V6_HASH_FN(ipe.ipe_addr.i6, 1017 ipe.ipe_mask.i6, iph->iph_size); 1018 } else 1019 #endif 1020 return NULL; 1021 1022 for (ent = iph->iph_table[hv]; ent != NULL; ent = ent->ipe_hnext) { 1023 if (ent->ipe_family != ipe.ipe_family) 1024 continue; 1025 if (IP6_NEQ(&ipe.ipe_addr, &ent->ipe_addr)) 1026 continue; 1027 if (IP6_NEQ(&ipe.ipe_mask, &ent->ipe_mask)) 1028 continue; 1029 break; 1030 } 1031 1032 return ent; 1033 } 1034 1035 1036 /* ------------------------------------------------------------------------ */ 1037 /* Function: ipf_iphmfindgroup */ 1038 /* Returns: int - 0 = success, else error */ 1039 /* Parameters: softc(I) - pointer to soft context main structure */ 1040 /* tptr(I) - */ 1041 /* aptr(I) - */ 1042 /* */ 1043 /* Search a hash table for a matching entry and return the pointer stored */ 1044 /* in it for use as the next group of rules to search. */ 1045 /* */ 1046 /* This function is exposed becaues it is used in the group-map feature. */ 1047 /* ------------------------------------------------------------------------ */ 1048 void * 1049 ipf_iphmfindgroup(ipf_main_softc_t *softc, void *tptr, void *aptr) 1050 { 1051 struct in_addr *addr; 1052 iphtable_t *iph; 1053 iphtent_t *ipe; 1054 void *rval; 1055 1056 READ_ENTER(&softc->ipf_poolrw); 1057 iph = tptr; 1058 addr = aptr; 1059 1060 ipe = ipf_iphmfind(iph, addr); 1061 if (ipe != NULL) 1062 rval = ipe->ipe_ptr; 1063 else 1064 rval = NULL; 1065 RWLOCK_EXIT(&softc->ipf_poolrw); 1066 return rval; 1067 } 1068 1069 1070 /* ------------------------------------------------------------------------ */ 1071 /* Function: ipf_iphmfindip */ 1072 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 1073 /* Parameters: softc(I) - pointer to soft context main structure */ 1074 /* tptr(I) - pointer to the pool to search */ 1075 /* ipversion(I) - IP protocol version (4 or 6) */ 1076 /* aptr(I) - pointer to address information */ 1077 /* bytes(I) - packet length */ 1078 /* */ 1079 /* Search the hash table for a given address and return a search result. */ 1080 /* ------------------------------------------------------------------------ */ 1081 static int 1082 ipf_iphmfindip(ipf_main_softc_t *softc, void *tptr, int ipversion, void *aptr, 1083 u_int bytes) 1084 { 1085 struct in_addr *addr; 1086 iphtable_t *iph; 1087 iphtent_t *ipe; 1088 int rval; 1089 1090 if (tptr == NULL || aptr == NULL) 1091 return -1; 1092 1093 iph = tptr; 1094 addr = aptr; 1095 1096 READ_ENTER(&softc->ipf_poolrw); 1097 if (ipversion == 4) { 1098 ipe = ipf_iphmfind(iph, addr); 1099 #ifdef USE_INET6 1100 } else if (ipversion == 6) { 1101 ipe = ipf_iphmfind6(iph, (i6addr_t *)addr); 1102 #endif 1103 } else { 1104 ipe = NULL; 1105 } 1106 1107 if (ipe != NULL) { 1108 rval = 0; 1109 ipe->ipe_hits++; 1110 ipe->ipe_bytes += bytes; 1111 } else { 1112 rval = 1; 1113 } 1114 RWLOCK_EXIT(&softc->ipf_poolrw); 1115 return rval; 1116 } 1117 1118 1119 /* ------------------------------------------------------------------------ */ 1120 /* Function: ipf_iphmfindip */ 1121 /* Parameters: iph(I) - pointer to hash table */ 1122 /* addr(I) - pointer to IPv4 address */ 1123 /* Locks: ipf_poolrw */ 1124 /* */ 1125 /* ------------------------------------------------------------------------ */ 1126 static iphtent_t * 1127 ipf_iphmfind(iphtable_t *iph, struct in_addr *addr) 1128 { 1129 u_32_t msk, ips; 1130 iphtent_t *ipe; 1131 u_int hv; 1132 int i; 1133 1134 i = 0; 1135 maskloop: 1136 msk = iph->iph_v4_masks.imt4_active[i]; 1137 ips = addr->s_addr & msk; 1138 hv = IPE_V4_HASH_FN(ips, msk, iph->iph_size); 1139 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_hnext) { 1140 if ((ipe->ipe_family != AF_INET) || 1141 (ipe->ipe_mask.in4_addr != msk) || 1142 (ipe->ipe_addr.in4_addr != ips)) { 1143 continue; 1144 } 1145 break; 1146 } 1147 1148 if (ipe == NULL) { 1149 i++; 1150 if (i < iph->iph_v4_masks.imt4_max) 1151 goto maskloop; 1152 } 1153 return ipe; 1154 } 1155 1156 1157 /* ------------------------------------------------------------------------ */ 1158 /* Function: ipf_htable_iter_next */ 1159 /* Returns: int - 0 = success, else error */ 1160 /* Parameters: softc(I) - pointer to soft context main structure */ 1161 /* arg(I) - pointer to local context to use */ 1162 /* token(I) - */ 1163 /* ilp(I) - */ 1164 /* */ 1165 /* ------------------------------------------------------------------------ */ 1166 static int 1167 ipf_htable_iter_next(ipf_main_softc_t *softc, void *arg, ipftoken_t *token, 1168 ipflookupiter_t *ilp) 1169 { 1170 ipf_htable_softc_t *softh = arg; 1171 iphtent_t *node, zn, *nextnode; 1172 iphtable_t *iph, zp, *nextiph; 1173 void *hnext; 1174 int err; 1175 1176 err = 0; 1177 iph = NULL; 1178 node = NULL; 1179 nextiph = NULL; 1180 nextnode = NULL; 1181 1182 READ_ENTER(&softc->ipf_poolrw); 1183 1184 switch (ilp->ili_otype) 1185 { 1186 case IPFLOOKUPITER_LIST : 1187 iph = token->ipt_data; 1188 if (iph == NULL) { 1189 nextiph = softh->ipf_htables[(int)ilp->ili_unit + 1]; 1190 } else { 1191 nextiph = iph->iph_next; 1192 } 1193 1194 if (nextiph != NULL) { 1195 ATOMIC_INC(nextiph->iph_ref); 1196 token->ipt_data = nextiph; 1197 } else { 1198 bzero((char *)&zp, sizeof(zp)); 1199 nextiph = &zp; 1200 token->ipt_data = NULL; 1201 } 1202 hnext = nextiph->iph_next; 1203 break; 1204 1205 case IPFLOOKUPITER_NODE : 1206 node = token->ipt_data; 1207 if (node == NULL) { 1208 iph = ipf_htable_find(arg, ilp->ili_unit, 1209 ilp->ili_name); 1210 if (iph == NULL) { 1211 IPFERROR(30009); 1212 err = ESRCH; 1213 } else { 1214 nextnode = iph->iph_list; 1215 } 1216 } else { 1217 nextnode = node->ipe_next; 1218 } 1219 1220 if (nextnode != NULL) { 1221 ATOMIC_INC(nextnode->ipe_ref); 1222 token->ipt_data = nextnode; 1223 } else { 1224 bzero((char *)&zn, sizeof(zn)); 1225 nextnode = &zn; 1226 token->ipt_data = NULL; 1227 } 1228 hnext = nextnode->ipe_next; 1229 break; 1230 1231 default : 1232 IPFERROR(30010); 1233 err = EINVAL; 1234 hnext = NULL; 1235 break; 1236 } 1237 1238 RWLOCK_EXIT(&softc->ipf_poolrw); 1239 if (err != 0) 1240 return err; 1241 1242 switch (ilp->ili_otype) 1243 { 1244 case IPFLOOKUPITER_LIST : 1245 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); 1246 if (err != 0) { 1247 IPFERROR(30011); 1248 err = EFAULT; 1249 } 1250 if (iph != NULL) { 1251 WRITE_ENTER(&softc->ipf_poolrw); 1252 ipf_htable_deref(softc, softh, iph); 1253 RWLOCK_EXIT(&softc->ipf_poolrw); 1254 } 1255 break; 1256 1257 case IPFLOOKUPITER_NODE : 1258 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 1259 if (err != 0) { 1260 IPFERROR(30012); 1261 err = EFAULT; 1262 } 1263 if (node != NULL) { 1264 WRITE_ENTER(&softc->ipf_poolrw); 1265 ipf_htent_deref(softc, node); 1266 RWLOCK_EXIT(&softc->ipf_poolrw); 1267 } 1268 break; 1269 } 1270 1271 if (hnext == NULL) 1272 ipf_token_mark_complete(token); 1273 1274 return err; 1275 } 1276 1277 1278 /* ------------------------------------------------------------------------ */ 1279 /* Function: ipf_htable_iter_deref */ 1280 /* Returns: int - 0 = success, else error */ 1281 /* Parameters: softc(I) - pointer to soft context main structure */ 1282 /* arg(I) - pointer to local context to use */ 1283 /* otype(I) - which data structure type is being walked */ 1284 /* unit(I) - ipfilter device to which we are working on */ 1285 /* data(I) - pointer to old data structure */ 1286 /* */ 1287 /* ------------------------------------------------------------------------ */ 1288 static int 1289 ipf_htable_iter_deref(ipf_main_softc_t *softc, void *arg, int otype, int unit, 1290 void *data) 1291 { 1292 1293 if (data == NULL) 1294 return EFAULT; 1295 1296 if (unit < -1 || unit > IPL_LOGMAX) 1297 return EINVAL; 1298 1299 switch (otype) 1300 { 1301 case IPFLOOKUPITER_LIST : 1302 ipf_htable_deref(softc, arg, (iphtable_t *)data); 1303 break; 1304 1305 case IPFLOOKUPITER_NODE : 1306 ipf_htent_deref(arg, (iphtent_t *)data); 1307 break; 1308 default : 1309 break; 1310 } 1311 1312 return 0; 1313 } 1314 1315 1316 #ifdef USE_INET6 1317 /* ------------------------------------------------------------------------ */ 1318 /* Function: ipf_iphmfind6 */ 1319 /* Parameters: iph(I) - pointer to hash table */ 1320 /* addr(I) - pointer to IPv6 address */ 1321 /* Locks: ipf_poolrw */ 1322 /* */ 1323 /* ------------------------------------------------------------------------ */ 1324 static iphtent_t * 1325 ipf_iphmfind6(iphtable_t *iph, i6addr_t *addr) 1326 { 1327 i6addr_t *msk, ips; 1328 iphtent_t *ipe; 1329 u_int hv; 1330 int i; 1331 1332 i = 0; 1333 maskloop: 1334 msk = iph->iph_v6_masks.imt6_active + i; 1335 ips.i6[0] = addr->i6[0] & msk->i6[0]; 1336 ips.i6[1] = addr->i6[1] & msk->i6[1]; 1337 ips.i6[2] = addr->i6[2] & msk->i6[2]; 1338 ips.i6[3] = addr->i6[3] & msk->i6[3]; 1339 hv = IPE_V6_HASH_FN(ips.i6, msk->i6, iph->iph_size); 1340 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 1341 if ((ipe->ipe_family != AF_INET6) || 1342 IP6_NEQ(&ipe->ipe_mask, msk) || 1343 IP6_NEQ(&ipe->ipe_addr, &ips)) { 1344 continue; 1345 } 1346 break; 1347 } 1348 1349 if (ipe == NULL) { 1350 i++; 1351 if (i < iph->iph_v6_masks.imt6_max) 1352 goto maskloop; 1353 } 1354 return ipe; 1355 } 1356 #endif 1357 1358 1359 static void 1360 ipf_htable_expire(ipf_main_softc_t *softc, void *arg) 1361 { 1362 ipf_htable_softc_t *softh = arg; 1363 iphtent_t *n; 1364 1365 while ((n = softh->ipf_node_explist) != NULL) { 1366 if (n->ipe_die > softc->ipf_ticks) 1367 break; 1368 1369 ipf_htent_remove(softc, softh, n->ipe_owner, n); 1370 } 1371 } 1372 1373 1374 #ifndef _KERNEL 1375 1376 /* ------------------------------------------------------------------------ */ 1377 /* */ 1378 /* ------------------------------------------------------------------------ */ 1379 void 1380 ipf_htable_dump(softc, arg) 1381 ipf_main_softc_t *softc; 1382 void *arg; 1383 { 1384 ipf_htable_softc_t *softh = arg; 1385 iphtable_t *iph; 1386 int i; 1387 1388 printf("List of configured hash tables\n"); 1389 for (i = 0; i < IPL_LOGSIZE; i++) 1390 for (iph = softh->ipf_htables[i]; iph != NULL; 1391 iph = iph->iph_next) 1392 printhash(iph, bcopywrap, NULL, opts, NULL); 1393 1394 } 1395 #endif 1396