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  *
6*ab25eeb5Syz  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
117c478bd9Sstevel@tonic-gate 
127c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
137c478bd9Sstevel@tonic-gate # undef KERNEL
147c478bd9Sstevel@tonic-gate # undef _KERNEL
157c478bd9Sstevel@tonic-gate # define        KERNEL	1
167c478bd9Sstevel@tonic-gate # define        _KERNEL	1
177c478bd9Sstevel@tonic-gate #endif
18*ab25eeb5Syz #if defined(__osf__)
19*ab25eeb5Syz # define _PROTO_NET_H_
20*ab25eeb5Syz #endif
217c478bd9Sstevel@tonic-gate #include <sys/param.h>
227c478bd9Sstevel@tonic-gate #include <sys/errno.h>
237c478bd9Sstevel@tonic-gate #include <sys/types.h>
247c478bd9Sstevel@tonic-gate #include <sys/time.h>
257c478bd9Sstevel@tonic-gate #include <sys/file.h>
267c478bd9Sstevel@tonic-gate #if __FreeBSD_version >= 220000 && defined(_KERNEL)
277c478bd9Sstevel@tonic-gate # include <sys/fcntl.h>
287c478bd9Sstevel@tonic-gate # include <sys/filio.h>
297c478bd9Sstevel@tonic-gate #else
307c478bd9Sstevel@tonic-gate # include <sys/ioctl.h>
317c478bd9Sstevel@tonic-gate #endif
327c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
337c478bd9Sstevel@tonic-gate # include <string.h>
347c478bd9Sstevel@tonic-gate # define _KERNEL
357c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
367c478bd9Sstevel@tonic-gate struct file;
377c478bd9Sstevel@tonic-gate # endif
387c478bd9Sstevel@tonic-gate # include <sys/uio.h>
397c478bd9Sstevel@tonic-gate # undef _KERNEL
407c478bd9Sstevel@tonic-gate #endif
417c478bd9Sstevel@tonic-gate #include <sys/socket.h>
42*ab25eeb5Syz #if (defined(__osf__) || defined(AIX) || defined(__hpux) || defined(__sgi)) && defined(_KERNEL)
43*ab25eeb5Syz # ifdef __osf__
44*ab25eeb5Syz #  include <net/radix.h>
45*ab25eeb5Syz # endif
46*ab25eeb5Syz # include "radix_ipf_local.h"
47*ab25eeb5Syz # define _RADIX_H_
48*ab25eeb5Syz #endif
497c478bd9Sstevel@tonic-gate #include <net/if.h>
507c478bd9Sstevel@tonic-gate #if defined(__FreeBSD__)
517c478bd9Sstevel@tonic-gate #  include <sys/cdefs.h>
527c478bd9Sstevel@tonic-gate #  include <sys/proc.h>
537c478bd9Sstevel@tonic-gate #endif
547c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
557c478bd9Sstevel@tonic-gate # include <sys/systm.h>
567c478bd9Sstevel@tonic-gate # if !defined(__SVR4) && !defined(__svr4__)
577c478bd9Sstevel@tonic-gate #  include <sys/mbuf.h>
587c478bd9Sstevel@tonic-gate # endif
597c478bd9Sstevel@tonic-gate #endif
607c478bd9Sstevel@tonic-gate #include <netinet/in.h>
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
637c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
647c478bd9Sstevel@tonic-gate #include "netinet/ip_pool.h"
657c478bd9Sstevel@tonic-gate #include "netinet/ip_htable.h"
667c478bd9Sstevel@tonic-gate #include "netinet/ip_lookup.h"
67*ab25eeb5Syz /* END OF INCLUDES */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate #if !defined(lint)
70*ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_lookup.c,v 2.35.2.7 2005/06/12 07:18:20 darrenr Exp $";
717c478bd9Sstevel@tonic-gate #endif
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate #ifdef	IPFILTER_LOOKUP
747c478bd9Sstevel@tonic-gate int	ip_lookup_inited = 0;
757c478bd9Sstevel@tonic-gate 
767c478bd9Sstevel@tonic-gate static int iplookup_addnode __P((caddr_t));
777c478bd9Sstevel@tonic-gate static int iplookup_delnode __P((caddr_t data));
787c478bd9Sstevel@tonic-gate static int iplookup_addtable __P((caddr_t));
797c478bd9Sstevel@tonic-gate static int iplookup_deltable __P((caddr_t));
807c478bd9Sstevel@tonic-gate static int iplookup_stats __P((caddr_t));
817c478bd9Sstevel@tonic-gate static int iplookup_flush __P((caddr_t));
827c478bd9Sstevel@tonic-gate 
837c478bd9Sstevel@tonic-gate 
84*ab25eeb5Syz /* ------------------------------------------------------------------------ */
85*ab25eeb5Syz /* Function:    iplookup_init                                               */
86*ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
87*ab25eeb5Syz /* Parameters:  Nil                                                         */
88*ab25eeb5Syz /*                                                                          */
89*ab25eeb5Syz /* Initialise all of the subcomponents of the lookup infrstructure.         */
90*ab25eeb5Syz /* ------------------------------------------------------------------------ */
917c478bd9Sstevel@tonic-gate int ip_lookup_init()
927c478bd9Sstevel@tonic-gate {
93*ab25eeb5Syz 
947c478bd9Sstevel@tonic-gate 	if (ip_pool_init() == -1)
957c478bd9Sstevel@tonic-gate 		return -1;
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate 	RWLOCK_INIT(&ip_poolrw, "ip pool rwlock");
987c478bd9Sstevel@tonic-gate 
997c478bd9Sstevel@tonic-gate 	ip_lookup_inited = 1;
1007c478bd9Sstevel@tonic-gate 
1017c478bd9Sstevel@tonic-gate 	return 0;
1027c478bd9Sstevel@tonic-gate }
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 
105*ab25eeb5Syz /* ------------------------------------------------------------------------ */
106*ab25eeb5Syz /* Function:    iplookup_unload                                             */
107*ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
108*ab25eeb5Syz /* Parameters:  Nil                                                         */
109*ab25eeb5Syz /*                                                                          */
110*ab25eeb5Syz /* Free up all pool related memory that has been allocated whilst IPFilter  */
111*ab25eeb5Syz /* has been running.  Also, do any other deinitialisation required such     */
112*ab25eeb5Syz /* ip_lookup_init() can be called again, safely.                            */
113*ab25eeb5Syz /* ------------------------------------------------------------------------ */
1147c478bd9Sstevel@tonic-gate void ip_lookup_unload()
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	ip_pool_fini();
1177c478bd9Sstevel@tonic-gate 	fr_htable_unload();
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	if (ip_lookup_inited == 1) {
1207c478bd9Sstevel@tonic-gate 		RW_DESTROY(&ip_poolrw);
1217c478bd9Sstevel@tonic-gate 		ip_lookup_inited = 0;
1227c478bd9Sstevel@tonic-gate 	}
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 
126*ab25eeb5Syz /* ------------------------------------------------------------------------ */
127*ab25eeb5Syz /* Function:    iplookup_ioctl                                              */
128*ab25eeb5Syz /* Returns:     int      - 0 = success, else error                          */
129*ab25eeb5Syz /* Parameters:  data(IO) - pointer to ioctl data to be copied to/from user  */
130*ab25eeb5Syz /*                         space.                                           */
131*ab25eeb5Syz /*              cmd(I)   - ioctl command number                             */
132*ab25eeb5Syz /*              mode(I)  - file mode bits used with open                    */
133*ab25eeb5Syz /*                                                                          */
134*ab25eeb5Syz /* Handle ioctl commands sent to the ioctl device.  For the most part, this */
135*ab25eeb5Syz /* involves just calling another function to handle the specifics of each   */
136*ab25eeb5Syz /* command.                                                                 */
137*ab25eeb5Syz /* ------------------------------------------------------------------------ */
1387c478bd9Sstevel@tonic-gate int ip_lookup_ioctl(data, cmd, mode)
1397c478bd9Sstevel@tonic-gate caddr_t data;
140*ab25eeb5Syz ioctlcmd_t cmd;
1417c478bd9Sstevel@tonic-gate int mode;
1427c478bd9Sstevel@tonic-gate {
1437c478bd9Sstevel@tonic-gate 	int err;
144*ab25eeb5Syz 	SPL_INT(s);
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	mode = mode;	/* LINT */
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 	SPL_NET(s);
1497c478bd9Sstevel@tonic-gate 
1507c478bd9Sstevel@tonic-gate 	switch (cmd)
1517c478bd9Sstevel@tonic-gate 	{
1527c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPADDNODE :
153*ab25eeb5Syz 	case SIOCLOOKUPADDNODEW :
1547c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1557c478bd9Sstevel@tonic-gate 		err = iplookup_addnode(data);
1567c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1577c478bd9Sstevel@tonic-gate 		break;
1587c478bd9Sstevel@tonic-gate 
1597c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPDELNODE :
160*ab25eeb5Syz 	case SIOCLOOKUPDELNODEW :
1617c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1627c478bd9Sstevel@tonic-gate 		err = iplookup_delnode(data);
1637c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1647c478bd9Sstevel@tonic-gate 		break;
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPADDTABLE :
1677c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1687c478bd9Sstevel@tonic-gate 		err = iplookup_addtable(data);
1697c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1707c478bd9Sstevel@tonic-gate 		break;
1717c478bd9Sstevel@tonic-gate 
1727c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPDELTABLE :
1737c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1747c478bd9Sstevel@tonic-gate 		err = iplookup_deltable(data);
1757c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1767c478bd9Sstevel@tonic-gate 		break;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPSTAT :
179*ab25eeb5Syz 	case SIOCLOOKUPSTATW :
1807c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1817c478bd9Sstevel@tonic-gate 		err = iplookup_stats(data);
1827c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1837c478bd9Sstevel@tonic-gate 		break;
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 	case SIOCLOOKUPFLUSH :
1867c478bd9Sstevel@tonic-gate 		WRITE_ENTER(&ip_poolrw);
1877c478bd9Sstevel@tonic-gate 		err = iplookup_flush(data);
1887c478bd9Sstevel@tonic-gate 		RWLOCK_EXIT(&ip_poolrw);
1897c478bd9Sstevel@tonic-gate 		break;
1907c478bd9Sstevel@tonic-gate 
1917c478bd9Sstevel@tonic-gate 	default :
1927c478bd9Sstevel@tonic-gate 		err = EINVAL;
1937c478bd9Sstevel@tonic-gate 		break;
1947c478bd9Sstevel@tonic-gate 	}
1957c478bd9Sstevel@tonic-gate 	SPL_X(s);
1967c478bd9Sstevel@tonic-gate 	return err;
1977c478bd9Sstevel@tonic-gate }
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 
200*ab25eeb5Syz /* ------------------------------------------------------------------------ */
201*ab25eeb5Syz /* Function:    iplookup_addnode                                            */
202*ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
203*ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
204*ab25eeb5Syz /*                                                                          */
205*ab25eeb5Syz /* Add a new data node to a lookup structure.  First, check to see if the   */
206*ab25eeb5Syz /* parent structure refered to by name exists and if it does, then go on to */
207*ab25eeb5Syz /* add a node to it.                                                        */
208*ab25eeb5Syz /* ------------------------------------------------------------------------ */
2097c478bd9Sstevel@tonic-gate static int iplookup_addnode(data)
2107c478bd9Sstevel@tonic-gate caddr_t data;
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	ip_pool_node_t node, *m;
2137c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2147c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2157c478bd9Sstevel@tonic-gate 	iphtent_t hte;
2167c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
2177c478bd9Sstevel@tonic-gate 	int err;
2187c478bd9Sstevel@tonic-gate 
219*ab25eeb5Syz 	err = 0;
220*ab25eeb5Syz 	BCOPYIN(data, &op, sizeof(op));
2217c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
2247c478bd9Sstevel@tonic-gate 	{
2257c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
2267c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(node))
2277c478bd9Sstevel@tonic-gate 			return EINVAL;
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
2307c478bd9Sstevel@tonic-gate 		if (err != 0)
2317c478bd9Sstevel@tonic-gate 			return EFAULT;
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate 		p = ip_pool_find(op.iplo_unit, op.iplo_name);
2347c478bd9Sstevel@tonic-gate 		if (p == NULL)
2357c478bd9Sstevel@tonic-gate 			return ESRCH;
2367c478bd9Sstevel@tonic-gate 
2377c478bd9Sstevel@tonic-gate 		/*
2387c478bd9Sstevel@tonic-gate 		 * add an entry to a pool - return an error if it already
2397c478bd9Sstevel@tonic-gate 		 * exists remove an entry from a pool - if it exists
2407c478bd9Sstevel@tonic-gate 		 * - in both cases, the pool *must* exist!
2417c478bd9Sstevel@tonic-gate 		 */
2427663b816Sml 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
2437c478bd9Sstevel@tonic-gate 		if (m)
2447c478bd9Sstevel@tonic-gate 			return EEXIST;
2457663b816Sml 		err = ip_pool_insert(p, &node.ipn_addr,
2467663b816Sml 				     &node.ipn_mask, node.ipn_info);
2477c478bd9Sstevel@tonic-gate 		break;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
2507c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(hte))
2517c478bd9Sstevel@tonic-gate 			return EINVAL;
2527c478bd9Sstevel@tonic-gate 
2537c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
2547c478bd9Sstevel@tonic-gate 		if (err != 0)
2557c478bd9Sstevel@tonic-gate 			return EFAULT;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 		iph = fr_findhtable(op.iplo_unit, op.iplo_name);
2587c478bd9Sstevel@tonic-gate 		if (iph == NULL)
2597c478bd9Sstevel@tonic-gate 			return ESRCH;
2607c478bd9Sstevel@tonic-gate 		err = fr_addhtent(iph, &hte);
2617c478bd9Sstevel@tonic-gate 		break;
2627c478bd9Sstevel@tonic-gate 
2637c478bd9Sstevel@tonic-gate 	default :
2647c478bd9Sstevel@tonic-gate 		err = EINVAL;
2657c478bd9Sstevel@tonic-gate 		break;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate 	return err;
2687c478bd9Sstevel@tonic-gate }
2697c478bd9Sstevel@tonic-gate 
2707c478bd9Sstevel@tonic-gate 
271*ab25eeb5Syz /* ------------------------------------------------------------------------ */
272*ab25eeb5Syz /* Function:    iplookup_delnode                                            */
273*ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
274*ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
275*ab25eeb5Syz /*                                                                          */
276*ab25eeb5Syz /* Delete a node from a lookup table by first looking for the table it is   */
277*ab25eeb5Syz /* in and then deleting the entry that gets found.                          */
278*ab25eeb5Syz /* ------------------------------------------------------------------------ */
2797c478bd9Sstevel@tonic-gate static int iplookup_delnode(data)
2807c478bd9Sstevel@tonic-gate caddr_t data;
2817c478bd9Sstevel@tonic-gate {
2827c478bd9Sstevel@tonic-gate 	ip_pool_node_t node, *m;
2837c478bd9Sstevel@tonic-gate 	iplookupop_t op;
2847c478bd9Sstevel@tonic-gate 	iphtable_t *iph;
2857c478bd9Sstevel@tonic-gate 	iphtent_t hte;
2867c478bd9Sstevel@tonic-gate 	ip_pool_t *p;
2877c478bd9Sstevel@tonic-gate 	int err;
2887c478bd9Sstevel@tonic-gate 
289*ab25eeb5Syz 	err = 0;
290*ab25eeb5Syz 	BCOPYIN(data, &op, sizeof(op));
291*ab25eeb5Syz 
2927c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
2957c478bd9Sstevel@tonic-gate 	{
2967c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
2977c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(node))
2987c478bd9Sstevel@tonic-gate 			return EINVAL;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &node, sizeof(node));
3017c478bd9Sstevel@tonic-gate 		if (err != 0)
3027c478bd9Sstevel@tonic-gate 			return EFAULT;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 		p = ip_pool_find(op.iplo_unit, op.iplo_name);
3057c478bd9Sstevel@tonic-gate 		if (!p)
3067c478bd9Sstevel@tonic-gate 			return ESRCH;
3077c478bd9Sstevel@tonic-gate 
3087663b816Sml 		m = ip_pool_findeq(p, &node.ipn_addr, &node.ipn_mask);
3097c478bd9Sstevel@tonic-gate 		if (m == NULL)
3107c478bd9Sstevel@tonic-gate 			return ENOENT;
3117c478bd9Sstevel@tonic-gate 		err = ip_pool_remove(p, m);
3127c478bd9Sstevel@tonic-gate 		break;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
3157c478bd9Sstevel@tonic-gate 		if (op.iplo_size != sizeof(hte))
3167c478bd9Sstevel@tonic-gate 			return EINVAL;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 		err = COPYIN(op.iplo_struct, &hte, sizeof(hte));
3197c478bd9Sstevel@tonic-gate 		if (err != 0)
3207c478bd9Sstevel@tonic-gate 			return EFAULT;
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 		iph = fr_findhtable(op.iplo_unit, op.iplo_name);
3237c478bd9Sstevel@tonic-gate 		if (iph == NULL)
3247c478bd9Sstevel@tonic-gate 			return ESRCH;
3257c478bd9Sstevel@tonic-gate 		err = fr_delhtent(iph, &hte);
3267c478bd9Sstevel@tonic-gate 		break;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 	default :
3297c478bd9Sstevel@tonic-gate 		err = EINVAL;
3307c478bd9Sstevel@tonic-gate 		break;
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 	return err;
3337c478bd9Sstevel@tonic-gate }
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 
336*ab25eeb5Syz /* ------------------------------------------------------------------------ */
337*ab25eeb5Syz /* Function:    iplookup_addtable                                           */
338*ab25eeb5Syz /* Returns:     int     - 0 = success, else error                           */
339*ab25eeb5Syz /* Parameters:  data(I) - pointer to data from ioctl call                   */
340*ab25eeb5Syz /*                                                                          */
341*ab25eeb5Syz /* Create a new lookup table, if one doesn't already exist using the name   */
342*ab25eeb5Syz /* for this one.                                                            */
343*ab25eeb5Syz /* ------------------------------------------------------------------------ */
3447c478bd9Sstevel@tonic-gate static int iplookup_addtable(data)
3457c478bd9Sstevel@tonic-gate caddr_t data;
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	iplookupop_t op;
3487c478bd9Sstevel@tonic-gate 	int err;
3497c478bd9Sstevel@tonic-gate 
350*ab25eeb5Syz 	err = 0;
351*ab25eeb5Syz 	BCOPYIN(data, &op, sizeof(op));
352*ab25eeb5Syz 
3537c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
3547c478bd9Sstevel@tonic-gate 
3557c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
3567c478bd9Sstevel@tonic-gate 	{
3577c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
3587c478bd9Sstevel@tonic-gate 		if (ip_pool_find(op.iplo_unit, op.iplo_name) != NULL)
3597c478bd9Sstevel@tonic-gate 			err = EEXIST;
3607c478bd9Sstevel@tonic-gate 		else
3617c478bd9Sstevel@tonic-gate 			err = ip_pool_create(&op);
3627c478bd9Sstevel@tonic-gate 		break;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
3657c478bd9Sstevel@tonic-gate 		if (fr_findhtable(op.iplo_unit, op.iplo_name) != NULL)
3667c478bd9Sstevel@tonic-gate 			err = EEXIST;
3677c478bd9Sstevel@tonic-gate 		else
3687c478bd9Sstevel@tonic-gate 			err = fr_newhtable(&op);
3697c478bd9Sstevel@tonic-gate 		break;
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	default :
3727c478bd9Sstevel@tonic-gate 		err = EINVAL;
3737c478bd9Sstevel@tonic-gate 		break;
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 	return err;
3767c478bd9Sstevel@tonic-gate }
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 
3797c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3807c478bd9Sstevel@tonic-gate /* Function:    iplookup_deltable                                           */
3817c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
3827c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
3837c478bd9Sstevel@tonic-gate /*                                                                          */
3847c478bd9Sstevel@tonic-gate /* Decodes ioctl request to remove a particular hash table or pool and      */
3857c478bd9Sstevel@tonic-gate /* calls the relevant function to do the cleanup.                           */
3867c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3877c478bd9Sstevel@tonic-gate static int iplookup_deltable(data)
3887c478bd9Sstevel@tonic-gate caddr_t data;
3897c478bd9Sstevel@tonic-gate {
3907c478bd9Sstevel@tonic-gate 	iplookupop_t op;
3917c478bd9Sstevel@tonic-gate 	int err;
3927c478bd9Sstevel@tonic-gate 
393*ab25eeb5Syz 	BCOPYIN(data, &op, sizeof(op));
3947c478bd9Sstevel@tonic-gate 	op.iplo_name[sizeof(op.iplo_name) - 1] = '\0';
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	if (op.iplo_arg & IPLT_ANON)
3977c478bd9Sstevel@tonic-gate 		op.iplo_arg &= IPLT_ANON;
3987c478bd9Sstevel@tonic-gate 
3997c478bd9Sstevel@tonic-gate 	/*
4007c478bd9Sstevel@tonic-gate 	 * create a new pool - fail if one already exists with
4017c478bd9Sstevel@tonic-gate 	 * the same #
4027c478bd9Sstevel@tonic-gate 	 */
4037c478bd9Sstevel@tonic-gate 	switch (op.iplo_type)
4047c478bd9Sstevel@tonic-gate 	{
4057c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
4067c478bd9Sstevel@tonic-gate 		err = ip_pool_destroy(&op);
4077c478bd9Sstevel@tonic-gate 		break;
4087c478bd9Sstevel@tonic-gate 
4097c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
4107c478bd9Sstevel@tonic-gate 		err = fr_removehtable(&op);
4117c478bd9Sstevel@tonic-gate 		break;
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 	default :
4147c478bd9Sstevel@tonic-gate 		err = EINVAL;
4157c478bd9Sstevel@tonic-gate 		break;
4167c478bd9Sstevel@tonic-gate 	}
4177c478bd9Sstevel@tonic-gate 	return err;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 
4217c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4227c478bd9Sstevel@tonic-gate /* Function:    iplookup_stats                                              */
4237c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4247c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
4257c478bd9Sstevel@tonic-gate /*                                                                          */
4267c478bd9Sstevel@tonic-gate /* Copy statistical information from inside the kernel back to user space.  */
4277c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4287c478bd9Sstevel@tonic-gate static int iplookup_stats(data)
4297c478bd9Sstevel@tonic-gate caddr_t data;
4307c478bd9Sstevel@tonic-gate {
4317c478bd9Sstevel@tonic-gate 	iplookupop_t op;
4327663b816Sml 	int err;
4337c478bd9Sstevel@tonic-gate 
4347663b816Sml 	err = 0;
435*ab25eeb5Syz 	BCOPYIN(data, &op, sizeof(op));
4367c478bd9Sstevel@tonic-gate 
4377663b816Sml 	switch (op.iplo_type)
4387663b816Sml 	{
4397663b816Sml 	case IPLT_POOL :
4407663b816Sml 		err = ip_pool_statistics(&op);
4417663b816Sml 		break;
4427663b816Sml 
4437663b816Sml 	case IPLT_HASH :
4447663b816Sml 		err = fr_gethtablestat(&op);
4457663b816Sml 		break;
4467c478bd9Sstevel@tonic-gate 
4477663b816Sml 	default :
4487663b816Sml 		err = EINVAL;
4497663b816Sml 		break;
4507663b816Sml 	}
4517c478bd9Sstevel@tonic-gate 	return err;
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4567c478bd9Sstevel@tonic-gate /* Function:    iplookup_flush                                              */
4577c478bd9Sstevel@tonic-gate /* Returns:     int     - 0 = success, else error                           */
4587c478bd9Sstevel@tonic-gate /* Parameters:  data(I) - pointer to data from ioctl call                   */
4597c478bd9Sstevel@tonic-gate /*                                                                          */
4607c478bd9Sstevel@tonic-gate /* A flush is called when we want to flush all the nodes from a particular  */
4617c478bd9Sstevel@tonic-gate /* entry in the hash table/pool or want to remove all groups from those.    */
4627c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4637c478bd9Sstevel@tonic-gate static int iplookup_flush(data)
4647c478bd9Sstevel@tonic-gate caddr_t data;
4657c478bd9Sstevel@tonic-gate {
466*ab25eeb5Syz 	int err, unit, num, type;
467*ab25eeb5Syz 	iplookupflush_t flush;
4687c478bd9Sstevel@tonic-gate 
469*ab25eeb5Syz 	err = 0;
470*ab25eeb5Syz 	BCOPYIN(data, &flush, sizeof(flush));
4717c478bd9Sstevel@tonic-gate 
4727c478bd9Sstevel@tonic-gate 	flush.iplf_name[sizeof(flush.iplf_name) - 1] = '\0';
4737c478bd9Sstevel@tonic-gate 
4747c478bd9Sstevel@tonic-gate 	unit = flush.iplf_unit;
4757c478bd9Sstevel@tonic-gate 	if ((unit < 0 || unit > IPL_LOGMAX) && (unit != IPLT_ALL))
4767c478bd9Sstevel@tonic-gate 		return EINVAL;
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	type = flush.iplf_type;
4797c478bd9Sstevel@tonic-gate 	err = EINVAL;
4807c478bd9Sstevel@tonic-gate 	num = 0;
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate 	if (type == IPLT_POOL || type == IPLT_ALL) {
4837c478bd9Sstevel@tonic-gate 		err = 0;
484*ab25eeb5Syz 		num = ip_pool_flush(&flush);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 	if (type == IPLT_HASH  || type == IPLT_ALL) {
4887c478bd9Sstevel@tonic-gate 		err = 0;
489*ab25eeb5Syz 		num += fr_flushhtable(&flush);
4907c478bd9Sstevel@tonic-gate 	}
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 	if (err == 0) {
4937c478bd9Sstevel@tonic-gate 		flush.iplf_count = num;
4947c478bd9Sstevel@tonic-gate 		err = COPYOUT(&flush, data, sizeof(flush));
4957c478bd9Sstevel@tonic-gate 	}
4967c478bd9Sstevel@tonic-gate 	return err;
4977c478bd9Sstevel@tonic-gate }
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate void ip_lookup_deref(type, ptr)
5017c478bd9Sstevel@tonic-gate int type;
5027c478bd9Sstevel@tonic-gate void *ptr;
5037c478bd9Sstevel@tonic-gate {
5047c478bd9Sstevel@tonic-gate 	if (ptr == NULL)
5057c478bd9Sstevel@tonic-gate 		return;
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate 	WRITE_ENTER(&ip_poolrw);
5087c478bd9Sstevel@tonic-gate 	switch (type)
5097c478bd9Sstevel@tonic-gate 	{
5107c478bd9Sstevel@tonic-gate 	case IPLT_POOL :
5117c478bd9Sstevel@tonic-gate 		ip_pool_deref(ptr);
5127c478bd9Sstevel@tonic-gate 		break;
513*ab25eeb5Syz 
5147c478bd9Sstevel@tonic-gate 	case IPLT_HASH :
5157c478bd9Sstevel@tonic-gate 		fr_derefhtable(ptr);
5167c478bd9Sstevel@tonic-gate 		break;
5177c478bd9Sstevel@tonic-gate 	}
5187c478bd9Sstevel@tonic-gate 	RWLOCK_EXIT(&ip_poolrw);
5197c478bd9Sstevel@tonic-gate }
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate #else /* IPFILTER_LOOKUP */
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate /*ARGSUSED*/
5257c478bd9Sstevel@tonic-gate int ip_lookup_ioctl(data, cmd, mode)
5267c478bd9Sstevel@tonic-gate caddr_t data;
527*ab25eeb5Syz ioctlcmd_t cmd;
5287c478bd9Sstevel@tonic-gate int mode;
5297c478bd9Sstevel@tonic-gate {
5307c478bd9Sstevel@tonic-gate 	return EIO;
5317c478bd9Sstevel@tonic-gate }
5327c478bd9Sstevel@tonic-gate #endif /* IPFILTER_LOOKUP */
533