xref: /titanic_52/usr/src/uts/common/inet/ipf/ip_lookup.c (revision bb1d9de55b0c95d4bd8ff7f06a294587a25a6c2e)
1ab25eeb5Syz155240 /*
2ab25eeb5Syz155240  * Copyright (C) 2002-2003 by Darren Reed.
3ab25eeb5Syz155240  *
4ab25eeb5Syz155240  * See the IPFILTER.LICENCE file for details on licencing.
5ab25eeb5Syz155240  *
6*bb1d9de5SJohn Ojemann  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
7ab25eeb5Syz155240  * Use is subject to license terms.
8ab25eeb5Syz155240  */
9ab25eeb5Syz155240 
10ab25eeb5Syz155240 #if defined(KERNEL) || defined(_KERNEL)
11ab25eeb5Syz155240 # undef KERNEL
12ab25eeb5Syz155240 # undef _KERNEL
13ab25eeb5Syz155240 # define        KERNEL	1
14ab25eeb5Syz155240 # define        _KERNEL	1
15ab25eeb5Syz155240 #endif
16ab25eeb5Syz155240 #if defined(__osf__)
17ab25eeb5Syz155240 # define _PROTO_NET_H_
18ab25eeb5Syz155240 #endif
19ab25eeb5Syz155240 #include <sys/param.h>
20ab25eeb5Syz155240 #include <sys/errno.h>
21ab25eeb5Syz155240 #include <sys/types.h>
22ab25eeb5Syz155240 #include <sys/time.h>
23ab25eeb5Syz155240 #include <sys/file.h>
24ab25eeb5Syz155240 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
25ab25eeb5Syz155240 # include <sys/fcntl.h>
26ab25eeb5Syz155240 # include <sys/filio.h>
27ab25eeb5Syz155240 #else
28ab25eeb5Syz155240 # include <sys/ioctl.h>
29ab25eeb5Syz155240 #endif
30ab25eeb5Syz155240 #if !defined(_KERNEL)
31ab25eeb5Syz155240 # include <string.h>
32ab25eeb5Syz155240 # define _KERNEL
33ab25eeb5Syz155240 # ifdef __OpenBSD__
34ab25eeb5Syz155240 struct file;
35ab25eeb5Syz155240 # endif
36ab25eeb5Syz155240 # include <sys/uio.h>
37ab25eeb5Syz155240 # undef _KERNEL
38ab25eeb5Syz155240 #endif
39ab25eeb5Syz155240 #include <sys/socket.h>
40ab25eeb5Syz155240 #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
41ab25eeb5Syz155240 # ifdef __osf__
42ab25eeb5Syz155240 #  include <net/radix.h>
43ab25eeb5Syz155240 # endif
44ab25eeb5Syz155240 # include "radix_ipf_local.h"
45ab25eeb5Syz155240 # define _RADIX_H_
46ab25eeb5Syz155240 #endif
47ab25eeb5Syz155240 #include <net/if.h>
48ab25eeb5Syz155240 #if defined(__FreeBSD__)
49ab25eeb5Syz155240 #  include <sys/cdefs.h>
50ab25eeb5Syz155240 #  include <sys/proc.h>
51ab25eeb5Syz155240 #endif
52ab25eeb5Syz155240 #if defined(_KERNEL)
53ab25eeb5Syz155240 # include <sys/systm.h>
54ab25eeb5Syz155240 # if !defined(__SVR4) && !defined(__svr4__)
55ab25eeb5Syz155240 #  include <sys/mbuf.h>
56ab25eeb5Syz155240 # endif
57ab25eeb5Syz155240 #endif
58ab25eeb5Syz155240 #include <netinet/in.h>
59ab25eeb5Syz155240 
60ab25eeb5Syz155240 #include "netinet/ip_compat.h"
61ab25eeb5Syz155240 #include "netinet/ip_fil.h"
62ab25eeb5Syz155240 #include "netinet/ip_pool.h"
63ab25eeb5Syz155240 #include "netinet/ip_htable.h"
64ab25eeb5Syz155240 #include "netinet/ip_lookup.h"
65f4b3ec61Sdh155122 #include "netinet/ipf_stack.h"
66ab25eeb5Syz155240 /* END OF INCLUDES */
67ab25eeb5Syz155240 
68ab25eeb5Syz155240 #if !defined(lint)
69ab25eeb5Syz155240 static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $";
70ab25eeb5Syz155240 #endif
71ab25eeb5Syz155240 
72ab25eeb5Syz155240 #ifdef	IPFILTER_LOOKUP
73f4b3ec61Sdh155122 static int iplookup_addnode __P((caddr_t, ipf_stack_t *));
74f4b3ec61Sdh155122 static int iplookup_delnode __P((caddr_t data, ipf_stack_t *));
75f4b3ec61Sdh155122 static int iplookup_addtable __P((caddr_t, ipf_stack_t *));
76f4b3ec61Sdh155122 static int iplookup_deltable __P((caddr_t, ipf_stack_t *));
77f4b3ec61Sdh155122 static int iplookup_stats __P((caddr_t, ipf_stack_t *));
78f4b3ec61Sdh155122 static int iplookup_flush __P((caddr_t, ipf_stack_t *));
79ab25eeb5Syz155240 
80ab25eeb5Syz155240 
81ab25eeb5Syz155240 
82ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
83ab25eeb5Syz155240 /* Function:    iplookup_init                                               */
84ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
85ab25eeb5Syz155240 /* Parameters:  Nil                                                         */
86ab25eeb5Syz155240 /*                                                                          */
87ab25eeb5Syz155240 /* Initialise all of the subcomponents of the lookup infrstructure.         */
88ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
89f4b3ec61Sdh155122 int ip_lookup_init(ifs)
90f4b3ec61Sdh155122 ipf_stack_t *ifs;
91ab25eeb5Syz155240 {
92ab25eeb5Syz155240 
93f4b3ec61Sdh155122 	if (ip_pool_init(ifs) == -1)
94ab25eeb5Syz155240 		return -1;
95ab25eeb5Syz155240 
96f4b3ec61Sdh155122 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "ip pool rwlock");
97ab25eeb5Syz155240 
98f4b3ec61Sdh155122 	ifs->ifs_ip_lookup_inited = 1;
99f4b3ec61Sdh155122 	ifs->ifs_ipftokenhead = NULL;
100f4b3ec61Sdh155122 	ifs->ifs_ipftokentail = &ifs->ifs_ipftokenhead;
101ab25eeb5Syz155240 	return 0;
102ab25eeb5Syz155240 }
103ab25eeb5Syz155240 
104ab25eeb5Syz155240 
105ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
106ab25eeb5Syz155240 /* Function:    iplookup_unload                                             */
107ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
108ab25eeb5Syz155240 /* Parameters:  Nil                                                         */
109ab25eeb5Syz155240 /*                                                                          */
110ab25eeb5Syz155240 /* Free up all pool related memory that has been allocated whilst IPFilter  */
111ab25eeb5Syz155240 /* has been running.  Also, do any other deinitialisation required such     */
112ab25eeb5Syz155240 /* ip_lookup_init() can be called again, safely.                            */
113ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
114f4b3ec61Sdh155122 void ip_lookup_unload(ifs)
115f4b3ec61Sdh155122 ipf_stack_t *ifs;
116ab25eeb5Syz155240 {
117f4b3ec61Sdh155122 	ip_pool_fini(ifs);
118f4b3ec61Sdh155122 	fr_htable_unload(ifs);
119ab25eeb5Syz155240 
120f4b3ec61Sdh155122 	if (ifs->ifs_ip_lookup_inited == 1) {
121f4b3ec61Sdh155122 		RW_DESTROY(&ifs->ifs_ip_poolrw);
122f4b3ec61Sdh155122 		ifs->ifs_ip_lookup_inited = 0;
123ab25eeb5Syz155240 	}
124ab25eeb5Syz155240 }
125ab25eeb5Syz155240 
126ab25eeb5Syz155240 
127ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
128ab25eeb5Syz155240 /* Function:    iplookup_ioctl                                              */
129ab25eeb5Syz155240 /* Returns:     int      - 0 = success, else error                          */
130ab25eeb5Syz155240 /* Parameters:  data(IO) - pointer to ioctl data to be copied to/from user  */
131ab25eeb5Syz155240 /*                         space.                                           */
132ab25eeb5Syz155240 /*              cmd(I)   - ioctl command number                             */
133ab25eeb5Syz155240 /*              mode(I)  - file mode bits used with open                    */
134ab25eeb5Syz155240 /*                                                                          */
135ab25eeb5Syz155240 /* Handle ioctl commands sent to the ioctl device.  For the most part, this */
136ab25eeb5Syz155240 /* involves just calling another function to handle the specifics of each   */
137ab25eeb5Syz155240 /* command.                                                                 */
138ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
139f4b3ec61Sdh155122 int ip_lookup_ioctl(data, cmd, mode, uid, ctx, ifs)
140ab25eeb5Syz155240 caddr_t data;
141ab25eeb5Syz155240 ioctlcmd_t cmd;
142f4b3ec61Sdh155122 int mode, uid;
143f4b3ec61Sdh155122 void *ctx;
144f4b3ec61Sdh155122 ipf_stack_t *ifs;
145ab25eeb5Syz155240 {
146ab25eeb5Syz155240 	int err;
147ab25eeb5Syz155240 	SPL_INT(s);
148ab25eeb5Syz155240 
149ab25eeb5Syz155240 	mode = mode;	/* LINT */
150ab25eeb5Syz155240 
151ab25eeb5Syz155240 	SPL_NET(s);
152ab25eeb5Syz155240 
153ab25eeb5Syz155240 	switch (cmd)
154ab25eeb5Syz155240 	{
155ab25eeb5Syz155240 	case SIOCLOOKUPADDNODE :
156ab25eeb5Syz155240 	case SIOCLOOKUPADDNODEW :
157f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
158f4b3ec61Sdh155122 		err = iplookup_addnode(data, ifs);
159f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
160ab25eeb5Syz155240 		break;
161ab25eeb5Syz155240 
162ab25eeb5Syz155240 	case SIOCLOOKUPDELNODE :
163ab25eeb5Syz155240 	case SIOCLOOKUPDELNODEW :
164f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
165f4b3ec61Sdh155122 		err = iplookup_delnode(data, ifs);
166f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
167ab25eeb5Syz155240 		break;
168ab25eeb5Syz155240 
169ab25eeb5Syz155240 	case SIOCLOOKUPADDTABLE :
170f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
171f4b3ec61Sdh155122 		err = iplookup_addtable(data, ifs);
172f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
173ab25eeb5Syz155240 		break;
174ab25eeb5Syz155240 
175ab25eeb5Syz155240 	case SIOCLOOKUPDELTABLE :
176f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
177f4b3ec61Sdh155122 		err = iplookup_deltable(data, ifs);
178f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
179ab25eeb5Syz155240 		break;
180ab25eeb5Syz155240 
181ab25eeb5Syz155240 	case SIOCLOOKUPSTAT :
182ab25eeb5Syz155240 	case SIOCLOOKUPSTATW :
183f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
184f4b3ec61Sdh155122 		err = iplookup_stats(data, ifs);
185f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
186ab25eeb5Syz155240 		break;
187ab25eeb5Syz155240 
188ab25eeb5Syz155240 	case SIOCLOOKUPFLUSH :
189f4b3ec61Sdh155122 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
190f4b3ec61Sdh155122 		err = iplookup_flush(data, ifs);
191f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
192f4b3ec61Sdh155122 		break;
193f4b3ec61Sdh155122 
194f4b3ec61Sdh155122 	case SIOCLOOKUPITER :
195f4b3ec61Sdh155122 		err = ip_lookup_iterate(data, uid, ctx, ifs);
196ab25eeb5Syz155240 		break;
197ab25eeb5Syz155240 
198ab25eeb5Syz155240 	default :
199ab25eeb5Syz155240 		err = EINVAL;
200ab25eeb5Syz155240 		break;
201ab25eeb5Syz155240 	}
202ab25eeb5Syz155240 	SPL_X(s);
203ab25eeb5Syz155240 	return err;
204ab25eeb5Syz155240 }
205ab25eeb5Syz155240 
206ab25eeb5Syz155240 
207ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
208ab25eeb5Syz155240 /* Function:    iplookup_addnode                                            */
209ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
210ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
211ab25eeb5Syz155240 /*                                                                          */
212ab25eeb5Syz155240 /* Add a new data node to a lookup structure.  First, check to see if the   */
213ab25eeb5Syz155240 /* parent structure refered to by name exists and if it does, then go on to */
214ab25eeb5Syz155240 /* add a node to it.                                                        */
215ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
216f4b3ec61Sdh155122 static int iplookup_addnode(data, ifs)
217ab25eeb5Syz155240 caddr_t data;
218f4b3ec61Sdh155122 ipf_stack_t *ifs;
219ab25eeb5Syz155240 {
220ab25eeb5Syz155240 	ip_pool_node_t node, *m;
221ab25eeb5Syz155240 	iplookupop_t op;
222ab25eeb5Syz155240 	iphtable_t *iph;
223ab25eeb5Syz155240 	iphtent_t hte;
224ab25eeb5Syz155240 	ip_pool_t *p;
225ab25eeb5Syz155240 	int err;
226ab25eeb5Syz155240 
227*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
228*bb1d9de5SJohn Ojemann 	if (err != 0)
229*bb1d9de5SJohn Ojemann 		return EFAULT;
230*bb1d9de5SJohn Ojemann 
231ab25eeb5Syz155240 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
232ab25eeb5Syz155240 
233ab25eeb5Syz155240 	switch (op.iplo_type)
234ab25eeb5Syz155240 	{
235ab25eeb5Syz155240 	case IPLT_POOL :
236ab25eeb5Syz155240 		if (op.iplo_size != sizeof(node))
237ab25eeb5Syz155240 			return EINVAL;
238ab25eeb5Syz155240 
239ab25eeb5Syz155240 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
240ab25eeb5Syz155240 		if (err != 0)
241ab25eeb5Syz155240 			return EFAULT;
242ab25eeb5Syz155240 
243f4b3ec61Sdh155122 		p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs);
244ab25eeb5Syz155240 		if (p == NULL)
245ab25eeb5Syz155240 			return ESRCH;
246ab25eeb5Syz155240 
247ab25eeb5Syz155240 		/*
248ab25eeb5Syz155240 		 * add an entry to a pool - return an error if it already
249ab25eeb5Syz155240 		 * exists remove an entry from a pool - if it exists
250ab25eeb5Syz155240 		 * - in both cases, the pool *must* exist!
251ab25eeb5Syz155240 		 */
252ab25eeb5Syz155240 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
253ab25eeb5Syz155240 		if (m)
254ab25eeb5Syz155240 			return EEXIST;
255ab25eeb5Syz155240 		err = ip_pool_insert(p, &node.ipn_addr,
256f4b3ec61Sdh155122 				     &node.ipn_mask, node.ipn_info, ifs);
257ab25eeb5Syz155240 		break;
258ab25eeb5Syz155240 
259ab25eeb5Syz155240 	case IPLT_HASH :
260ab25eeb5Syz155240 		if (op.iplo_size != sizeof(hte))
261ab25eeb5Syz155240 			return EINVAL;
262ab25eeb5Syz155240 
263ab25eeb5Syz155240 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
264ab25eeb5Syz155240 		if (err != 0)
265ab25eeb5Syz155240 			return EFAULT;
266ab25eeb5Syz155240 
267f4b3ec61Sdh155122 		iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs);
268ab25eeb5Syz155240 		if (iph == NULL)
269ab25eeb5Syz155240 			return ESRCH;
270f4b3ec61Sdh155122 		err = fr_addhtent(iph, &hte, ifs);
271ab25eeb5Syz155240 		break;
272ab25eeb5Syz155240 
273ab25eeb5Syz155240 	default :
274ab25eeb5Syz155240 		err = EINVAL;
275ab25eeb5Syz155240 		break;
276ab25eeb5Syz155240 	}
277ab25eeb5Syz155240 	return err;
278ab25eeb5Syz155240 }
279ab25eeb5Syz155240 
280ab25eeb5Syz155240 
281ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
282ab25eeb5Syz155240 /* Function:    iplookup_delnode                                            */
283ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
284ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
285ab25eeb5Syz155240 /*                                                                          */
286ab25eeb5Syz155240 /* Delete a node from a lookup table by first looking for the table it is   */
287ab25eeb5Syz155240 /* in and then deleting the entry that gets found.                          */
288ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
289f4b3ec61Sdh155122 static int iplookup_delnode(data, ifs)
290ab25eeb5Syz155240 caddr_t data;
291f4b3ec61Sdh155122 ipf_stack_t *ifs;
292ab25eeb5Syz155240 {
293ab25eeb5Syz155240 	ip_pool_node_t node, *m;
294ab25eeb5Syz155240 	iplookupop_t op;
295ab25eeb5Syz155240 	iphtable_t *iph;
296ab25eeb5Syz155240 	iphtent_t hte;
297ab25eeb5Syz155240 	ip_pool_t *p;
298ab25eeb5Syz155240 	int err;
299ab25eeb5Syz155240 
300*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
301*bb1d9de5SJohn Ojemann 	if (err != 0)
302*bb1d9de5SJohn Ojemann 		return EFAULT;
303ab25eeb5Syz155240 
304ab25eeb5Syz155240 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
305ab25eeb5Syz155240 
306ab25eeb5Syz155240 	switch (op.iplo_type)
307ab25eeb5Syz155240 	{
308ab25eeb5Syz155240 	case IPLT_POOL :
309ab25eeb5Syz155240 		if (op.iplo_size != sizeof(node))
310ab25eeb5Syz155240 			return EINVAL;
311ab25eeb5Syz155240 
312ab25eeb5Syz155240 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
313ab25eeb5Syz155240 		if (err != 0)
314ab25eeb5Syz155240 			return EFAULT;
315ab25eeb5Syz155240 
316f4b3ec61Sdh155122 		p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs);
317ab25eeb5Syz155240 		if (!p)
318ab25eeb5Syz155240 			return ESRCH;
319ab25eeb5Syz155240 
320ab25eeb5Syz155240 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
321ab25eeb5Syz155240 		if (m == NULL)
322ab25eeb5Syz155240 			return ENOENT;
323f4b3ec61Sdh155122 		err = ip_pool_remove(p, m, ifs);
324ab25eeb5Syz155240 		break;
325ab25eeb5Syz155240 
326ab25eeb5Syz155240 	case IPLT_HASH :
327ab25eeb5Syz155240 		if (op.iplo_size != sizeof(hte))
328ab25eeb5Syz155240 			return EINVAL;
329ab25eeb5Syz155240 
330ab25eeb5Syz155240 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
331ab25eeb5Syz155240 		if (err != 0)
332ab25eeb5Syz155240 			return EFAULT;
333ab25eeb5Syz155240 
334f4b3ec61Sdh155122 		iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs);
335ab25eeb5Syz155240 		if (iph == NULL)
336ab25eeb5Syz155240 			return ESRCH;
337f4b3ec61Sdh155122 		err = fr_delhtent(iph, &hte, ifs);
338ab25eeb5Syz155240 		break;
339ab25eeb5Syz155240 
340ab25eeb5Syz155240 	default :
341ab25eeb5Syz155240 		err = EINVAL;
342ab25eeb5Syz155240 		break;
343ab25eeb5Syz155240 	}
344ab25eeb5Syz155240 	return err;
345ab25eeb5Syz155240 }
346ab25eeb5Syz155240 
347ab25eeb5Syz155240 
348ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
349ab25eeb5Syz155240 /* Function:    iplookup_addtable                                           */
350ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
351ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
352ab25eeb5Syz155240 /*                                                                          */
353ab25eeb5Syz155240 /* Create a new lookup table, if one doesn't already exist using the name   */
354ab25eeb5Syz155240 /* for this one.                                                            */
355ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
356f4b3ec61Sdh155122 static int iplookup_addtable(data, ifs)
357ab25eeb5Syz155240 caddr_t data;
358f4b3ec61Sdh155122 ipf_stack_t *ifs;
359ab25eeb5Syz155240 {
360ab25eeb5Syz155240 	iplookupop_t op;
361ab25eeb5Syz155240 	int err;
362ab25eeb5Syz155240 
363*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
364*bb1d9de5SJohn Ojemann 	if (err != 0)
365*bb1d9de5SJohn Ojemann 		return EFAULT;
366ab25eeb5Syz155240 
367ab25eeb5Syz155240 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
368ab25eeb5Syz155240 
369ab25eeb5Syz155240 	switch (op.iplo_type)
370ab25eeb5Syz155240 	{
371ab25eeb5Syz155240 	case IPLT_POOL :
372f4b3ec61Sdh155122 		if (ip_pool_find(op.iplo_unit, op.iplo_name, ifs) != NULL)
373ab25eeb5Syz155240 			err = EEXIST;
374ab25eeb5Syz155240 		else
375f4b3ec61Sdh155122 			err = ip_pool_create(&op, ifs);
376ab25eeb5Syz155240 		break;
377ab25eeb5Syz155240 
378ab25eeb5Syz155240 	case IPLT_HASH :
379f4b3ec61Sdh155122 		if (fr_findhtable(op.iplo_unit, op.iplo_name, ifs) != NULL)
380ab25eeb5Syz155240 			err = EEXIST;
381ab25eeb5Syz155240 		else
382f4b3ec61Sdh155122 			err = fr_newhtable(&op, ifs);
383ab25eeb5Syz155240 		break;
384ab25eeb5Syz155240 
385ab25eeb5Syz155240 	default :
386ab25eeb5Syz155240 		err = EINVAL;
387ab25eeb5Syz155240 		break;
388ab25eeb5Syz155240 	}
389ab25eeb5Syz155240 	return err;
390ab25eeb5Syz155240 }
391ab25eeb5Syz155240 
392ab25eeb5Syz155240 
393ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
394ab25eeb5Syz155240 /* Function:    iplookup_deltable                                           */
395ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
396ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
397ab25eeb5Syz155240 /*                                                                          */
398ab25eeb5Syz155240 /* Decodes ioctl request to remove a particular hash table or pool and      */
399ab25eeb5Syz155240 /* calls the relevant function to do the cleanup.                           */
400ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
401f4b3ec61Sdh155122 static int iplookup_deltable(data, ifs)
402ab25eeb5Syz155240 caddr_t data;
403f4b3ec61Sdh155122 ipf_stack_t *ifs;
404ab25eeb5Syz155240 {
405ab25eeb5Syz155240 	iplookupop_t op;
406ab25eeb5Syz155240 	int err;
407ab25eeb5Syz155240 
408*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
409*bb1d9de5SJohn Ojemann 	if (err != 0)
410*bb1d9de5SJohn Ojemann 		return EFAULT;
411*bb1d9de5SJohn Ojemann 
412ab25eeb5Syz155240 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
413ab25eeb5Syz155240 
414ab25eeb5Syz155240 	if (op.iplo_arg & IPLT_ANON)
415ab25eeb5Syz155240 		op.iplo_arg &= IPLT_ANON;
416ab25eeb5Syz155240 
417ab25eeb5Syz155240 	/*
418ab25eeb5Syz155240 	 * create a new pool - fail if one already exists with
419ab25eeb5Syz155240 	 * the same #
420ab25eeb5Syz155240 	 */
421ab25eeb5Syz155240 	switch (op.iplo_type)
422ab25eeb5Syz155240 	{
423ab25eeb5Syz155240 	case IPLT_POOL :
424f4b3ec61Sdh155122 		err = ip_pool_destroy(&op, ifs);
425ab25eeb5Syz155240 		break;
426ab25eeb5Syz155240 
427ab25eeb5Syz155240 	case IPLT_HASH :
428f4b3ec61Sdh155122 		err = fr_removehtable(&op, ifs);
429ab25eeb5Syz155240 		break;
430ab25eeb5Syz155240 
431ab25eeb5Syz155240 	default :
432ab25eeb5Syz155240 		err = EINVAL;
433ab25eeb5Syz155240 		break;
434ab25eeb5Syz155240 	}
435ab25eeb5Syz155240 	return err;
436ab25eeb5Syz155240 }
437ab25eeb5Syz155240 
438ab25eeb5Syz155240 
439ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
440ab25eeb5Syz155240 /* Function:    iplookup_stats                                              */
441ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
442ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
443ab25eeb5Syz155240 /*                                                                          */
444ab25eeb5Syz155240 /* Copy statistical information from inside the kernel back to user space.  */
445ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
446f4b3ec61Sdh155122 static int iplookup_stats(data, ifs)
447ab25eeb5Syz155240 caddr_t data;
448f4b3ec61Sdh155122 ipf_stack_t *ifs;
449ab25eeb5Syz155240 {
450ab25eeb5Syz155240 	iplookupop_t op;
451ab25eeb5Syz155240 	int err;
452ab25eeb5Syz155240 
453*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
454*bb1d9de5SJohn Ojemann 	if (err != 0)
455*bb1d9de5SJohn Ojemann 		return EFAULT;
456ab25eeb5Syz155240 
457ab25eeb5Syz155240 	switch (op.iplo_type)
458ab25eeb5Syz155240 	{
459ab25eeb5Syz155240 	case IPLT_POOL :
460f4b3ec61Sdh155122 		err = ip_pool_statistics(&op, ifs);
461ab25eeb5Syz155240 		break;
462ab25eeb5Syz155240 
463ab25eeb5Syz155240 	case IPLT_HASH :
464f4b3ec61Sdh155122 		err = fr_gethtablestat(&op, ifs);
465ab25eeb5Syz155240 		break;
466ab25eeb5Syz155240 
467ab25eeb5Syz155240 	default :
468ab25eeb5Syz155240 		err = EINVAL;
469ab25eeb5Syz155240 		break;
470ab25eeb5Syz155240 	}
471ab25eeb5Syz155240 	return err;
472ab25eeb5Syz155240 }
473ab25eeb5Syz155240 
474ab25eeb5Syz155240 
475ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
476ab25eeb5Syz155240 /* Function:    iplookup_flush                                              */
477ab25eeb5Syz155240 /* Returns:     int     - 0 = success, else error                           */
478ab25eeb5Syz155240 /* Parameters:  data(I) - pointer to data from ioctl call                   */
479ab25eeb5Syz155240 /*                                                                          */
480ab25eeb5Syz155240 /* A flush is called when we want to flush all the nodes from a particular  */
481ab25eeb5Syz155240 /* entry in the hash table/pool or want to remove all groups from those.    */
482ab25eeb5Syz155240 /* ------------------------------------------------------------------------ */
483f4b3ec61Sdh155122 static int iplookup_flush(data, ifs)
484ab25eeb5Syz155240 caddr_t data;
485f4b3ec61Sdh155122 ipf_stack_t *ifs;
486ab25eeb5Syz155240 {
487ab25eeb5Syz155240 	int err, unit, num, type;
488ab25eeb5Syz155240 	iplookupflush_t flush;
489ab25eeb5Syz155240 
490*bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &flush, sizeof(flush));
491*bb1d9de5SJohn Ojemann 	if (err != 0)
492*bb1d9de5SJohn Ojemann 		return EFAULT;
493ab25eeb5Syz155240 
494ab25eeb5Syz155240 	flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
495ab25eeb5Syz155240 
496ab25eeb5Syz155240 	unit = flush.iplf_unit;
497ab25eeb5Syz155240 	if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
498ab25eeb5Syz155240 		return EINVAL;
499ab25eeb5Syz155240 
500ab25eeb5Syz155240 	type = flush.iplf_type;
501ab25eeb5Syz155240 	err = EINVAL;
502ab25eeb5Syz155240 	num = 0;
503ab25eeb5Syz155240 
504ab25eeb5Syz155240 	if (type == IPLT_POOL || type == IPLT_ALL) {
505ab25eeb5Syz155240 		err = 0;
506f4b3ec61Sdh155122 		num = ip_pool_flush(&flush, ifs);
507ab25eeb5Syz155240 	}
508ab25eeb5Syz155240 
509ab25eeb5Syz155240 	if (type == IPLT_HASH  || type == IPLT_ALL) {
510ab25eeb5Syz155240 		err = 0;
511f4b3ec61Sdh155122 		num += fr_flushhtable(&flush, ifs);
512ab25eeb5Syz155240 	}
513ab25eeb5Syz155240 
514ab25eeb5Syz155240 	if (err == 0) {
515ab25eeb5Syz155240 		flush.iplf_count = num;
516ab25eeb5Syz155240 		err = COPYOUT(&flush, data, sizeof(flush));
517ab25eeb5Syz155240 	}
518ab25eeb5Syz155240 	return err;
519ab25eeb5Syz155240 }
520ab25eeb5Syz155240 
521ab25eeb5Syz155240 
522f4b3ec61Sdh155122 
523f4b3ec61Sdh155122 void ip_lookup_deref(type, ptr, ifs)
524ab25eeb5Syz155240 int type;
525ab25eeb5Syz155240 void *ptr;
526f4b3ec61Sdh155122 ipf_stack_t *ifs;
527ab25eeb5Syz155240 {
528ab25eeb5Syz155240 	if (ptr == NULL)
529ab25eeb5Syz155240 		return;
530ab25eeb5Syz155240 
531f4b3ec61Sdh155122 	WRITE_ENTER(&ifs->ifs_ip_poolrw);
532ab25eeb5Syz155240 	switch (type)
533ab25eeb5Syz155240 	{
534ab25eeb5Syz155240 	case IPLT_POOL :
535f4b3ec61Sdh155122 		ip_pool_deref(ptr, ifs);
536ab25eeb5Syz155240 		break;
537ab25eeb5Syz155240 
538ab25eeb5Syz155240 	case IPLT_HASH :
539f4b3ec61Sdh155122 		fr_derefhtable(ptr, ifs);
540ab25eeb5Syz155240 		break;
541ab25eeb5Syz155240 	}
542f4b3ec61Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
543f4b3ec61Sdh155122 }
544f4b3ec61Sdh155122 
545f4b3ec61Sdh155122 
546f4b3ec61Sdh155122 int ip_lookup_iterate(data, uid, ctx, ifs)
547f4b3ec61Sdh155122 void *data;
548f4b3ec61Sdh155122 int uid;
549f4b3ec61Sdh155122 void *ctx;
550f4b3ec61Sdh155122 ipf_stack_t *ifs;
551f4b3ec61Sdh155122 {
552f4b3ec61Sdh155122 	ipflookupiter_t iter;
553f4b3ec61Sdh155122 	ipftoken_t *token;
554f4b3ec61Sdh155122 	int err;
555f4b3ec61Sdh155122 
556f4b3ec61Sdh155122 	err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER);
557f4b3ec61Sdh155122 	if (err != 0) {
558f4b3ec61Sdh155122 #ifdef _KERNEL
559f4b3ec61Sdh155122 		(void) printf("fr_inobj\n");
560f4b3ec61Sdh155122 #endif
561f4b3ec61Sdh155122 		return err;
562f4b3ec61Sdh155122 	}
563f4b3ec61Sdh155122 
564f4b3ec61Sdh155122 	if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) {
565f4b3ec61Sdh155122 #ifdef _KERNEL
566f4b3ec61Sdh155122 		(void) printf("unit=%d\n", iter.ili_unit);
567f4b3ec61Sdh155122 #endif
568f4b3ec61Sdh155122 		return EINVAL;
569f4b3ec61Sdh155122 	}
570f4b3ec61Sdh155122 
571f4b3ec61Sdh155122 	if (iter.ili_ival != IPFGENITER_LOOKUP) {
572f4b3ec61Sdh155122 #ifdef _KERNEL
573f4b3ec61Sdh155122 		(void) printf("ival=%d\n", iter.ili_ival);
574f4b3ec61Sdh155122 #endif
575f4b3ec61Sdh155122 		return EINVAL;
576f4b3ec61Sdh155122 	}
577f4b3ec61Sdh155122 
578f4b3ec61Sdh155122 	token = ipf_findtoken(iter.ili_key, uid, ctx, ifs);
579f4b3ec61Sdh155122 	if (token == NULL) {
580f4b3ec61Sdh155122 		RWLOCK_EXIT(&ifs->ifs_ipf_tokens);
581f4b3ec61Sdh155122 		return ESRCH;
582f4b3ec61Sdh155122 	}
583f4b3ec61Sdh155122 
584f4b3ec61Sdh155122 	switch (iter.ili_type)
585f4b3ec61Sdh155122 	{
586f4b3ec61Sdh155122 	case IPLT_POOL :
587f4b3ec61Sdh155122 		err = ip_pool_getnext(token, &iter, ifs);
588f4b3ec61Sdh155122 		break;
589f4b3ec61Sdh155122 	case IPLT_HASH :
590f4b3ec61Sdh155122 		err = fr_htable_getnext(token, &iter, ifs);
591f4b3ec61Sdh155122 		break;
592f4b3ec61Sdh155122 	default :
593f4b3ec61Sdh155122 #ifdef _KERNEL
594f4b3ec61Sdh155122 		(void) printf("type=%d\n", iter.ili_type);
595f4b3ec61Sdh155122 #endif
596f4b3ec61Sdh155122 		err = EINVAL;
597f4b3ec61Sdh155122 		break;
598f4b3ec61Sdh155122 	}
599f4b3ec61Sdh155122 	RWLOCK_EXIT(&ifs->ifs_ipf_tokens);
600f4b3ec61Sdh155122 
601f4b3ec61Sdh155122 	return err;
602f4b3ec61Sdh155122 }
603f4b3ec61Sdh155122 
604f4b3ec61Sdh155122 
605f4b3ec61Sdh155122 void ip_lookup_iterderef(type, data, ifs)
606f4b3ec61Sdh155122 u_32_t type;
607f4b3ec61Sdh155122 void *data;
608f4b3ec61Sdh155122 ipf_stack_t *ifs;
609f4b3ec61Sdh155122 {
610f4b3ec61Sdh155122 	iplookupiterkey_t	key;
611f4b3ec61Sdh155122 
612f4b3ec61Sdh155122 	key.ilik_key = type;
613f4b3ec61Sdh155122 
614f4b3ec61Sdh155122 	if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP)
615f4b3ec61Sdh155122 		return;
616f4b3ec61Sdh155122 
617f4b3ec61Sdh155122 	switch (key.ilik_unstr.ilik_type)
618f4b3ec61Sdh155122 	{
619f4b3ec61Sdh155122 	case IPLT_HASH :
620f4b3ec61Sdh155122 		fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype,
621f4b3ec61Sdh155122 				    (int)key.ilik_unstr.ilik_unit, data, ifs);
622f4b3ec61Sdh155122 		break;
623f4b3ec61Sdh155122 	case IPLT_POOL :
624f4b3ec61Sdh155122 		ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype,
625f4b3ec61Sdh155122 				  (int)key.ilik_unstr.ilik_unit, data, ifs);
626f4b3ec61Sdh155122 		break;
627f4b3ec61Sdh155122 	}
628ab25eeb5Syz155240 }
629ab25eeb5Syz155240 
630ab25eeb5Syz155240 
631ab25eeb5Syz155240 #else /* IPFILTER_LOOKUP */
632ab25eeb5Syz155240 
633ab25eeb5Syz155240 /*ARGSUSED*/
634f4b3ec61Sdh155122 int ip_lookup_ioctl(data, cmd, mode, uid, ifs)
635ab25eeb5Syz155240 caddr_t data;
636ab25eeb5Syz155240 ioctlcmd_t cmd;
637f4b3ec61Sdh155122 int mode, uid;
638f4b3ec61Sdh155122 ipf_stack_t *ifs;
639ab25eeb5Syz155240 {
640ab25eeb5Syz155240 	return EIO;
641ab25eeb5Syz155240 }
642ab25eeb5Syz155240 #endif /* IPFILTER_LOOKUP */
643