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 fr_delgroup(ipe->ipe_group, IPL_LOGIPF, 403 ifs->ifs_fr_active, ifs); 404 break; 405 406 default : 407 ipe->ipe_ptr = NULL; 408 ipe->ipe_value = 0; 409 break; 410 } 411 412 KFREE(ipe); 413 414 ifs->ifs_ipf_nhtnodes[iph->iph_unit]--; 415 416 return 0; 417 } 418 419 420 void *fr_iphmfindgroup(tptr, version, aptr, ifs) 421 void *tptr; 422 int version; 423 void *aptr; 424 ipf_stack_t *ifs; 425 { 426 i6addr_t *addr; 427 iphtable_t *iph; 428 iphtent_t *ipe; 429 void *rval; 430 431 if ((version != 4) 432 #ifdef USE_INET6 433 && (version != 6) 434 #endif 435 ) 436 return NULL; 437 438 READ_ENTER(&ifs->ifs_ip_poolrw); 439 iph = tptr; 440 addr = aptr; 441 442 #ifdef USE_INET6 443 if (version == 6) 444 ipe = fr_iphmfind6(iph, &addr->in6); 445 else 446 #endif 447 if (version == 4) 448 ipe = fr_iphmfind(iph, &addr->in4); 449 else 450 ipe = NULL; 451 if (ipe != NULL) 452 rval = ipe->ipe_ptr; 453 else 454 rval = NULL; 455 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 456 return rval; 457 } 458 459 460 /* ------------------------------------------------------------------------ */ 461 /* Function: fr_iphmfindip */ 462 /* Returns: int - 0 == +ve match, -1 == error, 1 == -ve/no match */ 463 /* Parameters: tptr(I) - pointer to the pool to search */ 464 /* version(I) - IP protocol version (4 or 6) */ 465 /* aptr(I) - pointer to address information */ 466 /* fin - pointer to packet information */ 467 /* ifs - ipf stack instance */ 468 /* */ 469 /* Search the hash table for a given address and return a search result. */ 470 /* ------------------------------------------------------------------------ */ 471 int fr_iphmfindip(tptr, version, aptr, fin, ifs) 472 void *tptr, *aptr; 473 int version; 474 fr_info_t *fin; 475 ipf_stack_t *ifs; 476 { 477 i6addr_t *addr; 478 iphtable_t *iph; 479 iphtent_t *ipe; 480 int rval; 481 482 if ((version != 4) 483 #ifdef USE_INET6 484 && (version != 6) 485 #endif 486 ) 487 return -1; 488 489 if (tptr == NULL || aptr == NULL) 490 return -1; 491 492 iph = tptr; 493 addr = aptr; 494 495 READ_ENTER(&ifs->ifs_ip_poolrw); 496 #ifdef USE_INET6 497 if (version == 6) 498 ipe = fr_iphmfind6(iph, &addr->in6); 499 else 500 #endif 501 if (version == 4) 502 ipe = fr_iphmfind(iph, &addr->in4); 503 else 504 ipe = NULL; 505 if (ipe != NULL) { 506 ipe->ipe_hits++; 507 ipe->ipe_bytes += fin->fin_plen; 508 rval = 0; 509 } else { 510 rval = 1; 511 } 512 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 513 return rval; 514 } 515 516 517 /* Locks: ip_poolrw */ 518 static iphtent_t *fr_iphmfind(iph, addr) 519 iphtable_t *iph; 520 struct in_addr *addr; 521 { 522 u_32_t hmsk, msk, ips; 523 iphtent_t *ipe; 524 u_int hv; 525 526 hmsk = iph->iph_masks[3]; 527 msk = 0xffffffff; 528 maskloop: 529 ips = ntohl(addr->s_addr) & msk; 530 hv = IPE_HASH_FN(ips, msk, iph->iph_size); 531 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 532 if (ipe->ipe_mask.in4_addr != msk || 533 ipe->ipe_addr.in4_addr != ips) { 534 continue; 535 } 536 break; 537 } 538 539 if ((ipe == NULL) && (hmsk != 0)) { 540 while (hmsk != 0) { 541 msk <<= 1; 542 if (hmsk & 0x80000000) 543 break; 544 hmsk <<= 1; 545 } 546 if (hmsk != 0) { 547 hmsk <<= 1; 548 goto maskloop; 549 } 550 } 551 return ipe; 552 } 553 554 555 #ifdef USE_INET6 556 /* Locks: ip_poolrw */ 557 static iphtent_t *fr_iphmfind6(iph, addr) 558 iphtable_t *iph; 559 struct in6_addr *addr; 560 { 561 u_32_t hmsk[4], msk[4], ips[4], *and; 562 iphtent_t *ipe; 563 u_int hv; 564 565 hmsk[0] = iph->iph_masks[0]; 566 hmsk[1] = iph->iph_masks[1]; 567 hmsk[2] = iph->iph_masks[2]; 568 hmsk[3] = iph->iph_masks[3]; 569 570 msk[0] = 0xffffffff; 571 msk[1] = 0xffffffff; 572 msk[2] = 0xffffffff; 573 msk[3] = 0xffffffff; 574 maskloop: 575 and = (u_32_t *)addr->s6_addr; 576 ips[0] = *and & msk[0]; 577 ips[1] = *(and + 1) & msk[1]; 578 ips[2] = *(and + 2) & msk[2]; 579 ips[3] = *(and + 3) & msk[3]; 580 581 hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk), 582 iph->iph_size); 583 for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) { 584 if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) || 585 bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16)) 586 continue; 587 break; 588 } 589 590 if ((ipe == NULL) && ((hmsk[0] != 0) || 591 (hmsk[1] != 0) || 592 (hmsk[2] != 0) || 593 (hmsk[3] != 0) )) { 594 while ((hmsk[0] != 0) && (hmsk[1] != 0) && 595 (hmsk[2] != 0) && (hmsk[3] != 0)) { 596 left_shift_ipv6((char *)msk); 597 if (hmsk[0] & 0x80000000) 598 break; 599 left_shift_ipv6((char *)hmsk); 600 } 601 if ((hmsk[0] != 0) && (hmsk[1] != 0) && 602 (hmsk[2] != 0) && (hmsk[3] != 0)) { 603 left_shift_ipv6((char *)hmsk); 604 goto maskloop; 605 } 606 } 607 return ipe; 608 } 609 610 611 /* 612 * sum4: ipv6 add -> 4 bytes values 613 */ 614 static uint32_t sum4(add) 615 uint32_t *add; 616 { 617 return (*add + *(add + 1) + *(add + 2) + *(add + 3)); 618 } 619 620 /* 621 * left shift on 128 bits 622 */ 623 static void left_shift_ipv6(data) 624 char *data; 625 { 626 u_32_t *sd; 627 628 sd = (u_32_t *)data; 629 sd[0] <<= 1; 630 if (sd[1] >= 0x80000000) 631 sd[0] += 1; 632 633 sd[1] <<= 1; 634 if (sd[2] >= 0x80000000) 635 sd[1] += 1; 636 637 sd[2] <<= 1; 638 if (sd[3] >= 0x80000000) 639 sd[2] += 1; 640 641 sd[3] <<= 1; 642 } 643 #endif 644 645 int fr_htable_getnext(token, ilp, ifs) 646 ipftoken_t *token; 647 ipflookupiter_t *ilp; 648 ipf_stack_t *ifs; 649 { 650 iphtent_t *node, zn, *nextnode; 651 iphtable_t *iph, zp, *nextiph; 652 int err; 653 654 err = 0; 655 iph = NULL; 656 node = NULL; 657 nextiph = NULL; 658 nextnode = NULL; 659 660 READ_ENTER(&ifs->ifs_ip_poolrw); 661 662 /* 663 * Get "previous" entry from the token and find the next entry. 664 * 665 * If we found an entry, add a reference to it and update the token. 666 * Otherwise, zero out data to be returned and NULL out token. 667 */ 668 switch (ilp->ili_otype) 669 { 670 case IPFLOOKUPITER_LIST : 671 iph = token->ipt_data; 672 if (iph == NULL) { 673 nextiph = ifs->ifs_ipf_htables[(int)ilp->ili_unit]; 674 } else { 675 nextiph = iph->iph_next; 676 } 677 if (nextiph != NULL) { 678 ATOMIC_INC(nextiph->iph_ref); 679 token->ipt_data = nextiph; 680 } else { 681 bzero((char *)&zp, sizeof(zp)); 682 nextiph = &zp; 683 token->ipt_data = NULL; 684 } 685 break; 686 687 case IPFLOOKUPITER_NODE : 688 node = token->ipt_data; 689 if (node == NULL) { 690 iph = fr_findhtable(ilp->ili_unit, ilp->ili_name, ifs); 691 if (iph == NULL) 692 err = ESRCH; 693 else { 694 nextnode = iph->iph_list; 695 } 696 } else { 697 nextnode = node->ipe_snext; 698 } 699 if (nextnode != NULL) { 700 ATOMIC_INC(nextnode->ipe_ref); 701 token->ipt_data = nextnode; 702 } else { 703 bzero((char *)&zn, sizeof(zn)); 704 nextnode = &zn; 705 token->ipt_data = NULL; 706 } 707 break; 708 709 default : 710 err = EINVAL; 711 break; 712 } 713 714 /* 715 * Now that we have ref, it's save to give up lock. 716 */ 717 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 718 if (err != 0) 719 return err; 720 721 /* 722 * Copy out data and clean up references and token as needed. 723 */ 724 switch (ilp->ili_otype) 725 { 726 case IPFLOOKUPITER_LIST : 727 err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph)); 728 if (err != 0) 729 err = EFAULT; 730 if (token->ipt_data == NULL) { 731 ipf_freetoken(token, ifs); 732 } else { 733 if (iph != NULL) { 734 WRITE_ENTER(&ifs->ifs_ip_poolrw); 735 fr_derefhtable(iph, ifs); 736 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 737 } 738 if (nextiph->iph_next == NULL) 739 ipf_freetoken(token, ifs); 740 } 741 break; 742 743 case IPFLOOKUPITER_NODE : 744 err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode)); 745 if (err != 0) 746 err = EFAULT; 747 if (token->ipt_data == NULL) { 748 ipf_freetoken(token, ifs); 749 } else { 750 if (node != NULL) { 751 WRITE_ENTER(&ifs->ifs_ip_poolrw); 752 fr_derefhtent(node); 753 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 754 } 755 if (nextnode->ipe_snext == NULL) 756 ipf_freetoken(token, ifs); 757 } 758 break; 759 } 760 761 return err; 762 } 763 764 765 void fr_htable_iterderef(otype, unit, data, ifs) 766 u_int otype; 767 int unit; 768 void *data; 769 ipf_stack_t *ifs; 770 { 771 772 if (data == NULL) 773 return; 774 775 if (unit < 0 || unit > IPL_LOGMAX) 776 return; 777 778 switch (otype) 779 { 780 case IPFLOOKUPITER_LIST : 781 WRITE_ENTER(&ifs->ifs_ip_poolrw); 782 fr_derefhtable((iphtable_t *)data, ifs); 783 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 784 break; 785 786 case IPFLOOKUPITER_NODE : 787 WRITE_ENTER(&ifs->ifs_ip_poolrw); 788 fr_derefhtent((iphtent_t *)data); 789 RWLOCK_EXIT(&ifs->ifs_ip_poolrw); 790 break; 791 default : 792 break; 793 } 794 } 795 #endif /* IPFILTER_LOOKUP */ 796