xref: /illumos-gate/usr/src/uts/common/inet/udp_impl.h (revision 89a7715a55deca73d03076f5c24463717f0aaa91)
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  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_UDP_IMPL_H
27 #define	_UDP_IMPL_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 /*
32  * UDP implementation private declarations.  These interfaces are
33  * used to build the IP module and are not meant to be accessed
34  * by any modules except IP itself.  They are undocumented and are
35  * subject to change without notice.
36  */
37 
38 #ifdef	__cplusplus
39 extern "C" {
40 #endif
41 
42 #ifdef _KERNEL
43 
44 #include <sys/int_types.h>
45 #include <sys/netstack.h>
46 
47 #include <netinet/in.h>
48 #include <netinet/ip6.h>
49 
50 #include <inet/common.h>
51 #include <inet/ip.h>
52 #include <inet/optcom.h>
53 
54 #define	UDP_MOD_ID		5607
55 
56 typedef struct udp_bits_s {
57 
58 	uint32_t
59 
60 	udpb_debug : 1,		/* SO_DEBUG "socket" option. */
61 	udpb_dontroute : 1,	/* SO_DONTROUTE "socket" option. */
62 	udpb_broadcast : 1,	/* SO_BROADCAST "socket" option. */
63 	udpb_useloopback : 1,	/* SO_USELOOPBACK "socket" option */
64 
65 	udpb_reuseaddr : 1,	/* SO_REUSEADDR "socket" option. */
66 	udpb_dgram_errind : 1,	/* SO_DGRAM_ERRIND option */
67 	udpb_recvdstaddr : 1,	/* IP_RECVDSTADDR option */
68 	udpb_recvopts : 1,	/* IP_RECVOPTS option */
69 
70 	udpb_unspec_source : 1,	/* IP*_UNSPEC_SRC option */
71 	udpb_ip_recvpktinfo : 1,	/* IPV6_RECVPKTINFO option  */
72 	udpb_ipv6_recvhoplimit : 1,	/* IPV6_RECVHOPLIMIT option */
73 	udpb_ipv6_recvhopopts : 1,	/* IPV6_RECVHOPOPTS option */
74 
75 	udpb_ipv6_recvdstopts : 1,	/* IPV6_RECVDSTOPTS option */
76 	udpb_ipv6_recvrthdr : 1,	/* IPV6_RECVRTHDR option */
77 	udpb_ipv6_recvtclass : 1,	/* IPV6_RECVTCLASS */
78 	udpb_ipv6_recvpathmtu : 1,	/* IPV6_RECVPATHMTU */
79 
80 	udpb_anon_priv_bind : 1,
81 	udpb_exclbind : 1,		/* ``exclusive'' binding */
82 	udpb_recvif : 1,		/* IP_RECVIF option */
83 	udpb_recvslla : 1,		/* IP_RECVSLLA option */
84 
85 	udpb_recvttl : 1,		/* IP_RECVTTL option */
86 	udpb_recvucred : 1,		/* IP_RECVUCRED option */
87 	udpb_old_ipv6_recvdstopts : 1,	/* old form of IPV6_DSTOPTS */
88 	udpb_ipv6_recvrthdrdstopts : 1,	/* IPV6_RECVRTHDRDSTOPTS */
89 
90 	udpb_rcvhdr : 1,		/* UDP_RCVHDR option */
91 	udpb_issocket : 1,		/* socket mode */
92 	udpb_direct_sockfs : 1,		/* direct calls to/from sockfs */
93 	udpb_timestamp : 1,		/* SO_TIMESTAMP "socket" option */
94 
95 	udpb_anon_mlp : 1,		/* SO_ANON_MLP */
96 	udpb_mac_exempt : 1,		/* SO_MAC_EXEMPT */
97 	udpb_nat_t_endpoint : 1,	/* UDP_NAT_T_ENDPOINT option */
98 	udpb_pad_to_bit_31 : 1;
99 } udp_bits_t;
100 
101 #define	udp_debug	udp_bits.udpb_debug
102 #define	udp_dontroute	udp_bits.udpb_dontroute
103 #define	udp_broadcast	udp_bits.udpb_broadcast
104 #define	udp_useloopback	udp_bits.udpb_useloopback
105 
106 #define	udp_reuseaddr		udp_bits.udpb_reuseaddr
107 #define	udp_dgram_errind	udp_bits.udpb_dgram_errind
108 #define	udp_recvdstaddr		udp_bits.udpb_recvdstaddr
109 #define	udp_recvopts		udp_bits.udpb_recvopts
110 
111 #define	udp_unspec_source	udp_bits.udpb_unspec_source
112 #define	udp_ip_recvpktinfo	udp_bits.udpb_ip_recvpktinfo
113 #define	udp_ipv6_recvhoplimit	udp_bits.udpb_ipv6_recvhoplimit
114 #define	udp_ipv6_recvhopopts	udp_bits.udpb_ipv6_recvhopopts
115 
116 #define	udp_ipv6_recvdstopts	udp_bits.udpb_ipv6_recvdstopts
117 #define	udp_ipv6_recvrthdr	udp_bits.udpb_ipv6_recvrthdr
118 #define	udp_ipv6_recvtclass	udp_bits.udpb_ipv6_recvtclass
119 #define	udp_ipv6_recvpathmtu	udp_bits.udpb_ipv6_recvpathmtu
120 
121 #define	udp_anon_priv_bind	udp_bits.udpb_anon_priv_bind
122 #define	udp_exclbind		udp_bits.udpb_exclbind
123 #define	udp_recvif		udp_bits.udpb_recvif
124 #define	udp_recvslla		udp_bits.udpb_recvslla
125 
126 #define	udp_recvttl		udp_bits.udpb_recvttl
127 #define	udp_recvucred		udp_bits.udpb_recvucred
128 #define	udp_old_ipv6_recvdstopts	udp_bits.udpb_old_ipv6_recvdstopts
129 #define	udp_ipv6_recvrthdrdstopts	udp_bits.udpb_ipv6_recvrthdrdstopts
130 
131 #define	udp_rcvhdr		udp_bits.udpb_rcvhdr
132 #define	udp_issocket		udp_bits.udpb_issocket
133 #define	udp_direct_sockfs	udp_bits.udpb_direct_sockfs
134 #define	udp_timestamp		udp_bits.udpb_timestamp
135 
136 #define	udp_anon_mlp		udp_bits.udpb_anon_mlp
137 #define	udp_mac_exempt		udp_bits.udpb_mac_exempt
138 #define	udp_nat_t_endpoint	udp_bits.udpb_nat_t_endpoint
139 
140 /*
141  * Bind hash list size and hash function.  It has to be a power of 2 for
142  * hashing.
143  */
144 #define	UDP_BIND_FANOUT_SIZE	512
145 #define	UDP_BIND_HASH(lport, size) \
146 	((ntohs((uint16_t)lport)) & (size - 1))
147 
148 /* UDP bind fanout hash structure. */
149 typedef struct udp_fanout_s {
150 	struct udp_s *uf_udp;
151 	kmutex_t uf_lock;
152 #if defined(_LP64) || defined(_I32LPx)
153 	char	uf_pad[48];
154 #else
155 	char	uf_pad[56];
156 #endif
157 } udp_fanout_t;
158 
159 /*
160  * dev_q is the write side queue of the entity below IP.
161  * If there is a module below IP, we can't optimize by looking
162  * at q_first of the queue below IP. If the driver is directly
163  * below IP and if the q_first is NULL, we optimize by not doing
164  * the canput check
165  */
166 #define	DEV_Q_IS_FLOW_CTLED(dev_q)					\
167 	(((dev_q)->q_next != NULL || (dev_q)->q_first != NULL) &&	\
168 	!canput(dev_q))
169 
170 /* Kstats */
171 typedef struct udp_stat {			/* Class "net" kstats */
172 	kstat_named_t	udp_ip_send;
173 	kstat_named_t	udp_ip_ire_send;
174 	kstat_named_t	udp_ire_null;
175 	kstat_named_t	udp_drain;
176 	kstat_named_t	udp_sock_fallback;
177 	kstat_named_t	udp_rrw_busy;
178 	kstat_named_t	udp_rrw_msgcnt;
179 	kstat_named_t	udp_out_sw_cksum;
180 	kstat_named_t	udp_out_sw_cksum_bytes;
181 	kstat_named_t	udp_out_opt;
182 	kstat_named_t	udp_out_err_notconn;
183 	kstat_named_t	udp_out_err_output;
184 	kstat_named_t	udp_out_err_tudr;
185 	kstat_named_t	udp_in_pktinfo;
186 	kstat_named_t	udp_in_recvdstaddr;
187 	kstat_named_t	udp_in_recvopts;
188 	kstat_named_t	udp_in_recvif;
189 	kstat_named_t	udp_in_recvslla;
190 	kstat_named_t	udp_in_recvucred;
191 	kstat_named_t	udp_in_recvttl;
192 	kstat_named_t	udp_in_recvhopopts;
193 	kstat_named_t	udp_in_recvhoplimit;
194 	kstat_named_t	udp_in_recvdstopts;
195 	kstat_named_t	udp_in_recvrtdstopts;
196 	kstat_named_t	udp_in_recvrthdr;
197 	kstat_named_t	udp_in_recvpktinfo;
198 	kstat_named_t	udp_in_recvtclass;
199 	kstat_named_t	udp_in_timestamp;
200 	kstat_named_t	udp_ip_rcvpktinfo;
201 	kstat_named_t	udp_direct_send;
202 	kstat_named_t	udp_bwsq_send;
203 	kstat_named_t	udp_connected_direct_send;
204 	kstat_named_t	udp_connected_bwsq_send;
205 #ifdef DEBUG
206 	kstat_named_t	udp_data_conn;
207 	kstat_named_t	udp_data_notconn;
208 #endif
209 
210 } udp_stat_t;
211 
212 /* Named Dispatch Parameter Management Structure */
213 typedef struct udpparam_s {
214 	uint32_t udp_param_min;
215 	uint32_t udp_param_max;
216 	uint32_t udp_param_value;
217 	char	*udp_param_name;
218 } udpparam_t;
219 
220 #define	UDP_NUM_EPRIV_PORTS	64
221 
222 /*
223  * UDP stack instances
224  */
225 struct udp_stack {
226 	netstack_t	*us_netstack;	/* Common netstack */
227 
228 	uint_t		us_bind_fanout_size;
229 	udp_fanout_t	*us_bind_fanout;
230 
231 	int		us_num_epriv_ports;
232 	in_port_t	us_epriv_ports[UDP_NUM_EPRIV_PORTS];
233 
234 	/* Hint not protected by any lock */
235 	in_port_t	us_next_port_to_try;
236 
237 	IDP		us_nd;	/* Points to table of UDP ND variables. */
238 	udpparam_t	*us_param_arr; 	/* ndd variable table */
239 
240 	kstat_t		*us_mibkp;	/* kstats exporting mib data */
241 	kstat_t		*us_kstat;
242 	udp_stat_t	us_statistics;
243 
244 	mib2_udp_t	us_udp_mib;	/* SNMP fixed size info */
245 
246 /*
247  * This controls the rate some ndd info report functions can be used
248  * by non-priviledged users.  It stores the last time such info is
249  * requested.  When those report functions are called again, this
250  * is checked with the current time and compare with the ndd param
251  * udp_ndd_get_info_interval.
252  */
253 	clock_t		us_last_ndd_get_info_time;
254 
255 /*
256  * The smallest anonymous port in the priviledged port range which UDP
257  * looks for free port.  Use in the option UDP_ANONPRIVBIND.
258  */
259 	in_port_t	us_min_anonpriv_port;
260 
261 };
262 typedef struct udp_stack udp_stack_t;
263 
264 /* Internal udp control structure, one per open stream */
265 typedef	struct udp_s {
266 	krwlock_t	udp_rwlock;	/* Protects most of udp_t */
267 	t_scalar_t	udp_pending_op;	/* The current TPI operation */
268 	/*
269 	 * Following fields up to udp_ipversion protected by conn_lock,
270 	 * and the fanout lock i.e.uf_lock. Need both locks to change the
271 	 * field, either lock is sufficient for reading the field.
272 	 */
273 	uint32_t	udp_state;	/* TPI state */
274 	in_port_t	udp_port;	/* Port bound to this stream */
275 	in_port_t	udp_dstport;	/* Connected port */
276 	in6_addr_t	udp_v6src;	/* Source address of this stream */
277 	in6_addr_t	udp_bound_v6src; /* Explicitly bound address */
278 	in6_addr_t	udp_v6dst;	/* Connected destination */
279 	/*
280 	 * IP format that packets transmitted from this struct should use.
281 	 * Value can be IP4_VERSION or IPV6_VERSION.
282 	 */
283 	ushort_t	udp_ipversion;
284 
285 	/* Written to only once at the time of opening the endpoint */
286 	sa_family_t	udp_family;	/* Family from socket() call */
287 
288 	/* Following protected by udp_rwlock */
289 	uint32_t	udp_flowinfo;	/* Connected flow id and tclass */
290 	uint32_t	udp_max_hdr_len; /* For write offset in stream head */
291 	uint32_t	udp_ip_snd_options_len; /* Len of IPv4 options */
292 	uchar_t		*udp_ip_snd_options;    /* Ptr to IPv4 options */
293 	uint32_t	udp_ip_rcv_options_len; /* Len of IPv4 options recvd */
294 	uchar_t		*udp_ip_rcv_options;    /* Ptr to IPv4 options recvd */
295 	uchar_t		udp_multicast_ttl;	/* IP*_MULTICAST_TTL/HOPS */
296 	ipaddr_t	udp_multicast_if_addr;  /* IP_MULTICAST_IF option */
297 	uint_t		udp_multicast_if_index;	/* IPV6_MULTICAST_IF option */
298 	int		udp_bound_if;		/* IP*_BOUND_IF option */
299 
300 	/* Written to only once at the time of opening the endpoint */
301 	conn_t		*udp_connp;
302 
303 	/* Following protected by udp_rwlock */
304 	udp_bits_t	udp_bits;		/* Bit fields defined above */
305 	uint8_t		udp_type_of_service;	/* IP_TOS option */
306 	uint8_t		udp_ttl;		/* TTL or hoplimit */
307 	ip6_pkt_t	udp_sticky_ipp;		/* Sticky options */
308 	uint8_t		*udp_sticky_hdrs;	/* Prebuilt IPv6 hdrs */
309 	uint_t		udp_sticky_hdrs_len;	/* Incl. ip6h and any ip6i */
310 
311 	/* Following 2 fields protected by the uf_lock */
312 	struct udp_s	*udp_bind_hash; /* Bind hash chain */
313 	struct udp_s	**udp_ptpbhn; /* Pointer to previous bind hash next. */
314 
315 	kmutex_t	udp_drain_lock;		/* lock for udp_rcv_list */
316 	/* Protected by udp_drain_lock */
317 	boolean_t	udp_drain_qfull;	/* drain queue is full */
318 
319 	/* Following protected by udp_rwlock */
320 	mblk_t		*udp_rcv_list_head;	/* b_next chain of mblks */
321 	mblk_t		*udp_rcv_list_tail;	/* last mblk in chain */
322 	uint_t		udp_rcv_cnt;		/* total data in rcv_list */
323 	uint_t		udp_rcv_msgcnt;		/* total msgs in rcv_list */
324 	size_t		udp_rcv_hiwat;		/* receive high watermark */
325 	uint_t		udp_label_len;		/* length of security label */
326 	uint_t		udp_label_len_v6;	/* len of v6 security label */
327 	in6_addr_t 	udp_v6lastdst;		/* most recent destination */
328 
329 	uint64_t	udp_open_time;	/* time when this was opened */
330 	pid_t		udp_open_pid;	/* process id when this was opened */
331 	udp_stack_t	*udp_us;		/* Stack instance for zone */
332 } udp_t;
333 
334 /* UDP Protocol header */
335 /* UDP Protocol header aligned */
336 typedef	struct udpahdr_s {
337 	in_port_t	uha_src_port;		/* Source port */
338 	in_port_t	uha_dst_port;		/* Destination port */
339 	uint16_t	uha_length;		/* UDP length */
340 	uint16_t	uha_checksum;		/* UDP checksum */
341 } udpha_t;
342 
343 #define	us_wroff_extra			us_param_arr[0].udp_param_value
344 #define	us_ipv4_ttl			us_param_arr[1].udp_param_value
345 #define	us_ipv6_hoplimit		us_param_arr[2].udp_param_value
346 #define	us_smallest_nonpriv_port	us_param_arr[3].udp_param_value
347 #define	us_do_checksum			us_param_arr[4].udp_param_value
348 #define	us_smallest_anon_port		us_param_arr[5].udp_param_value
349 #define	us_largest_anon_port		us_param_arr[6].udp_param_value
350 #define	us_xmit_hiwat			us_param_arr[7].udp_param_value
351 #define	us_xmit_lowat			us_param_arr[8].udp_param_value
352 #define	us_recv_hiwat			us_param_arr[9].udp_param_value
353 #define	us_max_buf			us_param_arr[10].udp_param_value
354 #define	us_ndd_get_info_interval	us_param_arr[11].udp_param_value
355 
356 
357 #define	UDP_STAT(us, x)		((us)->us_statistics.x.value.ui64++)
358 #define	UDP_STAT_UPDATE(us, x, n)	\
359 			((us)->us_statistics.x.value.ui64 += (n))
360 
361 #ifdef DEBUG
362 #define	UDP_DBGSTAT(us, x)	UDP_STAT(us, x)
363 #else
364 #define	UDP_DBGSTAT(us, x)
365 #endif /* DEBUG */
366 
367 extern int	udp_opt_default(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
368 extern int	udp_opt_get(queue_t *, t_scalar_t, t_scalar_t, uchar_t *);
369 extern int	udp_opt_set(queue_t *, uint_t, int, int, uint_t, uchar_t *,
370 		    uint_t *, uchar_t *, void *, cred_t *, mblk_t *);
371 extern mblk_t	*udp_snmp_get(queue_t *, mblk_t *);
372 extern int	udp_snmp_set(queue_t *, t_scalar_t, t_scalar_t, uchar_t *, int);
373 extern void	udp_close_free(conn_t *);
374 extern void	udp_quiesce_conn(conn_t *);
375 extern void	udp_ddi_init(void);
376 extern void	udp_ddi_destroy(void);
377 extern void	udp_resume_bind(conn_t *, mblk_t *);
378 extern void	udp_output(conn_t *connp, mblk_t *mp, struct sockaddr *addr,
379 		    socklen_t addrlen);
380 extern void	udp_wput(queue_t *, mblk_t *);
381 
382 extern int	udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name,
383     uchar_t *ptr);
384 extern int	udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name,
385     uchar_t *ptr);
386 extern int	udp_opt_set(queue_t *q, uint_t optset_context,
387     int level, int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
388     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk);
389 
390 /*
391  * Object to represent database of options to search passed to
392  * {sock,tpi}optcom_req() interface routine to take care of option
393  * management and associated methods.
394  */
395 extern optdb_obj_t	udp_opt_obj;
396 extern uint_t		udp_max_optsize;
397 
398 #endif	/*  _KERNEL */
399 
400 #ifdef	__cplusplus
401 }
402 #endif
403 
404 #endif	/* _UDP_IMPL_H */
405