xref: /illumos-gate/usr/src/uts/common/inet/ipf/solaris.c (revision 94bdecd9)
1ab25eeb5Syz /*
2ab25eeb5Syz  * Copyright (C) 1993-2001, 2003 by Darren Reed.
3ab25eeb5Syz  *
4ab25eeb5Syz  * See the IPFILTER.LICENCE file for details on licencing.
5ab25eeb5Syz  *
614d3298eSAlexandr Nedvedicky  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
7ab25eeb5Syz  * Use is subject to license terms.
8*94bdecd9SRob Gulewich  *
9*94bdecd9SRob Gulewich  * Copyright (c) 2014, Joyent, Inc.  All rights reserved.
10*94bdecd9SRob Gulewich  */
11*94bdecd9SRob Gulewich 
12*94bdecd9SRob Gulewich /*
13*94bdecd9SRob Gulewich  * ipfilter kernel module mutexes and locking:
14*94bdecd9SRob Gulewich  *
15*94bdecd9SRob Gulewich  * Enabling ipfilter creates a per-netstack ipf_stack_t object that is
16*94bdecd9SRob Gulewich  * stored in the ipf_stacks list, which is protected by ipf_stack_lock.
17*94bdecd9SRob Gulewich  * ipf_stack_t objects are accessed in three contexts:
18*94bdecd9SRob Gulewich  *
19*94bdecd9SRob Gulewich  * 1) administering that filter (eg: ioctls handled with iplioctl())
20*94bdecd9SRob Gulewich  * 2) reading log data (eg: iplread() / iplwrite())
21*94bdecd9SRob Gulewich  * 3) filtering packets (eg: ipf_hook4_* and ipf_hook6_* pfhooks
22*94bdecd9SRob Gulewich  *    functions)
23*94bdecd9SRob Gulewich  *
24*94bdecd9SRob Gulewich  * Each ipf_stack_t has a RW lock, ifs_ipf_global, protecting access to the
25*94bdecd9SRob Gulewich  * whole structure. The structure also has locks protecting the various
26*94bdecd9SRob Gulewich  * data structures used for filtering. The following guidelines should be
27*94bdecd9SRob Gulewich  * followed for ipf_stack_t locks:
28*94bdecd9SRob Gulewich  *
29*94bdecd9SRob Gulewich  * - ipf_stack_lock must be held when accessing the ipf_stacks list
30*94bdecd9SRob Gulewich  * - ipf_stack_lock should be held before acquiring ifs_ipf_global for
31*94bdecd9SRob Gulewich  *   a stack (the exception to this is ipf_stack_destroy(), which removes
32*94bdecd9SRob Gulewich  *   the ipf_stack_t from the list, then drops ipf_stack_lock before
33*94bdecd9SRob Gulewich  *   acquiring ifs_ipf_global)
34*94bdecd9SRob Gulewich  * - ifs_ipf_global must be held when accessing an ipf_stack_t in that list:
35*94bdecd9SRob Gulewich  *   - The write lock is held only during stack creation / destruction
36*94bdecd9SRob Gulewich  *   - The read lock should be held for all other accesses
37*94bdecd9SRob Gulewich  * - To alter the filtering data in the administrative context, one must:
38*94bdecd9SRob Gulewich  *   - acquire the read lock for ifs_ipf_global
39*94bdecd9SRob Gulewich  *   - then acquire the write lock for the data in question
40*94bdecd9SRob Gulewich  * - In the filtering path, the read lock needs to be held for each type of
41*94bdecd9SRob Gulewich  *   filtering data used
42*94bdecd9SRob Gulewich  * - ifs_ipf_global does not need to be held in the filtering path:
43*94bdecd9SRob Gulewich  *   - The filtering hooks don't need to modify the stack itself
44*94bdecd9SRob Gulewich  *   - The ipf_stack_t will not be destroyed until the hooks are unregistered.
45*94bdecd9SRob Gulewich  *     This requires a write lock on the hook, ensuring that no active hooks
46*94bdecd9SRob Gulewich  *     (eg: the filtering path) are running, and that the hooks won't be run
47*94bdecd9SRob Gulewich  *     afterward.
48*94bdecd9SRob Gulewich  *
49*94bdecd9SRob Gulewich  * Note that there is a deadlock possible when calling net_hook_register()
50*94bdecd9SRob Gulewich  * or net_hook_unregister() with ifs_ipf_global held: see the comments in
51*94bdecd9SRob Gulewich  * iplattach() and ipldetach() for details.
52ab25eeb5Syz  */
53ab25eeb5Syz 
54ab25eeb5Syz #include <sys/systm.h>
55ab25eeb5Syz #include <sys/types.h>
56ab25eeb5Syz #include <sys/param.h>
57ab25eeb5Syz #include <sys/errno.h>
58ab25eeb5Syz #include <sys/uio.h>
59ab25eeb5Syz #include <sys/buf.h>
60ab25eeb5Syz #include <sys/modctl.h>
61ab25eeb5Syz #include <sys/open.h>
62ab25eeb5Syz #include <sys/kmem.h>
63ab25eeb5Syz #include <sys/conf.h>
64ab25eeb5Syz #include <sys/cmn_err.h>
65ab25eeb5Syz #include <sys/stat.h>
66ab25eeb5Syz #include <sys/cred.h>
67ab25eeb5Syz #include <sys/dditypes.h>
68ab25eeb5Syz #include <sys/poll.h>
69ab25eeb5Syz #include <sys/autoconf.h>
70ab25eeb5Syz #include <sys/byteorder.h>
71ab25eeb5Syz #include <sys/socket.h>
72ab25eeb5Syz #include <sys/dlpi.h>
73ab25eeb5Syz #include <sys/stropts.h>
74ab25eeb5Syz #include <sys/kstat.h>
75ab25eeb5Syz #include <sys/sockio.h>
76381a2a9aSdr #include <sys/neti.h>
77381a2a9aSdr #include <sys/hook.h>
78ab25eeb5Syz #include <net/if.h>
79ab25eeb5Syz #if SOLARIS2 >= 6
8019397407SSherry Moore #include <net/if_types.h>
81ab25eeb5Syz #endif
82ab25eeb5Syz #include <net/af.h>
83ab25eeb5Syz #include <net/route.h>
84ab25eeb5Syz #include <netinet/in.h>
85ab25eeb5Syz #include <netinet/in_systm.h>
86ab25eeb5Syz #include <netinet/if_ether.h>
87ab25eeb5Syz #include <netinet/ip.h>
88ab25eeb5Syz #include <netinet/ip_var.h>
89ab25eeb5Syz #include <netinet/tcp.h>
90ab25eeb5Syz #include <netinet/udp.h>
91ab25eeb5Syz #include <netinet/tcpip.h>
92ab25eeb5Syz #include <netinet/ip_icmp.h>
93ab25eeb5Syz #include <sys/ddi.h>
94ab25eeb5Syz #include <sys/sunddi.h>
95ab25eeb5Syz #include "netinet/ip_compat.h"
96ab25eeb5Syz #include "netinet/ipl.h"
97ab25eeb5Syz #include "netinet/ip_fil.h"
98ab25eeb5Syz #include "netinet/ip_nat.h"
99ab25eeb5Syz #include "netinet/ip_frag.h"
100ab25eeb5Syz #include "netinet/ip_auth.h"
101ab25eeb5Syz #include "netinet/ip_state.h"
102f4b3ec61Sdh #include "netinet/ipf_stack.h"
103ab25eeb5Syz 
104ab25eeb5Syz extern	int	iplwrite __P((dev_t, struct uio *, cred_t *));
105ab25eeb5Syz 
106ab25eeb5Syz static	int	ipf_getinfo __P((dev_info_t *, ddi_info_cmd_t,
10719397407SSherry Moore 		    void *, void **));
108ab25eeb5Syz #if SOLARIS2 < 10
109ab25eeb5Syz static	int	ipf_identify __P((dev_info_t *));
110ab25eeb5Syz #endif
111ab25eeb5Syz static	int	ipf_attach __P((dev_info_t *, ddi_attach_cmd_t));
112ab25eeb5Syz static	int	ipf_detach __P((dev_info_t *, ddi_detach_cmd_t));
1137ddc9b1aSDarren Reed static	void	*ipf_stack_create __P((const netid_t));
1147ddc9b1aSDarren Reed static	void	ipf_stack_destroy __P((const netid_t, void *));
1158ad74188SDarren Reed static	void	ipf_stack_shutdown __P((const netid_t, void *));
116f4b3ec61Sdh static	int	ipf_property_g_update __P((dev_info_t *));
117ab25eeb5Syz static	char	*ipf_devfiles[] = { IPL_NAME, IPNAT_NAME, IPSTATE_NAME,
118ab25eeb5Syz 				    IPAUTH_NAME, IPSYNC_NAME, IPSCAN_NAME,
119ab25eeb5Syz 				    IPLOOKUP_NAME, NULL };
120*94bdecd9SRob Gulewich extern void 	*ipf_state;	/* DDI state */
121*94bdecd9SRob Gulewich extern vmem_t	*ipf_minor;	/* minor number arena */
122ab25eeb5Syz 
123ab25eeb5Syz static struct cb_ops ipf_cb_ops = {
124ab25eeb5Syz 	iplopen,
125ab25eeb5Syz 	iplclose,
126ab25eeb5Syz 	nodev,		/* strategy */
127ab25eeb5Syz 	nodev,		/* print */
128ab25eeb5Syz 	nodev,		/* dump */
129ab25eeb5Syz 	iplread,
130ab25eeb5Syz 	iplwrite,	/* write */
131ab25eeb5Syz 	iplioctl,	/* ioctl */
132ab25eeb5Syz 	nodev,		/* devmap */
133ab25eeb5Syz 	nodev,		/* mmap */
134ab25eeb5Syz 	nodev,		/* segmap */
135ab25eeb5Syz 	nochpoll,	/* poll */
136ab25eeb5Syz 	ddi_prop_op,
137ab25eeb5Syz 	NULL,
138ab25eeb5Syz 	D_MTSAFE,
139ab25eeb5Syz #if SOLARIS2 > 4
140ab25eeb5Syz 	CB_REV,
141ab25eeb5Syz 	nodev,		/* aread */
142ab25eeb5Syz 	nodev,		/* awrite */
143ab25eeb5Syz #endif
144ab25eeb5Syz };
145ab25eeb5Syz 
146ab25eeb5Syz static struct dev_ops ipf_ops = {
147ab25eeb5Syz 	DEVO_REV,
148ab25eeb5Syz 	0,
149ab25eeb5Syz 	ipf_getinfo,
150ab25eeb5Syz #if SOLARIS2 >= 10
151ab25eeb5Syz 	nulldev,
152