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
fr_htable_unload(ifs)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
fr_gethtablestat(op,ifs)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 */
fr_newhtable(op,ifs)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 */
fr_removehtable(op,ifs)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
fr_delhtable(iph,ifs)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
fr_derefhtable(iph,ifs)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
fr_derefhtent(ipe)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
fr_findhtable(unit,name,ifs)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
fr_flushhtable(op,ifs)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 */
fr_addhtent(iph,ipeo,ifs)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 */
fr_delhtent(iph,ipe,ifs)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
fr_iphmfindgroup(tptr,version,aptr,ifs)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 /* ------------------------------------------------------------------------ */
fr_iphmfindip(tptr,version,aptr,fin,ifs)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 */
fr_iphmfind(iph,addr)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 */
fr_iphmfind6(iph,addr)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 */
sum4(add)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 */
left_shift_ipv6(data)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
fr_htable_getnext(token,ilp,ifs)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
fr_htable_iterderef(otype,unit,data,ifs)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