xref: /illumos-gate/usr/src/uts/common/sys/netstack.h (revision 8c69cc8fbe729fa7b091e901c4b50508ccc6bb33)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright (c) 2016, Joyent, Inc. All rights reserved.
29  */
30 
31 #ifndef _SYS_NETSTACK_H
32 #define	_SYS_NETSTACK_H
33 
34 #include <sys/kstat.h>
35 #include <sys/cred.h>
36 #include <sys/mutex.h>
37 
38 #ifdef	__cplusplus
39 extern "C" {
40 #endif
41 
42 /*
43  * This allows various pieces in and around IP to have a separate instance
44  * for each instance of IP. This is used to support zones that have an
45  * exclusive stack.
46  * Pieces of software far removed from IP (e.g., kernel software
47  * sitting on top of TCP or UDP) probably should not use the netstack
48  * support; if such software wants to support separate zones it
49  * can do that using the zones framework (zone_key_create() etc)
50  * whether there is a shared IP stack or and exclusive IP stack underneath.
51  */
52 
53 /*
54  * Each netstack has an identifier. We reuse the zoneid allocation for
55  * this but have a separate typedef. Thus the shared stack (used by
56  * the global zone and other shared stack zones) have a zero ID, and
57  * the exclusive stacks have a netstackid that is the same as their zoneid.
58  */
59 typedef id_t	netstackid_t;
60 
61 #define	GLOBAL_NETSTACKID	0
62 
63 /*
64  * One for each module which uses netstack support.
65  * Used in netstack_register().
66  *
67  * The order of these is important for some modules both for
68  * the creation (which done in ascending order) and destruction (which is
69  * done in in decending order).
70  */
71 #define	NS_ALL		-1	/* Match all */
72 #define	NS_DLS		0
73 #define	NS_IPTUN	1
74 #define	NS_STR		2	/* autopush list etc */
75 #define	NS_HOOK		3
76 #define	NS_NETI		4
77 #define	NS_ARP		5
78 #define	NS_IP		6
79 #define	NS_ICMP		7
80 #define	NS_UDP		8
81 #define	NS_TCP		9
82 #define	NS_SCTP		10
83 #define	NS_RTS		11
84 #define	NS_IPSEC	12
85 #define	NS_KEYSOCK	13
86 #define	NS_SPDSOCK	14
87 #define	NS_IPSECAH	15
88 #define	NS_IPSECESP	16
89 #define	NS_IPNET	17
90 #define	NS_ILB		18
91 #define	NS_MAX		(NS_ILB+1)
92 
93 /*
94  * State maintained for each module which tracks the state of
95  * the create, shutdown and destroy callbacks.
96  *
97  * Keeps track of pending actions to avoid holding locks when
98  * calling into the create/shutdown/destroy functions in the module.
99  */
100 #ifdef _KERNEL
101 typedef struct {
102 	uint16_t 	nms_flags;
103 	kcondvar_t	nms_cv;
104 } nm_state_t;
105 
106 /*
107  * nms_flags
108  */
109 #define	NSS_CREATE_NEEDED	0x0001
110 #define	NSS_CREATE_INPROGRESS	0x0002
111 #define	NSS_CREATE_COMPLETED	0x0004
112 #define	NSS_SHUTDOWN_NEEDED	0x0010
113 #define	NSS_SHUTDOWN_INPROGRESS	0x0020
114 #define	NSS_SHUTDOWN_COMPLETED	0x0040
115 #define	NSS_DESTROY_NEEDED	0x0100
116 #define	NSS_DESTROY_INPROGRESS	0x0200
117 #define	NSS_DESTROY_COMPLETED	0x0400
118 
119 #define	NSS_CREATE_ALL	\
120 	(NSS_CREATE_NEEDED|NSS_CREATE_INPROGRESS|NSS_CREATE_COMPLETED)
121 #define	NSS_SHUTDOWN_ALL	\
122 	(NSS_SHUTDOWN_NEEDED|NSS_SHUTDOWN_INPROGRESS|NSS_SHUTDOWN_COMPLETED)
123 #define	NSS_DESTROY_ALL	\
124 	(NSS_DESTROY_NEEDED|NSS_DESTROY_INPROGRESS|NSS_DESTROY_COMPLETED)
125 
126 #define	NSS_ALL_INPROGRESS	\
127 	(NSS_CREATE_INPROGRESS|NSS_SHUTDOWN_INPROGRESS|NSS_DESTROY_INPROGRESS)
128 #else
129 /* User-level compile like IP Filter needs a netstack_t. Dummy */
130 typedef uint_t nm_state_t;
131 #endif /* _KERNEL */
132 
133 /*
134  * One for every netstack in the system.
135  * We use a union so that the compilar and lint can provide type checking -
136  * in principle we could have
137  * #define	netstack_arp		netstack_modules[NS_ARP]
138  * etc, but that would imply void * types hence no type checking by the
139  * compiler.
140  *
141  * All the fields in netstack_t except netstack_next are protected by
142  * netstack_lock. netstack_next is protected by netstack_g_lock.
143  */
144 struct netstack {
145 	union {
146 		void	*nu_modules[NS_MAX];
147 		struct {
148 			struct dls_stack	*nu_dls;
149 			struct iptun_stack	*nu_iptun;
150 			struct str_stack	*nu_str;
151 			struct hook_stack	*nu_hook;
152 			struct neti_stack	*nu_neti;
153 			struct arp_stack	*nu_arp;
154 			struct ip_stack		*nu_ip;
155 			struct icmp_stack	*nu_icmp;
156 			struct udp_stack	*nu_udp;
157 			struct tcp_stack	*nu_tcp;
158 			struct sctp_stack	*nu_sctp;
159 			struct rts_stack	*nu_rts;
160 			struct ipsec_stack	*nu_ipsec;
161 			struct keysock_stack	*nu_keysock;
162 			struct spd_stack	*nu_spdsock;
163 			struct ipsecah_stack	*nu_ipsecah;
164 			struct ipsecesp_stack	*nu_ipsecesp;
165 			struct ipnet_stack	*nu_ipnet;
166 			struct ilb_stack	*nu_ilb;
167 		} nu_s;
168 	} netstack_u;
169 #define	netstack_modules	netstack_u.nu_modules
170 #define	netstack_dls		netstack_u.nu_s.nu_dls
171 #define	netstack_iptun		netstack_u.nu_s.nu_iptun
172 #define	netstack_str		netstack_u.nu_s.nu_str
173 #define	netstack_hook		netstack_u.nu_s.nu_hook
174 #define	netstack_neti		netstack_u.nu_s.nu_neti
175 #define	netstack_arp		netstack_u.nu_s.nu_arp
176 #define	netstack_ip		netstack_u.nu_s.nu_ip
177 #define	netstack_icmp		netstack_u.nu_s.nu_icmp
178 #define	netstack_udp		netstack_u.nu_s.nu_udp
179 #define	netstack_tcp		netstack_u.nu_s.nu_tcp
180 #define	netstack_sctp		netstack_u.nu_s.nu_sctp
181 #define	netstack_rts		netstack_u.nu_s.nu_rts
182 #define	netstack_ipsec		netstack_u.nu_s.nu_ipsec
183 #define	netstack_keysock	netstack_u.nu_s.nu_keysock
184 #define	netstack_spdsock	netstack_u.nu_s.nu_spdsock
185 #define	netstack_ipsecah	netstack_u.nu_s.nu_ipsecah
186 #define	netstack_ipsecesp	netstack_u.nu_s.nu_ipsecesp
187 #define	netstack_ipnet		netstack_u.nu_s.nu_ipnet
188 #define	netstack_ilb		netstack_u.nu_s.nu_ilb
189 
190 	nm_state_t	netstack_m_state[NS_MAX]; /* module state */
191 
192 	kmutex_t	netstack_lock;
193 	struct netstack *netstack_next;
194 	netstackid_t	netstack_stackid;
195 	int		netstack_numzones;	/* Number of zones using this */
196 	int		netstack_refcnt;	/* Number of hold-rele */
197 	int		netstack_flags;	/* See below */
198 
199 #ifdef _KERNEL
200 	/* Needed to ensure that we run the callback functions in order */
201 	kcondvar_t	netstack_cv;
202 #endif
203 };
204 typedef struct netstack netstack_t;
205 
206 /* netstack_flags values */
207 #define	NSF_UNINIT		0x01		/* Not initialized */
208 #define	NSF_CLOSING		0x02		/* Going away */
209 #define	NSF_ZONE_CREATE		0x04		/* create callbacks inprog */
210 #define	NSF_ZONE_SHUTDOWN	0x08		/* shutdown callbacks */
211 #define	NSF_ZONE_DESTROY	0x10		/* destroy callbacks */
212 
213 #define	NSF_ZONE_INPROGRESS	\
214 	(NSF_ZONE_CREATE|NSF_ZONE_SHUTDOWN|NSF_ZONE_DESTROY)
215 
216 /*
217  * One for each of the NS_* values.
218  */
219 struct netstack_registry {
220 	int		nr_flags;	/* 0 if nothing registered */
221 	void		*(*nr_create)(netstackid_t, netstack_t *);
222 	void		(*nr_shutdown)(netstackid_t, void *);
223 	void		(*nr_destroy)(netstackid_t, void *);
224 };
225 
226 /* nr_flags values */
227 #define	NRF_REGISTERED	0x01
228 #define	NRF_DYING	0x02	/* No new creates */
229 
230 /*
231  * To support kstat_create_netstack() using kstat_add_zone we need
232  * to track both
233  *  - all zoneids that use the global/shared stack
234  *  - all kstats that have been added for the shared stack
235  */
236 
237 extern void netstack_init(void);
238 extern void netstack_hold(netstack_t *);
239 extern void netstack_rele(netstack_t *);
240 extern netstack_t *netstack_find_by_cred(const cred_t *);
241 extern netstack_t *netstack_find_by_stackid(netstackid_t);
242 extern netstack_t *netstack_find_by_zoneid(zoneid_t);
243 extern boolean_t netstack_inuse_by_stackid(netstackid_t stackid);
244 
245 extern zoneid_t netstackid_to_zoneid(netstackid_t);
246 extern zoneid_t netstack_get_zoneid(netstack_t *);
247 extern netstackid_t zoneid_to_netstackid(zoneid_t);
248 
249 extern netstack_t *netstack_get_current(void);
250 
251 /*
252  * Register interest in changes to the set of netstacks.
253  * The createfn and destroyfn are required, but the shutdownfn can be
254  * NULL.
255  * Note that due to the current zsd implementation, when the create
256  * function is called the zone isn't fully present, thus functions
257  * like zone_find_by_* will fail, hence the create function can not
258  * use many zones kernel functions including zcmn_err().
259  */
260 extern void	netstack_register(int,
261     void *(*)(netstackid_t, netstack_t *),
262     void (*)(netstackid_t, void *),
263     void (*)(netstackid_t, void *));
264 extern void	netstack_unregister(int);
265 extern kstat_t	*kstat_create_netstack(char *, int, char *, char *, uchar_t,
266     uint_t, uchar_t, netstackid_t);
267 extern void	kstat_delete_netstack(kstat_t *, netstackid_t);
268 
269 /*
270  * Simple support for walking all the netstacks.
271  * The caller of netstack_next() needs to call netstack_rele() when
272  * done with a netstack.
273  */
274 typedef	int	netstack_handle_t;
275 
276 extern void	netstack_next_init(netstack_handle_t *);
277 extern void	netstack_next_fini(netstack_handle_t *);
278 extern netstack_t	*netstack_next(netstack_handle_t *);
279 
280 #ifdef	__cplusplus
281 }
282 #endif
283 
284 
285 #endif	/* _SYS_NETSTACK_H */
286