xref: /onnv-gate/usr/src/uts/common/inet/ipf/ip_htable.c (revision 2393:76e0289ce525)
1*2393Syz155240 /*
2*2393Syz155240  * Copyright (C) 1993-2001, 2003 by Darren Reed.
3*2393Syz155240  *
4*2393Syz155240  * See the IPFILTER.LICENCE file for details on licencing.
5*2393Syz155240  *
6*2393Syz155240  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
7*2393Syz155240  * Use is subject to license terms.
8*2393Syz155240  */
9*2393Syz155240 
10*2393Syz155240 #pragma ident	"%Z%%M%	%I%	%E% SMI"
11*2393Syz155240 
12*2393Syz155240 #if defined(KERNEL) || defined(_KERNEL)
13*2393Syz155240 # undef KERNEL
14*2393Syz155240 # undef _KERNEL
15*2393Syz155240 # define        KERNEL	1
16*2393Syz155240 # define        _KERNEL	1
17*2393Syz155240 #endif
18*2393Syz155240 #include <sys/param.h>
19*2393Syz155240 #include <sys/types.h>
20*2393Syz155240 #include <sys/errno.h>
21*2393Syz155240 #include <sys/time.h>
22*2393Syz155240 #include <sys/file.h>
23*2393Syz155240 #if !defined(_KERNEL)
24*2393Syz155240 # include <stdlib.h>
25*2393Syz155240 # include <string.h>
26*2393Syz155240 # define _KERNEL
27*2393Syz155240 # ifdef __OpenBSD__
28*2393Syz155240 struct file;
29*2393Syz155240 # endif
30*2393Syz155240 # include <sys/uio.h>
31*2393Syz155240 # undef _KERNEL
32*2393Syz155240 #endif
33*2393Syz155240 #include <sys/socket.h>
34*2393Syz155240 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
35*2393Syz155240 # include <sys/malloc.h>
36*2393Syz155240 #endif
37*2393Syz155240 #if defined(__FreeBSD__)
38*2393Syz155240 #  include <sys/cdefs.h>
39*2393Syz155240 #  include <sys/proc.h>
40*2393Syz155240 #endif
41*2393Syz155240 #if !defined(__svr4__) && !defined(__SVR4) && !defined(__hpux) && \
42*2393Syz155240     !defined(linux)
43*2393Syz155240 # include <sys/mbuf.h>
44*2393Syz155240 #endif
45*2393Syz155240 #if defined(_KERNEL)
46*2393Syz155240 # include <sys/systm.h>
47*2393Syz155240 #else
48*2393Syz155240 # include <stdio.h>
49*2393Syz155240 #endif
50*2393Syz155240 #include <netinet/in.h>
51*2393Syz155240 #include <net/if.h>
52*2393Syz155240 
53*2393Syz155240 #include "netinet/ip_compat.h"
54*2393Syz155240 #include "netinet/ip_fil.h"
55*2393Syz155240 #include "netinet/ip_lookup.h"
56*2393Syz155240 #include "netinet/ip_htable.h"
57*2393Syz155240 /* END OF INCLUDES */
58*2393Syz155240 
59*2393Syz155240 #if !defined(lint)
60*2393Syz155240 static const char rcsid[] = "@(#)$Id: ip_htable.c,v 2.34.2.3 2005/05/14 05:11:38 darrenr Exp $";
61*2393Syz155240 #endif
62*2393Syz155240 
63*2393Syz155240 #ifdef	IPFILTER_LOOKUP
64*2393Syz155240 static iphtent_t *fr_iphmfind __P((iphtable_t *, struct in_addr *));
65*2393Syz155240 #ifdef USE_INET6
66*2393Syz155240 static iphtent_t *fr_iphmfind6 __P((iphtable_t *, struct in6_addr *));
67*2393Syz155240 static uint32_t sum4(uint32_t *);
68*2393Syz155240 static void left_shift_ipv6 __P((char *));
69*2393Syz155240 #endif
70*2393Syz155240 
71*2393Syz155240 static	u_long	ipht_nomem[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
72*2393Syz155240 static	u_long	ipf_nhtables[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
73*2393Syz155240 static	u_long	ipf_nhtnodes[IPL_LOGSIZE] = { 0, 0, 0, 0, 0, 0, 0, 0 };
74*2393Syz155240 
75*2393Syz155240 iphtable_t *ipf_htables[IPL_LOGSIZE] = { NULL, NULL, NULL, NULL,
76*2393Syz155240 					 NULL, NULL, NULL, NULL };
77*2393Syz155240 
78*2393Syz155240 
79*2393Syz155240 void fr_htable_unload()
80*2393Syz155240 {
81*2393Syz155240 	iplookupflush_t fop;
82*2393Syz155240 
83*2393Syz155240 	fop.iplf_unit = IPL_LOGALL;
84*2393Syz155240 	(void)fr_flushhtable(&fop);
85*2393Syz155240 }
86*2393Syz155240 
87*2393Syz155240 
88*2393Syz155240 int fr_gethtablestat(op)
89*2393Syz155240 iplookupop_t *op;
90*2393Syz155240 {
91*2393Syz155240 	iphtstat_t stats;
92*2393Syz155240 
93*2393Syz155240 	if (op->iplo_size != sizeof(stats))
94*2393Syz155240 		return EINVAL;
95*2393Syz155240 
96*2393Syz155240 	stats.iphs_tables = ipf_htables[op->iplo_unit];
97*2393Syz155240 	stats.iphs_numtables = ipf_nhtables[op->iplo_unit];
98*2393Syz155240 	stats.iphs_numnodes = ipf_nhtnodes[op->iplo_unit];
99*2393Syz155240 	stats.iphs_nomem = ipht_nomem[op->iplo_unit];
100*2393Syz155240 
101*2393Syz155240 	return COPYOUT(&stats, op->iplo_struct, sizeof(stats));
102*2393Syz155240 
103*2393Syz155240 }
104*2393Syz155240 
105*2393Syz155240 
106*2393Syz155240 /*
107*2393Syz155240  * Create a new hash table using the template passed.
108*2393Syz155240  */
109*2393Syz155240 int fr_newhtable(op)
110*2393Syz155240 iplookupop_t *op;
111*2393Syz155240 {
112*2393Syz155240 	iphtable_t *iph, *oiph;
113*2393Syz155240 	char name[FR_GROUPLEN];
114*2393Syz155240 	int err, i, unit;
115*2393Syz155240 
116*2393Syz155240 	KMALLOC(iph, iphtable_t *);
117*2393Syz155240 	if (iph == NULL) {
118*2393Syz155240 		ipht_nomem[op->iplo_unit]++;
119*2393Syz155240 		return ENOMEM;
120*2393Syz155240 	}
121*2393Syz155240 
122*2393Syz155240 	err = COPYIN(op->iplo_struct, iph, sizeof(*iph));
123*2393Syz155240 	if (err != 0) {
124*2393Syz155240 		KFREE(iph);
125*2393Syz155240 		return EFAULT;
126*2393Syz155240 	}
127*2393Syz155240 
128*2393Syz155240 	unit = op->iplo_unit;
129*2393Syz155240 	if (iph->iph_unit != unit) {
130*2393Syz155240 		KFREE(iph);
131*2393Syz155240 		return EINVAL;
132*2393Syz155240 	}
133*2393Syz155240 
134*2393Syz155240 	if ((op->iplo_arg & IPHASH_ANON) == 0) {
135*2393Syz155240 		if (fr_findhtable(op->iplo_unit, op->iplo_name) != NULL) {
136*2393Syz155240 			KFREE(iph);
137*2393Syz155240 			return EEXIST;
138*2393Syz155240 		}
139*2393Syz155240 	} else {
140*2393Syz155240 		i = IPHASH_ANON;
141*2393Syz155240 		do {
142*2393Syz155240 			i++;
143*2393Syz155240 #if defined(SNPRINTF) && defined(_KERNEL)
144*2393Syz155240 			(void)SNPRINTF(name, sizeof(name), "%u", i);
145*2393Syz155240 #else
146*2393Syz155240 			(void)sprintf(name, "%u", i);
147*2393Syz155240 #endif
148*2393Syz155240 			for (oiph = ipf_htables[unit]; oiph != NULL;
149*2393Syz155240 			     oiph = oiph->iph_next)
150*2393Syz155240 				if (strncmp(oiph->iph_name, name,
151*2393Syz155240 					    sizeof(oiph->iph_name)) == 0)
152*2393Syz155240 					break;
153*2393Syz155240 		} while (oiph != NULL);
154*2393Syz155240 		(void)strncpy(iph->iph_name, name, sizeof(iph->iph_name));
155*2393Syz155240 		err = COPYOUT(iph, op->iplo_struct, sizeof(*iph));
156*2393Syz155240 		if (err != 0) {
157*2393Syz155240 			KFREE(iph);
158*2393Syz155240 			return EFAULT;
159*2393Syz155240 		}
160*2393Syz155240 		iph->iph_type |= IPHASH_ANON;
161*2393Syz155240 	}
162*2393Syz155240 
163*2393Syz155240 	KMALLOCS(iph->iph_table, iphtent_t **,
164*2393Syz155240 		 iph->iph_size * sizeof(*iph->iph_table));
165*2393Syz155240 	if (iph->iph_table == NULL) {
166*2393Syz155240 		KFREE(iph);
167*2393Syz155240 		ipht_nomem[unit]++;
168*2393Syz155240 		return ENOMEM;
169*2393Syz155240 	}
170*2393Syz155240 
171*2393Syz155240 	bzero((char *)iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
172*2393Syz155240 	iph->iph_masks[0] = 0;
173*2393Syz155240 	iph->iph_masks[1] = 0;
174*2393Syz155240 	iph->iph_masks[2] = 0;
175*2393Syz155240 	iph->iph_masks[3] = 0;
176*2393Syz155240 
177*2393Syz155240 	iph->iph_next = ipf_htables[unit];
178*2393Syz155240 	iph->iph_pnext = &ipf_htables[unit];
179*2393Syz155240 	if (ipf_htables[unit] != NULL)
180*2393Syz155240 		ipf_htables[unit]->iph_pnext = &iph->iph_next;
181*2393Syz155240 	ipf_htables[unit] = iph;
182*2393Syz155240 
183*2393Syz155240 	ipf_nhtables[unit]++;
184*2393Syz155240 
185*2393Syz155240 	return 0;
186*2393Syz155240 }
187*2393Syz155240 
188*2393Syz155240 
189*2393Syz155240 /*
190*2393Syz155240  */
191*2393Syz155240 int fr_removehtable(op)
192*2393Syz155240 iplookupop_t *op;
193*2393Syz155240 {
194*2393Syz155240 	iphtable_t *iph;
195*2393Syz155240 
196*2393Syz155240 
197*2393Syz155240 	iph = fr_findhtable(op->iplo_unit, op->iplo_name);
198*2393Syz155240 	if (iph == NULL)
199*2393Syz155240 		return ESRCH;
200*2393Syz155240 
201*2393Syz155240 	if (iph->iph_unit != op->iplo_unit) {
202*2393Syz155240 		return EINVAL;
203*2393Syz155240 	}
204*2393Syz155240 
205*2393Syz155240 	if (iph->iph_ref != 0) {
206*2393Syz155240 		return EBUSY;
207*2393Syz155240 	}
208*2393Syz155240 
209*2393Syz155240 	fr_delhtable(iph);
210*2393Syz155240 
211*2393Syz155240 	return 0;
212*2393Syz155240 }
213*2393Syz155240 
214*2393Syz155240 
215*2393Syz155240 void fr_delhtable(iph)
216*2393Syz155240 iphtable_t *iph;
217*2393Syz155240 {
218*2393Syz155240 	iphtent_t *ipe;
219*2393Syz155240 	int i;
220*2393Syz155240 
221*2393Syz155240 	for (i = 0; i < iph->iph_size; i++)
222*2393Syz155240 		while ((ipe = iph->iph_table[i]) != NULL)
223*2393Syz155240 			if (fr_delhtent(iph, ipe) != 0)
224*2393Syz155240 				return;
225*2393Syz155240 
226*2393Syz155240 	*iph->iph_pnext = iph->iph_next;
227*2393Syz155240 	if (iph->iph_next != NULL)
228*2393Syz155240 		iph->iph_next->iph_pnext = iph->iph_pnext;
229*2393Syz155240 
230*2393Syz155240 	ipf_nhtables[iph->iph_unit]--;
231*2393Syz155240 
232*2393Syz155240 	if (iph->iph_ref == 0) {
233*2393Syz155240 		KFREES(iph->iph_table, iph->iph_size * sizeof(*iph->iph_table));
234*2393Syz155240 		KFREE(iph);
235*2393Syz155240 	}
236*2393Syz155240 }
237*2393Syz155240 
238*2393Syz155240 
239*2393Syz155240 void fr_derefhtable(iph)
240*2393Syz155240 iphtable_t *iph;
241*2393Syz155240 {
242*2393Syz155240 	iph->iph_ref--;
243*2393Syz155240 	if (iph->iph_ref == 0)
244*2393Syz155240 		fr_delhtable(iph);
245*2393Syz155240 }
246*2393Syz155240 
247*2393Syz155240 
248*2393Syz155240 iphtable_t *fr_findhtable(unit, name)
249*2393Syz155240 int unit;
250*2393Syz155240 char *name;
251*2393Syz155240 {
252*2393Syz155240 	iphtable_t *iph;
253*2393Syz155240 
254*2393Syz155240 	for (iph = ipf_htables[unit]; iph != NULL; iph = iph->iph_next)
255*2393Syz155240 		if (strncmp(iph->iph_name, name, sizeof(iph->iph_name)) == 0)
256*2393Syz155240 			break;
257*2393Syz155240 	return iph;
258*2393Syz155240 }
259*2393Syz155240 
260*2393Syz155240 
261*2393Syz155240 size_t fr_flushhtable(op)
262*2393Syz155240 iplookupflush_t *op;
263*2393Syz155240 {
264*2393Syz155240 	iphtable_t *iph;
265*2393Syz155240 	size_t freed;
266*2393Syz155240 	int i;
267*2393Syz155240 
268*2393Syz155240 	freed = 0;
269*2393Syz155240 
270*2393Syz155240 	for (i = 0; i <= IPL_LOGMAX; i++) {
271*2393Syz155240 		if (op->iplf_unit == i || op->iplf_unit == IPL_LOGALL) {
272*2393Syz155240 			while ((iph = ipf_htables[i]) != NULL) {
273*2393Syz155240 				fr_delhtable(iph);
274*2393Syz155240 				freed++;
275*2393Syz155240 			}
276*2393Syz155240 		}
277*2393Syz155240 	}
278*2393Syz155240 
279*2393Syz155240 	return freed;
280*2393Syz155240 }
281*2393Syz155240 
282*2393Syz155240 
283*2393Syz155240 /*
284*2393Syz155240  * Add an entry to a hash table.
285*2393Syz155240  */
286*2393Syz155240 int fr_addhtent(iph, ipeo)
287*2393Syz155240 iphtable_t *iph;
288*2393Syz155240 iphtent_t *ipeo;
289*2393Syz155240 {
290*2393Syz155240 	iphtent_t *ipe;
291*2393Syz155240 	u_int hv;
292*2393Syz155240 	int bits;
293*2393Syz155240 
294*2393Syz155240 	KMALLOC(ipe, iphtent_t *);
295*2393Syz155240 	if (ipe == NULL)
296*2393Syz155240 		return -1;
297*2393Syz155240 
298*2393Syz155240 	bcopy((char *)ipeo, (char *)ipe, sizeof(*ipe));
299*2393Syz155240 #ifdef USE_INET6
300*2393Syz155240 	if (ipe->ipe_family == AF_INET6) {
301*2393Syz155240 		bits = count6bits((u_32_t *)ipe->ipe_mask.in6_addr8);
302*2393Syz155240 		hv = IPE_HASH_FN(sum4((uint32_t *)ipe->ipe_addr.in6_addr8),
303*2393Syz155240 				 sum4((uint32_t *)ipe->ipe_mask.in6_addr8),
304*2393Syz155240 				 iph->iph_size);
305*2393Syz155240 	} else
306*2393Syz155240 #endif
307*2393Syz155240 	if (ipe->ipe_family == AF_INET)
308*2393Syz155240 	{
309*2393Syz155240 		ipe->ipe_addr.in4_addr &= ipe->ipe_mask.in4_addr;
310*2393Syz155240 		ipe->ipe_addr.in4_addr = ntohl(ipe->ipe_addr.in4_addr);
311*2393Syz155240 		bits = count4bits(ipe->ipe_mask.in4_addr);
312*2393Syz155240 		ipe->ipe_mask.in4_addr = ntohl(ipe->ipe_mask.in4_addr);
313*2393Syz155240 
314*2393Syz155240 		hv = IPE_HASH_FN(ipe->ipe_addr.in4_addr, ipe->ipe_mask.in4_addr,
315*2393Syz155240 				 iph->iph_size);
316*2393Syz155240 	} else
317*2393Syz155240 		return -1;
318*2393Syz155240 
319*2393Syz155240 	ipe->ipe_ref = 0;
320*2393Syz155240 	ipe->ipe_next = iph->iph_table[hv];
321*2393Syz155240 	ipe->ipe_pnext = iph->iph_table + hv;
322*2393Syz155240 
323*2393Syz155240 	if (iph->iph_table[hv] != NULL)
324*2393Syz155240 		iph->iph_table[hv]->ipe_pnext = &ipe->ipe_next;
325*2393Syz155240 	iph->iph_table[hv] = ipe;
326*2393Syz155240 #ifdef USE_INET6
327*2393Syz155240 	if (ipe->ipe_family == AF_INET6) {
328*2393Syz155240 		if ((bits >= 0) && (bits != 128))
329*2393Syz155240 			if (bits >= 96)
330*2393Syz155240 				iph->iph_masks[0] |= 1 << (bits - 96);
331*2393Syz155240 			else if (bits >= 64)
332*2393Syz155240 				iph->iph_masks[1] |= 1 << (bits - 64);
333*2393Syz155240 			else if (bits >= 32)
334*2393Syz155240 				iph->iph_masks[2] |= 1 << (bits - 32);
335*2393Syz155240 			else
336*2393Syz155240 				iph->iph_masks[3] |= 1 << bits;
337*2393Syz155240 
338*2393Syz155240 	} else
339*2393Syz155240 #endif
340*2393Syz155240 	{
341*2393Syz155240 		if ((bits >= 0) && (bits != 32))
342*2393Syz155240 			iph->iph_masks[3] |= 1 << bits;
343*2393Syz155240 	}
344*2393Syz155240 
345*2393Syz155240 	switch (iph->iph_type & ~IPHASH_ANON)
346*2393Syz155240 	{
347*2393Syz155240 	case IPHASH_GROUPMAP :
348*2393Syz155240 		ipe->ipe_ptr = fr_addgroup(ipe->ipe_group, NULL,
349*2393Syz155240 					   iph->iph_flags, IPL_LOGIPF,
350*2393Syz155240 					   fr_active);
351*2393Syz155240 		break;
352*2393Syz155240 
353*2393Syz155240 	default :
354*2393Syz155240 		ipe->ipe_ptr = NULL;
355*2393Syz155240 		ipe->ipe_value = 0;
356*2393Syz155240 		break;
357*2393Syz155240 	}
358*2393Syz155240 
359*2393Syz155240 	ipf_nhtnodes[iph->iph_unit]++;
360*2393Syz155240 
361*2393Syz155240 	return 0;
362*2393Syz155240 }
363*2393Syz155240 
364*2393Syz155240 
365*2393Syz155240 /*
366*2393Syz155240  * Delete an entry from a hash table.
367*2393Syz155240  */
368*2393Syz155240 int fr_delhtent(iph, ipe)
369*2393Syz155240 iphtable_t *iph;
370*2393Syz155240 iphtent_t *ipe;
371*2393Syz155240 {
372*2393Syz155240 
373*2393Syz155240 	if (ipe->ipe_ref != 0)
374*2393Syz155240 		return EBUSY;
375*2393Syz155240 
376*2393Syz155240 
377*2393Syz155240 	*ipe->ipe_pnext = ipe->ipe_next;
378*2393Syz155240 	if (ipe->ipe_next != NULL)
379*2393Syz155240 		ipe->ipe_next->ipe_pnext = ipe->ipe_pnext;
380*2393Syz155240 
381*2393Syz155240 	switch (iph->iph_type & ~IPHASH_ANON)
382*2393Syz155240 	{
383*2393Syz155240 	case IPHASH_GROUPMAP :
384*2393Syz155240 		if (ipe->ipe_group != NULL)
385*2393Syz155240 			fr_delgroup(ipe->ipe_group, IPL_LOGIPF, fr_active);
386*2393Syz155240 		break;
387*2393Syz155240 
388*2393Syz155240 	default :
389*2393Syz155240 		ipe->ipe_ptr = NULL;
390*2393Syz155240 		ipe->ipe_value = 0;
391*2393Syz155240 		break;
392*2393Syz155240 	}
393*2393Syz155240 
394*2393Syz155240 	KFREE(ipe);
395*2393Syz155240 
396*2393Syz155240 	ipf_nhtnodes[iph->iph_unit]--;
397*2393Syz155240 
398*2393Syz155240 	return 0;
399*2393Syz155240 }
400*2393Syz155240 
401*2393Syz155240 
402*2393Syz155240 void *fr_iphmfindgroup(tptr, version, aptr)
403*2393Syz155240 void *tptr;
404*2393Syz155240 int version;
405*2393Syz155240 void *aptr;
406*2393Syz155240 {
407*2393Syz155240 	i6addr_t *addr;
408*2393Syz155240 	iphtable_t *iph;
409*2393Syz155240 	iphtent_t *ipe;
410*2393Syz155240 	void *rval;
411*2393Syz155240 
412*2393Syz155240 	if ((version != 4)
413*2393Syz155240 #ifdef USE_INET6
414*2393Syz155240 	    && (version != 6)
415*2393Syz155240 #endif
416*2393Syz155240 	    )
417*2393Syz155240 		return NULL;
418*2393Syz155240 
419*2393Syz155240 	READ_ENTER(&ip_poolrw);
420*2393Syz155240 	iph = tptr;
421*2393Syz155240 	addr = aptr;
422*2393Syz155240 
423*2393Syz155240 #ifdef USE_INET6
424*2393Syz155240 	if (version == 6)
425*2393Syz155240 		ipe = fr_iphmfind6(iph, &addr->in6);
426*2393Syz155240 	else
427*2393Syz155240 #endif
428*2393Syz155240 	if (version == 4)
429*2393Syz155240 		ipe = fr_iphmfind(iph, &addr->in4);
430*2393Syz155240 	else
431*2393Syz155240 		ipe = NULL;
432*2393Syz155240 	if (ipe != NULL)
433*2393Syz155240 		rval = ipe->ipe_ptr;
434*2393Syz155240 	else
435*2393Syz155240 		rval = NULL;
436*2393Syz155240 	RWLOCK_EXIT(&ip_poolrw);
437*2393Syz155240 	return rval;
438*2393Syz155240 }
439*2393Syz155240 
440*2393Syz155240 
441*2393Syz155240 /* ------------------------------------------------------------------------ */
442*2393Syz155240 /* Function:    fr_iphmfindip                                               */
443*2393Syz155240 /* Returns:     int     - 0 == +ve match, -1 == error, 1 == -ve/no match    */
444*2393Syz155240 /* Parameters:  tptr(I)    - pointer to the pool to search                  */
445*2393Syz155240 /*              version(I) - IP protocol version (4 or 6)                   */
446*2393Syz155240 /*              aptr(I)    - pointer to address information                 */
447*2393Syz155240 /*                                                                          */
448*2393Syz155240 /* Search the hash table for a given address and return a search result.    */
449*2393Syz155240 /* ------------------------------------------------------------------------ */
450*2393Syz155240 int fr_iphmfindip(tptr, version, aptr)
451*2393Syz155240 void *tptr, *aptr;
452*2393Syz155240 int version;
453*2393Syz155240 {
454*2393Syz155240 	i6addr_t *addr;
455*2393Syz155240 	iphtable_t *iph;
456*2393Syz155240 	iphtent_t *ipe;
457*2393Syz155240 	int rval;
458*2393Syz155240 
459*2393Syz155240 	if ((version != 4)
460*2393Syz155240 #ifdef USE_INET6
461*2393Syz155240 	    && (version != 6)
462*2393Syz155240 #endif
463*2393Syz155240 	    )
464*2393Syz155240 		return -1;
465*2393Syz155240 
466*2393Syz155240 	if (tptr == NULL || aptr == NULL)
467*2393Syz155240 		return -1;
468*2393Syz155240 
469*2393Syz155240 	iph = tptr;
470*2393Syz155240 	addr = aptr;
471*2393Syz155240 
472*2393Syz155240 	READ_ENTER(&ip_poolrw);
473*2393Syz155240 #ifdef USE_INET6
474*2393Syz155240 	if (version == 6)
475*2393Syz155240 		ipe = fr_iphmfind6(iph, &addr->in6);
476*2393Syz155240 	else
477*2393Syz155240 #endif
478*2393Syz155240 	if (version == 4)
479*2393Syz155240 		ipe = fr_iphmfind(iph, &addr->in4);
480*2393Syz155240 	else
481*2393Syz155240 		ipe = NULL;
482*2393Syz155240 	if (ipe != NULL)
483*2393Syz155240 		rval = 0;
484*2393Syz155240 	else
485*2393Syz155240 		rval = 1;
486*2393Syz155240 	RWLOCK_EXIT(&ip_poolrw);
487*2393Syz155240 	return rval;
488*2393Syz155240 }
489*2393Syz155240 
490*2393Syz155240 
491*2393Syz155240 /* Locks:  ip_poolrw */
492*2393Syz155240 static iphtent_t *fr_iphmfind(iph, addr)
493*2393Syz155240 iphtable_t *iph;
494*2393Syz155240 struct in_addr *addr;
495*2393Syz155240 {
496*2393Syz155240 	u_32_t hmsk, msk, ips;
497*2393Syz155240 	iphtent_t *ipe;
498*2393Syz155240 	u_int hv;
499*2393Syz155240 
500*2393Syz155240 	hmsk = iph->iph_masks[3];
501*2393Syz155240 	msk = 0xffffffff;
502*2393Syz155240 maskloop:
503*2393Syz155240 	ips = ntohl(addr->s_addr) & msk;
504*2393Syz155240 	hv = IPE_HASH_FN(ips, msk, iph->iph_size);
505*2393Syz155240 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
506*2393Syz155240 		if (ipe->ipe_mask.in4_addr != msk ||
507*2393Syz155240 		    ipe->ipe_addr.in4_addr != ips) {
508*2393Syz155240 			continue;
509*2393Syz155240 		}
510*2393Syz155240 		break;
511*2393Syz155240 	}
512*2393Syz155240 
513*2393Syz155240 	if ((ipe == NULL) && (hmsk != 0)) {
514*2393Syz155240 		while (hmsk != 0) {
515*2393Syz155240 			msk <<= 1;
516*2393Syz155240 			if (hmsk & 0x80000000)
517*2393Syz155240 				break;
518*2393Syz155240 			hmsk <<= 1;
519*2393Syz155240 		}
520*2393Syz155240 		if (hmsk != 0) {
521*2393Syz155240 			hmsk <<= 1;
522*2393Syz155240 			goto maskloop;
523*2393Syz155240 		}
524*2393Syz155240 	}
525*2393Syz155240 	return ipe;
526*2393Syz155240 }
527*2393Syz155240 
528*2393Syz155240 
529*2393Syz155240 #ifdef USE_INET6
530*2393Syz155240 /* Locks:  ip_poolrw */
531*2393Syz155240 static iphtent_t *fr_iphmfind6(iph, addr)
532*2393Syz155240 iphtable_t *iph;
533*2393Syz155240 struct in6_addr *addr;
534*2393Syz155240 {
535*2393Syz155240 	u_32_t hmsk[4], msk[4], ips[4], *and;
536*2393Syz155240 	iphtent_t *ipe;
537*2393Syz155240 	u_int hv;
538*2393Syz155240 
539*2393Syz155240 	hmsk[0] = iph->iph_masks[0];
540*2393Syz155240 	hmsk[1] = iph->iph_masks[1];
541*2393Syz155240 	hmsk[2] = iph->iph_masks[2];
542*2393Syz155240 	hmsk[3] = iph->iph_masks[3];
543*2393Syz155240 
544*2393Syz155240 	msk[0] = 0xffffffff;
545*2393Syz155240 	msk[1] = 0xffffffff;
546*2393Syz155240 	msk[2] = 0xffffffff;
547*2393Syz155240 	msk[3] = 0xffffffff;
548*2393Syz155240 maskloop:
549*2393Syz155240 	and = (u_32_t *)addr->s6_addr;
550*2393Syz155240 	ips[0] = *and & msk[0];
551*2393Syz155240 	ips[1] = *(and + 1) & msk[1];
552*2393Syz155240 	ips[2] = *(and + 2) & msk[2];
553*2393Syz155240 	ips[3] = *(and + 3) & msk[3];
554*2393Syz155240 
555*2393Syz155240 	hv = IPE_HASH_FN(sum4((uint32_t *)addr), sum4((uint32_t *)msk),
556*2393Syz155240 			      iph->iph_size);
557*2393Syz155240 	for (ipe = iph->iph_table[hv]; (ipe != NULL); ipe = ipe->ipe_next) {
558*2393Syz155240 		if (bcmp((void *)&ipe->ipe_mask.in6, (void *)msk, 16) ||
559*2393Syz155240 		    bcmp((void *)&ipe->ipe_addr.in6, (void *)ips, 16))
560*2393Syz155240 			continue;
561*2393Syz155240 		break;
562*2393Syz155240 	}
563*2393Syz155240 
564*2393Syz155240 	if ((ipe == NULL) && ((hmsk[0] != 0) ||
565*2393Syz155240 			      (hmsk[1] != 0) ||
566*2393Syz155240 			      (hmsk[2] != 0) ||
567*2393Syz155240 			      (hmsk[3] != 0) )) {
568*2393Syz155240 		while ((hmsk[0] != 0) && (hmsk[1] != 0) &&
569*2393Syz155240 		       (hmsk[2] != 0) && (hmsk[3] != 0)) {
570*2393Syz155240 			left_shift_ipv6((char *)msk);
571*2393Syz155240 			if (hmsk[0] & 0x80000000)
572*2393Syz155240 				break;
573*2393Syz155240 			left_shift_ipv6((char *)hmsk);
574*2393Syz155240 		}
575*2393Syz155240 		if ((hmsk[0] != 0) && (hmsk[1] != 0) &&
576*2393Syz155240 		    (hmsk[2] != 0) && (hmsk[3] != 0)) {
577*2393Syz155240 			left_shift_ipv6((char *)hmsk);
578*2393Syz155240 			goto maskloop;
579*2393Syz155240 		}
580*2393Syz155240 	}
581*2393Syz155240 	return ipe;
582*2393Syz155240 }
583*2393Syz155240 
584*2393Syz155240 
585*2393Syz155240 /*
586*2393Syz155240  * sum4: ipv6 add -> 4 bytes values
587*2393Syz155240  */
588*2393Syz155240 static uint32_t sum4(add)
589*2393Syz155240 uint32_t *add;
590*2393Syz155240 {
591*2393Syz155240 	return (*add + *(add + 1) + *(add + 2) + *(add + 3));
592*2393Syz155240 }
593*2393Syz155240 
594*2393Syz155240 /*
595*2393Syz155240  * left shift on 128 bits
596*2393Syz155240  */
597*2393Syz155240 static void left_shift_ipv6(data)
598*2393Syz155240 char *data;
599*2393Syz155240 {
600*2393Syz155240 	u_32_t *sd;
601*2393Syz155240 
602*2393Syz155240 	sd = (u_32_t *)data;
603*2393Syz155240 	sd[0] <<= 1;
604*2393Syz155240 	if (sd[1] >= 0x80000000)
605*2393Syz155240 		sd[0] += 1;
606*2393Syz155240 
607*2393Syz155240 	sd[1] <<= 1;
608*2393Syz155240 	if (sd[2] >= 0x80000000)
609*2393Syz155240 		sd[1] += 1;
610*2393Syz155240 
611*2393Syz155240 	sd[2] <<= 1;
612*2393Syz155240 	if (sd[3] >= 0x80000000)
613*2393Syz155240 		sd[2] += 1;
614*2393Syz155240 
615*2393Syz155240 	sd[3] <<= 1;
616*2393Syz155240 }
617*2393Syz155240 #endif
618*2393Syz155240 #endif /* IPFILTER_LOOKUP */
619