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