1 /* 2 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 7 */ 8 9 #if defined(KERNEL) || defined(_KERNEL) 10 # undef KERNEL 11 # undef _KERNEL 12 # define KERNEL 1 13 # define _KERNEL 1 14 #endif 15 #include <sys/param.h> 16 #include <sys/types.h> 17 #include <sys/errno.h> 18 #include <sys/time.h> 19 #include <sys/file.h> 20 #if !defined(_KERNEL) 21 # include <stdlib.h> 22 # include <string.h> 23 # define _KERNEL 24 # ifdef __OpenBSD__ 25 struct file; 26 # endif 27 # include <sys/uio.h> 28 # undef _KERNEL 29 #endif 30 #include <sys/socket.h> 31 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 32 # include <sys/malloc.h> 33 #endif 34 #if defined(__FreeBSD__) 35 # include <sys/cdefs.h> 36 # include <sys/proc.h> 37 #endif 38 #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \ 39 !defined(linux) 40 # include <sys/mbuf.h> 41 #endif 42 #if defined(_KERNEL) 43 # include <sys/systm.h> 44 #else 45 # include <stdio.h> 46 #endif 47 #include <netinet/in.h> 48 #include <net/if.h> 49 50 #include "netinet/ip_compat.h" 51 #include "netinet/ip_fil.h" 52 #include "netinet/ip_lookup.h" 53 #include "netinet/ip_htable.h" 54 #include "netinet/ipf_stack.h" 55 /* END OF INCLUDES */ 56 57 #if !defined(lint) 58 static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $"; 59 #endif 60 61 #ifdef IPFILTER_LOOKUP 62 static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *)); 63 #ifdef USE_INET6 64 static iphtent_t *fr_iphmfind6 __P((iphtable_t *, struct in6_addr *)); 65 static uint32_t sum4(uint32_t *); 66 static void left_shift_ipv6 __P((char *)); 67 #endif 68 69 void fr_htable_unload(ifs) 70 ipf_stack_t *ifs; 71 { 72 iplookupflush_t fop; 73 74 fop.iplf_unit = IPL_LOGALL; 75 (void)fr_flushhtable(&fop, ifs); 76 } 77 78 79 int fr_gethtablestat(op, ifs) 80 iplookupop_t *op; 81 ipf_stack_t *ifs; 82 { 83 iphtstat_t stats; 84 85 if (op->iplo_size != sizeof(stats)) 86 return EINVAL; 87 88 stats.iphs_tables = ifs->ifs_ipf_htables[op->iplo_unit]; 89 stats.iphs_numtables = ifs->ifs_ipf_nhtables[op->iplo_unit]; 90 stats.iphs_numnodes = ifs->ifs_ipf_nhtnodes[op->iplo_unit]; 91 stats.iphs_nomem = ifs->ifs_ipht_nomem[op->iplo_unit]; 92 93 return COPYOUT(&stats, op->iplo_struct, sizeof(stats)); 94 95 } 96 97 98 /* 99 * Create a new hash table using the template passed. 100 */ 101 int fr_newhtable(op, ifs) 102 iplookupop_t *op; 103 ipf_stack_t *ifs; 104 { 105 iphtable_t *iph, *oiph; 106 char name[FR_GROUPLEN]; 107 int err, i, unit; 108 109 KMALLOC(iph, iphtable_t *); 110 if (iph == NULL) { 111 ifs->ifs_ipht_nomem[op->iplo_unit]++; 112 return ENOMEM; 113 } 114 115 err = COPYIN(op->iplo_struct, iph, sizeof(*iph)); 116 if (err != 0) { 117 KFREE(iph); 118 return EFAULT; 119 } 120 121 unit = op->iplo_unit; 122 if (iph->iph_unit != unit) { 123 KFREE(iph); 124 return EINVAL; 125 } 126 127 if ((op->iplo_arg & IPHASH_ANON) == 0) { 128 if (fr_findhtable(op->iplo_unit, op->iplo_name, ifs) != NULL) { 129 KFREE(iph); 130 return EEXIST; 131 } 132 } else { 133 i = IPHASH_ANON; 134 do { 135 i++; 136 #if defined(SNPRINTF) && defined(_KERNEL) 137 (void)SNPRINTF(name, sizeof(name), "%u", i); 138 #else 139 (void)sprintf(name, "%u", i); 140 #endif 141 for (oiph = ifs->ifs_ipf_htables[unit]; oiph != NULL; 142 oiph = oiph->iph_next) 143 if (strncmp(oiph->iph_name, name, 144 sizeof(oiph->iph_name)) == 0) 145 break; 146 } while (oiph != NULL); 147 (void)strncpy(iph->iph_name, name, sizeof(iph->iph_name)); 148 err = COPYOUT(iph, op->iplo_struct, sizeof(*iph)); 149 if (err != 0) { 150 KFREE(iph); 151 return EFAULT; 152 } 153 iph->iph_type |= IPHASH_ANON; 154 } 155 156 KMALLOCS(iph->iph_table, iphtent_t **, 157 iph->iph_size * sizeof(*iph->iph_table)); 158 if (iph->iph_table == NULL) { 159 KFREE(iph); 160 ifs->ifs_ipht_nomem[unit]++; 161 return ENOMEM; 162 } 163 164 bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 165 iph->iph_masks[0] = 0; 166 iph->iph_masks[1] = 0; 167 iph->iph_masks[2] = 0; 168 iph->iph_masks[3] = 0; 169 iph->iph_list = NULL; 170 171 iph->iph_ref = 1; 172 iph->iph_next = ifs->ifs_ipf_htables[unit]; 173 iph->iph_pnext = &ifs->ifs_ipf_htables[unit]; 174 if (ifs->ifs_ipf_htables[unit] != NULL) 175 ifs->ifs_ipf_htables[unit]->iph_pnext = &iph->iph_next; 176 ifs->ifs_ipf_htables[unit] = iph; 177 178 ifs->ifs_ipf_nhtables[unit]++; 179 180 return 0; 181 } 182 183 184 /* 185 */ 186 int fr_removehtable(op, ifs) 187 iplookupop_t *op; 188 ipf_stack_t *ifs; 189 { 190 iphtable_t *iph; 191 192 193 iph = fr_findhtable(op->iplo_unit, op->iplo_name, ifs); 194 if (iph == NULL) 195 return ESRCH; 196 197 if (iph->iph_unit != op->iplo_unit) { 198 return EINVAL; 199 } 200 201 if (iph->iph_ref != 1) { 202 return EBUSY; 203 } 204 205 fr_delhtable(iph, ifs); 206 207 return 0; 208 } 209 210 211 void fr_delhtable(iph, ifs) 212 iphtable_t *iph; 213 ipf_stack_t *ifs; 214 { 215 iphtent_t *ipe; 216 int i; 217 218 for (i = 0; i < iph->iph_size; i++) 219 while ((ipe = iph->iph_table[i]) != NULL) 220 if (fr_delhtent(iph, ipe, ifs) != 0) 221 return; 222 223 *iph->iph_pnext = iph->iph_next; 224 if (iph->iph_next != NULL) 225 iph->iph_next->iph_pnext = iph->iph_pnext; 226 227 ifs->ifs_ipf_nhtables[iph->iph_unit]--; 228 229 if (iph->iph_ref == 1) { 230 KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table)); 231 KFREE(iph); 232 } 233 } 234 235 236 void fr_derefhtable(iph, ifs) 237 iphtable_t *iph; 238 ipf_stack_t *ifs; 239 { 240 iph->iph_ref--; 241 if (iph->iph_ref == 0) 242 fr_delhtable(iph, ifs); 243 } 244 245 246 void fr_derefhtent(ipe) 247 iphtent_t *ipe; 248 { 249 ipe->ipe_ref--; 250 if (ipe->ipe_ref == 0) { 251 KFREE(ipe); 252 } 253 } 254 255 256 iphtable_t *fr_findhtable(unit, name, ifs) 257 int unit; 258 char *name; 259 ipf_stack_t *ifs; 260 { 261 iphtable_t *iph; 262 263 for (iph = ifs->ifs_ipf_htables[unit]; iph != NULL; iph = iph->iph_next) 264 if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0) 265 break; 266 return iph; 267 } 268 269 270 size_t fr_flushhtable(op, ifs) 271 iplookupflush_t *op; 272 ipf_stack_t *ifs; 273 { 274 iphtable_t *iph; 275 size_t freed; 276 int i; 277 278 freed = 0; 279 280 for (i = 0; i <= IPL_LOGMAX; i++) { 281 if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) { 282 while ((iph = ifs->ifs_ipf_htables[i]) != NULL) { 283 fr_delhtable(iph, ifs); 284 freed++; 285 } 286 } 287 } 288 289 return freed; 290 } 291 292 293 /* 294 * Add an entry to a hash table. 295 */ 296 int fr_addhtent(iph, ipeo, ifs) 297 iphtable_t *iph; 298 iphtent_t *ipeo; 299 ipf_stack_t *ifs; 300 { 301 iphtent_t *ipe; 302 u_int hv; 303 int bits; 304 305 KMALLOC(ipe, iphtent_t *); 306 if (ipe == NULL) 307 return -1; 308 309 bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe)); 310 #ifdef USE_INET6 311 if (ipe->ipe_family == AF_INET6) { 312 bits = count6bits((u_32_t *)ipe->ipe_mask.in6_addr8); 313 hv = IPE_HASH_FN(sum4((uint32_t *)ipe->ipe_addr.in6_addr8), 314 sum4((uint32_t *)ipe->ipe_mask.in6_addr8), 315 iph->iph_size); 316 } else 317 #endif 318 if (ipe->ipe_family == AF_INET) 319 { 320 ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr; 321 ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr); 322 bits = count4bits(ipe->ipe_mask.in4_addr); 323 ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr); 324 325 hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr, 326 iph->iph_size); 327 } else 328 return -1; 329 330 ipe->ipe_ref = 1; 331 ipe->ipe_next = iph->iph_table[hv]; 332 ipe->ipe_pnext = iph->iph_table + hv; 333 334 if (iph->iph_table[hv] != NULL) 335 iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next; 336 iph->iph_table[hv] = ipe; 337 338 ipe->ipe_snext = iph->iph_list; 339 ipe->ipe_psnext = &iph->iph_list; 340 if (ipe->ipe_next != NULL) 341 ipe->ipe_next->ipe_psnext = &ipe->ipe_snext; 342 iph->iph_list = ipe; 343 344 #ifdef USE_INET6 345 if (ipe->ipe_family == AF_INET6) { 346 if ((bits >= 0) && (bits != 128)) 347 if (bits >= 96) 348 iph->iph_masks[0] |= 1 << (bits - 96); 349 else if (bits >= 64) 350 iph->iph_masks[1] |= 1 << (bits - 64); 351 else if (bits >= 32) 352 iph->iph_masks[2] |= 1 << (bits - 32); 353 else 354 iph->iph_masks[3] |= 1 << bits; 355 356 } else 357 #endif 358 { 359 if ((bits >= 0) && (bits != 32)) 360 iph->iph_masks[3] |= 1 << bits; 361 } 362 363 switch (iph->iph_type & ~IPHASH_ANON) 364 { 365 case IPHASH_GROUPMAP : 366 ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL, 367 iph->iph_flags, IPL_LOGIPF, 368 ifs->ifs_fr_active, ifs); 369 break; 370 371 default : 372 ipe->ipe_ptr = NULL; 373 ipe->ipe_value = 0; 374 break; 375 } 376 377 ifs->ifs_ipf_nhtnodes[iph->iph_unit]++; 378 379 return 0; 380 } 381 382 383 /* 384 * Delete an entry from a hash table. 385 */ 386 int fr_delhtent(iph, ipe, ifs) 387 iphtable_t *iph; 388 iphtent_t *ipe; 389 ipf_stack_t *ifs; 390 { 391 if (ipe->ipe_ref != 1) 392 return EBUSY; 393 394 395 *ipe->ipe_pnext = ipe->ipe_next; 396 if (ipe->ipe_next != NULL) 397 ipe->ipe_next->ipe_pnext = ipe->ipe_pnext; 398 399 switch (iph->iph_type & ~IPHASH_ANON) 400 { 401 case IPHASH_GROUPMAP : 402 if (ipe->ipe_group != NULL) 403 fr_delgroup(ipe->ipe_group, IPL_LOGIPF, 404 ifs->ifs_fr_active, ifs); 405 break; 406 407 default : 408 ipe->ipe_ptr = NULL; 409 ipe->ipe_value = 0; 410 break; 411 } 412 413 KFREE(ipe); 414 415 ifs->ifs_ipf_nhtnodes[iph->iph_unit]--; 416 417 return 0; 418 } 419 420 421 void *fr_iphmfindgroup(tptr, version, aptr, ifs) 422 void *tptr; 423 int version; 424 void *aptr; 425 ipf_stack_t *ifs; 426 { 427 i6addr_t *addr; 428 iphtable_t *iph; 429 iphtent_t *ipe; 430 void *rval; 431 432 if ((version != 4) 433 #ifdef USE_INET6 434 && (version != 6) 435 #endif 436 ) 437 return NULL; 438 439 READ_ENTER(&ifs->ifs_ip_poolrw); 440 iph = tptr; 441 addr = aptr; 442 443 #ifdef USE_INET6 444 if (version == 6) 445 ipe = fr_iphmfind6(iph, &addr->in6); 446 else 447 #endif 448 if (version == 4) 449 ipe = fr_iphmfind(iph, &addr->in4); 450 else 451 ipe = NULL; 452 if (ipe != NULL) 453 rval = ipe->ipe_ptr; 454 else 455 rval = NULL; 456 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 457 return rval; 458 } 459 460 461 /* ------------------------------------------------------------------------ */ 462 /* Function: fr_iphmfindip */ 463 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 464 /* Parameters: tptr(I) - pointer to the pool to search */ 465 /* version(I) - IP protocol version (4 or 6) */ 466 /* aptr(I) - pointer to address information */ 467 /* fin - pointer to packet information */ 468 /* ifs - ipf stack instance */ 469 /* */ 470 /* Search the hash table for a given address and return a search result. */ 471 /* ------------------------------------------------------------------------ */ 472 int fr_iphmfindip(tptr, version, aptr, fin, ifs) 473 void *tptr, *aptr; 474 int version; 475 fr_info_t *fin; 476 ipf_stack_t *ifs; 477 { 478 i6addr_t *addr; 479 iphtable_t *iph; 480 iphtent_t *ipe; 481 int rval; 482 483 if ((version != 4) 484 #ifdef USE_INET6 485 && (version != 6) 486 #endif 487 ) 488 return -1; 489 490 if (tptr == NULL || aptr == NULL) 491 return -1; 492 493 iph = tptr; 494 addr = aptr; 495 496 READ_ENTER(&ifs->ifs_ip_poolrw); 497 #ifdef USE_INET6 498 if (version == 6) 499 ipe = fr_iphmfind6(iph, &addr->in6); 500 else 501 #endif 502 if (version == 4) 503 ipe = fr_iphmfind(iph, &addr->in4); 504 else 505 ipe = NULL; 506 if (ipe != NULL) { 507 ipe->ipe_hits++; 508 ipe->ipe_bytes += fin->fin_plen; 509 rval = 0; 510 } else { 511 rval = 1; 512 } 513 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 514 return rval; 515 } 516 517 518 /* Locks: ip_poolrw */ 519 static iphtent_t *fr_iphmfind(iph, addr) 520 iphtable_t *iph; 521 struct in_addr *addr; 522 { 523 u_32_t hmsk, msk, ips; 524 iphtent_t *ipe; 525 u_int hv; 526 527 hmsk = iph->iph_masks[3]; 528 msk = 0xffffffff; 529 maskloop: 530 ips = ntohl(addr->s_addr) & msk; 531 hv = IPE_HASH_FN(ips, msk, iph->iph_size); 532 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 533 if (ipe->ipe_mask.in4_addr != msk || 534 ipe->ipe_addr.in4_addr != ips) { 535 continue; 536 } 537 break; 538 } 539 540 if ((ipe == NULL) && (hmsk != 0)) { 541 while (hmsk != 0) { 542 msk <<= 1; 543 if (hmsk & 0x80000000) 544 break; 545 hmsk <<= 1; 546 } 547 if (hmsk != 0) { 548 hmsk <<= 1; 549 goto maskloop; 550 } 551 } 552 return ipe; 553 } 554 555 556 #ifdef USE_INET6 557 /* Locks: ip_poolrw */ 558 static iphtent_t *fr_iphmfind6(iph, addr) 559 iphtable_t *iph; 560 struct in6_addr *addr; 561 { 562 u_32_t hmsk[4], msk[4], ips[4], *and; 563 iphtent_t *ipe; 564 u_int hv; 565 566 hmsk[0] = iph->iph_masks[0]; 567 hmsk[1] = iph->iph_masks[1]; 568 hmsk[2] = iph->iph_masks[2]; 569 hmsk[3] = iph->iph_masks[3]; 570 571 msk[0] = 0xffffffff; 572 msk[1] = 0xffffffff; 573 msk[2] = 0xffffffff; 574 msk[3] = 0xffffffff; 575 maskloop: 576 and = (u_32_t *)addr->s6_addr; 577 ips[0] = *and & msk[0]; 578 ips[1] = *(and + 1) & msk[1]; 579 ips[2] = *(and + 2) & msk[2]; 580 ips[3] = *(and + 3) & msk[3]; 581 582 hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk), 583 iph->iph_size); 584 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 585 if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) || 586 bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16)) 587 continue; 588 break; 589 } 590 591 if ((ipe == NULL) && ((hmsk[0] != 0) || 592 (hmsk[1] != 0) || 593 (hmsk[2] != 0) || 594 (hmsk[3] != 0) )) { 595 while ((hmsk[0] != 0) && (hmsk[1] != 0) && 596 (hmsk[2] != 0) && (hmsk[3] != 0)) { 597 left_shift_ipv6((char *)msk); 598 if (hmsk[0] & 0x80000000) 599 break; 600 left_shift_ipv6((char *)hmsk); 601 } 602 if ((hmsk[0] != 0) && (hmsk[1] != 0) && 603 (hmsk[2] != 0) && (hmsk[3] != 0)) { 604 left_shift_ipv6((char *)hmsk); 605 goto maskloop; 606 } 607 } 608 return ipe; 609 } 610 611 612 /* 613 * sum4: ipv6 add -> 4 bytes values 614 */ 615 static uint32_t sum4(add) 616 uint32_t *add; 617 { 618 return (*add + *(add + 1) + *(add + 2) + *(add + 3)); 619 } 620 621 /* 622 * left shift on 128 bits 623 */ 624 static void left_shift_ipv6(data) 625 char *data; 626 { 627 u_32_t *sd; 628 629 sd = (u_32_t *)data; 630 sd[0] <<= 1; 631 if (sd[1] >= 0x80000000) 632 sd[0] += 1; 633 634 sd[1] <<= 1; 635 if (sd[2] >= 0x80000000) 636 sd[1] += 1; 637 638 sd[2] <<= 1; 639 if (sd[3] >= 0x80000000) 640 sd[2] += 1; 641 642 sd[3] <<= 1; 643 } 644 #endif 645 646 int fr_htable_getnext(token, ilp, ifs) 647 ipftoken_t *token; 648 ipflookupiter_t *ilp; 649 ipf_stack_t *ifs; 650 { 651 iphtent_t *node, zn, *nextnode; 652 iphtable_t *iph, zp, *nextiph; 653 int err; 654 655 err = 0; 656 iph = NULL; 657 node = NULL; 658 nextiph = NULL; 659 nextnode = NULL; 660 661 READ_ENTER(&ifs->ifs_ip_poolrw); 662 663 /* 664 * Get "previous" entry from the token and find the next entry. 665 * 666 * If we found an entry, add a reference to it and update the token. 667 * Otherwise, zero out data to be returned and NULL out token. 668 */ 669 switch (ilp->ili_otype) 670 { 671 case IPFLOOKUPITER_LIST : 672 iph = token->ipt_data; 673 if (iph == NULL) { 674 nextiph = ifs->ifs_ipf_htables[(int)ilp->ili_unit]; 675 } else { 676 nextiph = iph->iph_next; 677 } 678 if (nextiph != NULL) { 679 ATOMIC_INC(nextiph->iph_ref); 680 token->ipt_data = nextiph; 681 } else { 682 bzero((char *)&zp, sizeof(zp)); 683 nextiph = &zp; 684 token->ipt_data = NULL; 685 } 686 break; 687 688 case IPFLOOKUPITER_NODE : 689 node = token->ipt_data; 690 if (node == NULL) { 691 iph = fr_findhtable(ilp->ili_unit, ilp->ili_name, ifs); 692 if (iph == NULL) 693 err = ESRCH; 694 else { 695 nextnode = iph->iph_list; 696 } 697 } else { 698 nextnode = node->ipe_snext; 699 } 700 if (nextnode != NULL) { 701 ATOMIC_INC(nextnode->ipe_ref); 702 token->ipt_data = nextnode; 703 } else { 704 bzero((char *)&zn, sizeof(zn)); 705 nextnode = &zn; 706 token->ipt_data = NULL; 707 } 708 break; 709 710 default : 711 err = EINVAL; 712 break; 713 } 714 715 /* 716 * Now that we have ref, it's save to give up lock. 717 */ 718 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 719 if (err != 0) 720 return err; 721 722 /* 723 * Copy out data and clean up references and token as needed. 724 */ 725 switch (ilp->ili_otype) 726 { 727 case IPFLOOKUPITER_LIST : 728 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); 729 if (err != 0) 730 err = EFAULT; 731 if (token->ipt_data == NULL) { 732 ipf_freetoken(token, ifs); 733 } else { 734 if (iph != NULL) { 735 WRITE_ENTER(&ifs->ifs_ip_poolrw); 736 fr_derefhtable(iph, ifs); 737 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 738 } 739 if (nextiph->iph_next == NULL) 740 ipf_freetoken(token, ifs); 741 } 742 break; 743 744 case IPFLOOKUPITER_NODE : 745 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 746 if (err != 0) 747 err = EFAULT; 748 if (token->ipt_data == NULL) { 749 ipf_freetoken(token, ifs); 750 } else { 751 if (node != NULL) { 752 WRITE_ENTER(&ifs->ifs_ip_poolrw); 753 fr_derefhtent(node); 754 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 755 } 756 if (nextnode->ipe_snext == NULL) 757 ipf_freetoken(token, ifs); 758 } 759 break; 760 } 761 762 return err; 763 } 764 765 766 void fr_htable_iterderef(otype, unit, data, ifs) 767 u_int otype; 768 int unit; 769 void *data; 770 ipf_stack_t *ifs; 771 { 772 773 if (data == NULL) 774 return; 775 776 if (unit < 0 || unit > IPL_LOGMAX) 777 return; 778 779 switch (otype) 780 { 781 case IPFLOOKUPITER_LIST : 782 WRITE_ENTER(&ifs->ifs_ip_poolrw); 783 fr_derefhtable((iphtable_t *)data, ifs); 784 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 785 break; 786 787 case IPFLOOKUPITER_NODE : 788 WRITE_ENTER(&ifs->ifs_ip_poolrw); 789 fr_derefhtent((iphtent_t *)data); 790 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 791 break; 792 default : 793 break; 794 } 795 } 796 #endif /* IPFILTER_LOOKUP */ 797