17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1993-2001, 2003 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
6*de22af4eSJohn Ojemann  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
77c478bd9Sstevel@tonic-gate  */
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
107c478bd9Sstevel@tonic-gate # undef KERNEL
117c478bd9Sstevel@tonic-gate # undef _KERNEL
127c478bd9Sstevel@tonic-gate # define        KERNEL	1
137c478bd9Sstevel@tonic-gate # define        _KERNEL	1
147c478bd9Sstevel@tonic-gate #endif
157c478bd9Sstevel@tonic-gate #include <sys/param.h>
167c478bd9Sstevel@tonic-gate #include <sys/types.h>
177c478bd9Sstevel@tonic-gate #include <sys/errno.h>
187c478bd9Sstevel@tonic-gate #include <sys/time.h>
197c478bd9Sstevel@tonic-gate #include <sys/file.h>
207c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
217c478bd9Sstevel@tonic-gate # include <stdlib.h>
227c478bd9Sstevel@tonic-gate # include <string.h>
237c478bd9Sstevel@tonic-gate # define _KERNEL
247c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
257c478bd9Sstevel@tonic-gate struct file;
267c478bd9Sstevel@tonic-gate # endif
277c478bd9Sstevel@tonic-gate # include <sys/uio.h>
287c478bd9Sstevel@tonic-gate # undef _KERNEL
297c478bd9Sstevel@tonic-gate #endif
307c478bd9Sstevel@tonic-gate #include <sys/socket.h>
317c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
327c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
337c478bd9Sstevel@tonic-gate #endif
347c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__)
357c478bd9Sstevel@tonic-gate #  include <sys/cdefs.h>
367c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
377c478bd9Sstevel@tonic-gate #endif
38ab25eeb5Syz #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
39ab25eeb5Syz     !defined(linux)
407c478bd9Sstevel@tonic-gate # include <sys/mbuf.h>
417c478bd9Sstevel@tonic-gate #endif
427c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
437c478bd9Sstevel@tonic-gate # include <sys/systm.h>
447c478bd9Sstevel@tonic-gate #else
457c478bd9Sstevel@tonic-gate # include <stdio.h>
467c478bd9Sstevel@tonic-gate #endif
477c478bd9Sstevel@tonic-gate #include <netinet/in.h>
487c478bd9Sstevel@tonic-gate #include <net/if.h>
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
517c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
527c478bd9Sstevel@tonic-gate #include "netinet/ip_lookup.h"
537c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h"
54f4b3ec61Sdh #include "netinet/ipf_stack.h"
55ab25eeb5Syz /* END OF INCLUDES */
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate #if !defined(lint)
58ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $";
597c478bd9Sstevel@tonic-gate #endif
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_LOOKUP
627c478bd9Sstevel@tonic-gate static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
637663b816Sml #ifdef USE_INET6
647663b816Sml static iphtent_t *fr_iphmfind6 __P((iphtable_t *, struct in6_addr *));
657663b816Sml static uint32_t sum4(uint32_t *);
667663b816Sml static void left_shift_ipv6 __P((char *));
677663b816Sml #endif
687c478bd9Sstevel@tonic-gate 
69f4b3ec61Sdh void fr_htable_unload(ifs)
70f4b3ec61Sdh ipf_stack_t *ifs;
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	iplookupflush_t fop;
73ab25eeb5Syz 
74ab25eeb5Syz 	fop.iplf_unit = IPL_LOGALL;
75f4b3ec61Sdh 	(void)fr_flushhtable(&fop, ifs);
767c478bd9Sstevel@tonic-gate }
777c478bd9Sstevel@tonic-gate 
78ab25eeb5Syz 
79f4b3ec61Sdh int fr_gethtablestat(op, ifs)
807663b816Sml iplookupop_t *op;
81f4b3ec61Sdh ipf_stack_t *ifs;
827663b816Sml {
837663b816Sml 	iphtstat_t stats;
847663b816Sml 
857663b816Sml 	if (op->iplo_size != sizeof(stats))
867663b816Sml 		return EINVAL;
877663b816Sml 
88f4b3ec61Sdh 	stats.iphs_tables = ifs->ifs_ipf_htables[op->iplo_unit];
89f4b3ec61Sdh 	stats.iphs_numtables = ifs->ifs_ipf_nhtables[op->iplo_unit];
90f4b3ec61Sdh 	stats.iphs_numnodes = ifs->ifs_ipf_nhtnodes[op->iplo_unit];
91f4b3ec61Sdh 	stats.iphs_nomem = ifs->ifs_ipht_nomem[op->iplo_unit];
927663b816Sml 
937663b816Sml 	return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
947663b816Sml 
957663b816Sml }
967663b816Sml 
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate /*
997c478bd9Sstevel@tonic-gate  * Create a new hash table using the template passed.
1007c478bd9Sstevel@tonic-gate  */
101f4b3ec61Sdh int fr_newhtable(op, ifs)
1027c478bd9Sstevel@tonic-gate iplookupop_t *op;
103f4b3ec61Sdh ipf_stack_t *ifs;
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 	iphtable_t *iph, *oiph;
1067c478bd9Sstevel@tonic-gate 	char name[FR_GROUPLEN];
1077c478bd9Sstevel@tonic-gate 	int err, i, unit;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate 	KMALLOC(iph, iphtable_t *);
110ab25eeb5Syz 	if (iph == NULL) {
111f4b3ec61Sdh 		ifs->ifs_ipht_nomem[op->iplo_unit]++;
112ab25eeb5Syz 		return ENOMEM;
113ab25eeb5Syz 	}
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
1167c478bd9Sstevel@tonic-gate 	if (err != 0) {
1177c478bd9Sstevel@tonic-gate 		KFREE(iph);
1187c478bd9Sstevel@tonic-gate 		return EFAULT;
1197c478bd9Sstevel@tonic-gate 	}
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate 	unit = op->iplo_unit;
1227c478bd9Sstevel@tonic-gate 	if (iph->iph_unit != unit) {
1237c478bd9Sstevel@tonic-gate 		KFREE(iph);
1247c478bd9Sstevel@tonic-gate 		return EINVAL;
1257c478bd9Sstevel@tonic-gate 	}
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if ((op->iplo_arg & IPHASH_ANON) == 0) {
128f4b3ec61Sdh 		if (fr_findhtable(op->iplo_unit, op->iplo_name, ifs) != NULL) {
1297c478bd9Sstevel@tonic-gate 			KFREE(iph);
1307c478bd9Sstevel@tonic-gate 			return EEXIST;
1317c478bd9Sstevel@tonic-gate 		}
1327c478bd9Sstevel@tonic-gate 	} else {
1337c478bd9Sstevel@tonic-gate 		i = IPHASH_ANON;
1347c478bd9Sstevel@tonic-gate 		do {
1357c478bd9Sstevel@tonic-gate 			i++;
136ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
137ab25eeb5Syz 			(void)SNPRINTF(name, sizeof(name), "%u", i);
138ab25eeb5Syz #else
1397c478bd9Sstevel@tonic-gate 			(void)sprintf(name, "%u", i);
140ab25eeb5Syz #endif
141f4b3ec61Sdh 			for (oiph = ifs->ifs_ipf_htables[unit]; oiph != NULL;
1427c478bd9Sstevel@tonic-gate 			     oiph = oiph->iph_next)
1437c478bd9Sstevel@tonic-gate 				if (strncmp(oiph->iph_name, name,
1447c478bd9Sstevel@tonic-gate 					    sizeof(oiph->iph_name)) == 0)
1457c478bd9Sstevel@tonic-gate 					break;
1467c478bd9Sstevel@tonic-gate 		} while (oiph != NULL);
1477c478bd9Sstevel@tonic-gate 		(void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
1487c478bd9Sstevel@tonic-gate 		err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
1497c478bd9Sstevel@tonic-gate 		if (err != 0) {
1507c478bd9Sstevel@tonic-gate 			KFREE(iph);
1517c478bd9Sstevel@tonic-gate 			return EFAULT;
1527c478bd9Sstevel@tonic-gate 		}
1537c478bd9Sstevel@tonic-gate 		iph->iph_type |= IPHASH_ANON;
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	KMALLOCS(iph->iph_table, iphtent_t **,
1577c478bd9Sstevel@tonic-gate 		 iph->iph_size * sizeof(*iph->iph_table));
1587c478bd9Sstevel@tonic-gate 	if (iph->iph_table == NULL) {
1597c478bd9Sstevel@tonic-gate 		KFREE(iph);
160f4b3ec61Sdh 		ifs->ifs_ipht_nomem[unit]++;
1617c478bd9Sstevel@tonic-gate 		return ENOMEM;
1627c478bd9Sstevel@tonic-gate 	}
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 	bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
1657663b816Sml 	iph->iph_masks[0] = 0;
1667663b816Sml 	iph->iph_masks[1] = 0;
1677663b816Sml 	iph->iph_masks[2] = 0;
1687663b816Sml 	iph->iph_masks[3] = 0;
169f4b3ec61Sdh 	iph->iph_list = NULL;
1707c478bd9Sstevel@tonic-gate 
171f4b3ec61Sdh 	iph->iph_ref = 1;
172f4b3ec61Sdh 	iph->iph_next = ifs->ifs_ipf_htables[unit];
173f4b3ec61Sdh 	iph->iph_pnext = &ifs->ifs_ipf_htables[unit];
174f4b3ec61Sdh 	if (ifs->ifs_ipf_htables[unit] != NULL)
175f4b3ec61Sdh 		ifs->ifs_ipf_htables[unit]->iph_pnext = &iph->iph_next;
176f4b3ec61Sdh 	ifs->ifs_ipf_htables[unit] = iph;
1777663b816Sml 
178f4b3ec61Sdh 	ifs->ifs_ipf_nhtables[unit]++;
1797663b816Sml 
1807c478bd9Sstevel@tonic-gate 	return 0;
1817c478bd9Sstevel@tonic-gate }
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  */
186f4b3ec61Sdh int fr_removehtable(op, ifs)
1877c478bd9Sstevel@tonic-gate iplookupop_t *op;
188f4b3ec61Sdh ipf_stack_t *ifs;
1897c478bd9Sstevel@tonic-gate {
1907c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 
193f4b3ec61Sdh 	iph = fr_findhtable(op->iplo_unit, op->iplo_name, ifs);
1947c478bd9Sstevel@tonic-gate 	if (iph == NULL)
1957c478bd9Sstevel@tonic-gate 		return ESRCH;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (iph->iph_unit != op->iplo_unit) {
1987c478bd9Sstevel@tonic-gate 		return EINVAL;
1997c478bd9Sstevel@tonic-gate 	}
200f4b3ec61Sdh 
201f4b3ec61Sdh 	if (iph->iph_ref != 1) {
2027c478bd9Sstevel@tonic-gate 		return EBUSY;
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 
205f4b3ec61Sdh 	fr_delhtable(iph, ifs);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	return 0;
2087c478bd9Sstevel@tonic-gate }
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 
211f4b3ec61Sdh void fr_delhtable(iph, ifs)
2127c478bd9Sstevel@tonic-gate iphtable_t *iph;
213f4b3ec61Sdh ipf_stack_t *ifs;
2147c478bd9Sstevel@tonic-gate {
215ab25eeb5Syz 	iphtent_t *ipe;
216ab25eeb5Syz 	int i;
217ab25eeb5Syz 
218ab25eeb5Syz 	for (i = 0; i < iph->iph_size; i++)
219ab25eeb5Syz 		while ((ipe = iph->iph_table[i]) != NULL)
220f4b3ec61Sdh 			if (fr_delhtent(iph, ipe, ifs) != 0)
221ab25eeb5Syz 				return;
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	*iph->iph_pnext = iph->iph_next;
2247c478bd9Sstevel@tonic-gate 	if (iph->iph_next != NULL)
2257c478bd9Sstevel@tonic-gate 		iph->iph_next->iph_pnext = iph->iph_pnext;
2267c478bd9Sstevel@tonic-gate 
227f4b3ec61Sdh 	ifs->ifs_ipf_nhtables[iph->iph_unit]--;
228ab25eeb5Syz 
229f4b3ec61Sdh 	if (iph->iph_ref == 1) {
230ab25eeb5Syz 		KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
231ab25eeb5Syz 		KFREE(iph);
232ab25eeb5Syz 	}
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 
236f4b3ec61Sdh void fr_derefhtable(iph, ifs)
2377c478bd9Sstevel@tonic-gate iphtable_t *iph;
238f4b3ec61Sdh ipf_stack_t *ifs;
2397c478bd9Sstevel@tonic-gate {
2407c478bd9Sstevel@tonic-gate 	iph->iph_ref--;
2417c478bd9Sstevel@tonic-gate 	if (iph->iph_ref == 0)
242f4b3ec61Sdh 		fr_delhtable(iph, ifs);
243f4b3ec61Sdh }
244f4b3ec61Sdh 
245f4b3ec61Sdh 
246f4b3ec61Sdh void fr_derefhtent(ipe)
247f4b3ec61Sdh iphtent_t *ipe;
248f4b3ec61Sdh {
249f4b3ec61Sdh 	ipe->ipe_ref--;
250f4b3ec61Sdh 	if (ipe->ipe_ref == 0) {
251f4b3ec61Sdh 		KFREE(ipe);
252f4b3ec61Sdh 	}
2537c478bd9Sstevel@tonic-gate }
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 
256f4b3ec61Sdh iphtable_t *fr_findhtable(unit, name, ifs)
2577c478bd9Sstevel@tonic-gate int unit;
2587c478bd9Sstevel@tonic-gate char *name;
259f4b3ec61Sdh ipf_stack_t *ifs;
2607c478bd9Sstevel@tonic-gate {
2617c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2627c478bd9Sstevel@tonic-gate 
263f4b3ec61Sdh 	for (iph = ifs->ifs_ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
2647c478bd9Sstevel@tonic-gate 		if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
2657c478bd9Sstevel@tonic-gate 			break;
2667c478bd9Sstevel@tonic-gate 	return iph;
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate 
270f4b3ec61Sdh size_t fr_flushhtable(op, ifs)
2717c478bd9Sstevel@tonic-gate iplookupflush_t *op;
272f4b3ec61Sdh ipf_stack_t *ifs;
2737c478bd9Sstevel@tonic-gate {
2747c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
275ab25eeb5Syz 	size_t freed;
276ab25eeb5Syz 	int i;
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	freed = 0;
2797c478bd9Sstevel@tonic-gate 
280ab25eeb5Syz 	for (i = 0; i <= IPL_LOGMAX; i++) {
281ab25eeb5Syz 		if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
282f4b3ec61Sdh 			while ((iph = ifs->ifs_ipf_htables[i]) != NULL) {
283f4b3ec61Sdh 				fr_delhtable(iph, ifs);
284ab25eeb5Syz 				freed++;
2857c478bd9Sstevel@tonic-gate 			}
2867c478bd9Sstevel@tonic-gate 		}
287ab25eeb5Syz 	}
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	return freed;
2907c478bd9Sstevel@tonic-gate }
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate /*
2947c478bd9Sstevel@tonic-gate  * Add an entry to a hash table.
2957c478bd9Sstevel@tonic-gate  */
296f4b3ec61Sdh int fr_addhtent(iph, ipeo, ifs)
2977c478bd9Sstevel@tonic-gate iphtable_t *iph;
2987c478bd9Sstevel@tonic-gate iphtent_t *ipeo;
299f4b3ec61Sdh ipf_stack_t *ifs;
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
3027c478bd9Sstevel@tonic-gate 	u_int hv;
3037c478bd9Sstevel@tonic-gate 	int bits;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	KMALLOC(ipe, iphtent_t *);
3067c478bd9Sstevel@tonic-gate 	if (ipe == NULL)
3077c478bd9Sstevel@tonic-gate 		return -1;
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 	bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
3107663b816Sml #ifdef USE_INET6
3117663b816Sml 	if (ipe->ipe_family == AF_INET6) {
3127663b816Sml 		bits = count6bits((u_32_t *)ipe->ipe_mask.in6_addr8);
3137663b816Sml 		hv = IPE_HASH_FN(sum4((uint32_t *)ipe->ipe_addr.in6_addr8),
3147663b816Sml 				 sum4((uint32_t *)ipe->ipe_mask.in6_addr8),
3157663b816Sml 				 iph->iph_size);
3167663b816Sml 	} else
3177663b816Sml #endif
3187663b816Sml 	if (ipe->ipe_family == AF_INET)
3197663b816Sml 	{
3207663b816Sml 		ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
3217663b816Sml 		ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
3227663b816Sml 		bits = count4bits(ipe->ipe_mask.in4_addr);
3237663b816Sml 		ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
3247663b816Sml 
3257663b816Sml 		hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
3267663b816Sml 				 iph->iph_size);
3277663b816Sml 	} else
3287663b816Sml 		return -1;
3297c478bd9Sstevel@tonic-gate 
330f4b3ec61Sdh 	ipe->ipe_ref = 1;
3317c478bd9Sstevel@tonic-gate 	ipe->ipe_next = iph->iph_table[hv];
3327c478bd9Sstevel@tonic-gate 	ipe->ipe_pnext = iph->iph_table + hv;
3337c478bd9Sstevel@tonic-gate 
3347c478bd9Sstevel@tonic-gate 	if (iph->iph_table[hv] != NULL)
3357c478bd9Sstevel@tonic-gate 		iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next;
3367c478bd9Sstevel@tonic-gate 	iph->iph_table[hv] = ipe;
337f4b3ec61Sdh 
338f4b3ec61Sdh 	ipe->ipe_snext = iph->iph_list;
339f4b3ec61Sdh 	ipe->ipe_psnext = &iph->iph_list;
340f4b3ec61Sdh 	if (ipe->ipe_next != NULL)
341f4b3ec61Sdh 		ipe->ipe_next->ipe_psnext = &ipe->ipe_snext;
342f4b3ec61Sdh 	iph->iph_list = ipe;
343f4b3ec61Sdh 
3447663b816Sml #ifdef USE_INET6
3457663b816Sml 	if (ipe->ipe_family == AF_INET6) {
3467663b816Sml 		if ((bits >= 0) && (bits != 128))
3477663b816Sml 			if (bits >= 96)
3487663b816Sml 				iph->iph_masks[0] |= 1 << (bits - 96);
3497663b816Sml 			else if (bits >= 64)
3507663b816Sml 				iph->iph_masks[1] |= 1 << (bits - 64);
3517663b816Sml 			else if (bits >= 32)
3527663b816Sml 				iph->iph_masks[2] |= 1 << (bits - 32);
3537663b816Sml 			else
3547663b816Sml 				iph->iph_masks[3] |= 1 << bits;
3557663b816Sml 
3567663b816Sml 	} else
3577663b816Sml #endif
3587663b816Sml 	{
3597663b816Sml 		if ((bits >= 0) && (bits != 32))
3607663b816Sml 			iph->iph_masks[3] |= 1 << bits;
3617663b816Sml 	}
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	switch (iph->iph_type & ~IPHASH_ANON)
3647c478bd9Sstevel@tonic-gate 	{
3657c478bd9Sstevel@tonic-gate 	case IPHASH_GROUPMAP :
3667c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
3677c478bd9Sstevel@tonic-gate 					   iph->iph_flags, IPL_LOGIPF,
368f4b3ec61Sdh 					   ifs->ifs_fr_active, ifs);
3697c478bd9Sstevel@tonic-gate 		break;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	default :
3727c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = NULL;
3737c478bd9Sstevel@tonic-gate 		ipe->ipe_value = 0;
3747c478bd9Sstevel@tonic-gate 		break;
3757c478bd9Sstevel@tonic-gate 	}
3767c478bd9Sstevel@tonic-gate 
377f4b3ec61Sdh 	ifs->ifs_ipf_nhtnodes[iph->iph_unit]++;
3787663b816Sml 
3797c478bd9Sstevel@tonic-gate 	return 0;
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate 
3837c478bd9Sstevel@tonic-gate /*
3847c478bd9Sstevel@tonic-gate  * Delete an entry from a hash table.
3857c478bd9Sstevel@tonic-gate  */
386f4b3ec61Sdh int fr_delhtent(iph, ipe, ifs)
3877c478bd9Sstevel@tonic-gate iphtable_t *iph;
3887c478bd9Sstevel@tonic-gate iphtent_t *ipe;
389f4b3ec61Sdh ipf_stack_t *ifs;
3907c478bd9Sstevel@tonic-gate {
391f4b3ec61Sdh 	if (ipe->ipe_ref != 1)
3927c478bd9Sstevel@tonic-gate 		return EBUSY;
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	*ipe->ipe_pnext = ipe->ipe_next;
3967c478bd9Sstevel@tonic-gate 	if (ipe->ipe_next != NULL)
3977c478bd9Sstevel@tonic-gate 		ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	switch (iph->iph_type & ~IPHASH_ANON)
4007c478bd9Sstevel@tonic-gate 	{
4017c478bd9Sstevel@tonic-gate 	case IPHASH_GROUPMAP :
4027c478bd9Sstevel@tonic-gate 		if (ipe->ipe_group != NULL)
403f4b3ec61Sdh 			fr_delgroup(ipe->ipe_group, IPL_LOGIPF,
404f4b3ec61Sdh 				    ifs->ifs_fr_active, ifs);
4057c478bd9Sstevel@tonic-gate 		break;
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 	default :
4087c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = NULL;
4097c478bd9Sstevel@tonic-gate 		ipe->ipe_value = 0;
4107c478bd9Sstevel@tonic-gate 		break;
4117c478bd9Sstevel@tonic-gate 	}
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	KFREE(ipe);
4147c478bd9Sstevel@tonic-gate 
415f4b3ec61Sdh 	ifs->ifs_ipf_nhtnodes[iph->iph_unit]--;
416f4b3ec61Sdh 
4177c478bd9Sstevel@tonic-gate 	return 0;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 
421f4b3ec61Sdh void *fr_iphmfindgroup(tptr, version, aptr, ifs)
422ab25eeb5Syz void *tptr;
4237663b816Sml int version;
424ab25eeb5Syz void *aptr;
425f4b3ec61Sdh ipf_stack_t *ifs;
4267c478bd9Sstevel@tonic-gate {
4277663b816Sml 	i6addr_t *addr;
4287c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
4297c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
4307c478bd9Sstevel@tonic-gate 	void *rval;
4317c478bd9Sstevel@tonic-gate 
4327663b816Sml 	if ((version != 4)
4337663b816Sml #ifdef USE_INET6
4347663b816Sml 	    && (version != 6)
4357663b816Sml #endif
4367663b816Sml 	    )
4377663b816Sml 		return NULL;
4387663b816Sml 
439f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
4407c478bd9Sstevel@tonic-gate 	iph = tptr;
4417c478bd9Sstevel@tonic-gate 	addr = aptr;
4427c478bd9Sstevel@tonic-gate 
4437663b816Sml #ifdef USE_INET6
4447663b816Sml 	if (version == 6)
4457663b816Sml 		ipe = fr_iphmfind6(iph, &addr->in6);
4467663b816Sml 	else
4477663b816Sml #endif
4487663b816Sml 	if (version == 4)
4497663b816Sml 		ipe = fr_iphmfind(iph, &addr->in4);
4507663b816Sml 	else
4517663b816Sml 		ipe = NULL;
4527c478bd9Sstevel@tonic-gate 	if (ipe != NULL)
4537c478bd9Sstevel@tonic-gate 		rval = ipe->ipe_ptr;
4547c478bd9Sstevel@tonic-gate 	else
4557c478bd9Sstevel@tonic-gate 		rval = NULL;
456f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4577c478bd9Sstevel@tonic-gate 	return rval;
4587c478bd9Sstevel@tonic-gate }
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 
461ab25eeb5Syz /* ------------------------------------------------------------------------ */
462ab25eeb5Syz /* Function:    fr_iphmfindip                                               */
463ab25eeb5Syz /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
464ab25eeb5Syz /* Parameters:  tptr(I)    - pointer to the pool to search                  */
465ab25eeb5Syz /*              version(I) - IP protocol version (4 or 6)                   */
466ab25eeb5Syz /*              aptr(I)    - pointer to address information                 */
467*de22af4eSJohn Ojemann /*		fin	   - pointer to packet information		    */
468*de22af4eSJohn Ojemann /*		ifs	   - ipf stack instance				    */
469ab25eeb5Syz /*                                                                          */
470ab25eeb5Syz /* Search the hash table for a given address and return a search result.    */
471ab25eeb5Syz /* ------------------------------------------------------------------------ */
472*de22af4eSJohn Ojemann int fr_iphmfindip(tptr, version, aptr, fin, ifs)
4737c478bd9Sstevel@tonic-gate void *tptr, *aptr;
4747c478bd9Sstevel@tonic-gate int version;
475*de22af4eSJohn Ojemann fr_info_t *fin;
476f4b3ec61Sdh ipf_stack_t *ifs;
4777c478bd9Sstevel@tonic-gate {
4787663b816Sml 	i6addr_t *addr;
4797c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
4807c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
4817c478bd9Sstevel@tonic-gate 	int rval;
4827c478bd9Sstevel@tonic-gate 
483ab25eeb5Syz 	if ((version != 4)
484ab25eeb5Syz #ifdef USE_INET6
485ab25eeb5Syz 	    && (version != 6)
486ab25eeb5Syz #endif
487ab25eeb5Syz 	    )
488ab25eeb5Syz 		return -1;
489ab25eeb5Syz 
4907c478bd9Sstevel@tonic-gate 	if (tptr == NULL || aptr == NULL)
491ab25eeb5Syz 		return -1;
4927c478bd9Sstevel@tonic-gate 
4937c478bd9Sstevel@tonic-gate 	iph = tptr;
4947c478bd9Sstevel@tonic-gate 	addr = aptr;
4957c478bd9Sstevel@tonic-gate 
496f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
4977663b816Sml #ifdef USE_INET6
4987663b816Sml 	if (version == 6)
4997663b816Sml 		ipe = fr_iphmfind6(iph, &addr->in6);
5007663b816Sml 	else
5017663b816Sml #endif
5027663b816Sml 	if (version == 4)
5037663b816Sml 		ipe = fr_iphmfind(iph, &addr->in4);
5047663b816Sml 	else
5057663b816Sml 		ipe = NULL;
506*de22af4eSJohn Ojemann 	if (ipe != NULL) {
507*de22af4eSJohn Ojemann 		ipe->ipe_hits++;
508*de22af4eSJohn Ojemann 		ipe->ipe_bytes += fin->fin_plen;
5097c478bd9Sstevel@tonic-gate 		rval = 0;
510*de22af4eSJohn Ojemann 	} else {
5117c478bd9Sstevel@tonic-gate 		rval = 1;
512*de22af4eSJohn Ojemann 	}
513f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
5147c478bd9Sstevel@tonic-gate 	return rval;
5157c478bd9Sstevel@tonic-gate }
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate /* Locks:  ip_poolrw */
5197c478bd9Sstevel@tonic-gate static iphtent_t *fr_iphmfind(iph, addr)
5207c478bd9Sstevel@tonic-gate iphtable_t *iph;
5217c478bd9Sstevel@tonic-gate struct in_addr *addr;
5227c478bd9Sstevel@tonic-gate {
5237c478bd9Sstevel@tonic-gate 	u_32_t hmsk, msk, ips;
5247c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
5257c478bd9Sstevel@tonic-gate 	u_int hv;
5267c478bd9Sstevel@tonic-gate 
5277663b816Sml 	hmsk = iph->iph_masks[3];
5287c478bd9Sstevel@tonic-gate 	msk = 0xffffffff;
5297c478bd9Sstevel@tonic-gate maskloop:
5307c478bd9Sstevel@tonic-gate 	ips = ntohl(addr->s_addr) & msk;
5317c478bd9Sstevel@tonic-gate 	hv = IPE_HASH_FN(ips, msk, iph->iph_size);
5327c478bd9Sstevel@tonic-gate 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
5337c478bd9Sstevel@tonic-gate 		if (ipe->ipe_mask.in4_addr != msk ||
5347c478bd9Sstevel@tonic-gate 		    ipe->ipe_addr.in4_addr != ips) {
5357c478bd9Sstevel@tonic-gate 			continue;
5367c478bd9Sstevel@tonic-gate 		}
5377c478bd9Sstevel@tonic-gate 		break;
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	if ((ipe == NULL) && (hmsk != 0)) {
5417c478bd9Sstevel@tonic-gate 		while (hmsk != 0) {
5427c478bd9Sstevel@tonic-gate 			msk <<= 1;
5437c478bd9Sstevel@tonic-gate 			if (hmsk & 0x80000000)
5447c478bd9Sstevel@tonic-gate 				break;
5457c478bd9Sstevel@tonic-gate 			hmsk <<= 1;
5467c478bd9Sstevel@tonic-gate 		}
5477c478bd9Sstevel@tonic-gate 		if (hmsk != 0) {
5487c478bd9Sstevel@tonic-gate 			hmsk <<= 1;
5497c478bd9Sstevel@tonic-gate 			goto maskloop;
5507c478bd9Sstevel@tonic-gate 		}
5517c478bd9Sstevel@tonic-gate 	}
5527663b816Sml 	return ipe;
5537663b816Sml }
5547663b816Sml 
5557663b816Sml 
5567663b816Sml #ifdef USE_INET6
5577663b816Sml /* Locks:  ip_poolrw */
5587663b816Sml static iphtent_t *fr_iphmfind6(iph, addr)
5597663b816Sml iphtable_t *iph;
5607663b816Sml struct in6_addr *addr;
5617663b816Sml {
5627663b816Sml 	u_32_t hmsk[4], msk[4], ips[4], *and;
5637663b816Sml 	iphtent_t *ipe;
5647663b816Sml 	u_int hv;
5657663b816Sml 
5667663b816Sml 	hmsk[0] = iph->iph_masks[0];
5677663b816Sml 	hmsk[1] = iph->iph_masks[1];
5687663b816Sml 	hmsk[2] = iph->iph_masks[2];
5697663b816Sml 	hmsk[3] = iph->iph_masks[3];
5707663b816Sml 
5717663b816Sml 	msk[0] = 0xffffffff;
5727663b816Sml 	msk[1] = 0xffffffff;
5737663b816Sml 	msk[2] = 0xffffffff;
5747663b816Sml 	msk[3] = 0xffffffff;
5757663b816Sml maskloop:
5767663b816Sml 	and = (u_32_t *)addr->s6_addr;
5777663b816Sml 	ips[0] = *and & msk[0];
5787663b816Sml 	ips[1] = *(and + 1) & msk[1];
5797663b816Sml 	ips[2] = *(and + 2) & msk[2];
5807663b816Sml 	ips[3] = *(and + 3) & msk[3];
5817663b816Sml 
5827663b816Sml 	hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk),
5837663b816Sml 			      iph->iph_size);
5847663b816Sml 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
5857663b816Sml 		if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) ||
5867663b816Sml 		    bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16))
5877663b816Sml 			continue;
5887663b816Sml 		break;
5897663b816Sml 	}
5907663b816Sml 
5917663b816Sml 	if ((ipe == NULL) && ((hmsk[0] != 0) ||
5927663b816Sml 			      (hmsk[1] != 0) ||
5937663b816Sml 			      (hmsk[2] != 0) ||
5947663b816Sml 			      (hmsk[3] != 0) )) {
5957663b816Sml 		while ((hmsk[0] != 0) && (hmsk[1] != 0) &&
5967663b816Sml 		       (hmsk[2] != 0) && (hmsk[3] != 0)) {
5977663b816Sml 			left_shift_ipv6((char *)msk);
5987663b816Sml 			if (hmsk[0] & 0x80000000)
5997663b816Sml 				break;
6007663b816Sml 			left_shift_ipv6((char *)hmsk);
6017663b816Sml 		}
6027663b816Sml 		if ((hmsk[0] != 0) && (hmsk[1] != 0) &&
6037663b816Sml 		    (hmsk[2] != 0) && (hmsk[3] != 0)) {
6047663b816Sml 			left_shift_ipv6((char *)hmsk);
6057663b816Sml 			goto maskloop;
6067663b816Sml 		}
6077663b816Sml 	}
6087c478bd9Sstevel@tonic-gate 	return ipe;
6097c478bd9Sstevel@tonic-gate }
6107c478bd9Sstevel@tonic-gate 
6117663b816Sml 
6127663b816Sml /*
6137663b816Sml  * sum4: ipv6 add -> 4 bytes values
6147663b816Sml  */
6157663b816Sml static uint32_t sum4(add)
6167663b816Sml uint32_t *add;
6177663b816Sml {
6187663b816Sml 	return (*add + *(add + 1) + *(add + 2) + *(add + 3));
6197663b816Sml }
6207663b816Sml 
6217663b816Sml /*
6227663b816Sml  * left shift on 128 bits
6237663b816Sml  */
6247663b816Sml static void left_shift_ipv6(data)
6257663b816Sml char *data;
6267663b816Sml {
6277663b816Sml 	u_32_t *sd;
6287663b816Sml 
6297663b816Sml 	sd = (u_32_t *)data;
6307663b816Sml 	sd[0] <<= 1;
6317663b816Sml 	if (sd[1] >= 0x80000000)
6327663b816Sml 		sd[0] += 1;
6337663b816Sml 
6347663b816Sml 	sd[1] <<= 1;
6357663b816Sml 	if (sd[2] >= 0x80000000)
6367663b816Sml 		sd[1] += 1;
6377663b816Sml 
6387663b816Sml 	sd[2] <<= 1;
6397663b816Sml 	if (sd[3] >= 0x80000000)
6407663b816Sml 		sd[2] += 1;
6417663b816Sml 
6427663b816Sml 	sd[3] <<= 1;
6437663b816Sml }
6447663b816Sml #endif
645f4b3ec61Sdh 
646f4b3ec61Sdh int fr_htable_getnext(token, ilp, ifs)
647f4b3ec61Sdh ipftoken_t *token;
648f4b3ec61Sdh ipflookupiter_t *ilp;
649f4b3ec61Sdh ipf_stack_t *ifs;
650f4b3ec61Sdh {
651f4b3ec61Sdh 	iphtent_t *node, zn, *nextnode;
652f4b3ec61Sdh 	iphtable_t *iph, zp, *nextiph;
653f4b3ec61Sdh 	int err;
654f4b3ec61Sdh 
655f4b3ec61Sdh 	err = 0;
656f4b3ec61Sdh 	iph = NULL;
657f4b3ec61Sdh 	node = NULL;
658f4b3ec61Sdh 	nextiph = NULL;
659f4b3ec61Sdh 	nextnode = NULL;
660f4b3ec61Sdh 
661f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
662f4b3ec61Sdh 
663786c7074Sjojemann 	/*
664786c7074Sjojemann 	 * Get "previous" entry from the token and find the next entry.
665786c7074Sjojemann 	 *
666786c7074Sjojemann 	 * If we found an entry, add a reference to it and update the token.
667786c7074Sjojemann 	 * Otherwise, zero out data to be returned and NULL out token.
668786c7074Sjojemann 	 */
669f4b3ec61Sdh 	switch (ilp->ili_otype)
670f4b3ec61Sdh 	{
671f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
672f4b3ec61Sdh 		iph = token->ipt_data;
673f4b3ec61Sdh 		if (iph == NULL) {
674f4b3ec61Sdh 			nextiph = ifs->ifs_ipf_htables[(int)ilp->ili_unit];
675f4b3ec61Sdh 		} else {
676f4b3ec61Sdh 			nextiph = iph->iph_next;
677f4b3ec61Sdh 		}
678f4b3ec61Sdh 		if (nextiph != NULL) {
679786c7074Sjojemann 			ATOMIC_INC(nextiph->iph_ref);
680786c7074Sjojemann 			token->ipt_data = nextiph;
681f4b3ec61Sdh 		} else {
682f4b3ec61Sdh 			bzero((char *)&zp, sizeof(zp));
683f4b3ec61Sdh 			nextiph = &zp;
684786c7074Sjojemann 			token->ipt_data = NULL;
685f4b3ec61Sdh 		}
686f4b3ec61Sdh 		break;
687f4b3ec61Sdh 
688f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
689f4b3ec61Sdh 		node = token->ipt_data;
690f4b3ec61Sdh 		if (node == NULL) {
691f4b3ec61Sdh 			iph = fr_findhtable(ilp->ili_unit, ilp->ili_name, ifs);
692f4b3ec61Sdh 			if (iph == NULL)
693f4b3ec61Sdh 				err = ESRCH;
694f4b3ec61Sdh 			else {
695f4b3ec61Sdh 				nextnode = iph->iph_list;
696f4b3ec61Sdh 			}
697f4b3ec61Sdh 		} else {
698f4b3ec61Sdh 			nextnode = node->ipe_snext;
699f4b3ec61Sdh 		}
700f4b3ec61Sdh 		if (nextnode != NULL) {
701786c7074Sjojemann 			ATOMIC_INC(nextnode->ipe_ref);
702786c7074Sjojemann 			token->ipt_data = nextnode;
703f4b3ec61Sdh 		} else {
704f4b3ec61Sdh 			bzero((char *)&zn, sizeof(zn));
705f4b3ec61Sdh 			nextnode = &zn;
706786c7074Sjojemann 			token->ipt_data = NULL;
707f4b3ec61Sdh 		}
708f4b3ec61Sdh 		break;
709786c7074Sjojemann 
710f4b3ec61Sdh 	default :
711f4b3ec61Sdh 		err = EINVAL;
712f4b3ec61Sdh 		break;
713f4b3ec61Sdh 	}
714f4b3ec61Sdh 
715786c7074Sjojemann 	/*
716786c7074Sjojemann 	 * Now that we have ref, it's save to give up lock.
717786c7074Sjojemann 	 */
718f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
719f4b3ec61Sdh 	if (err != 0)
720f4b3ec61Sdh 		return err;
721f4b3ec61Sdh 
722786c7074Sjojemann 	/*
723786c7074Sjojemann 	 * Copy out data and clean up references and token as needed.
724786c7074Sjojemann 	 */
725f4b3ec61Sdh 	switch (ilp->ili_otype)
726f4b3ec61Sdh 	{
727f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
728f4b3ec61Sdh 		err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph));
729f4b3ec61Sdh 		if (err != 0)
730f4b3ec61Sdh 			err = EFAULT;
731786c7074Sjojemann 		if (token->ipt_data == NULL) {
732786c7074Sjojemann 			ipf_freetoken(token, ifs);
733786c7074Sjojemann 		} else {
734786c7074Sjojemann 			if (iph != NULL) {
735786c7074Sjojemann 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
736786c7074Sjojemann 				fr_derefhtable(iph, ifs);
737786c7074Sjojemann 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
738786c7074Sjojemann 			}
739786c7074Sjojemann 			if (nextiph->iph_next == NULL)
740786c7074Sjojemann 				ipf_freetoken(token, ifs);
741786c7074Sjojemann 		}
742f4b3ec61Sdh 		break;
743f4b3ec61Sdh 
744f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
745f4b3ec61Sdh 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
746f4b3ec61Sdh 		if (err != 0)
747f4b3ec61Sdh 			err = EFAULT;
748786c7074Sjojemann 		if (token->ipt_data == NULL) {
749786c7074Sjojemann 			ipf_freetoken(token, ifs);
750786c7074Sjojemann 		} else {
751786c7074Sjojemann 			if (node != NULL) {
752786c7074Sjojemann 				WRITE_ENTER(&ifs->ifs_ip_poolrw);
753786c7074Sjojemann 				fr_derefhtent(node);
754786c7074Sjojemann 				RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
755786c7074Sjojemann 			}
756786c7074Sjojemann 			if (nextnode->ipe_snext == NULL)
757786c7074Sjojemann 				ipf_freetoken(token, ifs);
758786c7074Sjojemann 		}
759f4b3ec61Sdh 		break;
760f4b3ec61Sdh 	}
761f4b3ec61Sdh 
762f4b3ec61Sdh 	return err;
763f4b3ec61Sdh }
764f4b3ec61Sdh 
765f4b3ec61Sdh 
766f4b3ec61Sdh void fr_htable_iterderef(otype, unit, data, ifs)
767f4b3ec61Sdh u_int otype;
768f4b3ec61Sdh int unit;
769f4b3ec61Sdh void *data;
770f4b3ec61Sdh ipf_stack_t *ifs;
771f4b3ec61Sdh {
772f4b3ec61Sdh 
773f4b3ec61Sdh 	if (data == NULL)
774f4b3ec61Sdh 		return;
775f4b3ec61Sdh 
776f4b3ec61Sdh 	if (unit < 0 || unit > IPL_LOGMAX)
777f4b3ec61Sdh 		return;
778f4b3ec61Sdh 
779f4b3ec61Sdh 	switch (otype)
780f4b3ec61Sdh 	{
781f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
782f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
783f4b3ec61Sdh 		fr_derefhtable((iphtable_t *)data, ifs);
784f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
785f4b3ec61Sdh 		break;
786f4b3ec61Sdh 
787f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
788f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
789f4b3ec61Sdh 		fr_derefhtent((iphtent_t *)data);
790f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
791f4b3ec61Sdh 		break;
792f4b3ec61Sdh 	default :
793f4b3ec61Sdh 		break;
794f4b3ec61Sdh 	}
795f4b3ec61Sdh }
7967c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */
797