17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 2002-2003 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
57c478bd9Sstevel@tonic-gate  *
6bb1d9de5SJohn Ojemann  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
117c478bd9Sstevel@tonic-gate # undef KERNEL
127c478bd9Sstevel@tonic-gate # undef _KERNEL
137c478bd9Sstevel@tonic-gate # define        KERNEL	1
147c478bd9Sstevel@tonic-gate # define        _KERNEL	1
157c478bd9Sstevel@tonic-gate #endif
16ab25eeb5Syz #if defined(__osf__)
17ab25eeb5Syz # define _PROTO_NET_H_
18ab25eeb5Syz #endif
197c478bd9Sstevel@tonic-gate #include <sys/param.h>
207c478bd9Sstevel@tonic-gate #include <sys/errno.h>
217c478bd9Sstevel@tonic-gate #include <sys/types.h>
227c478bd9Sstevel@tonic-gate #include <sys/time.h>
237c478bd9Sstevel@tonic-gate #include <sys/file.h>
247c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 220000 && defined(_KERNEL)
257c478bd9Sstevel@tonic-gate # include <sys/fcntl.h>
267c478bd9Sstevel@tonic-gate # include <sys/filio.h>
277c478bd9Sstevel@tonic-gate #else
287c478bd9Sstevel@tonic-gate # include <sys/ioctl.h>
297c478bd9Sstevel@tonic-gate #endif
307c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
317c478bd9Sstevel@tonic-gate # include <string.h>
327c478bd9Sstevel@tonic-gate # define _KERNEL
337c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
347c478bd9Sstevel@tonic-gate struct file;
357c478bd9Sstevel@tonic-gate # endif
367c478bd9Sstevel@tonic-gate # include <sys/uio.h>
377c478bd9Sstevel@tonic-gate # undef _KERNEL
387c478bd9Sstevel@tonic-gate #endif
397c478bd9Sstevel@tonic-gate #include <sys/socket.h>
40ab25eeb5Syz #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
41ab25eeb5Syz # ifdef __osf__
42ab25eeb5Syz #  include <net/radix.h>
43ab25eeb5Syz # endif
44ab25eeb5Syz # include "radix_ipf_local.h"
45ab25eeb5Syz # define _RADIX_H_
46ab25eeb5Syz #endif
477c478bd9Sstevel@tonic-gate #include <net/if.h>
487c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__)
497c478bd9Sstevel@tonic-gate #  include <sys/cdefs.h>
507c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
517c478bd9Sstevel@tonic-gate #endif
527c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
537c478bd9Sstevel@tonic-gate # include <sys/systm.h>
547c478bd9Sstevel@tonic-gate # if !defined(__SVR4) && !defined(__svr4__)
557c478bd9Sstevel@tonic-gate #  include <sys/mbuf.h>
567c478bd9Sstevel@tonic-gate # endif
577c478bd9Sstevel@tonic-gate #endif
587c478bd9Sstevel@tonic-gate #include <netinet/in.h>
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
617c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
627c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h"
637c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h"
647c478bd9Sstevel@tonic-gate #include "netinet/ip_lookup.h"
65f4b3ec61Sdh #include "netinet/ipf_stack.h"
66ab25eeb5Syz /* END OF INCLUDES */
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate #if !defined(lint)
69ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $";
707c478bd9Sstevel@tonic-gate #endif
717c478bd9Sstevel@tonic-gate 
727c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_LOOKUP
73f4b3ec61Sdh static int iplookup_addnode __P((caddr_t, ipf_stack_t *));
74f4b3ec61Sdh static int iplookup_delnode __P((caddr_t data, ipf_stack_t *));
75f4b3ec61Sdh static int iplookup_addtable __P((caddr_t, ipf_stack_t *));
76f4b3ec61Sdh static int iplookup_deltable __P((caddr_t, ipf_stack_t *));
77f4b3ec61Sdh static int iplookup_stats __P((caddr_t, ipf_stack_t *));
78f4b3ec61Sdh static int iplookup_flush __P((caddr_t, ipf_stack_t *));
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 
82ab25eeb5Syz /* ------------------------------------------------------------------------ */
83ab25eeb5Syz /* Function:    iplookup_init                                               */
84ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
85ab25eeb5Syz /* Parameters:  Nil                                                         */
86ab25eeb5Syz /*                                                                          */
87ab25eeb5Syz /* Initialise all of the subcomponents of the lookup infrstructure.         */
88ab25eeb5Syz /* ------------------------------------------------------------------------ */
ip_lookup_init(ifs)89f4b3ec61Sdh int ip_lookup_init(ifs)
90f4b3ec61Sdh ipf_stack_t *ifs;
917c478bd9Sstevel@tonic-gate {
92ab25eeb5Syz 
93f4b3ec61Sdh 	if (ip_pool_init(ifs) == -1)
947c478bd9Sstevel@tonic-gate 		return -1;
957c478bd9Sstevel@tonic-gate 
96f4b3ec61Sdh 	RWLOCK_INIT(&ifs->ifs_ip_poolrw, "ip pool rwlock");
977c478bd9Sstevel@tonic-gate 
98f4b3ec61Sdh 	ifs->ifs_ip_lookup_inited = 1;
99f4b3ec61Sdh 	ifs->ifs_ipftokenhead = NULL;
100f4b3ec61Sdh 	ifs->ifs_ipftokentail = &ifs->ifs_ipftokenhead;
1017c478bd9Sstevel@tonic-gate 	return 0;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
105ab25eeb5Syz /* ------------------------------------------------------------------------ */
106ab25eeb5Syz /* Function:    iplookup_unload                                             */
107ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
108ab25eeb5Syz /* Parameters:  Nil                                                         */
109ab25eeb5Syz /*                                                                          */
110ab25eeb5Syz /* Free up all pool related memory that has been allocated whilst IPFilter  */
111ab25eeb5Syz /* has been running.  Also, do any other deinitialisation required such     */
112ab25eeb5Syz /* ip_lookup_init() can be called again, safely.                            */
113ab25eeb5Syz /* ------------------------------------------------------------------------ */
ip_lookup_unload(ifs)114f4b3ec61Sdh void ip_lookup_unload(ifs)
115f4b3ec61Sdh ipf_stack_t *ifs;
1167c478bd9Sstevel@tonic-gate {
117f4b3ec61Sdh 	ip_pool_fini(ifs);
118f4b3ec61Sdh 	fr_htable_unload(ifs);
1197c478bd9Sstevel@tonic-gate 
120f4b3ec61Sdh 	if (ifs->ifs_ip_lookup_inited == 1) {
121f4b3ec61Sdh 		RW_DESTROY(&ifs->ifs_ip_poolrw);
122f4b3ec61Sdh 		ifs->ifs_ip_lookup_inited = 0;
1237c478bd9Sstevel@tonic-gate 	}
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate 
1267c478bd9Sstevel@tonic-gate 
127ab25eeb5Syz /* ------------------------------------------------------------------------ */
128ab25eeb5Syz /* Function:    iplookup_ioctl                                              */
129ab25eeb5Syz /* Returns:     int      - 0 = success, else error                          */
130ab25eeb5Syz /* Parameters:  data(IO) - pointer to ioctl data to be copied to/from user  */
131ab25eeb5Syz /*                         space.                                           */
132ab25eeb5Syz /*              cmd(I)   - ioctl command number                             */
133ab25eeb5Syz /*              mode(I)  - file mode bits used with open                    */
134ab25eeb5Syz /*                                                                          */
135ab25eeb5Syz /* Handle ioctl commands sent to the ioctl device.  For the most part, this */
136ab25eeb5Syz /* involves just calling another function to handle the specifics of each   */
137ab25eeb5Syz /* command.                                                                 */
138ab25eeb5Syz /* ------------------------------------------------------------------------ */
ip_lookup_ioctl(data,cmd,mode,uid,ctx,ifs)139f4b3ec61Sdh int ip_lookup_ioctl(data, cmd, mode, uid, ctx, ifs)
1407c478bd9Sstevel@tonic-gate caddr_t data;
141ab25eeb5Syz ioctlcmd_t cmd;
142f4b3ec61Sdh int mode, uid;
143f4b3ec61Sdh void *ctx;
144f4b3ec61Sdh ipf_stack_t *ifs;
1457c478bd9Sstevel@tonic-gate {
1467c478bd9Sstevel@tonic-gate 	int err;
147ab25eeb5Syz 	SPL_INT(s);
1487c478bd9Sstevel@tonic-gate 
1497c478bd9Sstevel@tonic-gate 	mode = mode;	/* LINT */
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	SPL_NET(s);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 	switch (cmd)
1547c478bd9Sstevel@tonic-gate 	{
1557c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPADDNODE :
156ab25eeb5Syz 	case SIOCLOOKUPADDNODEW :
157f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
158f4b3ec61Sdh 		err = iplookup_addnode(data, ifs);
159f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
1607c478bd9Sstevel@tonic-gate 		break;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPDELNODE :
163ab25eeb5Syz 	case SIOCLOOKUPDELNODEW :
164f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
165f4b3ec61Sdh 		err = iplookup_delnode(data, ifs);
166f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
1677c478bd9Sstevel@tonic-gate 		break;
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPADDTABLE :
170f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
171f4b3ec61Sdh 		err = iplookup_addtable(data, ifs);
172f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
1737c478bd9Sstevel@tonic-gate 		break;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPDELTABLE :
176f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
177f4b3ec61Sdh 		err = iplookup_deltable(data, ifs);
178f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
1797c478bd9Sstevel@tonic-gate 		break;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPSTAT :
182ab25eeb5Syz 	case SIOCLOOKUPSTATW :
183f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
184f4b3ec61Sdh 		err = iplookup_stats(data, ifs);
185f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
1867c478bd9Sstevel@tonic-gate 		break;
1877c478bd9Sstevel@tonic-gate 
1887c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPFLUSH :
189f4b3ec61Sdh 		WRITE_ENTER(&ifs->ifs_ip_poolrw);
190f4b3ec61Sdh 		err = iplookup_flush(data, ifs);
191f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
192f4b3ec61Sdh 		break;
193f4b3ec61Sdh 
194f4b3ec61Sdh 	case SIOCLOOKUPITER :
195f4b3ec61Sdh 		err = ip_lookup_iterate(data, uid, ctx, ifs);
1967c478bd9Sstevel@tonic-gate 		break;
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 	default :
1997c478bd9Sstevel@tonic-gate 		err = EINVAL;
2007c478bd9Sstevel@tonic-gate 		break;
2017c478bd9Sstevel@tonic-gate 	}
2027c478bd9Sstevel@tonic-gate 	SPL_X(s);
2037c478bd9Sstevel@tonic-gate 	return err;
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 
207ab25eeb5Syz /* ------------------------------------------------------------------------ */
208ab25eeb5Syz /* Function:    iplookup_addnode                                            */
209ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
210ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
211ab25eeb5Syz /*                                                                          */
212ab25eeb5Syz /* Add a new data node to a lookup structure.  First, check to see if the   */
213ab25eeb5Syz /* parent structure refered to by name exists and if it does, then go on to */
214ab25eeb5Syz /* add a node to it.                                                        */
215ab25eeb5Syz /* ------------------------------------------------------------------------ */
iplookup_addnode(data,ifs)216f4b3ec61Sdh static int iplookup_addnode(data, ifs)
2177c478bd9Sstevel@tonic-gate caddr_t data;
218f4b3ec61Sdh ipf_stack_t *ifs;
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	ip_pool_node_t node, *m;
2217c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2227c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2237c478bd9Sstevel@tonic-gate 	iphtent_t hte;
2247c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
2257c478bd9Sstevel@tonic-gate 	int err;
2267c478bd9Sstevel@tonic-gate 
227bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
228bb1d9de5SJohn Ojemann 	if (err != 0)
229bb1d9de5SJohn Ojemann 		return EFAULT;
230bb1d9de5SJohn Ojemann 
2317c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
2347c478bd9Sstevel@tonic-gate 	{
2357c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
2367c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(node))
2377c478bd9Sstevel@tonic-gate 			return EINVAL;
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
2407c478bd9Sstevel@tonic-gate 		if (err != 0)
2417c478bd9Sstevel@tonic-gate 			return EFAULT;
2427c478bd9Sstevel@tonic-gate 
243f4b3ec61Sdh 		p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs);
2447c478bd9Sstevel@tonic-gate 		if (p == NULL)
2457c478bd9Sstevel@tonic-gate 			return ESRCH;
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 		/*
2487c478bd9Sstevel@tonic-gate 		 * add an entry to a pool - return an error if it already
2497c478bd9Sstevel@tonic-gate 		 * exists remove an entry from a pool - if it exists
2507c478bd9Sstevel@tonic-gate 		 * - in both cases, the pool *must* exist!
2517c478bd9Sstevel@tonic-gate 		 */
2527663b816Sml 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
2537c478bd9Sstevel@tonic-gate 		if (m)
2547c478bd9Sstevel@tonic-gate 			return EEXIST;
2557663b816Sml 		err = ip_pool_insert(p, &node.ipn_addr,
256f4b3ec61Sdh 				     &node.ipn_mask, node.ipn_info, ifs);
2577c478bd9Sstevel@tonic-gate 		break;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
2607c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(hte))
2617c478bd9Sstevel@tonic-gate 			return EINVAL;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
2647c478bd9Sstevel@tonic-gate 		if (err != 0)
2657c478bd9Sstevel@tonic-gate 			return EFAULT;
2667c478bd9Sstevel@tonic-gate 
267f4b3ec61Sdh 		iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs);
2687c478bd9Sstevel@tonic-gate 		if (iph == NULL)
2697c478bd9Sstevel@tonic-gate 			return ESRCH;
270f4b3ec61Sdh 		err = fr_addhtent(iph, &hte, ifs);
2717c478bd9Sstevel@tonic-gate 		break;
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	default :
2747c478bd9Sstevel@tonic-gate 		err = EINVAL;
2757c478bd9Sstevel@tonic-gate 		break;
2767c478bd9Sstevel@tonic-gate 	}
2777c478bd9Sstevel@tonic-gate 	return err;
2787c478bd9Sstevel@tonic-gate }
2797c478bd9Sstevel@tonic-gate 
2807c478bd9Sstevel@tonic-gate 
281ab25eeb5Syz /* ------------------------------------------------------------------------ */
282ab25eeb5Syz /* Function:    iplookup_delnode                                            */
283ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
284ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
285ab25eeb5Syz /*                                                                          */
286ab25eeb5Syz /* Delete a node from a lookup table by first looking for the table it is   */
287ab25eeb5Syz /* in and then deleting the entry that gets found.                          */
288ab25eeb5Syz /* ------------------------------------------------------------------------ */
iplookup_delnode(data,ifs)289f4b3ec61Sdh static int iplookup_delnode(data, ifs)
2907c478bd9Sstevel@tonic-gate caddr_t data;
291f4b3ec61Sdh ipf_stack_t *ifs;
2927c478bd9Sstevel@tonic-gate {
2937c478bd9Sstevel@tonic-gate 	ip_pool_node_t node, *m;
2947c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2957c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2967c478bd9Sstevel@tonic-gate 	iphtent_t hte;
2977c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
2987c478bd9Sstevel@tonic-gate 	int err;
2997c478bd9Sstevel@tonic-gate 
300bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
301bb1d9de5SJohn Ojemann 	if (err != 0)
302bb1d9de5SJohn Ojemann 		return EFAULT;
303ab25eeb5Syz 
3047c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
3057c478bd9Sstevel@tonic-gate 
3067c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
3077c478bd9Sstevel@tonic-gate 	{
3087c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
3097c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(node))
3107c478bd9Sstevel@tonic-gate 			return EINVAL;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
3137c478bd9Sstevel@tonic-gate 		if (err != 0)
3147c478bd9Sstevel@tonic-gate 			return EFAULT;
3157c478bd9Sstevel@tonic-gate 
316f4b3ec61Sdh 		p = ip_pool_find(op.iplo_unit, op.iplo_name, ifs);
3177c478bd9Sstevel@tonic-gate 		if (!p)
3187c478bd9Sstevel@tonic-gate 			return ESRCH;
3197c478bd9Sstevel@tonic-gate 
3207663b816Sml 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
3217c478bd9Sstevel@tonic-gate 		if (m == NULL)
3227c478bd9Sstevel@tonic-gate 			return ENOENT;
323f4b3ec61Sdh 		err = ip_pool_remove(p, m, ifs);
3247c478bd9Sstevel@tonic-gate 		break;
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
3277c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(hte))
3287c478bd9Sstevel@tonic-gate 			return EINVAL;
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
3317c478bd9Sstevel@tonic-gate 		if (err != 0)
3327c478bd9Sstevel@tonic-gate 			return EFAULT;
3337c478bd9Sstevel@tonic-gate 
334f4b3ec61Sdh 		iph = fr_findhtable(op.iplo_unit, op.iplo_name, ifs);
3357c478bd9Sstevel@tonic-gate 		if (iph == NULL)
3367c478bd9Sstevel@tonic-gate 			return ESRCH;
337f4b3ec61Sdh 		err = fr_delhtent(iph, &hte, ifs);
3387c478bd9Sstevel@tonic-gate 		break;
3397c478bd9Sstevel@tonic-gate 
3407c478bd9Sstevel@tonic-gate 	default :
3417c478bd9Sstevel@tonic-gate 		err = EINVAL;
3427c478bd9Sstevel@tonic-gate 		break;
3437c478bd9Sstevel@tonic-gate 	}
3447c478bd9Sstevel@tonic-gate 	return err;
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 
348ab25eeb5Syz /* ------------------------------------------------------------------------ */
349ab25eeb5Syz /* Function:    iplookup_addtable                                           */
350ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
351ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
352ab25eeb5Syz /*                                                                          */
353ab25eeb5Syz /* Create a new lookup table, if one doesn't already exist using the name   */
354ab25eeb5Syz /* for this one.                                                            */
355ab25eeb5Syz /* ------------------------------------------------------------------------ */
iplookup_addtable(data,ifs)356f4b3ec61Sdh static int iplookup_addtable(data, ifs)
3577c478bd9Sstevel@tonic-gate caddr_t data;
358f4b3ec61Sdh ipf_stack_t *ifs;
3597c478bd9Sstevel@tonic-gate {
3607c478bd9Sstevel@tonic-gate 	iplookupop_t op;
3617c478bd9Sstevel@tonic-gate 	int err;
3627c478bd9Sstevel@tonic-gate 
363bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
364bb1d9de5SJohn Ojemann 	if (err != 0)
365bb1d9de5SJohn Ojemann 		return EFAULT;
366ab25eeb5Syz 
3677c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
3687c478bd9Sstevel@tonic-gate 
3697c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
3707c478bd9Sstevel@tonic-gate 	{
3717c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
372f4b3ec61Sdh 		if (ip_pool_find(op.iplo_unit, op.iplo_name, ifs) != NULL)
3737c478bd9Sstevel@tonic-gate 			err = EEXIST;
3747c478bd9Sstevel@tonic-gate 		else
375f4b3ec61Sdh 			err = ip_pool_create(&op, ifs);
3767c478bd9Sstevel@tonic-gate 		break;
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
379f4b3ec61Sdh 		if (fr_findhtable(op.iplo_unit, op.iplo_name, ifs) != NULL)
3807c478bd9Sstevel@tonic-gate 			err = EEXIST;
3817c478bd9Sstevel@tonic-gate 		else
382f4b3ec61Sdh 			err = fr_newhtable(&op, ifs);
3837c478bd9Sstevel@tonic-gate 		break;
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	default :
3867c478bd9Sstevel@tonic-gate 		err = EINVAL;
3877c478bd9Sstevel@tonic-gate 		break;
3887c478bd9Sstevel@tonic-gate 	}
3897c478bd9Sstevel@tonic-gate 	return err;
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3947c478bd9Sstevel@tonic-gate /* Function:    iplookup_deltable                                           */
3957c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3967c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
3977c478bd9Sstevel@tonic-gate /*                                                                          */
3987c478bd9Sstevel@tonic-gate /* Decodes ioctl request to remove a particular hash table or pool and      */
3997c478bd9Sstevel@tonic-gate /* calls the relevant function to do the cleanup.                           */
4007c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
iplookup_deltable(data,ifs)401f4b3ec61Sdh static int iplookup_deltable(data, ifs)
4027c478bd9Sstevel@tonic-gate caddr_t data;
403f4b3ec61Sdh ipf_stack_t *ifs;
4047c478bd9Sstevel@tonic-gate {
4057c478bd9Sstevel@tonic-gate 	iplookupop_t op;
4067c478bd9Sstevel@tonic-gate 	int err;
4077c478bd9Sstevel@tonic-gate 
408bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
409bb1d9de5SJohn Ojemann 	if (err != 0)
410bb1d9de5SJohn Ojemann 		return EFAULT;
411bb1d9de5SJohn Ojemann 
4127c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	if (op.iplo_arg & IPLT_ANON)
4157c478bd9Sstevel@tonic-gate 		op.iplo_arg &= IPLT_ANON;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	/*
4187c478bd9Sstevel@tonic-gate 	 * create a new pool - fail if one already exists with
4197c478bd9Sstevel@tonic-gate 	 * the same #
4207c478bd9Sstevel@tonic-gate 	 */
4217c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
4227c478bd9Sstevel@tonic-gate 	{
4237c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
424f4b3ec61Sdh 		err = ip_pool_destroy(&op, ifs);
4257c478bd9Sstevel@tonic-gate 		break;
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
428f4b3ec61Sdh 		err = fr_removehtable(&op, ifs);
4297c478bd9Sstevel@tonic-gate 		break;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	default :
4327c478bd9Sstevel@tonic-gate 		err = EINVAL;
4337c478bd9Sstevel@tonic-gate 		break;
4347c478bd9Sstevel@tonic-gate 	}
4357c478bd9Sstevel@tonic-gate 	return err;
4367c478bd9Sstevel@tonic-gate }
4377c478bd9Sstevel@tonic-gate 
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4407c478bd9Sstevel@tonic-gate /* Function:    iplookup_stats                                              */
4417c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4427c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
4437c478bd9Sstevel@tonic-gate /*                                                                          */
4447c478bd9Sstevel@tonic-gate /* Copy statistical information from inside the kernel back to user space.  */
4457c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
iplookup_stats(data,ifs)446f4b3ec61Sdh static int iplookup_stats(data, ifs)
4477c478bd9Sstevel@tonic-gate caddr_t data;
448f4b3ec61Sdh ipf_stack_t *ifs;
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate 	iplookupop_t op;
4517663b816Sml 	int err;
4527c478bd9Sstevel@tonic-gate 
453bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &op, sizeof(op));
454bb1d9de5SJohn Ojemann 	if (err != 0)
455bb1d9de5SJohn Ojemann 		return EFAULT;
4567c478bd9Sstevel@tonic-gate 
4577663b816Sml 	switch (op.iplo_type)
4587663b816Sml 	{
4597663b816Sml 	case IPLT_POOL :
460f4b3ec61Sdh 		err = ip_pool_statistics(&op, ifs);
4617663b816Sml 		break;
4627663b816Sml 
4637663b816Sml 	case IPLT_HASH :
464f4b3ec61Sdh 		err = fr_gethtablestat(&op, ifs);
4657663b816Sml 		break;
4667c478bd9Sstevel@tonic-gate 
4677663b816Sml 	default :
4687663b816Sml 		err = EINVAL;
4697663b816Sml 		break;
4707663b816Sml 	}
4717c478bd9Sstevel@tonic-gate 	return err;
4727c478bd9Sstevel@tonic-gate }
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4767c478bd9Sstevel@tonic-gate /* Function:    iplookup_flush                                              */
4777c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4787c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
4797c478bd9Sstevel@tonic-gate /*                                                                          */
4807c478bd9Sstevel@tonic-gate /* A flush is called when we want to flush all the nodes from a particular  */
4817c478bd9Sstevel@tonic-gate /* entry in the hash table/pool or want to remove all groups from those.    */
4827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
iplookup_flush(data,ifs)483f4b3ec61Sdh static int iplookup_flush(data, ifs)
4847c478bd9Sstevel@tonic-gate caddr_t data;
485f4b3ec61Sdh ipf_stack_t *ifs;
4867c478bd9Sstevel@tonic-gate {
487ab25eeb5Syz 	int err, unit, num, type;
488ab25eeb5Syz 	iplookupflush_t flush;
4897c478bd9Sstevel@tonic-gate 
490bb1d9de5SJohn Ojemann 	err = BCOPYIN(data, &flush, sizeof(flush));
491bb1d9de5SJohn Ojemann 	if (err != 0)
492bb1d9de5SJohn Ojemann 		return EFAULT;
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 	flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 	unit = flush.iplf_unit;
4977c478bd9Sstevel@tonic-gate 	if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
4987c478bd9Sstevel@tonic-gate 		return EINVAL;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	type = flush.iplf_type;
5017c478bd9Sstevel@tonic-gate 	err = EINVAL;
5027c478bd9Sstevel@tonic-gate 	num = 0;
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (type == IPLT_POOL || type == IPLT_ALL) {
5057c478bd9Sstevel@tonic-gate 		err = 0;
506f4b3ec61Sdh 		num = ip_pool_flush(&flush, ifs);
5077c478bd9Sstevel@tonic-gate 	}
5087c478bd9Sstevel@tonic-gate 
5097c478bd9Sstevel@tonic-gate 	if (type == IPLT_HASH  || type == IPLT_ALL) {
5107c478bd9Sstevel@tonic-gate 		err = 0;
511f4b3ec61Sdh 		num += fr_flushhtable(&flush, ifs);
5127c478bd9Sstevel@tonic-gate 	}
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 	if (err == 0) {
5157c478bd9Sstevel@tonic-gate 		flush.iplf_count = num;
5167c478bd9Sstevel@tonic-gate 		err = COPYOUT(&flush, data, sizeof(flush));
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 	return err;
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
522f4b3ec61Sdh 
ip_lookup_deref(type,ptr,ifs)523f4b3ec61Sdh void ip_lookup_deref(type, ptr, ifs)
5247c478bd9Sstevel@tonic-gate int type;
5257c478bd9Sstevel@tonic-gate void *ptr;
526f4b3ec61Sdh ipf_stack_t *ifs;
5277c478bd9Sstevel@tonic-gate {
5287c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5297c478bd9Sstevel@tonic-gate 		return;
5307c478bd9Sstevel@tonic-gate 
531f4b3ec61Sdh 	WRITE_ENTER(&ifs->ifs_ip_poolrw);
5327c478bd9Sstevel@tonic-gate 	switch (type)
5337c478bd9Sstevel@tonic-gate 	{
5347c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
535f4b3ec61Sdh 		ip_pool_deref(ptr, ifs);
536f4b3ec61Sdh 		break;
537f4b3ec61Sdh 
538f4b3ec61Sdh 	case IPLT_HASH :
539f4b3ec61Sdh 		fr_derefhtable(ptr, ifs);
540f4b3ec61Sdh 		break;
541f4b3ec61Sdh 	}
542f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ip_poolrw);
543f4b3ec61Sdh }
544f4b3ec61Sdh 
545*55fea89dSDan Cross 
ip_lookup_iterate(data,uid,ctx,ifs)546f4b3ec61Sdh int ip_lookup_iterate(data, uid, ctx, ifs)
547f4b3ec61Sdh void *data;
548f4b3ec61Sdh int uid;
549f4b3ec61Sdh void *ctx;
550f4b3ec61Sdh ipf_stack_t *ifs;
551f4b3ec61Sdh {
552f4b3ec61Sdh 	ipflookupiter_t iter;
553f4b3ec61Sdh 	ipftoken_t *token;
554f4b3ec61Sdh 	int err;
555f4b3ec61Sdh 
556f4b3ec61Sdh 	err = fr_inobj(data, &iter, IPFOBJ_LOOKUPITER);
557f4b3ec61Sdh 	if (err != 0) {
558f4b3ec61Sdh #ifdef _KERNEL
559f4b3ec61Sdh 		(void) printf("fr_inobj\n");
560f4b3ec61Sdh #endif
561f4b3ec61Sdh 		return err;
562f4b3ec61Sdh 	}
563f4b3ec61Sdh 
564f4b3ec61Sdh 	if (iter.ili_unit < 0 || iter.ili_unit > IPL_LOGMAX) {
565f4b3ec61Sdh #ifdef _KERNEL
566f4b3ec61Sdh 		(void) printf("unit=%d\n", iter.ili_unit);
567f4b3ec61Sdh #endif
568f4b3ec61Sdh 		return EINVAL;
569f4b3ec61Sdh 	}
570f4b3ec61Sdh 
571f4b3ec61Sdh 	if (iter.ili_ival != IPFGENITER_LOOKUP) {
572f4b3ec61Sdh #ifdef _KERNEL
573f4b3ec61Sdh 		(void) printf("ival=%d\n", iter.ili_ival);
574f4b3ec61Sdh #endif
575f4b3ec61Sdh 		return EINVAL;
576f4b3ec61Sdh 	}
577f4b3ec61Sdh 
578f4b3ec61Sdh 	token = ipf_findtoken(iter.ili_key, uid, ctx, ifs);
579f4b3ec61Sdh 	if (token == NULL) {
580f4b3ec61Sdh 		RWLOCK_EXIT(&ifs->ifs_ipf_tokens);
581f4b3ec61Sdh 		return ESRCH;
582f4b3ec61Sdh 	}
583f4b3ec61Sdh 
584f4b3ec61Sdh 	switch (iter.ili_type)
585f4b3ec61Sdh 	{
586f4b3ec61Sdh 	case IPLT_POOL :
587f4b3ec61Sdh 		err = ip_pool_getnext(token, &iter, ifs);
588f4b3ec61Sdh 		break;
589f4b3ec61Sdh 	case IPLT_HASH :
590f4b3ec61Sdh 		err = fr_htable_getnext(token, &iter, ifs);
591f4b3ec61Sdh 		break;
592f4b3ec61Sdh 	default :
593f4b3ec61Sdh #ifdef _KERNEL
594f4b3ec61Sdh 		(void) printf("type=%d\n", iter.ili_type);
595f4b3ec61Sdh #endif
596f4b3ec61Sdh 		err = EINVAL;
5977c478bd9Sstevel@tonic-gate 		break;
598f4b3ec61Sdh 	}
599f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ipf_tokens);
600ab25eeb5Syz 
601f4b3ec61Sdh 	return err;
602f4b3ec61Sdh }
603f4b3ec61Sdh 
604f4b3ec61Sdh 
ip_lookup_iterderef(type,data,ifs)605f4b3ec61Sdh void ip_lookup_iterderef(type, data, ifs)
606f4b3ec61Sdh u_32_t type;
607f4b3ec61Sdh void *data;
608f4b3ec61Sdh ipf_stack_t *ifs;
609f4b3ec61Sdh {
610f4b3ec61Sdh 	iplookupiterkey_t	key;
611f4b3ec61Sdh 
612f4b3ec61Sdh 	key.ilik_key = type;
613f4b3ec61Sdh 
614f4b3ec61Sdh 	if (key.ilik_unstr.ilik_ival != IPFGENITER_LOOKUP)
615f4b3ec61Sdh 		return;
616f4b3ec61Sdh 
617f4b3ec61Sdh 	switch (key.ilik_unstr.ilik_type)
618f4b3ec61Sdh 	{
6197c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
620f4b3ec61Sdh 		fr_htable_iterderef((u_int)key.ilik_unstr.ilik_otype,
621f4b3ec61Sdh 				    (int)key.ilik_unstr.ilik_unit, data, ifs);
622f4b3ec61Sdh 		break;
623f4b3ec61Sdh 	case IPLT_POOL :
624f4b3ec61Sdh 		ip_pool_iterderef((u_int)key.ilik_unstr.ilik_otype,
625f4b3ec61Sdh 				  (int)key.ilik_unstr.ilik_unit, data, ifs);
6267c478bd9Sstevel@tonic-gate 		break;
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate #else /* IPFILTER_LOOKUP */
6327c478bd9Sstevel@tonic-gate 
6337c478bd9Sstevel@tonic-gate /*ARGSUSED*/
ip_lookup_ioctl(data,cmd,mode,uid,ifs)634f4b3ec61Sdh int ip_lookup_ioctl(data, cmd, mode, uid, ifs)
6357c478bd9Sstevel@tonic-gate caddr_t data;
636ab25eeb5Syz ioctlcmd_t cmd;
637f4b3ec61Sdh int mode, uid;
638f4b3ec61Sdh ipf_stack_t *ifs;
6397c478bd9Sstevel@tonic-gate {
6407c478bd9Sstevel@tonic-gate 	return EIO;
6417c478bd9Sstevel@tonic-gate }
6427c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */
643