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*f4b3ec61Sdh  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
137c478bd9Sstevel@tonic-gate # undef KERNEL
147c478bd9Sstevel@tonic-gate # undef _KERNEL
157c478bd9Sstevel@tonic-gate # define        KERNEL	1
167c478bd9Sstevel@tonic-gate # define        _KERNEL	1
177c478bd9Sstevel@tonic-gate #endif
187c478bd9Sstevel@tonic-gate #include <sys/param.h>
197c478bd9Sstevel@tonic-gate #include <sys/types.h>
207c478bd9Sstevel@tonic-gate #include <sys/errno.h>
217c478bd9Sstevel@tonic-gate #include <sys/time.h>
227c478bd9Sstevel@tonic-gate #include <sys/file.h>
237c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
247c478bd9Sstevel@tonic-gate # include <stdlib.h>
257c478bd9Sstevel@tonic-gate # include <string.h>
267c478bd9Sstevel@tonic-gate # define _KERNEL
277c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
287c478bd9Sstevel@tonic-gate struct file;
297c478bd9Sstevel@tonic-gate # endif
307c478bd9Sstevel@tonic-gate # include <sys/uio.h>
317c478bd9Sstevel@tonic-gate # undef _KERNEL
327c478bd9Sstevel@tonic-gate #endif
337c478bd9Sstevel@tonic-gate #include <sys/socket.h>
347c478bd9Sstevel@tonic-gate #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
357c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
367c478bd9Sstevel@tonic-gate #endif
377c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__)
387c478bd9Sstevel@tonic-gate #  include <sys/cdefs.h>
397c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
407c478bd9Sstevel@tonic-gate #endif
41ab25eeb5Syz #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
42ab25eeb5Syz     !defined(linux)
437c478bd9Sstevel@tonic-gate # include <sys/mbuf.h>
447c478bd9Sstevel@tonic-gate #endif
457c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
467c478bd9Sstevel@tonic-gate # include <sys/systm.h>
477c478bd9Sstevel@tonic-gate #else
487c478bd9Sstevel@tonic-gate # include <stdio.h>
497c478bd9Sstevel@tonic-gate #endif
507c478bd9Sstevel@tonic-gate #include <netinet/in.h>
517c478bd9Sstevel@tonic-gate #include <net/if.h>
527c478bd9Sstevel@tonic-gate 
537c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
547c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
557c478bd9Sstevel@tonic-gate #include "netinet/ip_lookup.h"
567c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h"
57*f4b3ec61Sdh #include "netinet/ipf_stack.h"
58ab25eeb5Syz /* END OF INCLUDES */
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #if !defined(lint)
61ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $";
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_LOOKUP
657c478bd9Sstevel@tonic-gate static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
667663b816Sml #ifdef USE_INET6
677663b816Sml static iphtent_t *fr_iphmfind6 __P((iphtable_t *, struct in6_addr *));
687663b816Sml static uint32_t sum4(uint32_t *);
697663b816Sml static void left_shift_ipv6 __P((char *));
707663b816Sml #endif
717c478bd9Sstevel@tonic-gate 
72*f4b3ec61Sdh void fr_htable_unload(ifs)
73*f4b3ec61Sdh ipf_stack_t *ifs;
747c478bd9Sstevel@tonic-gate {
757c478bd9Sstevel@tonic-gate 	iplookupflush_t fop;
76ab25eeb5Syz 
77ab25eeb5Syz 	fop.iplf_unit = IPL_LOGALL;
78*f4b3ec61Sdh 	(void)fr_flushhtable(&fop, ifs);
797c478bd9Sstevel@tonic-gate }
807c478bd9Sstevel@tonic-gate 
81ab25eeb5Syz 
82*f4b3ec61Sdh int fr_gethtablestat(op, ifs)
837663b816Sml iplookupop_t *op;
84*f4b3ec61Sdh ipf_stack_t *ifs;
857663b816Sml {
867663b816Sml 	iphtstat_t stats;
877663b816Sml 
887663b816Sml 	if (op->iplo_size != sizeof(stats))
897663b816Sml 		return EINVAL;
907663b816Sml 
91*f4b3ec61Sdh 	stats.iphs_tables = ifs->ifs_ipf_htables[op->iplo_unit];
92*f4b3ec61Sdh 	stats.iphs_numtables = ifs->ifs_ipf_nhtables[op->iplo_unit];
93*f4b3ec61Sdh 	stats.iphs_numnodes = ifs->ifs_ipf_nhtnodes[op->iplo_unit];
94*f4b3ec61Sdh 	stats.iphs_nomem = ifs->ifs_ipht_nomem[op->iplo_unit];
957663b816Sml 
967663b816Sml 	return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
977663b816Sml 
987663b816Sml }
997663b816Sml 
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate  * Create a new hash table using the template passed.
1037c478bd9Sstevel@tonic-gate  */
104*f4b3ec61Sdh int fr_newhtable(op, ifs)
1057c478bd9Sstevel@tonic-gate iplookupop_t *op;
106*f4b3ec61Sdh ipf_stack_t *ifs;
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	iphtable_t *iph, *oiph;
1097c478bd9Sstevel@tonic-gate 	char name[FR_GROUPLEN];
1107c478bd9Sstevel@tonic-gate 	int err, i, unit;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	KMALLOC(iph, iphtable_t *);
113ab25eeb5Syz 	if (iph == NULL) {
114*f4b3ec61Sdh 		ifs->ifs_ipht_nomem[op->iplo_unit]++;
115ab25eeb5Syz 		return ENOMEM;
116ab25eeb5Syz 	}
1177c478bd9Sstevel@tonic-gate 
1187c478bd9Sstevel@tonic-gate 	err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
1197c478bd9Sstevel@tonic-gate 	if (err != 0) {
1207c478bd9Sstevel@tonic-gate 		KFREE(iph);
1217c478bd9Sstevel@tonic-gate 		return EFAULT;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	unit = op->iplo_unit;
1257c478bd9Sstevel@tonic-gate 	if (iph->iph_unit != unit) {
1267c478bd9Sstevel@tonic-gate 		KFREE(iph);
1277c478bd9Sstevel@tonic-gate 		return EINVAL;
1287c478bd9Sstevel@tonic-gate 	}
1297c478bd9Sstevel@tonic-gate 
1307c478bd9Sstevel@tonic-gate 	if ((op->iplo_arg & IPHASH_ANON) == 0) {
131*f4b3ec61Sdh 		if (fr_findhtable(op->iplo_unit, op->iplo_name, ifs) != NULL) {
1327c478bd9Sstevel@tonic-gate 			KFREE(iph);
1337c478bd9Sstevel@tonic-gate 			return EEXIST;
1347c478bd9Sstevel@tonic-gate 		}
1357c478bd9Sstevel@tonic-gate 	} else {
1367c478bd9Sstevel@tonic-gate 		i = IPHASH_ANON;
1377c478bd9Sstevel@tonic-gate 		do {
1387c478bd9Sstevel@tonic-gate 			i++;
139ab25eeb5Syz #if defined(SNPRINTF) && defined(_KERNEL)
140ab25eeb5Syz 			(void)SNPRINTF(name, sizeof(name), "%u", i);
141ab25eeb5Syz #else
1427c478bd9Sstevel@tonic-gate 			(void)sprintf(name, "%u", i);
143ab25eeb5Syz #endif
144*f4b3ec61Sdh 			for (oiph = ifs->ifs_ipf_htables[unit]; oiph != NULL;
1457c478bd9Sstevel@tonic-gate 			     oiph = oiph->iph_next)
1467c478bd9Sstevel@tonic-gate 				if (strncmp(oiph->iph_name, name,
1477c478bd9Sstevel@tonic-gate 					    sizeof(oiph->iph_name)) == 0)
1487c478bd9Sstevel@tonic-gate 					break;
1497c478bd9Sstevel@tonic-gate 		} while (oiph != NULL);
1507c478bd9Sstevel@tonic-gate 		(void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
1517c478bd9Sstevel@tonic-gate 		err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
1527c478bd9Sstevel@tonic-gate 		if (err != 0) {
1537c478bd9Sstevel@tonic-gate 			KFREE(iph);
1547c478bd9Sstevel@tonic-gate 			return EFAULT;
1557c478bd9Sstevel@tonic-gate 		}
1567c478bd9Sstevel@tonic-gate 		iph->iph_type |= IPHASH_ANON;
1577c478bd9Sstevel@tonic-gate 	}
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	KMALLOCS(iph->iph_table, iphtent_t **,
1607c478bd9Sstevel@tonic-gate 		 iph->iph_size * sizeof(*iph->iph_table));
1617c478bd9Sstevel@tonic-gate 	if (iph->iph_table == NULL) {
1627c478bd9Sstevel@tonic-gate 		KFREE(iph);
163*f4b3ec61Sdh 		ifs->ifs_ipht_nomem[unit]++;
1647c478bd9Sstevel@tonic-gate 		return ENOMEM;
1657c478bd9Sstevel@tonic-gate 	}
1667c478bd9Sstevel@tonic-gate 
1677c478bd9Sstevel@tonic-gate 	bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
1687663b816Sml 	iph->iph_masks[0] = 0;
1697663b816Sml 	iph->iph_masks[1] = 0;
1707663b816Sml 	iph->iph_masks[2] = 0;
1717663b816Sml 	iph->iph_masks[3] = 0;
172*f4b3ec61Sdh 	iph->iph_list = NULL;
1737c478bd9Sstevel@tonic-gate 
174*f4b3ec61Sdh 	iph->iph_ref = 1;
175*f4b3ec61Sdh 	iph->iph_next = ifs->ifs_ipf_htables[unit];
176*f4b3ec61Sdh 	iph->iph_pnext = &ifs->ifs_ipf_htables[unit];
177*f4b3ec61Sdh 	if (ifs->ifs_ipf_htables[unit] != NULL)
178*f4b3ec61Sdh 		ifs->ifs_ipf_htables[unit]->iph_pnext = &iph->iph_next;
179*f4b3ec61Sdh 	ifs->ifs_ipf_htables[unit] = iph;
1807663b816Sml 
181*f4b3ec61Sdh 	ifs->ifs_ipf_nhtables[unit]++;
1827663b816Sml 
1837c478bd9Sstevel@tonic-gate 	return 0;
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate 
1867c478bd9Sstevel@tonic-gate 
1877c478bd9Sstevel@tonic-gate /*
1887c478bd9Sstevel@tonic-gate  */
189*f4b3ec61Sdh int fr_removehtable(op, ifs)
1907c478bd9Sstevel@tonic-gate iplookupop_t *op;
191*f4b3ec61Sdh ipf_stack_t *ifs;
1927c478bd9Sstevel@tonic-gate {
1937c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
196*f4b3ec61Sdh 	iph = fr_findhtable(op->iplo_unit, op->iplo_name, ifs);
1977c478bd9Sstevel@tonic-gate 	if (iph == NULL)
1987c478bd9Sstevel@tonic-gate 		return ESRCH;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 	if (iph->iph_unit != op->iplo_unit) {
2017c478bd9Sstevel@tonic-gate 		return EINVAL;
2027c478bd9Sstevel@tonic-gate 	}
203*f4b3ec61Sdh 
204*f4b3ec61Sdh 	if (iph->iph_ref != 1) {
2057c478bd9Sstevel@tonic-gate 		return EBUSY;
2067c478bd9Sstevel@tonic-gate 	}
2077c478bd9Sstevel@tonic-gate 
208*f4b3ec61Sdh 	fr_delhtable(iph, ifs);
2097c478bd9Sstevel@tonic-gate 
2107c478bd9Sstevel@tonic-gate 	return 0;
2117c478bd9Sstevel@tonic-gate }
2127c478bd9Sstevel@tonic-gate 
2137c478bd9Sstevel@tonic-gate 
214*f4b3ec61Sdh void fr_delhtable(iph, ifs)
2157c478bd9Sstevel@tonic-gate iphtable_t *iph;
216*f4b3ec61Sdh ipf_stack_t *ifs;
2177c478bd9Sstevel@tonic-gate {
218ab25eeb5Syz 	iphtent_t *ipe;
219ab25eeb5Syz 	int i;
220ab25eeb5Syz 
221ab25eeb5Syz 	for (i = 0; i < iph->iph_size; i++)
222ab25eeb5Syz 		while ((ipe = iph->iph_table[i]) != NULL)
223*f4b3ec61Sdh 			if (fr_delhtent(iph, ipe, ifs) != 0)
224ab25eeb5Syz 				return;
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate 	*iph->iph_pnext = iph->iph_next;
2277c478bd9Sstevel@tonic-gate 	if (iph->iph_next != NULL)
2287c478bd9Sstevel@tonic-gate 		iph->iph_next->iph_pnext = iph->iph_pnext;
2297c478bd9Sstevel@tonic-gate 
230*f4b3ec61Sdh 	ifs->ifs_ipf_nhtables[iph->iph_unit]--;
231ab25eeb5Syz 
232*f4b3ec61Sdh 	if (iph->iph_ref == 1) {
233ab25eeb5Syz 		KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
234ab25eeb5Syz 		KFREE(iph);
235ab25eeb5Syz 	}
2367c478bd9Sstevel@tonic-gate }
2377c478bd9Sstevel@tonic-gate 
2387c478bd9Sstevel@tonic-gate 
239*f4b3ec61Sdh void fr_derefhtable(iph, ifs)
2407c478bd9Sstevel@tonic-gate iphtable_t *iph;
241*f4b3ec61Sdh ipf_stack_t *ifs;
2427c478bd9Sstevel@tonic-gate {
2437c478bd9Sstevel@tonic-gate 	iph->iph_ref--;
2447c478bd9Sstevel@tonic-gate 	if (iph->iph_ref == 0)
245*f4b3ec61Sdh 		fr_delhtable(iph, ifs);
246*f4b3ec61Sdh }
247*f4b3ec61Sdh 
248*f4b3ec61Sdh 
249*f4b3ec61Sdh void fr_derefhtent(ipe)
250*f4b3ec61Sdh iphtent_t *ipe;
251*f4b3ec61Sdh {
252*f4b3ec61Sdh 	ipe->ipe_ref--;
253*f4b3ec61Sdh 	if (ipe->ipe_ref == 0) {
254*f4b3ec61Sdh 		KFREE(ipe);
255*f4b3ec61Sdh 	}
2567c478bd9Sstevel@tonic-gate }
2577c478bd9Sstevel@tonic-gate 
2587c478bd9Sstevel@tonic-gate 
259*f4b3ec61Sdh iphtable_t *fr_findhtable(unit, name, ifs)
2607c478bd9Sstevel@tonic-gate int unit;
2617c478bd9Sstevel@tonic-gate char *name;
262*f4b3ec61Sdh ipf_stack_t *ifs;
2637c478bd9Sstevel@tonic-gate {
2647c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2657c478bd9Sstevel@tonic-gate 
266*f4b3ec61Sdh 	for (iph = ifs->ifs_ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
2677c478bd9Sstevel@tonic-gate 		if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
2687c478bd9Sstevel@tonic-gate 			break;
2697c478bd9Sstevel@tonic-gate 	return iph;
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate 
2727c478bd9Sstevel@tonic-gate 
273*f4b3ec61Sdh size_t fr_flushhtable(op, ifs)
2747c478bd9Sstevel@tonic-gate iplookupflush_t *op;
275*f4b3ec61Sdh ipf_stack_t *ifs;
2767c478bd9Sstevel@tonic-gate {
2777c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
278ab25eeb5Syz 	size_t freed;
279ab25eeb5Syz 	int i;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	freed = 0;
2827c478bd9Sstevel@tonic-gate 
283ab25eeb5Syz 	for (i = 0; i <= IPL_LOGMAX; i++) {
284ab25eeb5Syz 		if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
285*f4b3ec61Sdh 			while ((iph = ifs->ifs_ipf_htables[i]) != NULL) {
286*f4b3ec61Sdh 				fr_delhtable(iph, ifs);
287ab25eeb5Syz 				freed++;
2887c478bd9Sstevel@tonic-gate 			}
2897c478bd9Sstevel@tonic-gate 		}
290ab25eeb5Syz 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	return freed;
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate /*
2977c478bd9Sstevel@tonic-gate  * Add an entry to a hash table.
2987c478bd9Sstevel@tonic-gate  */
299*f4b3ec61Sdh int fr_addhtent(iph, ipeo, ifs)
3007c478bd9Sstevel@tonic-gate iphtable_t *iph;
3017c478bd9Sstevel@tonic-gate iphtent_t *ipeo;
302*f4b3ec61Sdh ipf_stack_t *ifs;
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
3057c478bd9Sstevel@tonic-gate 	u_int hv;
3067c478bd9Sstevel@tonic-gate 	int bits;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	KMALLOC(ipe, iphtent_t *);
3097c478bd9Sstevel@tonic-gate 	if (ipe == NULL)
3107c478bd9Sstevel@tonic-gate 		return -1;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
3137663b816Sml #ifdef USE_INET6
3147663b816Sml 	if (ipe->ipe_family == AF_INET6) {
3157663b816Sml 		bits = count6bits((u_32_t *)ipe->ipe_mask.in6_addr8);
3167663b816Sml 		hv = IPE_HASH_FN(sum4((uint32_t *)ipe->ipe_addr.in6_addr8),
3177663b816Sml 				 sum4((uint32_t *)ipe->ipe_mask.in6_addr8),
3187663b816Sml 				 iph->iph_size);
3197663b816Sml 	} else
3207663b816Sml #endif
3217663b816Sml 	if (ipe->ipe_family == AF_INET)
3227663b816Sml 	{
3237663b816Sml 		ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
3247663b816Sml 		ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
3257663b816Sml 		bits = count4bits(ipe->ipe_mask.in4_addr);
3267663b816Sml 		ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
3277663b816Sml 
3287663b816Sml 		hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
3297663b816Sml 				 iph->iph_size);
3307663b816Sml 	} else
3317663b816Sml 		return -1;
3327c478bd9Sstevel@tonic-gate 
333*f4b3ec61Sdh 	ipe->ipe_ref = 1;
3347c478bd9Sstevel@tonic-gate 	ipe->ipe_next = iph->iph_table[hv];
3357c478bd9Sstevel@tonic-gate 	ipe->ipe_pnext = iph->iph_table + hv;
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate 	if (iph->iph_table[hv] != NULL)
3387c478bd9Sstevel@tonic-gate 		iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next;
3397c478bd9Sstevel@tonic-gate 	iph->iph_table[hv] = ipe;
340*f4b3ec61Sdh 
341*f4b3ec61Sdh 	ipe->ipe_snext = iph->iph_list;
342*f4b3ec61Sdh 	ipe->ipe_psnext = &iph->iph_list;
343*f4b3ec61Sdh 	if (ipe->ipe_next != NULL)
344*f4b3ec61Sdh 		ipe->ipe_next->ipe_psnext = &ipe->ipe_snext;
345*f4b3ec61Sdh 	iph->iph_list = ipe;
346*f4b3ec61Sdh 
3477663b816Sml #ifdef USE_INET6
3487663b816Sml 	if (ipe->ipe_family == AF_INET6) {
3497663b816Sml 		if ((bits >= 0) && (bits != 128))
3507663b816Sml 			if (bits >= 96)
3517663b816Sml 				iph->iph_masks[0] |= 1 << (bits - 96);
3527663b816Sml 			else if (bits >= 64)
3537663b816Sml 				iph->iph_masks[1] |= 1 << (bits - 64);
3547663b816Sml 			else if (bits >= 32)
3557663b816Sml 				iph->iph_masks[2] |= 1 << (bits - 32);
3567663b816Sml 			else
3577663b816Sml 				iph->iph_masks[3] |= 1 << bits;
3587663b816Sml 
3597663b816Sml 	} else
3607663b816Sml #endif
3617663b816Sml 	{
3627663b816Sml 		if ((bits >= 0) && (bits != 32))
3637663b816Sml 			iph->iph_masks[3] |= 1 << bits;
3647663b816Sml 	}
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate 	switch (iph->iph_type & ~IPHASH_ANON)
3677c478bd9Sstevel@tonic-gate 	{
3687c478bd9Sstevel@tonic-gate 	case IPHASH_GROUPMAP :
3697c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
3707c478bd9Sstevel@tonic-gate 					   iph->iph_flags, IPL_LOGIPF,
371*f4b3ec61Sdh 					   ifs->ifs_fr_active, ifs);
3727c478bd9Sstevel@tonic-gate 		break;
3737c478bd9Sstevel@tonic-gate 
3747c478bd9Sstevel@tonic-gate 	default :
3757c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = NULL;
3767c478bd9Sstevel@tonic-gate 		ipe->ipe_value = 0;
3777c478bd9Sstevel@tonic-gate 		break;
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 
380*f4b3ec61Sdh 	ifs->ifs_ipf_nhtnodes[iph->iph_unit]++;
3817663b816Sml 
3827c478bd9Sstevel@tonic-gate 	return 0;
3837c478bd9Sstevel@tonic-gate }
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate  * Delete an entry from a hash table.
3887c478bd9Sstevel@tonic-gate  */
389*f4b3ec61Sdh int fr_delhtent(iph, ipe, ifs)
3907c478bd9Sstevel@tonic-gate iphtable_t *iph;
3917c478bd9Sstevel@tonic-gate iphtent_t *ipe;
392*f4b3ec61Sdh ipf_stack_t *ifs;
3937c478bd9Sstevel@tonic-gate {
394*f4b3ec61Sdh 	if (ipe->ipe_ref != 1)
3957c478bd9Sstevel@tonic-gate 		return EBUSY;
3967c478bd9Sstevel@tonic-gate 
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	*ipe->ipe_pnext = ipe->ipe_next;
3997c478bd9Sstevel@tonic-gate 	if (ipe->ipe_next != NULL)
4007c478bd9Sstevel@tonic-gate 		ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
4017c478bd9Sstevel@tonic-gate 
4027c478bd9Sstevel@tonic-gate 	switch (iph->iph_type & ~IPHASH_ANON)
4037c478bd9Sstevel@tonic-gate 	{
4047c478bd9Sstevel@tonic-gate 	case IPHASH_GROUPMAP :
4057c478bd9Sstevel@tonic-gate 		if (ipe->ipe_group != NULL)
406*f4b3ec61Sdh 			fr_delgroup(ipe->ipe_group, IPL_LOGIPF,
407*f4b3ec61Sdh 				    ifs->ifs_fr_active, ifs);
4087c478bd9Sstevel@tonic-gate 		break;
4097c478bd9Sstevel@tonic-gate 
4107c478bd9Sstevel@tonic-gate 	default :
4117c478bd9Sstevel@tonic-gate 		ipe->ipe_ptr = NULL;
4127c478bd9Sstevel@tonic-gate 		ipe->ipe_value = 0;
4137c478bd9Sstevel@tonic-gate 		break;
4147c478bd9Sstevel@tonic-gate 	}
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	KFREE(ipe);
4177c478bd9Sstevel@tonic-gate 
418*f4b3ec61Sdh 	ifs->ifs_ipf_nhtnodes[iph->iph_unit]--;
419*f4b3ec61Sdh 
4207c478bd9Sstevel@tonic-gate 	return 0;
4217c478bd9Sstevel@tonic-gate }
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 
424*f4b3ec61Sdh void *fr_iphmfindgroup(tptr, version, aptr, ifs)
425ab25eeb5Syz void *tptr;
4267663b816Sml int version;
427ab25eeb5Syz void *aptr;
428*f4b3ec61Sdh ipf_stack_t *ifs;
4297c478bd9Sstevel@tonic-gate {
4307663b816Sml 	i6addr_t *addr;
4317c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
4327c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
4337c478bd9Sstevel@tonic-gate 	void *rval;
4347c478bd9Sstevel@tonic-gate 
4357663b816Sml 	if ((version != 4)
4367663b816Sml #ifdef USE_INET6
4377663b816Sml 	    && (version != 6)
4387663b816Sml #endif
4397663b816Sml 	    )
4407663b816Sml 		return NULL;
4417663b816Sml 
442*f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
4437c478bd9Sstevel@tonic-gate 	iph = tptr;
4447c478bd9Sstevel@tonic-gate 	addr = aptr;
4457c478bd9Sstevel@tonic-gate 
4467663b816Sml #ifdef USE_INET6
4477663b816Sml 	if (version == 6)
4487663b816Sml 		ipe = fr_iphmfind6(iph, &addr->in6);
4497663b816Sml 	else
4507663b816Sml #endif
4517663b816Sml 	if (version == 4)
4527663b816Sml 		ipe = fr_iphmfind(iph, &addr->in4);
4537663b816Sml 	else
4547663b816Sml 		ipe = NULL;
4557c478bd9Sstevel@tonic-gate 	if (ipe != NULL)
4567c478bd9Sstevel@tonic-gate 		rval = ipe->ipe_ptr;
4577c478bd9Sstevel@tonic-gate 	else
4587c478bd9Sstevel@tonic-gate 		rval = NULL;
459*f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
4607c478bd9Sstevel@tonic-gate 	return rval;
4617c478bd9Sstevel@tonic-gate }
4627c478bd9Sstevel@tonic-gate 
4637c478bd9Sstevel@tonic-gate 
464ab25eeb5Syz /* ------------------------------------------------------------------------ */
465ab25eeb5Syz /* Function:    fr_iphmfindip                                               */
466ab25eeb5Syz /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
467ab25eeb5Syz /* Parameters:  tptr(I)    - pointer to the pool to search                  */
468ab25eeb5Syz /*              version(I) - IP protocol version (4 or 6)                   */
469ab25eeb5Syz /*              aptr(I)    - pointer to address information                 */
470ab25eeb5Syz /*                                                                          */
471ab25eeb5Syz /* Search the hash table for a given address and return a search result.    */
472ab25eeb5Syz /* ------------------------------------------------------------------------ */
473*f4b3ec61Sdh int fr_iphmfindip(tptr, version, aptr, ifs)
4747c478bd9Sstevel@tonic-gate void *tptr, *aptr;
4757c478bd9Sstevel@tonic-gate int version;
476*f4b3ec61Sdh 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 
496*f4b3ec61Sdh 	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;
5067c478bd9Sstevel@tonic-gate 	if (ipe != NULL)
5077c478bd9Sstevel@tonic-gate 		rval = 0;
5087c478bd9Sstevel@tonic-gate 	else
5097c478bd9Sstevel@tonic-gate 		rval = 1;
510*f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
5117c478bd9Sstevel@tonic-gate 	return rval;
5127c478bd9Sstevel@tonic-gate }
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 
5157c478bd9Sstevel@tonic-gate /* Locks:  ip_poolrw */
5167c478bd9Sstevel@tonic-gate static iphtent_t *fr_iphmfind(iph, addr)
5177c478bd9Sstevel@tonic-gate iphtable_t *iph;
5187c478bd9Sstevel@tonic-gate struct in_addr *addr;
5197c478bd9Sstevel@tonic-gate {
5207c478bd9Sstevel@tonic-gate 	u_32_t hmsk, msk, ips;
5217c478bd9Sstevel@tonic-gate 	iphtent_t *ipe;
5227c478bd9Sstevel@tonic-gate 	u_int hv;
5237c478bd9Sstevel@tonic-gate 
5247663b816Sml 	hmsk = iph->iph_masks[3];
5257c478bd9Sstevel@tonic-gate 	msk = 0xffffffff;
5267c478bd9Sstevel@tonic-gate maskloop:
5277c478bd9Sstevel@tonic-gate 	ips = ntohl(addr->s_addr) & msk;
5287c478bd9Sstevel@tonic-gate 	hv = IPE_HASH_FN(ips, msk, iph->iph_size);
5297c478bd9Sstevel@tonic-gate 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
5307c478bd9Sstevel@tonic-gate 		if (ipe->ipe_mask.in4_addr != msk ||
5317c478bd9Sstevel@tonic-gate 		    ipe->ipe_addr.in4_addr != ips) {
5327c478bd9Sstevel@tonic-gate 			continue;
5337c478bd9Sstevel@tonic-gate 		}
5347c478bd9Sstevel@tonic-gate 		break;
5357c478bd9Sstevel@tonic-gate 	}
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	if ((ipe == NULL) && (hmsk != 0)) {
5387c478bd9Sstevel@tonic-gate 		while (hmsk != 0) {
5397c478bd9Sstevel@tonic-gate 			msk <<= 1;
5407c478bd9Sstevel@tonic-gate 			if (hmsk & 0x80000000)
5417c478bd9Sstevel@tonic-gate 				break;
5427c478bd9Sstevel@tonic-gate 			hmsk <<= 1;
5437c478bd9Sstevel@tonic-gate 		}
5447c478bd9Sstevel@tonic-gate 		if (hmsk != 0) {
5457c478bd9Sstevel@tonic-gate 			hmsk <<= 1;
5467c478bd9Sstevel@tonic-gate 			goto maskloop;
5477c478bd9Sstevel@tonic-gate 		}
5487c478bd9Sstevel@tonic-gate 	}
5497663b816Sml 	return ipe;
5507663b816Sml }
5517663b816Sml 
5527663b816Sml 
5537663b816Sml #ifdef USE_INET6
5547663b816Sml /* Locks:  ip_poolrw */
5557663b816Sml static iphtent_t *fr_iphmfind6(iph, addr)
5567663b816Sml iphtable_t *iph;
5577663b816Sml struct in6_addr *addr;
5587663b816Sml {
5597663b816Sml 	u_32_t hmsk[4], msk[4], ips[4], *and;
5607663b816Sml 	iphtent_t *ipe;
5617663b816Sml 	u_int hv;
5627663b816Sml 
5637663b816Sml 	hmsk[0] = iph->iph_masks[0];
5647663b816Sml 	hmsk[1] = iph->iph_masks[1];
5657663b816Sml 	hmsk[2] = iph->iph_masks[2];
5667663b816Sml 	hmsk[3] = iph->iph_masks[3];
5677663b816Sml 
5687663b816Sml 	msk[0] = 0xffffffff;
5697663b816Sml 	msk[1] = 0xffffffff;
5707663b816Sml 	msk[2] = 0xffffffff;
5717663b816Sml 	msk[3] = 0xffffffff;
5727663b816Sml maskloop:
5737663b816Sml 	and = (u_32_t *)addr->s6_addr;
5747663b816Sml 	ips[0] = *and & msk[0];
5757663b816Sml 	ips[1] = *(and + 1) & msk[1];
5767663b816Sml 	ips[2] = *(and + 2) & msk[2];
5777663b816Sml 	ips[3] = *(and + 3) & msk[3];
5787663b816Sml 
5797663b816Sml 	hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk),
5807663b816Sml 			      iph->iph_size);
5817663b816Sml 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
5827663b816Sml 		if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) ||
5837663b816Sml 		    bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16))
5847663b816Sml 			continue;
5857663b816Sml 		break;
5867663b816Sml 	}
5877663b816Sml 
5887663b816Sml 	if ((ipe == NULL) && ((hmsk[0] != 0) ||
5897663b816Sml 			      (hmsk[1] != 0) ||
5907663b816Sml 			      (hmsk[2] != 0) ||
5917663b816Sml 			      (hmsk[3] != 0) )) {
5927663b816Sml 		while ((hmsk[0] != 0) && (hmsk[1] != 0) &&
5937663b816Sml 		       (hmsk[2] != 0) && (hmsk[3] != 0)) {
5947663b816Sml 			left_shift_ipv6((char *)msk);
5957663b816Sml 			if (hmsk[0] & 0x80000000)
5967663b816Sml 				break;
5977663b816Sml 			left_shift_ipv6((char *)hmsk);
5987663b816Sml 		}
5997663b816Sml 		if ((hmsk[0] != 0) && (hmsk[1] != 0) &&
6007663b816Sml 		    (hmsk[2] != 0) && (hmsk[3] != 0)) {
6017663b816Sml 			left_shift_ipv6((char *)hmsk);
6027663b816Sml 			goto maskloop;
6037663b816Sml 		}
6047663b816Sml 	}
6057c478bd9Sstevel@tonic-gate 	return ipe;
6067c478bd9Sstevel@tonic-gate }
6077c478bd9Sstevel@tonic-gate 
6087663b816Sml 
6097663b816Sml /*
6107663b816Sml  * sum4: ipv6 add -> 4 bytes values
6117663b816Sml  */
6127663b816Sml static uint32_t sum4(add)
6137663b816Sml uint32_t *add;
6147663b816Sml {
6157663b816Sml 	return (*add + *(add + 1) + *(add + 2) + *(add + 3));
6167663b816Sml }
6177663b816Sml 
6187663b816Sml /*
6197663b816Sml  * left shift on 128 bits
6207663b816Sml  */
6217663b816Sml static void left_shift_ipv6(data)
6227663b816Sml char *data;
6237663b816Sml {
6247663b816Sml 	u_32_t *sd;
6257663b816Sml 
6267663b816Sml 	sd = (u_32_t *)data;
6277663b816Sml 	sd[0] <<= 1;
6287663b816Sml 	if (sd[1] >= 0x80000000)
6297663b816Sml 		sd[0] += 1;
6307663b816Sml 
6317663b816Sml 	sd[1] <<= 1;
6327663b816Sml 	if (sd[2] >= 0x80000000)
6337663b816Sml 		sd[1] += 1;
6347663b816Sml 
6357663b816Sml 	sd[2] <<= 1;
6367663b816Sml 	if (sd[3] >= 0x80000000)
6377663b816Sml 		sd[2] += 1;
6387663b816Sml 
6397663b816Sml 	sd[3] <<= 1;
6407663b816Sml }
6417663b816Sml #endif
642*f4b3ec61Sdh 
643*f4b3ec61Sdh int fr_htable_getnext(token, ilp, ifs)
644*f4b3ec61Sdh ipftoken_t *token;
645*f4b3ec61Sdh ipflookupiter_t *ilp;
646*f4b3ec61Sdh ipf_stack_t *ifs;
647*f4b3ec61Sdh {
648*f4b3ec61Sdh 	iphtent_t *node, zn, *nextnode;
649*f4b3ec61Sdh 	iphtable_t *iph, zp, *nextiph;
650*f4b3ec61Sdh 	int err;
651*f4b3ec61Sdh 
652*f4b3ec61Sdh 	err = 0;
653*f4b3ec61Sdh 	iph = NULL;
654*f4b3ec61Sdh 	node = NULL;
655*f4b3ec61Sdh 	nextiph = NULL;
656*f4b3ec61Sdh 	nextnode = NULL;
657*f4b3ec61Sdh 
658*f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ip_poolrw);
659*f4b3ec61Sdh 
660*f4b3ec61Sdh 	switch (ilp->ili_otype)
661*f4b3ec61Sdh 	{
662*f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
663*f4b3ec61Sdh 		iph = token->ipt_data;
664*f4b3ec61Sdh 		if (iph == NULL) {
665*f4b3ec61Sdh 			nextiph = ifs->ifs_ipf_htables[(int)ilp->ili_unit];
666*f4b3ec61Sdh 		} else {
667*f4b3ec61Sdh 			nextiph = iph->iph_next;
668*f4b3ec61Sdh 		}
669*f4b3ec61Sdh 
670*f4b3ec61Sdh 		if (nextiph != NULL) {
671*f4b3ec61Sdh 			if (nextiph->iph_next == NULL)
672*f4b3ec61Sdh 				token->ipt_alive = 0;
673*f4b3ec61Sdh 			else {
674*f4b3ec61Sdh 				ATOMIC_INC(nextiph->iph_ref);
675*f4b3ec61Sdh 			}
676*f4b3ec61Sdh 		} else {
677*f4b3ec61Sdh 			bzero((char *)&zp, sizeof(zp));
678*f4b3ec61Sdh 			nextiph = &zp;
679*f4b3ec61Sdh 		}
680*f4b3ec61Sdh 		break;
681*f4b3ec61Sdh 
682*f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
683*f4b3ec61Sdh 		node = token->ipt_data;
684*f4b3ec61Sdh 		if (node == NULL) {
685*f4b3ec61Sdh 			iph = fr_findhtable(ilp->ili_unit, ilp->ili_name, ifs);
686*f4b3ec61Sdh 			if (iph == NULL)
687*f4b3ec61Sdh 				err = ESRCH;
688*f4b3ec61Sdh 			else {
689*f4b3ec61Sdh 				nextnode = iph->iph_list;
690*f4b3ec61Sdh 			}
691*f4b3ec61Sdh 		} else {
692*f4b3ec61Sdh 			nextnode = node->ipe_snext;
693*f4b3ec61Sdh 		}
694*f4b3ec61Sdh 
695*f4b3ec61Sdh 		if (nextnode != NULL) {
696*f4b3ec61Sdh 			if (nextnode->ipe_snext == NULL)
697*f4b3ec61Sdh 				token->ipt_alive = 0;
698*f4b3ec61Sdh 			else {
699*f4b3ec61Sdh 				ATOMIC_INC(nextnode->ipe_ref);
700*f4b3ec61Sdh 			}
701*f4b3ec61Sdh 		} else {
702*f4b3ec61Sdh 			bzero((char *)&zn, sizeof(zn));
703*f4b3ec61Sdh 			nextnode = &zn;
704*f4b3ec61Sdh 		}
705*f4b3ec61Sdh 		break;
706*f4b3ec61Sdh 	default :
707*f4b3ec61Sdh 		err = EINVAL;
708*f4b3ec61Sdh 		break;
709*f4b3ec61Sdh 	}
710*f4b3ec61Sdh 
711*f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
712*f4b3ec61Sdh 	if (err != 0)
713*f4b3ec61Sdh 		return err;
714*f4b3ec61Sdh 
715*f4b3ec61Sdh 	switch (ilp->ili_otype)
716*f4b3ec61Sdh 	{
717*f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
718*f4b3ec61Sdh 		if (iph != NULL) {
719*f4b3ec61Sdh 			WRITE_ENTER(&ifs->ifs_ip_poolrw);
720*f4b3ec61Sdh 			fr_derefhtable(iph, ifs);
721*f4b3ec61Sdh 			RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
722*f4b3ec61Sdh 		}
723*f4b3ec61Sdh 		token->ipt_data = nextiph;
724*f4b3ec61Sdh 		err = COPYOUT(nextiph, ilp->ili_data, sizeof(*nextiph));
725*f4b3ec61Sdh 		if (err != 0)
726*f4b3ec61Sdh 			err = EFAULT;
727*f4b3ec61Sdh 		break;
728*f4b3ec61Sdh 
729*f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
730*f4b3ec61Sdh 		if (node != NULL) {
731*f4b3ec61Sdh 			WRITE_ENTER(&ifs->ifs_ip_poolrw);
732*f4b3ec61Sdh 			fr_derefhtent(node);
733*f4b3ec61Sdh 			RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
734*f4b3ec61Sdh 		}
735*f4b3ec61Sdh 		token->ipt_data = nextnode;
736*f4b3ec61Sdh 		err = COPYOUT(nextnode, ilp->ili_data, sizeof(*nextnode));
737*f4b3ec61Sdh 		if (err != 0)
738*f4b3ec61Sdh 			err = EFAULT;
739*f4b3ec61Sdh 		break;
740*f4b3ec61Sdh 	}
741*f4b3ec61Sdh 
742*f4b3ec61Sdh 	return err;
743*f4b3ec61Sdh }
744*f4b3ec61Sdh 
745*f4b3ec61Sdh 
746*f4b3ec61Sdh void fr_htable_iterderef(otype, unit, data, ifs)
747*f4b3ec61Sdh u_int otype;
748*f4b3ec61Sdh int unit;
749*f4b3ec61Sdh void *data;
750*f4b3ec61Sdh ipf_stack_t *ifs;
751*f4b3ec61Sdh {
752*f4b3ec61Sdh 
753*f4b3ec61Sdh 	if (data == NULL)
754*f4b3ec61Sdh 		return;
755*f4b3ec61Sdh 
756*f4b3ec61Sdh 	if (unit < 0 || unit > IPL_LOGMAX)
757*f4b3ec61Sdh 		return;
758*f4b3ec61Sdh 
759*f4b3ec61Sdh 	switch (otype)
760*f4b3ec61Sdh 	{
761*f4b3ec61Sdh 	case IPFLOOKUPITER_LIST :
762*f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
763*f4b3ec61Sdh 		fr_derefhtable((iphtable_t *)data, ifs);
764*f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
765*f4b3ec61Sdh 		break;
766*f4b3ec61Sdh 
767*f4b3ec61Sdh 	case IPFLOOKUPITER_NODE :
768*f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
769*f4b3ec61Sdh 		fr_derefhtent((iphtent_t *)data);
770*f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
771*f4b3ec61Sdh 		break;
772*f4b3ec61Sdh 	default :
773*f4b3ec61Sdh 		break;
774*f4b3ec61Sdh 	}
775*f4b3ec61Sdh }
7767c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */
777