xref: /titanic_52/usr/src/uts/common/inet/udp/udp.c (revision 5d54f3d8999eac1762fe0a8c7177d20f1f201fae)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 /* Copyright (c) 1990 Mentat Inc. */
27 
28 #pragma ident	"%Z%%M%	%I%	%E% SMI"
29 
30 const char udp_version[] = "%Z%%M%	%I%	%E% SMI";
31 
32 #include <sys/types.h>
33 #include <sys/stream.h>
34 #include <sys/stropts.h>
35 #include <sys/strlog.h>
36 #include <sys/strsun.h>
37 #define	_SUN_TPI_VERSION 2
38 #include <sys/tihdr.h>
39 #include <sys/timod.h>
40 #include <sys/tiuser.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/strsubr.h>
44 #include <sys/suntpi.h>
45 #include <sys/xti_inet.h>
46 #include <sys/cmn_err.h>
47 #include <sys/kmem.h>
48 #include <sys/policy.h>
49 #include <sys/ucred.h>
50 #include <sys/zone.h>
51 
52 #include <sys/socket.h>
53 #include <sys/vtrace.h>
54 #include <sys/debug.h>
55 #include <sys/isa_defs.h>
56 #include <sys/random.h>
57 #include <netinet/in.h>
58 #include <netinet/ip6.h>
59 #include <netinet/icmp6.h>
60 #include <netinet/udp.h>
61 #include <net/if.h>
62 
63 #include <inet/common.h>
64 #include <inet/ip.h>
65 #include <inet/ip6.h>
66 #include <inet/ip_ire.h>
67 #include <inet/mi.h>
68 #include <inet/mib2.h>
69 #include <inet/nd.h>
70 #include <inet/optcom.h>
71 #include <inet/snmpcom.h>
72 #include <inet/kstatcom.h>
73 #include <inet/udp_impl.h>
74 
75 /*
76  * The ipsec_info.h header file is here since it has the defination for the
77  * M_CTL message types used by IP to convey information to the ULP. The
78  * ipsec_info.h needs the pfkeyv2.h, hence the latters presence.
79  */
80 #include <net/pfkeyv2.h>
81 #include <inet/ipsec_info.h>
82 
83 /*
84  * Object to represent database of options to search passed to
85  * {sock,tpi}optcom_req() interface routine to take care of option
86  * management and associated methods.
87  * XXX. These and other externs should really move to a udp header file.
88  */
89 extern optdb_obj_t	udp_opt_obj;
90 extern uint_t		udp_max_optsize;
91 
92 
93 /*
94  * Synchronization notes:
95  *
96  * UDP uses a combination of the queue-pair STREAMS perimeter, a global
97  * lock and a set of bind hash locks to protect its data structures.
98  *
99  * The queue-pair perimeter is not acquired exclusively in the put
100  * procedures thus when udp_rput or udp_wput needs exclusive access to
101  * the udp_t instance structure it will use qwriter(..., PERIM_INNER) to
102  * asynchronously acquire exclusive access to the udp_t instance.
103  *
104  * When UDP global data needs to be modified the udp_g_lock mutex is acquired.
105  * Currently, udp_g_head and udp_g_epriv_ports[] are protected by it.
106  *
107  * When an UDP endpoint is bound to a local port, it is inserted into
108  * a bind hash list.  The list consists of an array of udp_fanout_t buckets.
109  * The size of the array is controlled by the udp_bind_fanout_size variable.
110  * This variable can be changed in /etc/system if the default value is
111  * not large enough.  Each bind hash bucket is protected by a per bucket lock.
112  * It protects the udp_bind_hash and udp_ptpbhn fields in the udp_t
113  * structure.  An UDP endpoint is removed from the bind hash list only
114  * when it is being unbound or being closed.  The per bucket lock also
115  * protects an UDP endpoint's state changes.
116  */
117 
118 /*
119  * Bind hash list size and hash function.  It has to be a power of 2 for
120  * hashing.
121  */
122 #define	UDP_BIND_FANOUT_SIZE	512
123 #define	UDP_BIND_HASH(lport) \
124 	((ntohs((uint16_t)lport)) & (udp_bind_fanout_size - 1))
125 
126 /* UDP bind fanout hash structure. */
127 typedef struct udp_fanout_s {
128 	udp_t *uf_udp;
129 	kmutex_t uf_lock;
130 #if defined(_LP64) || defined(_I32LPx)
131 	char	uf_pad[48];
132 #else
133 	char	uf_pad[56];
134 #endif
135 } udp_fanout_t;
136 
137 uint_t udp_bind_fanout_size = UDP_BIND_FANOUT_SIZE;
138 /* udp_fanout_t *udp_bind_fanout. */
139 static udp_fanout_t *udp_bind_fanout;
140 
141 /*
142  * This controls the rate some ndd info report functions can be used
143  * by non-priviledged users.  It stores the last time such info is
144  * requested.  When those report functions are called again, this
145  * is checked with the current time and compare with the ndd param
146  * udp_ndd_get_info_interval.
147  */
148 static clock_t udp_last_ndd_get_info_time;
149 #define	NDD_TOO_QUICK_MSG \
150 	"ndd get info rate too high for non-priviledged users, try again " \
151 	"later.\n"
152 #define	NDD_OUT_OF_BUF_MSG	"<< Out of buffer >>\n"
153 
154 /* Named Dispatch Parameter Management Structure */
155 typedef struct udpparam_s {
156 	uint32_t udp_param_min;
157 	uint32_t udp_param_max;
158 	uint32_t udp_param_value;
159 	char	*udp_param_name;
160 } udpparam_t;
161 
162 static void	udp_addr_req(queue_t *q, mblk_t *mp);
163 static void	udp_bind(queue_t *q, mblk_t *mp);
164 static void	udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp);
165 static void	udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock);
166 static int	udp_build_hdrs(queue_t *q, udp_t *udp);
167 static void	udp_capability_req(queue_t *q, mblk_t *mp);
168 static int	udp_close(queue_t *q);
169 static void	udp_connect(queue_t *q, mblk_t *mp);
170 static void	udp_disconnect(queue_t *q, mblk_t *mp);
171 static void	udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error,
172 		    int sys_error);
173 static void	udp_err_ack_prim(queue_t *q, mblk_t *mp, int primitive,
174 		    t_scalar_t tlierr, int unixerr);
175 static int	udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp,
176 		    cred_t *cr);
177 static int	udp_extra_priv_ports_add(queue_t *q, mblk_t *mp,
178 		    char *value, caddr_t cp, cred_t *cr);
179 static int	udp_extra_priv_ports_del(queue_t *q, mblk_t *mp,
180 		    char *value, caddr_t cp, cred_t *cr);
181 static void	udp_icmp_error(queue_t *q, mblk_t *mp);
182 static void	udp_icmp_error_ipv6(queue_t *q, mblk_t *mp);
183 static void	udp_info_req(queue_t *q, mblk_t *mp);
184 static mblk_t	*udp_ip_bind_mp(udp_t *udp, t_scalar_t bind_prim,
185 		    t_scalar_t addr_length);
186 static int	udp_open(queue_t *q, dev_t *devp, int flag, int sflag,
187 		    cred_t *credp);
188 static  int	udp_unitdata_opt_process(queue_t *q, mblk_t *mp,
189 		    int *errorp, void *thisdg_attrs);
190 static boolean_t udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name);
191 int		udp_opt_default(queue_t *q, t_scalar_t level, t_scalar_t name,
192 		    uchar_t *ptr);
193 int		udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name,
194 		    uchar_t *ptr);
195 int		udp_opt_set(queue_t *q, uint_t optset_context,
196 		    int level, int name,
197 		    uint_t inlen, uchar_t *invalp,
198 		    uint_t *outlenp, uchar_t *outvalp,
199 		    void *thisdg_attrs, cred_t *cr, mblk_t *mblk);
200 static int	udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr);
201 static boolean_t udp_param_register(udpparam_t *udppa, int cnt);
202 static int	udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
203 		    cred_t *cr);
204 static int	udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
205 		    uchar_t **optbufp, uint_t *optlenp);
206 static void	udp_report_item(mblk_t *mp, udp_t *udp);
207 static void	udp_rput(queue_t *q, mblk_t *mp);
208 static	void	udp_rput_bind_ack(queue_t *q, mblk_t *mp);
209 static void	udp_rput_other(queue_t *q, mblk_t *mp);
210 static int	udp_snmp_get(queue_t *q, mblk_t *mpctl);
211 static int	udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name,
212 		    uchar_t *ptr, int len);
213 static int	udp_status_report(queue_t *q, mblk_t *mp, caddr_t cp,
214 		    cred_t *cr);
215 static void	udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err);
216 static void	udp_unbind(queue_t *q, mblk_t *mp);
217 static in_port_t udp_update_next_port(in_port_t port, boolean_t random);
218 static void	udp_wput(queue_t *q, mblk_t *mp);
219 static void	udp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6,
220 		    t_scalar_t tudr_optlen);
221 static void	udp_wput_other(queue_t *q, mblk_t *mp);
222 static void	udp_wput_iocdata(queue_t *q, mblk_t *mp);
223 
224 static void	udp_kstat_init(void);
225 static void	udp_kstat_fini(void);
226 static int	udp_kstat_update(kstat_t *kp, int rw);
227 
228 major_t UDP6_MAJ;
229 #define		UDP6		"udp6"
230 
231 #define		UDP_MAXPACKET_IPV4	\
232 	(IP_MAXPACKET - UDPH_SIZE - IP_SIMPLE_HDR_LENGTH)
233 #define		UDP_MAXPACKET_IPV6	\
234 	(IP_MAXPACKET - UDPH_SIZE - IPV6_HDR_LEN)
235 
236 static struct module_info info =  {
237 	5607, "udp", 1, INFPSZ, 512, 128
238 };
239 
240 static struct qinit rinit = {
241 	(pfi_t)udp_rput, NULL, udp_open, udp_close, NULL, &info
242 };
243 
244 static struct qinit winit = {
245 	(pfi_t)udp_wput, NULL, NULL, NULL, NULL, &info
246 };
247 
248 struct streamtab udpinfo = {
249 	&rinit, &winit
250 };
251 
252 static	sin_t	sin_null;	/* Zero address for quick clears */
253 static	sin6_t	sin6_null;	/* Zero address for quick clears */
254 
255 /* Protected by udp_g_lock */
256 static void	*udp_g_head;	/* Head for list of open udp streams. */
257 kmutex_t	udp_g_lock;	/* Protects the above variable */
258 
259 /* Hint not protected by any lock */
260 static in_port_t	udp_g_next_port_to_try;
261 
262 /*
263  * Extra privileged ports. In host byte order. Protected by udp_g_lock.
264  */
265 #define	UDP_NUM_EPRIV_PORTS	64
266 static int	udp_g_num_epriv_ports = UDP_NUM_EPRIV_PORTS;
267 static in_port_t udp_g_epriv_ports[UDP_NUM_EPRIV_PORTS] = { 2049, 4045 };
268 
269 /* Only modified during _init and _fini thus no locking is needed. */
270 static IDP	udp_g_nd;	/* Points to table of UDP ND variables. */
271 
272 /* MIB-2 stuff for SNMP */
273 static mib2_udp_t	udp_mib;	/* SNMP fixed size info */
274 static kstat_t		*udp_mibkp;	/* kstat exporting udp_mib data */
275 
276 
277 /* Default structure copied into T_INFO_ACK messages */
278 static struct T_info_ack udp_g_t_info_ack_ipv4 = {
279 	T_INFO_ACK,
280 	UDP_MAXPACKET_IPV4,	/* TSDU_size. Excl. headers */
281 	T_INVALID,	/* ETSU_size.  udp does not support expedited data. */
282 	T_INVALID,	/* CDATA_size. udp does not support connect data. */
283 	T_INVALID,	/* DDATA_size. udp does not support disconnect data. */
284 	sizeof (sin_t),	/* ADDR_size. */
285 	0,		/* OPT_size - not initialized here */
286 	UDP_MAXPACKET_IPV4,	/* TIDU_size.  Excl. headers */
287 	T_CLTS,		/* SERV_type.  udp supports connection-less. */
288 	TS_UNBND,	/* CURRENT_state.  This is set from udp_state. */
289 	(XPG4_1|SENDZERO) /* PROVIDER_flag */
290 };
291 
292 static	struct T_info_ack udp_g_t_info_ack_ipv6 = {
293 	T_INFO_ACK,
294 	UDP_MAXPACKET_IPV6,	/* TSDU_size.  Excl. headers */
295 	T_INVALID,	/* ETSU_size.  udp does not support expedited data. */
296 	T_INVALID,	/* CDATA_size. udp does not support connect data. */
297 	T_INVALID,	/* DDATA_size. udp does not support disconnect data. */
298 	sizeof (sin6_t), /* ADDR_size. */
299 	0,		/* OPT_size - not initialized here */
300 	UDP_MAXPACKET_IPV6,	/* TIDU_size. Excl. headers */
301 	T_CLTS,		/* SERV_type.  udp supports connection-less. */
302 	TS_UNBND,	/* CURRENT_state.  This is set from udp_state. */
303 	(XPG4_1|SENDZERO) /* PROVIDER_flag */
304 };
305 
306 /* largest UDP port number */
307 #define	UDP_MAX_PORT	65535
308 
309 /*
310  * Table of ND variables supported by udp.  These are loaded into udp_g_nd
311  * in udp_open.
312  * All of these are alterable, within the min/max values given, at run time.
313  */
314 static udpparam_t	udp_param_arr[] = {
315 	/* min	max		value		name */
316 	{ 0L,	256,		32,		"udp_wroff_extra" },
317 	{ 1L,	255,		255,		"udp_ipv4_ttl" },
318 	{ 0, IPV6_MAX_HOPS, IPV6_DEFAULT_HOPS,	"udp_ipv6_hoplimit"},
319 	{ 1024,	(32 * 1024),	1024,		"udp_smallest_nonpriv_port" },
320 	{ 0,	1,		1,		"udp_do_checksum" },
321 	{ 1024,	UDP_MAX_PORT,	(32 * 1024),	"udp_smallest_anon_port" },
322 	{ 1024,	UDP_MAX_PORT,	UDP_MAX_PORT,	"udp_largest_anon_port" },
323 	{ 4096,	1024*1024,	56*1024,	"udp_xmit_hiwat"},
324 	{ 0,	1024*1024,	1024,		"udp_xmit_lowat"},
325 	{ 4096,	1024*1024,	56*1024,	"udp_recv_hiwat"},
326 	{ 65536, 1024*1024*1024, 2*1024*1024,	"udp_max_buf"},
327 	{ 100,	60000,		1000,		"udp_ndd_get_info_interval"},
328 };
329 #define	udp_wroff_extra			udp_param_arr[0].udp_param_value
330 #define	udp_ipv4_ttl			udp_param_arr[1].udp_param_value
331 #define	udp_ipv6_hoplimit		udp_param_arr[2].udp_param_value
332 #define	udp_smallest_nonpriv_port	udp_param_arr[3].udp_param_value
333 #define	udp_do_checksum			udp_param_arr[4].udp_param_value
334 #define	udp_smallest_anon_port		udp_param_arr[5].udp_param_value
335 #define	udp_largest_anon_port		udp_param_arr[6].udp_param_value
336 #define	udp_xmit_hiwat			udp_param_arr[7].udp_param_value
337 #define	udp_xmit_lowat			udp_param_arr[8].udp_param_value
338 #define	udp_recv_hiwat			udp_param_arr[9].udp_param_value
339 #define	udp_max_buf			udp_param_arr[10].udp_param_value
340 #define	udp_ndd_get_info_interval	udp_param_arr[11].udp_param_value
341 
342 /*
343  * The smallest anonymous port in the priviledged port range which UDP
344  * looks for free port.  Use in the option UDP_ANONPRIVBIND.
345  */
346 static in_port_t udp_min_anonpriv_port = 512;
347 
348 /* If set to 0, pick ephemeral port sequentially; otherwise randomly. */
349 uint32_t udp_random_anon_port = 1;
350 
351 /*
352  * Hook functions to enable cluster networking.
353  * On non-clustered systems these vectors must always be NULL
354  */
355 
356 void (*cl_inet_bind)(uchar_t protocol, sa_family_t addr_family,
357 			uint8_t *laddrp, in_port_t lport) = NULL;
358 void (*cl_inet_unbind)(uint8_t protocol, sa_family_t addr_family,
359 			uint8_t *laddrp, in_port_t lport) = NULL;
360 
361 /*
362  * Return the next anonymous port in the priviledged port range for
363  * bind checking.
364  */
365 static in_port_t
366 udp_get_next_priv_port(void)
367 {
368 	static in_port_t next_priv_port = IPPORT_RESERVED - 1;
369 
370 	if (next_priv_port < udp_min_anonpriv_port) {
371 		next_priv_port = IPPORT_RESERVED - 1;
372 	}
373 	return (next_priv_port--);
374 }
375 
376 /* UDP bind hash report triggered via the Named Dispatch mechanism. */
377 /* ARGSUSED */
378 static int
379 udp_bind_hash_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
380 {
381 	udp_fanout_t	*udpf;
382 	udp_t		*udp;
383 	int		i;
384 	zoneid_t	zoneid;
385 
386 	/* Refer to comments in udp_status_report(). */
387 	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
388 		if (ddi_get_lbolt() - udp_last_ndd_get_info_time <
389 		    drv_usectohz(udp_ndd_get_info_interval * 1000)) {
390 			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
391 			return (0);
392 		}
393 	}
394 	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
395 		/* The following may work even if we cannot get a large buf. */
396 		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
397 		return (0);
398 	}
399 
400 	(void) mi_mpprintf(mp,
401 	    "UDP     " MI_COL_HDRPAD_STR
402 	/*   12345678[89ABCDEF] */
403 	    " zone lport src addr        dest addr       port  state");
404 	/*    1234 12345 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx 12345 UNBOUND */
405 
406 	udp = (udp_t *)q->q_ptr;
407 	zoneid = udp->udp_zoneid;
408 
409 	for (i = 0; i < udp_bind_fanout_size; i++) {
410 		udpf = &udp_bind_fanout[i];
411 		mutex_enter(&udpf->uf_lock);
412 
413 		/* Print the hash index. */
414 		udp = udpf->uf_udp;
415 		if (zoneid != GLOBAL_ZONEID) {
416 			/* skip to first entry in this zone; might be none */
417 			while (udp != NULL &&
418 			    udp->udp_zoneid != zoneid)
419 				udp = udp->udp_bind_hash;
420 		}
421 		if (udp != NULL) {
422 			uint_t print_len, buf_len;
423 
424 			buf_len = mp->b_cont->b_datap->db_lim -
425 			    mp->b_cont->b_wptr;
426 			print_len = snprintf((char *)mp->b_cont->b_wptr,
427 			    buf_len, "%d\n", i);
428 			if (print_len < buf_len) {
429 				mp->b_cont->b_wptr += print_len;
430 			} else {
431 				mp->b_cont->b_wptr += buf_len;
432 			}
433 			for (; udp != NULL; udp = udp->udp_bind_hash) {
434 				if (zoneid == GLOBAL_ZONEID ||
435 				    zoneid == udp->udp_zoneid)
436 					udp_report_item(mp->b_cont, udp);
437 			}
438 		}
439 		mutex_exit(&udpf->uf_lock);
440 	}
441 	udp_last_ndd_get_info_time = ddi_get_lbolt();
442 	return (0);
443 }
444 
445 /*
446  * Hash list removal routine for udp_t structures.
447  */
448 static void
449 udp_bind_hash_remove(udp_t *udp, boolean_t caller_holds_lock)
450 {
451 	udp_t	*udpnext;
452 	kmutex_t *lockp;
453 
454 	if (udp->udp_ptpbhn == NULL)
455 		return;
456 
457 	/*
458 	 * Extract the lock pointer in case there are concurrent
459 	 * hash_remove's for this instance.
460 	 */
461 	ASSERT(udp->udp_port != 0);
462 	if (!caller_holds_lock) {
463 		lockp = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)].uf_lock;
464 		ASSERT(lockp != NULL);
465 		mutex_enter(lockp);
466 	}
467 	if (udp->udp_ptpbhn != NULL) {
468 		udpnext = udp->udp_bind_hash;
469 		if (udpnext != NULL) {
470 			udpnext->udp_ptpbhn = udp->udp_ptpbhn;
471 			udp->udp_bind_hash = NULL;
472 		}
473 		*udp->udp_ptpbhn = udpnext;
474 		udp->udp_ptpbhn = NULL;
475 	}
476 	if (!caller_holds_lock) {
477 		mutex_exit(lockp);
478 	}
479 }
480 
481 static void
482 udp_bind_hash_insert(udp_fanout_t *uf, udp_t *udp)
483 {
484 	udp_t	**udpp;
485 	udp_t	*udpnext;
486 
487 	ASSERT(MUTEX_HELD(&uf->uf_lock));
488 	if (udp->udp_ptpbhn != NULL) {
489 		udp_bind_hash_remove(udp, B_TRUE);
490 	}
491 	udpp = &uf->uf_udp;
492 	udpnext = udpp[0];
493 	if (udpnext != NULL) {
494 		/*
495 		 * If the new udp bound to the INADDR_ANY address
496 		 * and the first one in the list is not bound to
497 		 * INADDR_ANY we skip all entries until we find the
498 		 * first one bound to INADDR_ANY.
499 		 * This makes sure that applications binding to a
500 		 * specific address get preference over those binding to
501 		 * INADDR_ANY.
502 		 */
503 		if (V6_OR_V4_INADDR_ANY(udp->udp_bound_v6src) &&
504 		    !V6_OR_V4_INADDR_ANY(udpnext->udp_bound_v6src)) {
505 			while ((udpnext = udpp[0]) != NULL &&
506 			    !V6_OR_V4_INADDR_ANY(
507 			    udpnext->udp_bound_v6src)) {
508 				udpp = &(udpnext->udp_bind_hash);
509 			}
510 			if (udpnext != NULL)
511 				udpnext->udp_ptpbhn = &udp->udp_bind_hash;
512 		} else {
513 			udpnext->udp_ptpbhn = &udp->udp_bind_hash;
514 		}
515 	}
516 	udp->udp_bind_hash = udpnext;
517 	udp->udp_ptpbhn = udpp;
518 	udpp[0] = udp;
519 }
520 
521 /*
522  * This routine is called to handle each O_T_BIND_REQ/T_BIND_REQ message
523  * passed to udp_wput.
524  * It associates a port number and local address with the stream.
525  * The O_T_BIND_REQ/T_BIND_REQ is passed downstream to ip with the UDP
526  * protocol type (IPPROTO_UDP) placed in the message following the address.
527  * A T_BIND_ACK message is passed upstream when ip acknowledges the request.
528  * (Called as writer.)
529  *
530  * Note that UDP over IPv4 and IPv6 sockets can use the same port number
531  * without setting SO_REUSEADDR. This is needed so that they
532  * can be viewed as two independent transport protocols.
533  * However, anonymouns ports are allocated from the same range to avoid
534  * duplicating the udp_g_next_port_to_try.
535  */
536 static void
537 udp_bind(queue_t *q, mblk_t *mp)
538 {
539 	sin_t		*sin;
540 	sin6_t		*sin6;
541 	mblk_t		*mp1;
542 	in_port_t	port;		/* Host byte order */
543 	in_port_t	requested_port;	/* Host byte order */
544 	struct T_bind_req *tbr;
545 	udp_t		*udp;
546 	int		count;
547 	in6_addr_t	v6src;
548 	boolean_t	bind_to_req_port_only;
549 	int		loopmax;
550 	udp_fanout_t	*udpf;
551 	in_port_t	lport;		/* Network byte order */
552 	zoneid_t	zoneid;
553 
554 	udp = (udp_t *)q->q_ptr;
555 	if ((mp->b_wptr - mp->b_rptr) < sizeof (*tbr)) {
556 		(void) mi_strlog(q, 1, SL_ERROR|SL_TRACE,
557 		    "udp_bind: bad req, len %u",
558 		    (uint_t)(mp->b_wptr - mp->b_rptr));
559 		udp_err_ack(q, mp, TPROTO, 0);
560 		return;
561 	}
562 	if (udp->udp_state != TS_UNBND) {
563 		(void) mi_strlog(q, 1, SL_ERROR|SL_TRACE,
564 		    "udp_bind: bad state, %u", udp->udp_state);
565 		udp_err_ack(q, mp, TOUTSTATE, 0);
566 		return;
567 	}
568 	/*
569 	 * Reallocate the message to make sure we have enough room for an
570 	 * address and the protocol type.
571 	 */
572 	mp1 = reallocb(mp, sizeof (struct T_bind_ack) + sizeof (sin6_t) + 1, 1);
573 	if (!mp1) {
574 		udp_err_ack(q, mp, TSYSERR, ENOMEM);
575 		return;
576 	}
577 
578 	mp = mp1;
579 	tbr = (struct T_bind_req *)mp->b_rptr;
580 	switch (tbr->ADDR_length) {
581 	case 0:			/* Request for a generic port */
582 		tbr->ADDR_offset = sizeof (struct T_bind_req);
583 		if (udp->udp_family == AF_INET) {
584 			tbr->ADDR_length = sizeof (sin_t);
585 			sin = (sin_t *)&tbr[1];
586 			*sin = sin_null;
587 			sin->sin_family = AF_INET;
588 			mp->b_wptr = (uchar_t *)&sin[1];
589 		} else {
590 			ASSERT(udp->udp_family == AF_INET6);
591 			tbr->ADDR_length = sizeof (sin6_t);
592 			sin6 = (sin6_t *)&tbr[1];
593 			*sin6 = sin6_null;
594 			sin6->sin6_family = AF_INET6;
595 			mp->b_wptr = (uchar_t *)&sin6[1];
596 		}
597 		port = 0;
598 		break;
599 
600 	case sizeof (sin_t):	/* Complete IPv4 address */
601 		sin = (sin_t *)mi_offset_param(mp, tbr->ADDR_offset,
602 		    sizeof (sin_t));
603 		if (sin == NULL || !OK_32PTR((char *)sin)) {
604 			udp_err_ack(q, mp, TSYSERR, EINVAL);
605 			return;
606 		}
607 		if (udp->udp_family != AF_INET ||
608 		    sin->sin_family != AF_INET) {
609 			udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT);
610 			return;
611 		}
612 		port = ntohs(sin->sin_port);
613 		break;
614 
615 	case sizeof (sin6_t):	/* complete IPv6 address */
616 		sin6 = (sin6_t *)mi_offset_param(mp, tbr->ADDR_offset,
617 		    sizeof (sin6_t));
618 		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
619 			udp_err_ack(q, mp, TSYSERR, EINVAL);
620 			return;
621 		}
622 		if (udp->udp_family != AF_INET6 ||
623 		    sin6->sin6_family != AF_INET6) {
624 			udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT);
625 			return;
626 		}
627 		port = ntohs(sin6->sin6_port);
628 		break;
629 
630 	default:		/* Invalid request */
631 		(void) mi_strlog(q, 1, SL_ERROR|SL_TRACE,
632 		    "udp_bind: bad ADDR_length length %u", tbr->ADDR_length);
633 		udp_err_ack(q, mp, TBADADDR, 0);
634 		return;
635 	}
636 
637 	requested_port = port;
638 
639 	if (requested_port == 0 || tbr->PRIM_type == O_T_BIND_REQ)
640 		bind_to_req_port_only = B_FALSE;
641 	else			/* T_BIND_REQ and requested_port != 0 */
642 		bind_to_req_port_only = B_TRUE;
643 
644 	if (requested_port == 0) {
645 		/*
646 		 * If the application passed in zero for the port number, it
647 		 * doesn't care which port number we bind to. Get one in the
648 		 * valid range.
649 		 */
650 		if (udp->udp_anon_priv_bind) {
651 			port = udp_get_next_priv_port();
652 		} else {
653 			port = udp_update_next_port(udp_g_next_port_to_try,
654 			    B_TRUE);
655 		}
656 	} else {
657 		/*
658 		 * If the port is in the well-known privileged range,
659 		 * make sure the caller was privileged.
660 		 */
661 		int i;
662 		boolean_t priv = B_FALSE;
663 
664 		if (port < udp_smallest_nonpriv_port) {
665 			priv = B_TRUE;
666 		} else {
667 			for (i = 0; i < udp_g_num_epriv_ports; i++) {
668 				if (port == udp_g_epriv_ports[i]) {
669 					priv = B_TRUE;
670 					break;
671 				}
672 			}
673 		}
674 
675 		if (priv) {
676 			cred_t *cr = DB_CREDDEF(mp, udp->udp_credp);
677 
678 			if (secpolicy_net_privaddr(cr, port) != 0) {
679 				udp_err_ack(q, mp, TACCES, 0);
680 				return;
681 			}
682 		}
683 	}
684 
685 	/*
686 	 * Copy the source address into our udp structure. This address
687 	 * may still be zero; if so, IP will fill in the correct address
688 	 * each time an outbound packet is passed to it.
689 	 */
690 	if (udp->udp_family == AF_INET) {
691 		ASSERT(sin != NULL);
692 		ASSERT(udp->udp_ipversion == IPV4_VERSION);
693 		udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE +
694 		    udp->udp_ip_snd_options_len;
695 		IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &v6src);
696 	} else {
697 		ASSERT(sin6 != NULL);
698 		v6src = sin6->sin6_addr;
699 		if (IN6_IS_ADDR_V4MAPPED(&v6src)) {
700 			udp->udp_ipversion = IPV4_VERSION;
701 			udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
702 			    UDPH_SIZE + udp->udp_ip_snd_options_len;
703 		} else {
704 			udp->udp_ipversion = IPV6_VERSION;
705 			udp->udp_max_hdr_len = udp->udp_sticky_hdrs_len;
706 		}
707 	}
708 
709 	/*
710 	 * If udp_reuseaddr is not set, then we have to make sure that
711 	 * the IP address and port number the application requested
712 	 * (or we selected for the application) is not being used by
713 	 * another stream.  If another stream is already using the
714 	 * requested IP address and port, the behavior depends on
715 	 * "bind_to_req_port_only". If set the bind fails; otherwise we
716 	 * search for any an unused port to bind to the the stream.
717 	 *
718 	 * As per the BSD semantics, as modified by the Deering multicast
719 	 * changes, if udp_reuseaddr is set, then we allow multiple binds
720 	 * to the same port independent of the local IP address.
721 	 *
722 	 * This is slightly different than in SunOS 4.X which did not
723 	 * support IP multicast. Note that the change implemented by the
724 	 * Deering multicast code effects all binds - not only binding
725 	 * to IP multicast addresses.
726 	 *
727 	 * Note that when binding to port zero we ignore SO_REUSEADDR in
728 	 * order to guarantee a unique port.
729 	 */
730 
731 	count = 0;
732 	if (udp->udp_anon_priv_bind) {
733 		/* loopmax = (IPPORT_RESERVED-1) - udp_min_anonpriv_port + 1 */
734 		loopmax = IPPORT_RESERVED - udp_min_anonpriv_port;
735 	} else {
736 		loopmax = udp_largest_anon_port - udp_smallest_anon_port + 1;
737 	}
738 
739 	zoneid = udp->udp_zoneid;
740 	for (;;) {
741 		udp_t		*udp1;
742 		boolean_t	is_inaddr_any;
743 		boolean_t	found_exclbind = B_FALSE;
744 
745 		is_inaddr_any = V6_OR_V4_INADDR_ANY(v6src);
746 		/*
747 		 * Walk through the list of udp streams bound to
748 		 * requested port with the same IP address.
749 		 */
750 		lport = htons(port);
751 		udpf = &udp_bind_fanout[UDP_BIND_HASH(lport)];
752 		mutex_enter(&udpf->uf_lock);
753 		for (udp1 = udpf->uf_udp; udp1 != NULL;
754 		    udp1 = udp1->udp_bind_hash) {
755 			if (lport != udp1->udp_port ||
756 			    zoneid != udp1->udp_zoneid)
757 				continue;
758 
759 			/*
760 			 * If UDP_EXCLBIND is set for either the bound or
761 			 * binding endpoint, the semantics of bind
762 			 * is changed according to the following chart.
763 			 *
764 			 * spec = specified address (v4 or v6)
765 			 * unspec = unspecified address (v4 or v6)
766 			 * A = specified addresses are different for endpoints
767 			 *
768 			 * bound	bind to		allowed?
769 			 * -------------------------------------
770 			 * unspec	unspec		no
771 			 * unspec	spec		no
772 			 * spec		unspec		no
773 			 * spec		spec		yes if A
774 			 */
775 			if (udp1->udp_exclbind || udp->udp_exclbind) {
776 				if (V6_OR_V4_INADDR_ANY(
777 				    udp1->udp_bound_v6src) ||
778 				    is_inaddr_any ||
779 				    IN6_ARE_ADDR_EQUAL(&udp1->udp_bound_v6src,
780 				    &v6src)) {
781 					found_exclbind = B_TRUE;
782 					break;
783 				}
784 				continue;
785 			}
786 
787 			/*
788 			 * Check ipversion to allow IPv4 and IPv6 sockets to
789 			 * have disjoint port number spaces.
790 			 */
791 			if (udp->udp_ipversion != udp1->udp_ipversion)
792 				continue;
793 
794 			/*
795 			 * No difference depending on SO_REUSEADDR.
796 			 *
797 			 * If existing port is bound to a
798 			 * non-wildcard IP address and
799 			 * the requesting stream is bound to
800 			 * a distinct different IP addresses
801 			 * (non-wildcard, also), keep going.
802 			 */
803 			if (!is_inaddr_any &&
804 			    !V6_OR_V4_INADDR_ANY(udp1->udp_bound_v6src) &&
805 			    !IN6_ARE_ADDR_EQUAL(&udp1->udp_bound_v6src,
806 			    &v6src)) {
807 				continue;
808 			}
809 			break;
810 		}
811 
812 		if (!found_exclbind &&
813 		    (udp->udp_reuseaddr && requested_port != 0)) {
814 			break;
815 		}
816 
817 		if (udp1 == NULL) {
818 			/*
819 			 * No other stream has this IP address
820 			 * and port number. We can use it.
821 			 */
822 			break;
823 		}
824 		mutex_exit(&udpf->uf_lock);
825 		if (bind_to_req_port_only) {
826 			/*
827 			 * We get here only when requested port
828 			 * is bound (and only first  of the for()
829 			 * loop iteration).
830 			 *
831 			 * The semantics of this bind request
832 			 * require it to fail so we return from
833 			 * the routine (and exit the loop).
834 			 *
835 			 */
836 			udp_err_ack(q, mp, TADDRBUSY, 0);
837 			return;
838 		}
839 
840 		if (udp->udp_anon_priv_bind) {
841 			port = udp_get_next_priv_port();
842 		} else {
843 			if ((count == 0) && (requested_port != 0)) {
844 				/*
845 				 * If the application wants us to find
846 				 * a port, get one to start with. Set
847 				 * requested_port to 0, so that we will
848 				 * update udp_g_next_port_to_try below.
849 				 */
850 				port = udp_update_next_port(
851 				    udp_g_next_port_to_try, B_TRUE);
852 				requested_port = 0;
853 			} else {
854 				port = udp_update_next_port(port + 1, B_FALSE);
855 			}
856 		}
857 
858 		if (++count >= loopmax) {
859 			/*
860 			 * We've tried every possible port number and
861 			 * there are none available, so send an error
862 			 * to the user.
863 			 */
864 			udp_err_ack(q, mp, TNOADDR, 0);
865 			return;
866 		}
867 	}
868 
869 	/*
870 	 * Copy the source address into our udp structure.  This address
871 	 * may still be zero; if so, ip will fill in the correct address
872 	 * each time an outbound packet is passed to it.
873 	 * If we are binding to a broadcast or multicast address udp_rput
874 	 * will clear the source address when it receives the T_BIND_ACK.
875 	 */
876 	udp->udp_v6src = udp->udp_bound_v6src = v6src;
877 	udp->udp_port = lport;
878 	/*
879 	 * Now reset the the next anonymous port if the application requested
880 	 * an anonymous port, or we handed out the next anonymous port.
881 	 */
882 	if ((requested_port == 0) && (!udp->udp_anon_priv_bind)) {
883 		udp_g_next_port_to_try = port + 1;
884 	}
885 
886 	/* Initialize the O_T_BIND_REQ/T_BIND_REQ for ip. */
887 	if (udp->udp_family == AF_INET) {
888 		sin->sin_port = udp->udp_port;
889 	} else {
890 		int error;
891 
892 		sin6->sin6_port = udp->udp_port;
893 		/* Rebuild the header template */
894 		error = udp_build_hdrs(q, udp);
895 		if (error != 0) {
896 			mutex_exit(&udpf->uf_lock);
897 			udp_err_ack(q, mp, TSYSERR, error);
898 			return;
899 		}
900 	}
901 	udp->udp_state = TS_IDLE;
902 	udp_bind_hash_insert(udpf, udp);
903 	mutex_exit(&udpf->uf_lock);
904 
905 	if (cl_inet_bind) {
906 		/*
907 		 * Running in cluster mode - register bind information
908 		 */
909 		if (udp->udp_ipversion == IPV4_VERSION) {
910 			(*cl_inet_bind)(IPPROTO_UDP, AF_INET,
911 			    (uint8_t *)(&V4_PART_OF_V6(udp->udp_v6src)),
912 			    (in_port_t)udp->udp_port);
913 		} else {
914 			(*cl_inet_bind)(IPPROTO_UDP, AF_INET6,
915 			    (uint8_t *)&(udp->udp_v6src),
916 			    (in_port_t)udp->udp_port);
917 		}
918 
919 	}
920 
921 	/* Pass the protocol number in the message following the address. */
922 	*mp->b_wptr++ = IPPROTO_UDP;
923 	if (!V6_OR_V4_INADDR_ANY(udp->udp_v6src)) {
924 		/*
925 		 * Append a request for an IRE if udp_v6src not
926 		 * zero (IPv4 - INADDR_ANY, or IPv6 - all-zeroes address).
927 		 */
928 		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
929 		if (!mp->b_cont) {
930 			udp_err_ack(q, mp, TSYSERR, ENOMEM);
931 			return;
932 		}
933 		mp->b_cont->b_wptr += sizeof (ire_t);
934 		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
935 	}
936 	putnext(q, mp);
937 }
938 
939 /*
940  * This routine handles each T_CONN_REQ message passed to udp.  It
941  * associates a default destination address with the stream.
942  *
943  * This routine sends down a T_BIND_REQ to IP with the following mblks:
944  *	T_BIND_REQ	- specifying local and remote address/port
945  *	IRE_DB_REQ_TYPE	- to get an IRE back containing ire_type and src
946  *	T_OK_ACK	- for the T_CONN_REQ
947  *	T_CONN_CON	- to keep the TPI user happy
948  *
949  * The connect completes in udp_rput.
950  * When a T_BIND_ACK is received information is extracted from the IRE
951  * and the two appended messages are sent to the TPI user.
952  * Should udp_rput receive T_ERROR_ACK for the T_BIND_REQ it will convert
953  * it to an error ack for the appropriate primitive.
954  */
955 static void
956 udp_connect(queue_t *q, mblk_t *mp)
957 {
958 	sin6_t	*sin6;
959 	sin_t	*sin;
960 	struct T_conn_req	*tcr;
961 	udp_t	*udp, *udp1;
962 	in6_addr_t v6dst;
963 	ipaddr_t v4dst;
964 	uint16_t dstport;
965 	uint32_t flowinfo;
966 	mblk_t	*mp1, *mp2;
967 	udp_fanout_t	*udpf;
968 
969 	udp = (udp_t *)q->q_ptr;
970 	tcr = (struct T_conn_req *)mp->b_rptr;
971 
972 	/* A bit of sanity checking */
973 	if ((mp->b_wptr - mp->b_rptr) < sizeof (struct T_conn_req)) {
974 		udp_err_ack(q, mp, TPROTO, 0);
975 		return;
976 	}
977 	/*
978 	 * This UDP must have bound to a port already before doing
979 	 * a connect.
980 	 */
981 	if (udp->udp_state == TS_UNBND) {
982 		(void) mi_strlog(q, 1, SL_ERROR|SL_TRACE,
983 		    "udp_connect: bad state, %u", udp->udp_state);
984 		udp_err_ack(q, mp, TOUTSTATE, 0);
985 		return;
986 	}
987 	ASSERT(udp->udp_port != 0 && udp->udp_ptpbhn != NULL);
988 
989 	udpf = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)];
990 	if (udp->udp_state == TS_DATA_XFER) {
991 		/* Already connected - clear out state */
992 		mutex_enter(&udpf->uf_lock);
993 		udp->udp_v6src = udp->udp_bound_v6src;
994 		udp->udp_state = TS_IDLE;
995 		mutex_exit(&udpf->uf_lock);
996 	}
997 
998 	if (tcr->OPT_length != 0) {
999 		udp_err_ack(q, mp, TBADOPT, 0);
1000 		return;
1001 	}
1002 
1003 	/*
1004 	 * Determine packet type based on type of address passed in
1005 	 * the request should contain an IPv4 or IPv6 address.
1006 	 * Make sure that address family matches the type of
1007 	 * family of the the address passed down
1008 	 */
1009 	switch (tcr->DEST_length) {
1010 	default:
1011 		udp_err_ack(q, mp, TBADADDR, 0);
1012 		return;
1013 
1014 	case sizeof (sin_t):
1015 		sin = (sin_t *)mi_offset_param(mp, tcr->DEST_offset,
1016 		    sizeof (sin_t));
1017 		if (sin == NULL || !OK_32PTR((char *)sin)) {
1018 			udp_err_ack(q, mp, TSYSERR, EINVAL);
1019 			return;
1020 		}
1021 		if (udp->udp_family != AF_INET ||
1022 		    sin->sin_family != AF_INET) {
1023 			udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT);
1024 			return;
1025 		}
1026 		v4dst = sin->sin_addr.s_addr;
1027 		dstport = sin->sin_port;
1028 		IN6_IPADDR_TO_V4MAPPED(v4dst, &v6dst);
1029 		ASSERT(udp->udp_ipversion == IPV4_VERSION);
1030 		udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE +
1031 		    udp->udp_ip_snd_options_len;
1032 		break;
1033 
1034 	case sizeof (sin6_t):
1035 		sin6 = (sin6_t *)mi_offset_param(mp, tcr->DEST_offset,
1036 		    sizeof (sin6_t));
1037 		if (sin6 == NULL || !OK_32PTR((char *)sin6)) {
1038 			udp_err_ack(q, mp, TSYSERR, EINVAL);
1039 			return;
1040 		}
1041 		if (udp->udp_family != AF_INET6 ||
1042 		    sin6->sin6_family != AF_INET6) {
1043 			udp_err_ack(q, mp, TSYSERR, EAFNOSUPPORT);
1044 			return;
1045 		}
1046 		v6dst = sin6->sin6_addr;
1047 		if (IN6_IS_ADDR_V4MAPPED(&v6dst)) {
1048 			IN6_V4MAPPED_TO_IPADDR(&v6dst, v4dst);
1049 			udp->udp_ipversion = IPV4_VERSION;
1050 			udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
1051 			    UDPH_SIZE + udp->udp_ip_snd_options_len;
1052 			flowinfo = 0;
1053 		} else {
1054 			udp->udp_ipversion = IPV6_VERSION;
1055 			udp->udp_max_hdr_len = udp->udp_sticky_hdrs_len;
1056 			flowinfo = sin6->sin6_flowinfo;
1057 		}
1058 		dstport = sin6->sin6_port;
1059 		break;
1060 	}
1061 	if (dstport == 0) {
1062 		udp_err_ack(q, mp, TBADADDR, 0);
1063 		return;
1064 	}
1065 
1066 	/*
1067 	 * Create a default IP header with no IP options.
1068 	 */
1069 	udp->udp_dstport = dstport;
1070 	if (udp->udp_ipversion == IPV4_VERSION) {
1071 		/*
1072 		 * Interpret a zero destination to mean loopback.
1073 		 * Update the T_CONN_REQ (sin/sin6) since it is used to
1074 		 * generate the T_CONN_CON.
1075 		 */
1076 		if (v4dst == INADDR_ANY) {
1077 			v4dst = htonl(INADDR_LOOPBACK);
1078 			IN6_IPADDR_TO_V4MAPPED(v4dst, &v6dst);
1079 			if (udp->udp_family == AF_INET) {
1080 				sin->sin_addr.s_addr = v4dst;
1081 			} else {
1082 				sin6->sin6_addr = v6dst;
1083 			}
1084 		}
1085 		udp->udp_v6dst = v6dst;
1086 		udp->udp_flowinfo = 0;
1087 
1088 		/*
1089 		 * If the destination address is multicast and
1090 		 * an outgoing multicast interface has been set,
1091 		 * use the address of that interface as our
1092 		 * source address if no source address has been set.
1093 		 */
1094 		if (V4_PART_OF_V6(udp->udp_v6src) == INADDR_ANY &&
1095 		    CLASSD(v4dst) &&
1096 		    udp->udp_multicast_if_addr != INADDR_ANY) {
1097 			IN6_IPADDR_TO_V4MAPPED(udp->udp_multicast_if_addr,
1098 			    &udp->udp_v6src);
1099 		}
1100 	} else {
1101 		ASSERT(udp->udp_ipversion == IPV6_VERSION);
1102 		/*
1103 		 * Interpret a zero destination to mean loopback.
1104 		 * Update the T_CONN_REQ (sin/sin6) since it is used to
1105 		 * generate the T_CONN_CON.
1106 		 */
1107 		if (IN6_IS_ADDR_UNSPECIFIED(&v6dst)) {
1108 			v6dst = ipv6_loopback;
1109 			sin6->sin6_addr = v6dst;
1110 		}
1111 		udp->udp_v6dst = v6dst;
1112 		udp->udp_flowinfo = flowinfo;
1113 		/*
1114 		 * If the destination address is multicast and
1115 		 * an outgoing multicast interface has been set,
1116 		 * then the ip bind logic will pick the correct source
1117 		 * address (i.e. matching the outgoing multicast interface).
1118 		 */
1119 	}
1120 
1121 	/*
1122 	 * Verify that the src/port/dst/port is unique for all
1123 	 * connections in TS_DATA_XFER
1124 	 */
1125 	mutex_enter(&udpf->uf_lock);
1126 	for (udp1 = udpf->uf_udp; udp1 != NULL; udp1 = udp1->udp_bind_hash) {
1127 		if (udp1->udp_state != TS_DATA_XFER)
1128 			continue;
1129 		if (udp->udp_port != udp1->udp_port ||
1130 		    udp->udp_ipversion != udp1->udp_ipversion ||
1131 		    dstport != udp1->udp_dstport ||
1132 		    !IN6_ARE_ADDR_EQUAL(&udp->udp_v6src, &udp1->udp_v6src) ||
1133 		    !IN6_ARE_ADDR_EQUAL(&v6dst, &udp1->udp_v6dst))
1134 			continue;
1135 		mutex_exit(&udpf->uf_lock);
1136 		udp_err_ack(q, mp, TBADADDR, 0);
1137 		return;
1138 	}
1139 	udp->udp_state = TS_DATA_XFER;
1140 	mutex_exit(&udpf->uf_lock);
1141 
1142 	/*
1143 	 * Send down bind to IP to verify that there is a route
1144 	 * and to determine the source address.
1145 	 * This will come back as T_BIND_ACK with an IRE_DB_TYPE in rput.
1146 	 */
1147 	if (udp->udp_family == AF_INET)
1148 		mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (ipa_conn_t));
1149 	else
1150 		mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (ipa6_conn_t));
1151 	if (mp1 == NULL) {
1152 		udp_err_ack(q, mp, TSYSERR, ENOMEM);
1153 bind_failed:
1154 		mutex_enter(&udpf->uf_lock);
1155 		udp->udp_state = TS_IDLE;
1156 		mutex_exit(&udpf->uf_lock);
1157 		return;
1158 	}
1159 
1160 	/*
1161 	 * We also have to send a connection confirmation to
1162 	 * keep TLI happy. Prepare it for udp_rput.
1163 	 */
1164 	if (udp->udp_family == AF_INET)
1165 		mp2 = mi_tpi_conn_con(NULL, (char *)sin,
1166 		    sizeof (*sin), NULL, 0);
1167 	else
1168 		mp2 = mi_tpi_conn_con(NULL, (char *)sin6,
1169 		    sizeof (*sin6), NULL, 0);
1170 	if (mp2 == NULL) {
1171 		freemsg(mp1);
1172 		udp_err_ack(q, mp, TSYSERR, ENOMEM);
1173 		goto bind_failed;
1174 	}
1175 
1176 	mp = mi_tpi_ok_ack_alloc(mp);
1177 	if (mp == NULL) {
1178 		/* Unable to reuse the T_CONN_REQ for the ack. */
1179 		freemsg(mp2);
1180 		udp_err_ack_prim(q, mp1, T_CONN_REQ, TSYSERR, ENOMEM);
1181 		goto bind_failed;
1182 	}
1183 
1184 	/* Hang onto the T_OK_ACK and T_CONN_CON for later. */
1185 	linkb(mp1, mp);
1186 	linkb(mp1, mp2);
1187 
1188 	putnext(q, mp1);
1189 }
1190 
1191 /* This is the close routine for udp.  It frees the per-stream data. */
1192 static int
1193 udp_close(queue_t *q)
1194 {
1195 	udp_t	*udp = (udp_t *)q->q_ptr;
1196 
1197 	TRACE_1(TR_FAC_UDP, TR_UDP_CLOSE,
1198 		"udp_close: q %p", q);
1199 
1200 	qprocsoff(q);
1201 
1202 	if (cl_inet_unbind != NULL && udp->udp_state == TS_IDLE) {
1203 		/*
1204 		 * Running in cluster mode - register unbind information
1205 		 */
1206 		if (udp->udp_ipversion == IPV4_VERSION) {
1207 			(*cl_inet_unbind)(IPPROTO_UDP, AF_INET,
1208 			    (uint8_t *)(&(V4_PART_OF_V6(udp->udp_v6src))),
1209 			    (in_port_t)udp->udp_port);
1210 		} else {
1211 			(*cl_inet_unbind)(IPPROTO_UDP, AF_INET6,
1212 			    (uint8_t *)(&(udp->udp_v6src)),
1213 			    (in_port_t)udp->udp_port);
1214 		}
1215 	}
1216 
1217 	udp_bind_hash_remove(udp, B_FALSE);
1218 	mutex_enter(&udp_g_lock);
1219 	/* Unlink the udp structure and release the minor device number. */
1220 	mi_close_unlink(&udp_g_head, (IDP)udp);
1221 	mutex_exit(&udp_g_lock);
1222 	/* If there are any options associated with the stream, free them. */
1223 	if (udp->udp_ip_snd_options)
1224 		mi_free((char *)udp->udp_ip_snd_options);
1225 
1226 	if (udp->udp_ip_rcv_options)
1227 		mi_free((char *)udp->udp_ip_rcv_options);
1228 
1229 	/* Free memory associated with sticky options */
1230 	if (udp->udp_sticky_hdrs_len != 0) {
1231 		kmem_free(udp->udp_sticky_hdrs,
1232 		    udp->udp_sticky_hdrs_len);
1233 		udp->udp_sticky_hdrs = NULL;
1234 		udp->udp_sticky_hdrs_len = 0;
1235 	}
1236 	if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) {
1237 		kmem_free(udp->udp_sticky_ipp.ipp_hopopts,
1238 		    udp->udp_sticky_ipp.ipp_hopoptslen);
1239 	}
1240 	if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) {
1241 		kmem_free(udp->udp_sticky_ipp.ipp_rtdstopts,
1242 		    udp->udp_sticky_ipp.ipp_rtdstoptslen);
1243 	}
1244 	if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) {
1245 		kmem_free(udp->udp_sticky_ipp.ipp_rthdr,
1246 		    udp->udp_sticky_ipp.ipp_rthdrlen);
1247 	}
1248 	if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) {
1249 		kmem_free(udp->udp_sticky_ipp.ipp_dstopts,
1250 		    udp->udp_sticky_ipp.ipp_dstoptslen);
1251 	}
1252 	udp->udp_sticky_ipp.ipp_fields &=
1253 	    ~(IPPF_HOPOPTS|IPPF_RTDSTOPTS|IPPF_RTHDR|IPPF_DSTOPTS);
1254 
1255 	crfree(udp->udp_credp);
1256 	/* Free the data structure */
1257 	mi_close_free((IDP)udp);
1258 	q->q_ptr = WR(q)->q_ptr = NULL;
1259 	return (0);
1260 }
1261 
1262 /*
1263  * This routine handles each T_DISCON_REQ message passed to udp
1264  * as an indicating that UDP is no longer connected. This results
1265  * in sending a T_BIND_REQ to IP to restore the binding to just
1266  * the local address/port.
1267  *
1268  * This routine sends down a T_BIND_REQ to IP with the following mblks:
1269  *	T_BIND_REQ	- specifying just the local address/port
1270  *	T_OK_ACK	- for the T_DISCON_REQ
1271  *
1272  * The disconnect completes in udp_rput.
1273  * When a T_BIND_ACK is received the appended T_OK_ACK is sent to the TPI user.
1274  * Should udp_rput receive T_ERROR_ACK for the T_BIND_REQ it will convert
1275  * it to an error ack for the appropriate primitive.
1276  */
1277 static void
1278 udp_disconnect(queue_t *q, mblk_t *mp)
1279 {
1280 	udp_t	*udp;
1281 	mblk_t	*mp1;
1282 	udp_fanout_t *udpf;
1283 
1284 	udp = (udp_t *)q->q_ptr;
1285 
1286 	if (udp->udp_state != TS_DATA_XFER) {
1287 		(void) mi_strlog(q, 1, SL_ERROR|SL_TRACE,
1288 		    "udp_disconnect: bad state, %u", udp->udp_state);
1289 		udp_err_ack(q, mp, TOUTSTATE, 0);
1290 		return;
1291 	}
1292 	udpf = &udp_bind_fanout[UDP_BIND_HASH(udp->udp_port)];
1293 	mutex_enter(&udpf->uf_lock);
1294 	udp->udp_v6src = udp->udp_bound_v6src;
1295 	udp->udp_state = TS_IDLE;
1296 	mutex_exit(&udpf->uf_lock);
1297 
1298 	/*
1299 	 * Send down bind to IP to remove the full binding and revert
1300 	 * to the local address binding.
1301 	 */
1302 	if (udp->udp_family == AF_INET)
1303 		mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (sin_t));
1304 	else
1305 		mp1 = udp_ip_bind_mp(udp, O_T_BIND_REQ, sizeof (sin6_t));
1306 	if (mp1 == NULL) {
1307 		udp_err_ack(q, mp, TSYSERR, ENOMEM);
1308 		return;
1309 	}
1310 	mp = mi_tpi_ok_ack_alloc(mp);
1311 	if (mp == NULL) {
1312 		/* Unable to reuse the T_DISCON_REQ for the ack. */
1313 		udp_err_ack_prim(q, mp1, T_DISCON_REQ, TSYSERR, ENOMEM);
1314 		return;
1315 	}
1316 
1317 	if (udp->udp_family == AF_INET6) {
1318 		int error;
1319 
1320 		/* Rebuild the header template */
1321 		error = udp_build_hdrs(q, udp);
1322 		if (error != 0) {
1323 			udp_err_ack_prim(q, mp, T_DISCON_REQ, TSYSERR, error);
1324 			freemsg(mp1);
1325 			return;
1326 		}
1327 	}
1328 	mutex_enter(&udpf->uf_lock);
1329 	udp->udp_discon_pending = 1;
1330 	mutex_exit(&udpf->uf_lock);
1331 
1332 	/* Append the T_OK_ACK to the T_BIND_REQ for udp_rput */
1333 	linkb(mp1, mp);
1334 	putnext(q, mp1);
1335 }
1336 
1337 /* This routine creates a T_ERROR_ACK message and passes it upstream. */
1338 static void
1339 udp_err_ack(queue_t *q, mblk_t *mp, t_scalar_t t_error, int sys_error)
1340 {
1341 	if ((mp = mi_tpi_err_ack_alloc(mp, t_error, sys_error)) != NULL)
1342 		qreply(q, mp);
1343 }
1344 
1345 /* Shorthand to generate and send TPI error acks to our client */
1346 static void
1347 udp_err_ack_prim(queue_t *q, mblk_t *mp, int primitive, t_scalar_t t_error,
1348     int sys_error)
1349 {
1350 	struct T_error_ack	*teackp;
1351 
1352 	if ((mp = tpi_ack_alloc(mp, sizeof (struct T_error_ack),
1353 	    M_PCPROTO, T_ERROR_ACK)) != NULL) {
1354 		teackp = (struct T_error_ack *)mp->b_rptr;
1355 		teackp->ERROR_prim = primitive;
1356 		teackp->TLI_error = t_error;
1357 		teackp->UNIX_error = sys_error;
1358 		qreply(q, mp);
1359 	}
1360 }
1361 
1362 /*ARGSUSED*/
1363 static int
1364 udp_extra_priv_ports_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
1365 {
1366 	int i;
1367 
1368 	for (i = 0; i < udp_g_num_epriv_ports; i++) {
1369 		if (udp_g_epriv_ports[i] != 0)
1370 			(void) mi_mpprintf(mp, "%d ", udp_g_epriv_ports[i]);
1371 	}
1372 	return (0);
1373 }
1374 
1375 /*
1376  * Hold udp_g_lock to prevent multiple threads from changing udp_g_epriv_ports
1377  * at the same time.
1378  */
1379 /* ARGSUSED */
1380 static int
1381 udp_extra_priv_ports_add(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
1382     cred_t *cr)
1383 {
1384 	long	new_value;
1385 	int	i;
1386 
1387 	/*
1388 	 * Fail the request if the new value does not lie within the
1389 	 * port number limits.
1390 	 */
1391 	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
1392 	    new_value <= 0 || new_value >= 65536) {
1393 		return (EINVAL);
1394 	}
1395 
1396 	mutex_enter(&udp_g_lock);
1397 	/* Check if the value is already in the list */
1398 	for (i = 0; i < udp_g_num_epriv_ports; i++) {
1399 		if (new_value == udp_g_epriv_ports[i]) {
1400 			mutex_exit(&udp_g_lock);
1401 			return (EEXIST);
1402 		}
1403 	}
1404 	/* Find an empty slot */
1405 	for (i = 0; i < udp_g_num_epriv_ports; i++) {
1406 		if (udp_g_epriv_ports[i] == 0)
1407 			break;
1408 	}
1409 	if (i == udp_g_num_epriv_ports) {
1410 		mutex_exit(&udp_g_lock);
1411 		return (EOVERFLOW);
1412 	}
1413 
1414 	/* Set the new value */
1415 	udp_g_epriv_ports[i] = (in_port_t)new_value;
1416 	mutex_exit(&udp_g_lock);
1417 	return (0);
1418 }
1419 
1420 /*
1421  * Hold udp_g_lock to prevent multiple threads from changing udp_g_epriv_ports
1422  * at the same time.
1423  */
1424 /* ARGSUSED */
1425 static int
1426 udp_extra_priv_ports_del(queue_t *q, mblk_t *mp, char *value, caddr_t cp,
1427     cred_t *cr)
1428 {
1429 	long	new_value;
1430 	int	i;
1431 
1432 	/*
1433 	 * Fail the request if the new value does not lie within the
1434 	 * port number limits.
1435 	 */
1436 	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
1437 	    new_value <= 0 || new_value >= 65536) {
1438 		return (EINVAL);
1439 	}
1440 
1441 	mutex_enter(&udp_g_lock);
1442 	/* Check that the value is already in the list */
1443 	for (i = 0; i < udp_g_num_epriv_ports; i++) {
1444 		if (udp_g_epriv_ports[i] == new_value)
1445 			break;
1446 	}
1447 	if (i == udp_g_num_epriv_ports) {
1448 		mutex_exit(&udp_g_lock);
1449 		return (ESRCH);
1450 	}
1451 
1452 	/* Clear the value */
1453 	udp_g_epriv_ports[i] = 0;
1454 	mutex_exit(&udp_g_lock);
1455 	return (0);
1456 }
1457 
1458 /* At minimum we need 4 bytes of UDP header */
1459 #define	ICMP_MIN_UDP_HDR	4
1460 
1461 /*
1462  * udp_icmp_error is called by udp_rput to process ICMP msgs. passed up by IP.
1463  * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors.
1464  * Assumes that IP has pulled up everything up to and including the ICMP header.
1465  * An M_CTL could potentially come here from some other module (i.e. if UDP
1466  * is pushed on some module other than IP). Thus, if we find that the M_CTL
1467  * does not have enough ICMP information , following STREAMS conventions,
1468  * we send it upstream assuming it is an M_CTL we don't understand.
1469  */
1470 static void
1471 udp_icmp_error(queue_t *q, mblk_t *mp)
1472 {
1473 	icmph_t *icmph;
1474 	ipha_t	*ipha;
1475 	int	iph_hdr_length;
1476 	udpha_t	*udpha;
1477 	sin_t	sin;
1478 	sin6_t	sin6;
1479 	mblk_t	*mp1;
1480 	int	error = 0;
1481 	udp_t	*udp = (udp_t *)q->q_ptr;
1482 	size_t	mp_size = MBLKL(mp);
1483 
1484 	/*
1485 	 * Assume IP provides aligned packets - otherwise toss
1486 	 */
1487 	if (!OK_32PTR(mp->b_rptr)) {
1488 		freemsg(mp);
1489 		return;
1490 	}
1491 
1492 	/*
1493 	 * Verify that we have a complete IP header and the application has
1494 	 * asked for errors. If not, send it upstream.
1495 	 */
1496 	if (!udp->udp_dgram_errind || mp_size < sizeof (ipha_t)) {
1497 noticmpv4:
1498 		putnext(q, mp);
1499 		return;
1500 	}
1501 
1502 	ipha = (ipha_t *)mp->b_rptr;
1503 	/*
1504 	 * Verify IP version. Anything other than IPv4 or IPv6 packet is sent
1505 	 * upstream. ICMPv6  is handled in udp_icmp_error_ipv6.
1506 	 */
1507 	switch (IPH_HDR_VERSION(ipha)) {
1508 	case IPV6_VERSION:
1509 		udp_icmp_error_ipv6(q, mp);
1510 		return;
1511 	case IPV4_VERSION:
1512 		break;
1513 	default:
1514 		goto noticmpv4;
1515 	}
1516 
1517 	/* Skip past the outer IP and ICMP headers */
1518 	iph_hdr_length = IPH_HDR_LENGTH(ipha);
1519 	icmph = (icmph_t *)&mp->b_rptr[iph_hdr_length];
1520 	/*
1521 	 * If we don't have the correct outer IP header length or if the ULP
1522 	 * is not IPPROTO_ICMP or if we don't have a complete inner IP header
1523 	 * send the packet upstream.
1524 	 */
1525 	if (iph_hdr_length < sizeof (ipha_t) ||
1526 	    ipha->ipha_protocol != IPPROTO_ICMP ||
1527 	    (ipha_t *)&icmph[1] + 1 > (ipha_t *)mp->b_wptr) {
1528 		goto noticmpv4;
1529 	}
1530 	ipha = (ipha_t *)&icmph[1];
1531 
1532 	/* Skip past the inner IP and find the ULP header */
1533 	iph_hdr_length = IPH_HDR_LENGTH(ipha);
1534 	udpha = (udpha_t *)((char *)ipha + iph_hdr_length);
1535 	/*
1536 	 * If we don't have the correct inner IP header length or if the ULP
1537 	 * is not IPPROTO_UDP or if we don't have at least ICMP_MIN_UDP_HDR
1538 	 * bytes of UDP header, send it upstream.
1539 	 */
1540 	if (iph_hdr_length < sizeof (ipha_t) ||
1541 	    ipha->ipha_protocol != IPPROTO_UDP ||
1542 	    (uchar_t *)udpha + ICMP_MIN_UDP_HDR > mp->b_wptr) {
1543 		goto noticmpv4;
1544 	}
1545 
1546 	switch (icmph->icmph_type) {
1547 	case ICMP_DEST_UNREACHABLE:
1548 		switch (icmph->icmph_code) {
1549 		case ICMP_FRAGMENTATION_NEEDED:
1550 			/*
1551 			 * IP has already adjusted the path MTU.
1552 			 * XXX Somehow pass MTU indication to application?
1553 			 */
1554 			break;
1555 		case ICMP_PORT_UNREACHABLE:
1556 		case ICMP_PROTOCOL_UNREACHABLE:
1557 			error = ECONNREFUSED;
1558 			break;
1559 		default:
1560 			/* Transient errors */
1561 			break;
1562 		}
1563 		break;
1564 	default:
1565 		/* Transient errors */
1566 		break;
1567 	}
1568 	if (error == 0) {
1569 		freemsg(mp);
1570 		return;
1571 	}
1572 
1573 	switch (udp->udp_family) {
1574 	case AF_INET:
1575 		sin = sin_null;
1576 		sin.sin_family = AF_INET;
1577 		sin.sin_addr.s_addr = ipha->ipha_dst;
1578 		sin.sin_port = udpha->uha_dst_port;
1579 		mp1 = mi_tpi_uderror_ind((char *)&sin, sizeof (sin_t), NULL, 0,
1580 		    error);
1581 		break;
1582 	case AF_INET6:
1583 		sin6 = sin6_null;
1584 		sin6.sin6_family = AF_INET6;
1585 		IN6_IPADDR_TO_V4MAPPED(ipha->ipha_dst, &sin6.sin6_addr);
1586 		sin6.sin6_port = udpha->uha_dst_port;
1587 
1588 		mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t),
1589 		    NULL, 0, error);
1590 		break;
1591 	}
1592 	if (mp1)
1593 		putnext(q, mp1);
1594 	freemsg(mp);
1595 }
1596 
1597 /*
1598  * udp_icmp_error_ipv6 is called by udp_icmp_error to process ICMP for IPv6.
1599  * Generates the appropriate T_UDERROR_IND for permanent (non-transient) errors.
1600  * Assumes that IP has pulled up all the extension headers as well as the
1601  * ICMPv6 header.
1602  * An M_CTL could potentially come here from some other module (i.e. if UDP
1603  * is pushed on some module other than IP). Thus, if we find that the M_CTL
1604  * does not have enough ICMP information , following STREAMS conventions,
1605  * we send it upstream assuming it is an M_CTL we don't understand. The reason
1606  * it might get here is if the non-ICMP M_CTL accidently has 6 in the version
1607  * field (when cast to ipha_t in udp_icmp_error).
1608  */
1609 static void
1610 udp_icmp_error_ipv6(queue_t *q, mblk_t *mp)
1611 {
1612 	udp_t		*udp = (udp_t *)q->q_ptr;
1613 	icmp6_t		*icmp6;
1614 	ip6_t		*ip6h, *outer_ip6h;
1615 	uint16_t	hdr_length;
1616 	uint8_t		*nexthdrp;
1617 	udpha_t		*udpha;
1618 	sin6_t		sin6;
1619 	mblk_t		*mp1;
1620 	int		error = 0;
1621 	size_t		mp_size = MBLKL(mp);
1622 
1623 	/*
1624 	 * Verify that we have a complete IP header. If not, send it upstream.
1625 	 */
1626 	if (mp_size < sizeof (ip6_t)) {
1627 noticmpv6:
1628 		putnext(q, mp);
1629 		return;
1630 	}
1631 
1632 	outer_ip6h = (ip6_t *)mp->b_rptr;
1633 	/*
1634 	 * Verify this is an ICMPV6 packet, else send it upstream
1635 	 */
1636 	if (outer_ip6h->ip6_nxt == IPPROTO_ICMPV6) {
1637 		hdr_length = IPV6_HDR_LEN;
1638 	} else if (!ip_hdr_length_nexthdr_v6(mp, outer_ip6h, &hdr_length,
1639 	    &nexthdrp) ||
1640 	    *nexthdrp != IPPROTO_ICMPV6) {
1641 		goto noticmpv6;
1642 	}
1643 	icmp6 = (icmp6_t *)&mp->b_rptr[hdr_length];
1644 	ip6h = (ip6_t *)&icmp6[1];
1645 	/*
1646 	 * Verify we have a complete ICMP and inner IP header.
1647 	 */
1648 	if ((uchar_t *)&ip6h[1] > mp->b_wptr)
1649 		goto noticmpv6;
1650 
1651 	if (!ip_hdr_length_nexthdr_v6(mp, ip6h, &hdr_length, &nexthdrp))
1652 		goto noticmpv6;
1653 	udpha = (udpha_t *)((char *)ip6h + hdr_length);
1654 	/*
1655 	 * Validate inner header. If the ULP is not IPPROTO_UDP or if we don't
1656 	 * have at least ICMP_MIN_UDP_HDR bytes of  UDP header send the
1657 	 * packet upstream.
1658 	 */
1659 	if ((*nexthdrp != IPPROTO_UDP) ||
1660 	    ((uchar_t *)udpha + ICMP_MIN_UDP_HDR) > mp->b_wptr) {
1661 		goto noticmpv6;
1662 	}
1663 
1664 	switch (icmp6->icmp6_type) {
1665 	case ICMP6_DST_UNREACH:
1666 		switch (icmp6->icmp6_code) {
1667 		case ICMP6_DST_UNREACH_NOPORT:
1668 			error = ECONNREFUSED;
1669 			break;
1670 		case ICMP6_DST_UNREACH_ADMIN:
1671 		case ICMP6_DST_UNREACH_NOROUTE:
1672 		case ICMP6_DST_UNREACH_BEYONDSCOPE:
1673 		case ICMP6_DST_UNREACH_ADDR:
1674 			/* Transient errors */
1675 			break;
1676 		default:
1677 			break;
1678 		}
1679 		break;
1680 	case ICMP6_PACKET_TOO_BIG: {
1681 		struct T_unitdata_ind	*tudi;
1682 		struct T_opthdr		*toh;
1683 		size_t			udi_size;
1684 		mblk_t			*newmp;
1685 		t_scalar_t		opt_length = sizeof (struct T_opthdr) +
1686 		    sizeof (struct ip6_mtuinfo);
1687 		sin6_t			*sin6;
1688 		struct ip6_mtuinfo	*mtuinfo;
1689 
1690 		/*
1691 		 * If the application has requested to receive path mtu
1692 		 * information, send up an empty message containing an
1693 		 * IPV6_PATHMTU ancillary data item.
1694 		 */
1695 		if (!udp->udp_ipv6_recvpathmtu)
1696 			break;
1697 
1698 		udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t) +
1699 		    opt_length;
1700 		if ((newmp = allocb(udi_size, BPRI_MED)) == NULL) {
1701 			BUMP_MIB(&udp_mib, udpInErrors);
1702 			break;
1703 		}
1704 
1705 		/*
1706 		 * newmp->b_cont is left to NULL on purpose.  This is an
1707 		 * empty message containing only ancillary data.
1708 		 */
1709 		newmp->b_datap->db_type = M_PROTO;
1710 		tudi = (struct T_unitdata_ind *)newmp->b_rptr;
1711 		newmp->b_wptr = (uchar_t *)tudi + udi_size;
1712 		tudi->PRIM_type = T_UNITDATA_IND;
1713 		tudi->SRC_length = sizeof (sin6_t);
1714 		tudi->SRC_offset = sizeof (struct T_unitdata_ind);
1715 		tudi->OPT_offset = tudi->SRC_offset + sizeof (sin6_t);
1716 		tudi->OPT_length = opt_length;
1717 
1718 		sin6 = (sin6_t *)&tudi[1];
1719 		bzero(sin6, sizeof (sin6_t));
1720 		sin6->sin6_family = AF_INET6;
1721 		sin6->sin6_addr = udp->udp_v6dst;
1722 
1723 		toh = (struct T_opthdr *)&sin6[1];
1724 		toh->level = IPPROTO_IPV6;
1725 		toh->name = IPV6_PATHMTU;
1726 		toh->len = opt_length;
1727 		toh->status = 0;
1728 
1729 		mtuinfo = (struct ip6_mtuinfo *)&toh[1];
1730 		bzero(mtuinfo, sizeof (struct ip6_mtuinfo));
1731 		mtuinfo->ip6m_addr.sin6_family = AF_INET6;
1732 		mtuinfo->ip6m_addr.sin6_addr = ip6h->ip6_dst;
1733 		mtuinfo->ip6m_mtu = icmp6->icmp6_mtu;
1734 		/*
1735 		 * We've consumed everything we need from the original
1736 		 * message.  Free it, then send our empty message.
1737 		 */
1738 		freemsg(mp);
1739 		putnext(q, newmp);
1740 		return;
1741 	}
1742 	case ICMP6_TIME_EXCEEDED:
1743 		/* Transient errors */
1744 		break;
1745 	case ICMP6_PARAM_PROB:
1746 		/* If this corresponds to an ICMP_PROTOCOL_UNREACHABLE */
1747 		if (icmp6->icmp6_code == ICMP6_PARAMPROB_NEXTHEADER &&
1748 		    (uchar_t *)ip6h + icmp6->icmp6_pptr ==
1749 		    (uchar_t *)nexthdrp) {
1750 			error = ECONNREFUSED;
1751 			break;
1752 		}
1753 		break;
1754 	}
1755 	if (error == 0) {
1756 		freemsg(mp);
1757 		return;
1758 	}
1759 
1760 	sin6 = sin6_null;
1761 	sin6.sin6_family = AF_INET6;
1762 	sin6.sin6_addr = ip6h->ip6_dst;
1763 	sin6.sin6_port = udpha->uha_dst_port;
1764 	sin6.sin6_flowinfo = ip6h->ip6_vcf & ~IPV6_VERS_AND_FLOW_MASK;
1765 
1766 	mp1 = mi_tpi_uderror_ind((char *)&sin6, sizeof (sin6_t), NULL, 0,
1767 	    error);
1768 	if (mp1)
1769 		putnext(q, mp1);
1770 	freemsg(mp);
1771 }
1772 
1773 /*
1774  * This routine responds to T_ADDR_REQ messages.  It is called by udp_wput.
1775  * The local address is filled in if endpoint is bound. The remote address
1776  * is filled in if remote address has been precified ("connected endpoint")
1777  * (The concept of connected CLTS sockets is alien to published TPI
1778  *  but we support it anyway).
1779  */
1780 static void
1781 udp_addr_req(queue_t *q, mblk_t *mp)
1782 {
1783 	udp_t	*udp = (udp_t *)q->q_ptr;
1784 	sin_t	*sin;
1785 	sin6_t	*sin6;
1786 	mblk_t	*ackmp;
1787 	struct T_addr_ack *taa;
1788 
1789 	/* Make it large enough for worst case */
1790 	ackmp = reallocb(mp, sizeof (struct T_addr_ack) +
1791 	    2 * sizeof (sin6_t), 1);
1792 	if (ackmp == NULL) {
1793 		udp_err_ack(q, mp, TSYSERR, ENOMEM);
1794 		return;
1795 	}
1796 	taa = (struct T_addr_ack *)ackmp->b_rptr;
1797 
1798 	bzero(taa, sizeof (struct T_addr_ack));
1799 	ackmp->b_wptr = (uchar_t *)&taa[1];
1800 
1801 	taa->PRIM_type = T_ADDR_ACK;
1802 	ackmp->b_datap->db_type = M_PCPROTO;
1803 	/*
1804 	 * Note: Following code assumes 32 bit alignment of basic
1805 	 * data structures like sin_t and struct T_addr_ack.
1806 	 */
1807 	if (udp->udp_state != TS_UNBND) {
1808 		/*
1809 		 * Fill in local address first
1810 		 */
1811 		taa->LOCADDR_offset = sizeof (*taa);
1812 		if (udp->udp_family == AF_INET) {
1813 			taa->LOCADDR_length = sizeof (sin_t);
1814 			sin = (sin_t *)&taa[1];
1815 			/* Fill zeroes and then initialize non-zero fields */
1816 			*sin = sin_null;
1817 			sin->sin_family = AF_INET;
1818 			if (!IN6_IS_ADDR_V4MAPPED_ANY(&udp->udp_v6src) &&
1819 			    !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) {
1820 				IN6_V4MAPPED_TO_IPADDR(&udp->udp_v6src,
1821 				    sin->sin_addr.s_addr);
1822 			} else {
1823 				/*
1824 				 * INADDR_ANY
1825 				 * udp_v6src is not set, we might be bound to
1826 				 * broadcast/multicast. Use udp_bound_v6src as
1827 				 * local address instead (that could
1828 				 * also still be INADDR_ANY)
1829 				 */
1830 				IN6_V4MAPPED_TO_IPADDR(&udp->udp_bound_v6src,
1831 				    sin->sin_addr.s_addr);
1832 			}
1833 			sin->sin_port = udp->udp_port;
1834 			ackmp->b_wptr = (uchar_t *)&sin[1];
1835 			if (udp->udp_state == TS_DATA_XFER) {
1836 				/*
1837 				 * connected, fill remote address too
1838 				 */
1839 				taa->REMADDR_length = sizeof (sin_t);
1840 				/* assumed 32-bit alignment */
1841 				taa->REMADDR_offset = taa->LOCADDR_offset +
1842 				    taa->LOCADDR_length;
1843 
1844 				sin = (sin_t *)(ackmp->b_rptr +
1845 				    taa->REMADDR_offset);
1846 				/* initialize */
1847 				*sin = sin_null;
1848 				sin->sin_family = AF_INET;
1849 				sin->sin_addr.s_addr =
1850 				    V4_PART_OF_V6(udp->udp_v6dst);
1851 				sin->sin_port = udp->udp_dstport;
1852 				ackmp->b_wptr = (uchar_t *)&sin[1];
1853 			}
1854 		} else {
1855 			taa->LOCADDR_length = sizeof (sin6_t);
1856 			sin6 = (sin6_t *)&taa[1];
1857 			/* Fill zeroes and then initialize non-zero fields */
1858 			*sin6 = sin6_null;
1859 			sin6->sin6_family = AF_INET6;
1860 			if (!IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) {
1861 				sin6->sin6_addr = udp->udp_v6src;
1862 			} else {
1863 				/*
1864 				 * UNSPECIFIED
1865 				 * udp_v6src is not set, we might be bound to
1866 				 * broadcast/multicast. Use udp_bound_v6src as
1867 				 * local address instead (that could
1868 				 * also still be UNSPECIFIED)
1869 				 */
1870 				sin6->sin6_addr =
1871 				    udp->udp_bound_v6src;
1872 			}
1873 			sin6->sin6_port = udp->udp_port;
1874 			ackmp->b_wptr = (uchar_t *)&sin6[1];
1875 			if (udp->udp_state == TS_DATA_XFER) {
1876 				/*
1877 				 * connected, fill remote address too
1878 				 */
1879 				taa->REMADDR_length = sizeof (sin6_t);
1880 				/* assumed 32-bit alignment */
1881 				taa->REMADDR_offset = taa->LOCADDR_offset +
1882 				    taa->LOCADDR_length;
1883 
1884 				sin6 = (sin6_t *)(ackmp->b_rptr +
1885 				    taa->REMADDR_offset);
1886 				/* initialize */
1887 				*sin6 = sin6_null;
1888 				sin6->sin6_family = AF_INET6;
1889 				sin6->sin6_addr = udp->udp_v6dst;
1890 				sin6->sin6_port =  udp->udp_dstport;
1891 				ackmp->b_wptr = (uchar_t *)&sin6[1];
1892 			}
1893 			ackmp->b_wptr = (uchar_t *)&sin6[1];
1894 		}
1895 	}
1896 	ASSERT(ackmp->b_wptr <= ackmp->b_datap->db_lim);
1897 	qreply(q, ackmp);
1898 }
1899 
1900 static void
1901 udp_copy_info(struct T_info_ack *tap, udp_t *udp)
1902 {
1903 	if (udp->udp_family == AF_INET) {
1904 		*tap = udp_g_t_info_ack_ipv4;
1905 	} else {
1906 		*tap = udp_g_t_info_ack_ipv6;
1907 	}
1908 	tap->CURRENT_state = udp->udp_state;
1909 	tap->OPT_size = udp_max_optsize;
1910 }
1911 
1912 /*
1913  * This routine responds to T_CAPABILITY_REQ messages.  It is called by
1914  * udp_wput.  Much of the T_CAPABILITY_ACK information is copied from
1915  * udp_g_t_info_ack.  The current state of the stream is copied from
1916  * udp_state.
1917  */
1918 static void
1919 udp_capability_req(queue_t *q, mblk_t *mp)
1920 {
1921 	udp_t			*udp = (udp_t *)q->q_ptr;
1922 	t_uscalar_t		cap_bits1;
1923 	struct T_capability_ack	*tcap;
1924 
1925 	cap_bits1 = ((struct T_capability_req *)mp->b_rptr)->CAP_bits1;
1926 
1927 	mp = tpi_ack_alloc(mp, sizeof (struct T_capability_ack),
1928 	    mp->b_datap->db_type, T_CAPABILITY_ACK);
1929 	if (!mp)
1930 		return;
1931 
1932 	tcap = (struct T_capability_ack *)mp->b_rptr;
1933 	tcap->CAP_bits1 = 0;
1934 
1935 	if (cap_bits1 & TC1_INFO) {
1936 		udp_copy_info(&tcap->INFO_ack, udp);
1937 		tcap->CAP_bits1 |= TC1_INFO;
1938 	}
1939 
1940 	qreply(q, mp);
1941 }
1942 
1943 /*
1944  * This routine responds to T_INFO_REQ messages.  It is called by udp_wput.
1945  * Most of the T_INFO_ACK information is copied from udp_g_t_info_ack.
1946  * The current state of the stream is copied from udp_state.
1947  */
1948 static void
1949 udp_info_req(queue_t *q, mblk_t *mp)
1950 {
1951 	udp_t	*udp = (udp_t *)q->q_ptr;
1952 
1953 	/* Create a T_INFO_ACK message. */
1954 	mp = tpi_ack_alloc(mp, sizeof (struct T_info_ack), M_PCPROTO,
1955 	    T_INFO_ACK);
1956 	if (!mp)
1957 		return;
1958 	udp_copy_info((struct T_info_ack *)mp->b_rptr, udp);
1959 	qreply(q, mp);
1960 }
1961 
1962 /*
1963  * IP recognizes seven kinds of bind requests:
1964  *
1965  * - A zero-length address binds only to the protocol number.
1966  *
1967  * - A 4-byte address is treated as a request to
1968  * validate that the address is a valid local IPv4
1969  * address, appropriate for an application to bind to.
1970  * IP does the verification, but does not make any note
1971  * of the address at this time.
1972  *
1973  * - A 16-byte address contains is treated as a request
1974  * to validate a local IPv6 address, as the 4-byte
1975  * address case above.
1976  *
1977  * - A 16-byte sockaddr_in to validate the local IPv4 address and also
1978  * use it for the inbound fanout of packets.
1979  *
1980  * - A 24-byte sockaddr_in6 to validate the local IPv6 address and also
1981  * use it for the inbound fanout of packets.
1982  *
1983  * - A 12-byte address (ipa_conn_t) containing complete IPv4 fanout
1984  * information consisting of local and remote addresses
1985  * and ports.  In this case, the addresses are both
1986  * validated as appropriate for this operation, and, if
1987  * so, the information is retained for use in the
1988  * inbound fanout.
1989  *
1990  * - A 36-byte address address (ipa6_conn_t) containing complete IPv6
1991  * fanout information, like the 12-byte case above.
1992  *
1993  * IP will also fill in the IRE request mblk with information
1994  * regarding our peer.  In all cases, we notify IP of our protocol
1995  * type by appending a single protocol byte to the bind request.
1996  */
1997 static mblk_t *
1998 udp_ip_bind_mp(udp_t *udp, t_scalar_t bind_prim, t_scalar_t addr_length)
1999 {
2000 	char	*cp;
2001 	mblk_t	*mp;
2002 	struct T_bind_req *tbr;
2003 	ipa_conn_t	*ac;
2004 	ipa6_conn_t	*ac6;
2005 	sin_t		*sin;
2006 	sin6_t		*sin6;
2007 
2008 	ASSERT(bind_prim == O_T_BIND_REQ || bind_prim == T_BIND_REQ);
2009 
2010 	mp = allocb(sizeof (*tbr) + addr_length + 1, BPRI_HI);
2011 	if (!mp)
2012 		return (mp);
2013 	mp->b_datap->db_type = M_PROTO;
2014 	tbr = (struct T_bind_req *)mp->b_rptr;
2015 	tbr->PRIM_type = bind_prim;
2016 	tbr->ADDR_offset = sizeof (*tbr);
2017 	tbr->CONIND_number = 0;
2018 	tbr->ADDR_length = addr_length;
2019 	cp = (char *)&tbr[1];
2020 	switch (addr_length) {
2021 	case sizeof (ipa_conn_t):
2022 		ASSERT(udp->udp_family == AF_INET);
2023 		/* Append a request for an IRE */
2024 		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
2025 		if (!mp->b_cont) {
2026 			freemsg(mp);
2027 			return (NULL);
2028 		}
2029 		mp->b_cont->b_wptr += sizeof (ire_t);
2030 		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
2031 
2032 		/* cp known to be 32 bit aligned */
2033 		ac = (ipa_conn_t *)cp;
2034 		ac->ac_laddr = V4_PART_OF_V6(udp->udp_v6src);
2035 		ac->ac_faddr = V4_PART_OF_V6(udp->udp_v6dst);
2036 		ac->ac_fport = udp->udp_dstport;
2037 		ac->ac_lport = udp->udp_port;
2038 		break;
2039 
2040 	case sizeof (ipa6_conn_t):
2041 		ASSERT(udp->udp_family == AF_INET6);
2042 		/* Append a request for an IRE */
2043 		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
2044 		if (!mp->b_cont) {
2045 			freemsg(mp);
2046 			return (NULL);
2047 		}
2048 		mp->b_cont->b_wptr += sizeof (ire_t);
2049 		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
2050 
2051 		/* cp known to be 32 bit aligned */
2052 		ac6 = (ipa6_conn_t *)cp;
2053 		ac6->ac6_laddr = udp->udp_v6src;
2054 		ac6->ac6_faddr = udp->udp_v6dst;
2055 		ac6->ac6_fport = udp->udp_dstport;
2056 		ac6->ac6_lport = udp->udp_port;
2057 		break;
2058 
2059 	case sizeof (sin_t):
2060 		ASSERT(udp->udp_family == AF_INET);
2061 		/* Append a request for an IRE */
2062 		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
2063 		if (!mp->b_cont) {
2064 			freemsg(mp);
2065 			return (NULL);
2066 		}
2067 		mp->b_cont->b_wptr += sizeof (ire_t);
2068 		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
2069 
2070 		sin = (sin_t *)cp;
2071 		*sin = sin_null;
2072 		sin->sin_family = AF_INET;
2073 		sin->sin_addr.s_addr = V4_PART_OF_V6(udp->udp_bound_v6src);
2074 		sin->sin_port = udp->udp_port;
2075 		break;
2076 
2077 	case sizeof (sin6_t):
2078 		ASSERT(udp->udp_family == AF_INET6);
2079 		/* Append a request for an IRE */
2080 		mp->b_cont = allocb(sizeof (ire_t), BPRI_HI);
2081 		if (!mp->b_cont) {
2082 			freemsg(mp);
2083 			return (NULL);
2084 		}
2085 		mp->b_cont->b_wptr += sizeof (ire_t);
2086 		mp->b_cont->b_datap->db_type = IRE_DB_REQ_TYPE;
2087 
2088 		sin6 = (sin6_t *)cp;
2089 		*sin6 = sin6_null;
2090 		sin6->sin6_family = AF_INET6;
2091 		sin6->sin6_addr = udp->udp_bound_v6src;
2092 		sin6->sin6_port = udp->udp_port;
2093 		break;
2094 	}
2095 	/* Add protocol number to end */
2096 	cp[addr_length] = (char)IPPROTO_UDP;
2097 	mp->b_wptr = (uchar_t *)&cp[addr_length + 1];
2098 	return (mp);
2099 }
2100 
2101 /*
2102  * This is the open routine for udp.  It allocates a udp_t structure for
2103  * the stream and, on the first open of the module, creates an ND table.
2104  */
2105 static int
2106 udp_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
2107 {
2108 	int	err;
2109 	udp_t	*udp;
2110 
2111 	TRACE_1(TR_FAC_UDP, TR_UDP_OPEN, "udp_open: q %p", q);
2112 
2113 	/*
2114 	 * Defer the qprocson until everything is initialized since
2115 	 * we are D_MTPERQ and after qprocson the rput routine can
2116 	 * run.
2117 	 */
2118 
2119 	/* If the stream is already open, return immediately. */
2120 	if (q->q_ptr != NULL)
2121 		return (0);
2122 
2123 	/* If this is not a push of udp as a module, fail. */
2124 	if (sflag != MODOPEN)
2125 		return (EINVAL);
2126 
2127 	/*
2128 	 * Create and initialize a udp_t structure for this stream.
2129 	 */
2130 	udp = (udp_t *)mi_open_alloc_sleep(sizeof (udp_t));
2131 
2132 	/* Set the initial state of the stream and the privilege status. */
2133 	q->q_ptr = WR(q)->q_ptr = udp;
2134 	udp->udp_state = TS_UNBND;
2135 	if (getmajor(*devp) == (major_t)UDP6_MAJ) {
2136 		udp->udp_family = AF_INET6;
2137 		udp->udp_ipversion = IPV6_VERSION;
2138 		udp->udp_max_hdr_len = IPV6_HDR_LEN + UDPH_SIZE;
2139 		udp->udp_ttl = udp_ipv6_hoplimit;
2140 	} else {
2141 		udp->udp_family = AF_INET;
2142 		udp->udp_ipversion = IPV4_VERSION;
2143 		udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE;
2144 		udp->udp_ttl = udp_ipv4_ttl;
2145 	}
2146 
2147 	/*
2148 	 * The receive hiwat is only looked at on the stream head queue.
2149 	 * Store in q_hiwat in order to return on SO_RCVBUF getsockopts.
2150 	 */
2151 	q->q_hiwat = udp_recv_hiwat;
2152 
2153 	udp->udp_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
2154 	udp->udp_multicast_loop = IP_DEFAULT_MULTICAST_LOOP;
2155 	udp->udp_credp = credp;
2156 	crhold(credp);
2157 
2158 	udp->udp_zoneid = getzoneid();
2159 
2160 	/*
2161 	 * Acquire the lock and link it into the list of open streams.
2162 	 */
2163 	mutex_enter(&udp_g_lock);
2164 	err = mi_open_link(&udp_g_head, (IDP)udp, devp, flag, sflag, credp);
2165 	mutex_exit(&udp_g_lock);
2166 	if (err != 0)
2167 		goto error;
2168 
2169 	qprocson(q);
2170 
2171 	/*
2172 	 * The transmit hiwat/lowat is only looked at on IP's queue.
2173 	 * Store in q_hiwat in order to return on SO_SNDBUF
2174 	 * getsockopts.
2175 	 */
2176 	WR(q)->q_hiwat = udp_xmit_hiwat;
2177 	WR(q)->q_next->q_hiwat = WR(q)->q_hiwat;
2178 	WR(q)->q_lowat = udp_xmit_lowat;
2179 	WR(q)->q_next->q_lowat = WR(q)->q_lowat;
2180 
2181 	if (udp->udp_family == AF_INET6) {
2182 		/* Build initial header template for transmit */
2183 		if ((err = udp_build_hdrs(q, udp)) != 0) {
2184 			qprocsoff(q);
2185 			/*
2186 			 * Unlink the udp structure and release
2187 			 * the minor device number.
2188 			 */
2189 			mutex_enter(&udp_g_lock);
2190 			mi_close_unlink(&udp_g_head, (IDP)udp);
2191 			mutex_exit(&udp_g_lock);
2192 			goto error;
2193 		}
2194 	}
2195 
2196 	/* Set the Stream head write offset. */
2197 	(void) mi_set_sth_wroff(q, udp->udp_max_hdr_len + udp_wroff_extra);
2198 	(void) mi_set_sth_hiwat(q, q->q_hiwat);
2199 	return (0);
2200 
2201 error:
2202 	q->q_ptr = WR(q)->q_ptr = NULL;
2203 	crfree(credp);
2204 	mi_close_free((IDP)udp);
2205 	return (err);
2206 }
2207 
2208 /*
2209  * Which UDP options OK to set through T_UNITDATA_REQ...
2210  */
2211 /* ARGSUSED */
2212 static boolean_t
2213 udp_opt_allow_udr_set(t_scalar_t level, t_scalar_t name)
2214 {
2215 
2216 	return (B_TRUE);
2217 }
2218 
2219 /*
2220  * This routine gets default values of certain options whose default
2221  * values are maintained by protcol specific code
2222  */
2223 /* ARGSUSED */
2224 int
2225 udp_opt_default(queue_t	*q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
2226 {
2227 	int *i1 = (int *)ptr;
2228 
2229 	switch (level) {
2230 	case IPPROTO_IP:
2231 		switch (name) {
2232 		case IP_MULTICAST_TTL:
2233 			*ptr = (uchar_t)IP_DEFAULT_MULTICAST_TTL;
2234 			return (sizeof (uchar_t));
2235 		case IP_MULTICAST_LOOP:
2236 			*ptr = (uchar_t)IP_DEFAULT_MULTICAST_LOOP;
2237 			return (sizeof (uchar_t));
2238 		}
2239 		break;
2240 	case IPPROTO_IPV6:
2241 		switch (name) {
2242 		case IPV6_MULTICAST_HOPS:
2243 			*i1 = IP_DEFAULT_MULTICAST_TTL;
2244 			return (sizeof (int));
2245 		case IPV6_MULTICAST_LOOP:
2246 			*i1 = IP_DEFAULT_MULTICAST_LOOP;
2247 			return (sizeof (int));
2248 		case IPV6_UNICAST_HOPS:
2249 			*i1 = udp_ipv6_hoplimit;
2250 			return (sizeof (int));
2251 		}
2252 		break;
2253 	}
2254 	return (-1);
2255 }
2256 
2257 /*
2258  * This routine retrieves the current status of socket options.
2259  * It returns the size of the option retrieved.
2260  */
2261 int
2262 udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr)
2263 {
2264 	int	*i1 = (int *)ptr;
2265 	udp_t	*udp = (udp_t *)q->q_ptr;
2266 	ip6_pkt_t	*ipp = &udp->udp_sticky_ipp;
2267 
2268 	switch (level) {
2269 	case SOL_SOCKET:
2270 		switch (name) {
2271 		case SO_DEBUG:
2272 			*i1 = udp->udp_debug;
2273 			break;	/* goto sizeof (int) option return */
2274 		case SO_REUSEADDR:
2275 			*i1 = udp->udp_reuseaddr;
2276 			break;	/* goto sizeof (int) option return */
2277 		case SO_TYPE:
2278 			*i1 = SOCK_DGRAM;
2279 			break;	/* goto sizeof (int) option return */
2280 
2281 		/*
2282 		 * The following three items are available here,
2283 		 * but are only meaningful to IP.
2284 		 */
2285 		case SO_DONTROUTE:
2286 			*i1 = udp->udp_dontroute;
2287 			break;	/* goto sizeof (int) option return */
2288 		case SO_USELOOPBACK:
2289 			*i1 = udp->udp_useloopback;
2290 			break;	/* goto sizeof (int) option return */
2291 		case SO_BROADCAST:
2292 			*i1 = udp->udp_broadcast;
2293 			break;	/* goto sizeof (int) option return */
2294 
2295 		case SO_SNDBUF:
2296 			*i1 = q->q_hiwat;
2297 			break;	/* goto sizeof (int) option return */
2298 		case SO_RCVBUF:
2299 			*i1 = RD(q)->q_hiwat;
2300 			break;	/* goto sizeof (int) option return */
2301 		case SO_DGRAM_ERRIND:
2302 			*i1 = udp->udp_dgram_errind;
2303 			break;	/* goto sizeof (int) option return */
2304 		case SO_RECVUCRED:
2305 			*i1 = udp->udp_recvucred;
2306 			break;	/* goto sizeof (int) option return */
2307 		default:
2308 			return (-1);
2309 		}
2310 		break;
2311 	case IPPROTO_IP:
2312 		if (udp->udp_family != AF_INET)
2313 			return (-1);
2314 		switch (name) {
2315 		case IP_OPTIONS:
2316 		case T_IP_OPTIONS:
2317 			if (udp->udp_ip_rcv_options_len)
2318 				bcopy(udp->udp_ip_rcv_options, ptr,
2319 				    udp->udp_ip_rcv_options_len);
2320 			return (udp->udp_ip_rcv_options_len);
2321 		case IP_TOS:
2322 		case T_IP_TOS:
2323 			*i1 = (int)udp->udp_type_of_service;
2324 			break;	/* goto sizeof (int) option return */
2325 		case IP_TTL:
2326 			*i1 = (int)udp->udp_ttl;
2327 			break;	/* goto sizeof (int) option return */
2328 		case IP_MULTICAST_IF:
2329 			/* 0 address if not set */
2330 			*(ipaddr_t *)ptr = udp->udp_multicast_if_addr;
2331 			return (sizeof (ipaddr_t));
2332 		case IP_MULTICAST_TTL:
2333 			*(uchar_t *)ptr = udp->udp_multicast_ttl;
2334 			return (sizeof (uchar_t));
2335 		case IP_MULTICAST_LOOP:
2336 			*ptr = udp->udp_multicast_loop;
2337 			return (sizeof (uint8_t));
2338 		case IP_RECVOPTS:
2339 			*i1 = udp->udp_recvopts;
2340 			break;	/* goto sizeof (int) option return */
2341 		case IP_RECVDSTADDR:
2342 			*i1 = udp->udp_recvdstaddr;
2343 			break;	/* goto sizeof (int) option return */
2344 		case IP_RECVIF:
2345 			*i1 = udp->udp_recvif;
2346 			break;	/* goto sizeof (int) option return */
2347 		case IP_RECVSLLA:
2348 			*i1 = udp->udp_recvslla;
2349 			break;	/* goto sizeof (int) option return */
2350 		case IP_RECVTTL:
2351 			*i1 = udp->udp_recvttl;
2352 			break;	/* goto sizeof (int) option return */
2353 		case IP_ADD_MEMBERSHIP:
2354 		case IP_DROP_MEMBERSHIP:
2355 		case IP_BLOCK_SOURCE:
2356 		case IP_UNBLOCK_SOURCE:
2357 		case IP_ADD_SOURCE_MEMBERSHIP:
2358 		case IP_DROP_SOURCE_MEMBERSHIP:
2359 		case MCAST_JOIN_GROUP:
2360 		case MCAST_LEAVE_GROUP:
2361 		case MCAST_BLOCK_SOURCE:
2362 		case MCAST_UNBLOCK_SOURCE:
2363 		case MCAST_JOIN_SOURCE_GROUP:
2364 		case MCAST_LEAVE_SOURCE_GROUP:
2365 		case IP_DONTFAILOVER_IF:
2366 			/* cannot "get" the value for these */
2367 			return (-1);
2368 		case IP_BOUND_IF:
2369 			/* Zero if not set */
2370 			*i1 = udp->udp_bound_if;
2371 			break;	/* goto sizeof (int) option return */
2372 		case IP_UNSPEC_SRC:
2373 			*i1 = udp->udp_unspec_source;
2374 			break;	/* goto sizeof (int) option return */
2375 		case IP_XMIT_IF:
2376 			*i1 = udp->udp_xmit_if;
2377 			break; /* goto sizeof (int) option return */
2378 		default:
2379 			return (-1);
2380 		}
2381 		break;
2382 	case IPPROTO_IPV6:
2383 		if (udp->udp_family != AF_INET6)
2384 			return (-1);
2385 		switch (name) {
2386 		case IPV6_UNICAST_HOPS:
2387 			*i1 = (unsigned int)udp->udp_ttl;
2388 			break;	/* goto sizeof (int) option return */
2389 		case IPV6_MULTICAST_IF:
2390 			/* 0 index if not set */
2391 			*i1 = udp->udp_multicast_if_index;
2392 			break;	/* goto sizeof (int) option return */
2393 		case IPV6_MULTICAST_HOPS:
2394 			*i1 = udp->udp_multicast_ttl;
2395 			break;	/* goto sizeof (int) option return */
2396 		case IPV6_MULTICAST_LOOP:
2397 			*i1 = udp->udp_multicast_loop;
2398 			break;	/* goto sizeof (int) option return */
2399 		case IPV6_JOIN_GROUP:
2400 		case IPV6_LEAVE_GROUP:
2401 		case MCAST_JOIN_GROUP:
2402 		case MCAST_LEAVE_GROUP:
2403 		case MCAST_BLOCK_SOURCE:
2404 		case MCAST_UNBLOCK_SOURCE:
2405 		case MCAST_JOIN_SOURCE_GROUP:
2406 		case MCAST_LEAVE_SOURCE_GROUP:
2407 			/* cannot "get" the value for these */
2408 			return (-1);
2409 		case IPV6_BOUND_IF:
2410 			/* Zero if not set */
2411 			*i1 = udp->udp_bound_if;
2412 			break;	/* goto sizeof (int) option return */
2413 		case IPV6_UNSPEC_SRC:
2414 			*i1 = udp->udp_unspec_source;
2415 			break;	/* goto sizeof (int) option return */
2416 		case IPV6_RECVPKTINFO:
2417 			*i1 = udp->udp_ipv6_recvpktinfo;
2418 			break;	/* goto sizeof (int) option return */
2419 		case IPV6_RECVTCLASS:
2420 			*i1 = udp->udp_ipv6_recvtclass;
2421 			break;	/* goto sizeof (int) option return */
2422 		case IPV6_RECVPATHMTU:
2423 			*i1 = udp->udp_ipv6_recvpathmtu;
2424 			break;	/* goto sizeof (int) option return */
2425 		case IPV6_RECVHOPLIMIT:
2426 			*i1 = udp->udp_ipv6_recvhoplimit;
2427 			break;	/* goto sizeof (int) option return */
2428 		case IPV6_RECVHOPOPTS:
2429 			*i1 = udp->udp_ipv6_recvhopopts;
2430 			break;	/* goto sizeof (int) option return */
2431 		case IPV6_RECVDSTOPTS:
2432 			*i1 = udp->udp_ipv6_recvdstopts;
2433 			break;	/* goto sizeof (int) option return */
2434 		case _OLD_IPV6_RECVDSTOPTS:
2435 			*i1 = udp->udp_old_ipv6_recvdstopts;
2436 			break;	/* goto sizeof (int) option return */
2437 		case IPV6_RECVRTHDRDSTOPTS:
2438 			*i1 = udp->udp_ipv6_recvrthdrdstopts;
2439 			break;	/* goto sizeof (int) option return */
2440 		case IPV6_RECVRTHDR:
2441 			*i1 = udp->udp_ipv6_recvrthdr;
2442 			break;	/* goto sizeof (int) option return */
2443 		case IPV6_PKTINFO: {
2444 			/* XXX assumes that caller has room for max size! */
2445 			struct in6_pktinfo *pkti;
2446 
2447 			pkti = (struct in6_pktinfo *)ptr;
2448 			if (ipp->ipp_fields & IPPF_IFINDEX)
2449 				pkti->ipi6_ifindex = ipp->ipp_ifindex;
2450 			else
2451 				pkti->ipi6_ifindex = 0;
2452 			if (ipp->ipp_fields & IPPF_ADDR)
2453 				pkti->ipi6_addr = ipp->ipp_addr;
2454 			else
2455 				pkti->ipi6_addr = ipv6_all_zeros;
2456 			return (sizeof (struct in6_pktinfo));
2457 		}
2458 		case IPV6_TCLASS:
2459 			if (ipp->ipp_fields & IPPF_TCLASS)
2460 				*i1 = ipp->ipp_tclass;
2461 			else
2462 				*i1 = IPV6_FLOW_TCLASS(
2463 				    IPV6_DEFAULT_VERS_AND_FLOW);
2464 			break;	/* goto sizeof (int) option return */
2465 		case IPV6_NEXTHOP: {
2466 			sin6_t *sin6 = (sin6_t *)ptr;
2467 
2468 			if (!(ipp->ipp_fields & IPPF_NEXTHOP))
2469 				return (0);
2470 			*sin6 = sin6_null;
2471 			sin6->sin6_family = AF_INET6;
2472 			sin6->sin6_addr = ipp->ipp_nexthop;
2473 			return (sizeof (sin6_t));
2474 		}
2475 		case IPV6_HOPOPTS:
2476 			if (!(ipp->ipp_fields & IPPF_HOPOPTS))
2477 				return (0);
2478 			bcopy(ipp->ipp_hopopts, ptr, ipp->ipp_hopoptslen);
2479 			return (ipp->ipp_hopoptslen);
2480 		case IPV6_RTHDRDSTOPTS:
2481 			if (!(ipp->ipp_fields & IPPF_RTDSTOPTS))
2482 				return (0);
2483 			bcopy(ipp->ipp_rtdstopts, ptr, ipp->ipp_rtdstoptslen);
2484 			return (ipp->ipp_rtdstoptslen);
2485 		case IPV6_RTHDR:
2486 			if (!(ipp->ipp_fields & IPPF_RTHDR))
2487 				return (0);
2488 			bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen);
2489 			return (ipp->ipp_rthdrlen);
2490 		case IPV6_DSTOPTS:
2491 			if (!(ipp->ipp_fields & IPPF_DSTOPTS))
2492 				return (0);
2493 			bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen);
2494 			return (ipp->ipp_dstoptslen);
2495 		case IPV6_PATHMTU:
2496 			return (ip_fill_mtuinfo(&udp->udp_v6dst,
2497 				udp->udp_dstport, (struct ip6_mtuinfo *)ptr));
2498 		default:
2499 			return (-1);
2500 		}
2501 		break;
2502 	case IPPROTO_UDP:
2503 		switch (name) {
2504 		case UDP_ANONPRIVBIND:
2505 			*i1 = udp->udp_anon_priv_bind;
2506 			break;
2507 		case UDP_EXCLBIND:
2508 			*i1 = udp->udp_exclbind ? UDP_EXCLBIND : 0;
2509 			break;
2510 		case UDP_RCVHDR:
2511 			*i1 = udp->udp_rcvhdr ? 1 : 0;
2512 			break;
2513 		default:
2514 			return (-1);
2515 		}
2516 		break;
2517 	default:
2518 		return (-1);
2519 	}
2520 	return (sizeof (int));
2521 }
2522 
2523 /* This routine sets socket options. */
2524 /* ARGSUSED */
2525 int
2526 udp_opt_set(queue_t *q, uint_t optset_context, int level,
2527     int name, uint_t inlen, uchar_t *invalp, uint_t *outlenp,
2528     uchar_t *outvalp, void *thisdg_attrs, cred_t *cr, mblk_t *mblk)
2529 {
2530 	udp_t	*udp = (udp_t *)q->q_ptr;
2531 	int	*i1 = (int *)invalp;
2532 	boolean_t onoff = (*i1 == 0) ? 0 : 1;
2533 	boolean_t checkonly;
2534 	int	error;
2535 
2536 	switch (optset_context) {
2537 	case SETFN_OPTCOM_CHECKONLY:
2538 		checkonly = B_TRUE;
2539 		/*
2540 		 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
2541 		 * inlen != 0 implies value supplied and
2542 		 * 	we have to "pretend" to set it.
2543 		 * inlen == 0 implies that there is no
2544 		 * 	value part in T_CHECK request and just validation
2545 		 * done elsewhere should be enough, we just return here.
2546 		 */
2547 		if (inlen == 0) {
2548 			*outlenp = 0;
2549 			return (0);
2550 		}
2551 		break;
2552 	case SETFN_OPTCOM_NEGOTIATE:
2553 		checkonly = B_FALSE;
2554 		break;
2555 	case SETFN_UD_NEGOTIATE:
2556 	case SETFN_CONN_NEGOTIATE:
2557 		checkonly = B_FALSE;
2558 		/*
2559 		 * Negotiating local and "association-related" options
2560 		 * through T_UNITDATA_REQ.
2561 		 *
2562 		 * Following routine can filter out ones we do not
2563 		 * want to be "set" this way.
2564 		 */
2565 		if (!udp_opt_allow_udr_set(level, name)) {
2566 			*outlenp = 0;
2567 			return (EINVAL);
2568 		}
2569 		break;
2570 	default:
2571 		/*
2572 		 * We should never get here
2573 		 */
2574 		*outlenp = 0;
2575 		return (EINVAL);
2576 	}
2577 
2578 	ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
2579 	    (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
2580 
2581 	/*
2582 	 * For fixed length options, no sanity check
2583 	 * of passed in length is done. It is assumed *_optcom_req()
2584 	 * routines do the right thing.
2585 	 */
2586 
2587 	switch (level) {
2588 	case SOL_SOCKET:
2589 		switch (name) {
2590 		case SO_REUSEADDR:
2591 			if (!checkonly)
2592 				udp->udp_reuseaddr = onoff;
2593 			break;
2594 		case SO_DEBUG:
2595 			if (!checkonly)
2596 				udp->udp_debug = onoff;
2597 			break;
2598 		/*
2599 		 * The following three items are available here,
2600 		 * but are only meaningful to IP.
2601 		 */
2602 		case SO_DONTROUTE:
2603 			if (!checkonly)
2604 				udp->udp_dontroute = onoff;
2605 			break;
2606 		case SO_USELOOPBACK:
2607 			if (!checkonly)
2608 				udp->udp_useloopback = onoff;
2609 			break;
2610 		case SO_BROADCAST:
2611 			if (!checkonly)
2612 				udp->udp_broadcast = onoff;
2613 			break;
2614 
2615 		case SO_SNDBUF:
2616 			if (*i1 > udp_max_buf) {
2617 				*outlenp = 0;
2618 				return (ENOBUFS);
2619 			}
2620 			if (!checkonly) {
2621 				q->q_hiwat = *i1;
2622 				q->q_next->q_hiwat = *i1;
2623 			}
2624 			break;
2625 		case SO_RCVBUF:
2626 			if (*i1 > udp_max_buf) {
2627 				*outlenp = 0;
2628 				return (ENOBUFS);
2629 			}
2630 			if (!checkonly) {
2631 				RD(q)->q_hiwat = *i1;
2632 				(void) mi_set_sth_hiwat(RD(q), *i1);
2633 			}
2634 			break;
2635 		case SO_DGRAM_ERRIND:
2636 			if (!checkonly)
2637 				udp->udp_dgram_errind = onoff;
2638 			break;
2639 		case SO_RECVUCRED:
2640 			if (!checkonly)
2641 				udp->udp_recvucred = onoff;
2642 			break;
2643 		default:
2644 			*outlenp = 0;
2645 			return (EINVAL);
2646 		}
2647 		break;
2648 	case IPPROTO_IP:
2649 		if (udp->udp_family != AF_INET) {
2650 			*outlenp = 0;
2651 			return (ENOPROTOOPT);
2652 		}
2653 		switch (name) {
2654 		case IP_OPTIONS:
2655 		case T_IP_OPTIONS:
2656 			/* Save options for use by IP. */
2657 			if (inlen & 0x3) {
2658 				*outlenp = 0;
2659 				return (EINVAL);
2660 			}
2661 			if (checkonly)
2662 				break;
2663 
2664 			if (udp->udp_ip_snd_options) {
2665 				mi_free((char *)udp->udp_ip_snd_options);
2666 				udp->udp_ip_snd_options_len = 0;
2667 				udp->udp_ip_snd_options = NULL;
2668 			}
2669 			if (inlen) {
2670 				udp->udp_ip_snd_options =
2671 					(uchar_t *)mi_alloc(inlen, BPRI_HI);
2672 				if (udp->udp_ip_snd_options) {
2673 					bcopy(invalp, udp->udp_ip_snd_options,
2674 					    inlen);
2675 					udp->udp_ip_snd_options_len = inlen;
2676 				}
2677 			}
2678 			udp->udp_max_hdr_len = IP_SIMPLE_HDR_LENGTH +
2679 			    UDPH_SIZE + udp->udp_ip_snd_options_len;
2680 			(void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len +
2681 			    udp_wroff_extra);
2682 			break;
2683 		case IP_TTL:
2684 			if (!checkonly) {
2685 				udp->udp_ttl = (uchar_t)*i1;
2686 			}
2687 			break;
2688 		case IP_TOS:
2689 		case T_IP_TOS:
2690 			if (!checkonly) {
2691 				udp->udp_type_of_service = (uchar_t)*i1;
2692 			}
2693 			break;
2694 		case IP_MULTICAST_IF: {
2695 			/*
2696 			 * TODO should check OPTMGMT reply and undo this if
2697 			 * there is an error.
2698 			 */
2699 			struct in_addr *inap = (struct in_addr *)invalp;
2700 			if (!checkonly) {
2701 				udp->udp_multicast_if_addr =
2702 				    inap->s_addr;
2703 			}
2704 			break;
2705 		}
2706 		case IP_MULTICAST_TTL:
2707 			if (!checkonly)
2708 				udp->udp_multicast_ttl = *invalp;
2709 			break;
2710 		case IP_MULTICAST_LOOP:
2711 			if (!checkonly)
2712 				udp->udp_multicast_loop = *invalp;
2713 			break;
2714 		case IP_RECVOPTS:
2715 			if (!checkonly)
2716 				udp->udp_recvopts = onoff;
2717 			break;
2718 		case IP_RECVDSTADDR:
2719 			if (!checkonly)
2720 				udp->udp_recvdstaddr = onoff;
2721 			break;
2722 		case IP_RECVIF:
2723 			if (!checkonly)
2724 				udp->udp_recvif = onoff;
2725 			break;
2726 		case IP_RECVSLLA:
2727 			if (!checkonly)
2728 				udp->udp_recvslla = onoff;
2729 			break;
2730 		case IP_RECVTTL:
2731 			if (!checkonly)
2732 				udp->udp_recvttl = onoff;
2733 			break;
2734 		case IP_ADD_MEMBERSHIP:
2735 		case IP_DROP_MEMBERSHIP:
2736 		case IP_BLOCK_SOURCE:
2737 		case IP_UNBLOCK_SOURCE:
2738 		case IP_ADD_SOURCE_MEMBERSHIP:
2739 		case IP_DROP_SOURCE_MEMBERSHIP:
2740 		case MCAST_JOIN_GROUP:
2741 		case MCAST_LEAVE_GROUP:
2742 		case MCAST_BLOCK_SOURCE:
2743 		case MCAST_UNBLOCK_SOURCE:
2744 		case MCAST_JOIN_SOURCE_GROUP:
2745 		case MCAST_LEAVE_SOURCE_GROUP:
2746 		case IP_SEC_OPT:
2747 			/*
2748 			 * "soft" error (negative)
2749 			 * option not handled at this level
2750 			 * Do not modify *outlenp.
2751 			 */
2752 			return (-EINVAL);
2753 		case IP_BOUND_IF:
2754 			if (!checkonly)
2755 				udp->udp_bound_if = *i1;
2756 			break;
2757 		case IP_UNSPEC_SRC:
2758 			if (!checkonly)
2759 				udp->udp_unspec_source = onoff;
2760 			break;
2761 		case IP_XMIT_IF:
2762 			if (!checkonly)
2763 				udp->udp_xmit_if = *i1;
2764 			break;
2765 		default:
2766 			*outlenp = 0;
2767 			return (EINVAL);
2768 		}
2769 		break;
2770 	case IPPROTO_IPV6: {
2771 		ip6_pkt_t		*ipp;
2772 		boolean_t		sticky;
2773 
2774 		if (udp->udp_family != AF_INET6) {
2775 			*outlenp = 0;
2776 			return (ENOPROTOOPT);
2777 		}
2778 		/*
2779 		 * Deal with both sticky options and ancillary data
2780 		 */
2781 		if (thisdg_attrs == NULL) {
2782 			/* sticky options, or none */
2783 			ipp = &udp->udp_sticky_ipp;
2784 			sticky = B_TRUE;
2785 		} else {
2786 			/* ancillary data */
2787 			ipp = (ip6_pkt_t *)thisdg_attrs;
2788 			sticky = B_FALSE;
2789 		}
2790 
2791 		switch (name) {
2792 		case IPV6_MULTICAST_IF:
2793 			if (!checkonly)
2794 				udp->udp_multicast_if_index = *i1;
2795 			break;
2796 		case IPV6_UNICAST_HOPS:
2797 			/* -1 means use default */
2798 			if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) {
2799 				*outlenp = 0;
2800 				return (EINVAL);
2801 			}
2802 			if (!checkonly) {
2803 				if (*i1 == -1) {
2804 					udp->udp_ttl = ipp->ipp_unicast_hops =
2805 					    udp_ipv6_hoplimit;
2806 					ipp->ipp_fields &= ~IPPF_UNICAST_HOPS;
2807 					/* Pass modified value to IP. */
2808 					*i1 = udp->udp_ttl;
2809 				} else {
2810 					udp->udp_ttl = ipp->ipp_unicast_hops =
2811 					    (uint8_t)*i1;
2812 					ipp->ipp_fields |= IPPF_UNICAST_HOPS;
2813 				}
2814 				/* Rebuild the header template */
2815 				error = udp_build_hdrs(q, udp);
2816 				if (error != 0) {
2817 					*outlenp = 0;
2818 					return (error);
2819 				}
2820 			}
2821 			break;
2822 		case IPV6_MULTICAST_HOPS:
2823 			/* -1 means use default */
2824 			if (*i1 < -1 || *i1 > IPV6_MAX_HOPS) {
2825 				*outlenp = 0;
2826 				return (EINVAL);
2827 			}
2828 			if (!checkonly) {
2829 				if (*i1 == -1) {
2830 					udp->udp_multicast_ttl =
2831 					    ipp->ipp_multicast_hops =
2832 					    IP_DEFAULT_MULTICAST_TTL;
2833 					ipp->ipp_fields &= ~IPPF_MULTICAST_HOPS;
2834 					/* Pass modified value to IP. */
2835 					*i1 = udp->udp_multicast_ttl;
2836 				} else {
2837 					udp->udp_multicast_ttl =
2838 					    ipp->ipp_multicast_hops =
2839 					    (uint8_t)*i1;
2840 					ipp->ipp_fields |= IPPF_MULTICAST_HOPS;
2841 				}
2842 			}
2843 			break;
2844 		case IPV6_MULTICAST_LOOP:
2845 			if (*i1 != 0 && *i1 != 1) {
2846 				*outlenp = 0;
2847 				return (EINVAL);
2848 			}
2849 			if (!checkonly)
2850 				udp->udp_multicast_loop = *i1;
2851 			break;
2852 		case IPV6_JOIN_GROUP:
2853 		case IPV6_LEAVE_GROUP:
2854 		case MCAST_JOIN_GROUP:
2855 		case MCAST_LEAVE_GROUP:
2856 		case MCAST_BLOCK_SOURCE:
2857 		case MCAST_UNBLOCK_SOURCE:
2858 		case MCAST_JOIN_SOURCE_GROUP:
2859 		case MCAST_LEAVE_SOURCE_GROUP:
2860 			/*
2861 			 * "soft" error (negative)
2862 			 * option not handled at this level
2863 			 * Note: Do not modify *outlenp
2864 			 */
2865 			return (-EINVAL);
2866 		case IPV6_BOUND_IF:
2867 			if (!checkonly)
2868 				udp->udp_bound_if = *i1;
2869 			break;
2870 		case IPV6_UNSPEC_SRC:
2871 			if (!checkonly)
2872 				udp->udp_unspec_source = onoff;
2873 			break;
2874 		/*
2875 		 * Set boolean switches for ancillary data delivery
2876 		 */
2877 		case IPV6_RECVPKTINFO:
2878 			if (!checkonly)
2879 				udp->udp_ipv6_recvpktinfo = onoff;
2880 			break;
2881 		case IPV6_RECVTCLASS:
2882 			if (!checkonly) {
2883 				udp->udp_ipv6_recvtclass = onoff;
2884 			}
2885 			break;
2886 		case IPV6_RECVPATHMTU:
2887 			if (!checkonly) {
2888 				udp->udp_ipv6_recvpathmtu = onoff;
2889 			}
2890 			break;
2891 		case IPV6_RECVHOPLIMIT:
2892 			if (!checkonly)
2893 				udp->udp_ipv6_recvhoplimit = onoff;
2894 			break;
2895 		case IPV6_RECVHOPOPTS:
2896 			if (!checkonly)
2897 				udp->udp_ipv6_recvhopopts = onoff;
2898 			break;
2899 		case IPV6_RECVDSTOPTS:
2900 			if (!checkonly)
2901 				udp->udp_ipv6_recvdstopts = onoff;
2902 			break;
2903 		case _OLD_IPV6_RECVDSTOPTS:
2904 			if (!checkonly)
2905 				udp->udp_old_ipv6_recvdstopts = onoff;
2906 			break;
2907 		case IPV6_RECVRTHDRDSTOPTS:
2908 			if (!checkonly)
2909 				udp->udp_ipv6_recvrthdrdstopts = onoff;
2910 			break;
2911 		case IPV6_RECVRTHDR:
2912 			if (!checkonly)
2913 				udp->udp_ipv6_recvrthdr = onoff;
2914 			break;
2915 		/*
2916 		 * Set sticky options or ancillary data.
2917 		 * If sticky options, (re)build any extension headers
2918 		 * that might be needed as a result.
2919 		 */
2920 		case IPV6_PKTINFO:
2921 			/*
2922 			 * The source address and ifindex are verified
2923 			 * in ip_opt_set(). For ancillary data the
2924 			 * source address is checked in ip_wput_v6.
2925 			 */
2926 			if (inlen != 0 && inlen != sizeof (struct in6_pktinfo))
2927 				return (EINVAL);
2928 			if (checkonly)
2929 				break;
2930 
2931 			if (inlen == 0) {
2932 				ipp->ipp_fields &= ~(IPPF_IFINDEX|IPPF_ADDR);
2933 				ipp->ipp_sticky_ignored |=
2934 				    (IPPF_IFINDEX|IPPF_ADDR);
2935 			} else {
2936 				struct in6_pktinfo *pkti;
2937 
2938 				pkti = (struct in6_pktinfo *)invalp;
2939 				ipp->ipp_ifindex = pkti->ipi6_ifindex;
2940 				ipp->ipp_addr = pkti->ipi6_addr;
2941 				if (ipp->ipp_ifindex != 0)
2942 					ipp->ipp_fields |= IPPF_IFINDEX;
2943 				else
2944 					ipp->ipp_fields &= ~IPPF_IFINDEX;
2945 				if (!IN6_IS_ADDR_UNSPECIFIED(
2946 				    &ipp->ipp_addr))
2947 					ipp->ipp_fields |= IPPF_ADDR;
2948 				else
2949 					ipp->ipp_fields &= ~IPPF_ADDR;
2950 			}
2951 			if (sticky) {
2952 				error = udp_build_hdrs(q, udp);
2953 				if (error != 0)
2954 					return (error);
2955 			}
2956 			break;
2957 		case IPV6_HOPLIMIT:
2958 			if (sticky)
2959 				return (EINVAL);
2960 			if (inlen != 0 && inlen != sizeof (int))
2961 				return (EINVAL);
2962 			if (checkonly)
2963 				break;
2964 
2965 			if (inlen == 0) {
2966 				ipp->ipp_fields &= ~IPPF_HOPLIMIT;
2967 				ipp->ipp_sticky_ignored |= IPPF_HOPLIMIT;
2968 			} else {
2969 				if (*i1 > 255 || *i1 < -1)
2970 					return (EINVAL);
2971 				if (*i1 == -1)
2972 					ipp->ipp_hoplimit = udp_ipv6_hoplimit;
2973 				else
2974 					ipp->ipp_hoplimit = *i1;
2975 				ipp->ipp_fields |= IPPF_HOPLIMIT;
2976 			}
2977 			break;
2978 		case IPV6_TCLASS:
2979 			if (inlen != 0 && inlen != sizeof (int))
2980 				return (EINVAL);
2981 			if (checkonly)
2982 				break;
2983 
2984 			if (inlen == 0) {
2985 				ipp->ipp_fields &= ~IPPF_TCLASS;
2986 				ipp->ipp_sticky_ignored |= IPPF_TCLASS;
2987 			} else {
2988 				if (*i1 > 255 || *i1 < -1)
2989 					return (EINVAL);
2990 				if (*i1 == -1)
2991 					ipp->ipp_tclass = 0;
2992 				else
2993 					ipp->ipp_tclass = *i1;
2994 				ipp->ipp_fields |= IPPF_TCLASS;
2995 			}
2996 			if (sticky) {
2997 				error = udp_build_hdrs(q, udp);
2998 				if (error != 0)
2999 					return (error);
3000 			}
3001 			break;
3002 		case IPV6_NEXTHOP:
3003 			/*
3004 			 * IP will verify that the nexthop is reachable
3005 			 * and fail for sticky options.
3006 			 */
3007 			if (inlen != 0 && inlen != sizeof (sin6_t))
3008 				return (EINVAL);
3009 			if (checkonly)
3010 				break;
3011 
3012 			if (inlen == 0) {
3013 				ipp->ipp_fields &= ~IPPF_NEXTHOP;
3014 				ipp->ipp_sticky_ignored |= IPPF_NEXTHOP;
3015 			} else {
3016 				sin6_t *sin6 = (sin6_t *)invalp;
3017 
3018 				if (sin6->sin6_family != AF_INET6)
3019 					return (EAFNOSUPPORT);
3020 				if (IN6_IS_ADDR_V4MAPPED(
3021 				    &sin6->sin6_addr))
3022 					return (EADDRNOTAVAIL);
3023 				ipp->ipp_nexthop = sin6->sin6_addr;
3024 				if (!IN6_IS_ADDR_UNSPECIFIED(
3025 				    &ipp->ipp_nexthop))
3026 					ipp->ipp_fields |= IPPF_NEXTHOP;
3027 				else
3028 					ipp->ipp_fields &= ~IPPF_NEXTHOP;
3029 			}
3030 			if (sticky) {
3031 				error = udp_build_hdrs(q, udp);
3032 				if (error != 0)
3033 					return (error);
3034 			}
3035 			break;
3036 		case IPV6_HOPOPTS: {
3037 			ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
3038 			/*
3039 			 * Sanity checks - minimum size, size a multiple of
3040 			 * eight bytes, and matching size passed in.
3041 			 */
3042 			if (inlen != 0 &&
3043 			    inlen != (8 * (hopts->ip6h_len + 1)))
3044 				return (EINVAL);
3045 
3046 			if (checkonly)
3047 				break;
3048 
3049 			if (inlen == 0) {
3050 				if (sticky &&
3051 				    (ipp->ipp_fields & IPPF_HOPOPTS) != 0) {
3052 					kmem_free(ipp->ipp_hopopts,
3053 					    ipp->ipp_hopoptslen);
3054 					ipp->ipp_hopopts = NULL;
3055 					ipp->ipp_hopoptslen = 0;
3056 				}
3057 				ipp->ipp_fields &= ~IPPF_HOPOPTS;
3058 				ipp->ipp_sticky_ignored |= IPPF_HOPOPTS;
3059 			} else {
3060 				error = udp_pkt_set(invalp, inlen, sticky,
3061 				    (uchar_t **)&ipp->ipp_hopopts,
3062 				    &ipp->ipp_hopoptslen);
3063 				if (error != 0)
3064 					return (error);
3065 				ipp->ipp_fields |= IPPF_HOPOPTS;
3066 			}
3067 			if (sticky) {
3068 				error = udp_build_hdrs(q, udp);
3069 				if (error != 0)
3070 					return (error);
3071 			}
3072 			break;
3073 		}
3074 		case IPV6_RTHDRDSTOPTS: {
3075 			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
3076 
3077 			/*
3078 			 * Sanity checks - minimum size, size a multiple of
3079 			 * eight bytes, and matching size passed in.
3080 			 */
3081 			if (inlen != 0 &&
3082 			    inlen != (8 * (dopts->ip6d_len + 1)))
3083 				return (EINVAL);
3084 
3085 			if (checkonly)
3086 				break;
3087 
3088 			if (inlen == 0) {
3089 				if (sticky &&
3090 				    (ipp->ipp_fields & IPPF_RTDSTOPTS) != 0) {
3091 					kmem_free(ipp->ipp_rtdstopts,
3092 					    ipp->ipp_rtdstoptslen);
3093 					ipp->ipp_rtdstopts = NULL;
3094 					ipp->ipp_rtdstoptslen = 0;
3095 				}
3096 				ipp->ipp_fields &= ~IPPF_RTDSTOPTS;
3097 				ipp->ipp_sticky_ignored |= IPPF_RTDSTOPTS;
3098 			} else {
3099 				error = udp_pkt_set(invalp, inlen, sticky,
3100 				    (uchar_t **)&ipp->ipp_rtdstopts,
3101 				    &ipp->ipp_rtdstoptslen);
3102 				if (error != 0)
3103 					return (error);
3104 				ipp->ipp_fields |= IPPF_RTDSTOPTS;
3105 			}
3106 			if (sticky) {
3107 				error = udp_build_hdrs(q, udp);
3108 				if (error != 0)
3109 					return (error);
3110 			}
3111 			break;
3112 		}
3113 		case IPV6_DSTOPTS: {
3114 			ip6_dest_t *dopts = (ip6_dest_t *)invalp;
3115 
3116 			/*
3117 			 * Sanity checks - minimum size, size a multiple of
3118 			 * eight bytes, and matching size passed in.
3119 			 */
3120 			if (inlen != 0 &&
3121 			    inlen != (8 * (dopts->ip6d_len + 1)))
3122 				return (EINVAL);
3123 
3124 			if (checkonly)
3125 				break;
3126 
3127 			if (inlen == 0) {
3128 				if (sticky &&
3129 				    (ipp->ipp_fields & IPPF_DSTOPTS) != 0) {
3130 					kmem_free(ipp->ipp_dstopts,
3131 					    ipp->ipp_dstoptslen);
3132 					ipp->ipp_dstopts = NULL;
3133 					ipp->ipp_dstoptslen = 0;
3134 				}
3135 				ipp->ipp_fields &= ~IPPF_DSTOPTS;
3136 				ipp->ipp_sticky_ignored |= IPPF_DSTOPTS;
3137 			} else {
3138 				error = udp_pkt_set(invalp, inlen, sticky,
3139 				    (uchar_t **)&ipp->ipp_dstopts,
3140 				    &ipp->ipp_dstoptslen);
3141 				if (error != 0)
3142 					return (error);
3143 				ipp->ipp_fields |= IPPF_DSTOPTS;
3144 			}
3145 			if (sticky) {
3146 				error = udp_build_hdrs(q, udp);
3147 				if (error != 0)
3148 					return (error);
3149 			}
3150 			break;
3151 		}
3152 		case IPV6_RTHDR: {
3153 			ip6_rthdr_t *rt = (ip6_rthdr_t *)invalp;
3154 
3155 			/*
3156 			 * Sanity checks - minimum size, size a multiple of
3157 			 * eight bytes, and matching size passed in.
3158 			 */
3159 			if (inlen != 0 &&
3160 			    inlen != (8 * (rt->ip6r_len + 1)))
3161 				return (EINVAL);
3162 
3163 			if (checkonly)
3164 				break;
3165 
3166 			if (inlen == 0) {
3167 				if (sticky &&
3168 				    (ipp->ipp_fields & IPPF_RTHDR) != 0) {
3169 					kmem_free(ipp->ipp_rthdr,
3170 					    ipp->ipp_rthdrlen);
3171 					ipp->ipp_rthdr = NULL;
3172 					ipp->ipp_rthdrlen = 0;
3173 				}
3174 				ipp->ipp_fields &= ~IPPF_RTHDR;
3175 				ipp->ipp_sticky_ignored |= IPPF_RTHDR;
3176 			} else {
3177 				error = udp_pkt_set(invalp, inlen, sticky,
3178 				    (uchar_t **)&ipp->ipp_rthdr,
3179 				    &ipp->ipp_rthdrlen);
3180 				if (error != 0)
3181 					return (error);
3182 				ipp->ipp_fields |= IPPF_RTHDR;
3183 			}
3184 			if (sticky) {
3185 				error = udp_build_hdrs(q, udp);
3186 				if (error != 0)
3187 					return (error);
3188 			}
3189 			break;
3190 		}
3191 
3192 		case IPV6_DONTFRAG:
3193 			if (checkonly)
3194 				break;
3195 
3196 			if (onoff) {
3197 				ipp->ipp_fields |= IPPF_DONTFRAG;
3198 			} else {
3199 				ipp->ipp_fields &= ~IPPF_DONTFRAG;
3200 			}
3201 			break;
3202 
3203 		case IPV6_USE_MIN_MTU:
3204 			if (inlen != sizeof (int))
3205 				return (EINVAL);
3206 
3207 			if (*i1 < -1 || *i1 > 1)
3208 				return (EINVAL);
3209 
3210 			if (checkonly)
3211 				break;
3212 
3213 			ipp->ipp_fields |= IPPF_USE_MIN_MTU;
3214 			ipp->ipp_use_min_mtu = *i1;
3215 			break;
3216 
3217 		case IPV6_BOUND_PIF:
3218 		case IPV6_SEC_OPT:
3219 		case IPV6_DONTFAILOVER_IF:
3220 		case IPV6_SRC_PREFERENCES:
3221 		case IPV6_V6ONLY:
3222 			/* Handled at the IP level */
3223 			return (-EINVAL);
3224 		default:
3225 			*outlenp = 0;
3226 			return (EINVAL);
3227 		}
3228 		break;
3229 		}		/* end IPPROTO_IPV6 */
3230 	case IPPROTO_UDP:
3231 		switch (name) {
3232 		case UDP_ANONPRIVBIND:
3233 			if ((error = secpolicy_net_privaddr(cr, 0)) != 0) {
3234 				*outlenp = 0;
3235 				return (error);
3236 			}
3237 			if (!checkonly) {
3238 				udp->udp_anon_priv_bind = onoff;
3239 			}
3240 			break;
3241 		case UDP_EXCLBIND:
3242 			if (!checkonly)
3243 				udp->udp_exclbind = onoff;
3244 			break;
3245 		case UDP_RCVHDR:
3246 			if (!checkonly)
3247 				udp->udp_rcvhdr = onoff;
3248 			break;
3249 		default:
3250 			*outlenp = 0;
3251 			return (EINVAL);
3252 		}
3253 		break;
3254 	default:
3255 		*outlenp = 0;
3256 		return (EINVAL);
3257 	}
3258 	/*
3259 	 * Common case of OK return with outval same as inval.
3260 	 */
3261 	if (invalp != outvalp) {
3262 		/* don't trust bcopy for identical src/dst */
3263 		(void) bcopy(invalp, outvalp, inlen);
3264 	}
3265 	*outlenp = inlen;
3266 	return (0);
3267 }
3268 
3269 /*
3270  * Update udp_sticky_hdrs based on udp_sticky_ipp, udp_v6src, and udp_ttl.
3271  * The headers include ip6i_t (if needed), ip6_t, any sticky extension
3272  * headers, and the udp header.
3273  * Returns failure if can't allocate memory.
3274  */
3275 static int
3276 udp_build_hdrs(queue_t *q, udp_t *udp)
3277 {
3278 	uchar_t	*hdrs;
3279 	uint_t	hdrs_len;
3280 	ip6_t	*ip6h;
3281 	ip6i_t	*ip6i;
3282 	udpha_t	*udpha;
3283 	ip6_pkt_t *ipp = &udp->udp_sticky_ipp;
3284 
3285 	hdrs_len = ip_total_hdrs_len_v6(ipp) + UDPH_SIZE;
3286 	ASSERT(hdrs_len != 0);
3287 	if (hdrs_len != udp->udp_sticky_hdrs_len) {
3288 		/* Need to reallocate */
3289 		hdrs = kmem_alloc(hdrs_len, KM_NOSLEEP);
3290 		if (hdrs == NULL)
3291 			return (ENOMEM);
3292 
3293 		if (udp->udp_sticky_hdrs_len != 0) {
3294 			kmem_free(udp->udp_sticky_hdrs,
3295 			    udp->udp_sticky_hdrs_len);
3296 		}
3297 		udp->udp_sticky_hdrs = hdrs;
3298 		udp->udp_sticky_hdrs_len = hdrs_len;
3299 	}
3300 	ip_build_hdrs_v6(udp->udp_sticky_hdrs,
3301 	    udp->udp_sticky_hdrs_len - UDPH_SIZE, ipp, IPPROTO_UDP);
3302 
3303 	/* Set header fields not in ipp */
3304 	if (ipp->ipp_fields & IPPF_HAS_IP6I) {
3305 		ip6i = (ip6i_t *)udp->udp_sticky_hdrs;
3306 		ip6h = (ip6_t *)&ip6i[1];
3307 	} else {
3308 		ip6h = (ip6_t *)udp->udp_sticky_hdrs;
3309 	}
3310 
3311 	if (!(ipp->ipp_fields & IPPF_ADDR))
3312 		ip6h->ip6_src = udp->udp_v6src;
3313 
3314 	udpha = (udpha_t *)(udp->udp_sticky_hdrs + hdrs_len - UDPH_SIZE);
3315 	udpha->uha_src_port = udp->udp_port;
3316 
3317 	/* Try to get everything in a single mblk */
3318 	if (hdrs_len > udp->udp_max_hdr_len) {
3319 		udp->udp_max_hdr_len = hdrs_len;
3320 		(void) mi_set_sth_wroff(RD(q), udp->udp_max_hdr_len +
3321 		    udp_wroff_extra);
3322 	}
3323 	return (0);
3324 }
3325 
3326 /*
3327  * Set optbuf and optlen for the option.
3328  * If sticky is set allocate memory (if not already present).
3329  * Otherwise just point optbuf and optlen at invalp and inlen.
3330  * Returns failure if memory can not be allocated.
3331  */
3332 static int
3333 udp_pkt_set(uchar_t *invalp, uint_t inlen, boolean_t sticky,
3334     uchar_t **optbufp, uint_t *optlenp)
3335 {
3336 	uchar_t *optbuf;
3337 
3338 	if (!sticky) {
3339 		*optbufp = invalp;
3340 		*optlenp = inlen;
3341 		return (0);
3342 	}
3343 	if (inlen == *optlenp) {
3344 		/* Unchanged length - no need to realocate */
3345 		bcopy(invalp, *optbufp, inlen);
3346 		return (0);
3347 	}
3348 	if (inlen != 0) {
3349 		/* Allocate new buffer before free */
3350 		optbuf = kmem_alloc(inlen, KM_NOSLEEP);
3351 		if (optbuf == NULL)
3352 			return (ENOMEM);
3353 	} else {
3354 		optbuf = NULL;
3355 	}
3356 	/* Free old buffer */
3357 	if (*optlenp != 0)
3358 		kmem_free(*optbufp, *optlenp);
3359 
3360 	bcopy(invalp, optbuf, inlen);
3361 	*optbufp = optbuf;
3362 	*optlenp = inlen;
3363 	return (0);
3364 }
3365 
3366 /*
3367  * This routine retrieves the value of an ND variable in a udpparam_t
3368  * structure.  It is called through nd_getset when a user reads the
3369  * variable.
3370  */
3371 /* ARGSUSED */
3372 static int
3373 udp_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
3374 {
3375 	udpparam_t *udppa = (udpparam_t *)cp;
3376 
3377 	(void) mi_mpprintf(mp, "%d", udppa->udp_param_value);
3378 	return (0);
3379 }
3380 
3381 /*
3382  * Walk through the param array specified registering each element with the
3383  * named dispatch (ND) handler.
3384  */
3385 static boolean_t
3386 udp_param_register(udpparam_t *udppa, int cnt)
3387 {
3388 	for (; cnt-- > 0; udppa++) {
3389 		if (udppa->udp_param_name && udppa->udp_param_name[0]) {
3390 			if (!nd_load(&udp_g_nd, udppa->udp_param_name,
3391 			    udp_param_get, udp_param_set,
3392 			    (caddr_t)udppa)) {
3393 				nd_free(&udp_g_nd);
3394 				return (B_FALSE);
3395 			}
3396 		}
3397 	}
3398 	if (!nd_load(&udp_g_nd, "udp_extra_priv_ports",
3399 	    udp_extra_priv_ports_get, NULL, NULL)) {
3400 		nd_free(&udp_g_nd);
3401 		return (B_FALSE);
3402 	}
3403 	if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_add",
3404 	    NULL, udp_extra_priv_ports_add, NULL)) {
3405 		nd_free(&udp_g_nd);
3406 		return (B_FALSE);
3407 	}
3408 	if (!nd_load(&udp_g_nd, "udp_extra_priv_ports_del",
3409 	    NULL, udp_extra_priv_ports_del, NULL)) {
3410 		nd_free(&udp_g_nd);
3411 		return (B_FALSE);
3412 	}
3413 	if (!nd_load(&udp_g_nd, "udp_status", udp_status_report, NULL,
3414 	    NULL)) {
3415 		nd_free(&udp_g_nd);
3416 		return (B_FALSE);
3417 	}
3418 	if (!nd_load(&udp_g_nd, "udp_bind_hash", udp_bind_hash_report, NULL,
3419 	    NULL)) {
3420 		nd_free(&udp_g_nd);
3421 		return (B_FALSE);
3422 	}
3423 	return (B_TRUE);
3424 }
3425 
3426 /* This routine sets an ND variable in a udpparam_t structure. */
3427 /* ARGSUSED */
3428 static int
3429 udp_param_set(queue_t *q, mblk_t *mp, char *value, caddr_t cp, cred_t *cr)
3430 {
3431 	long		new_value;
3432 	udpparam_t	*udppa = (udpparam_t *)cp;
3433 
3434 	/*
3435 	 * Fail the request if the new value does not lie within the
3436 	 * required bounds.
3437 	 */
3438 	if (ddi_strtol(value, NULL, 10, &new_value) != 0 ||
3439 	    new_value < udppa->udp_param_min ||
3440 	    new_value > udppa->udp_param_max) {
3441 		return (EINVAL);
3442 	}
3443 
3444 	/* Set the new value */
3445 	udppa->udp_param_value = new_value;
3446 	return (0);
3447 }
3448 
3449 static void
3450 udp_rput(queue_t *q, mblk_t *mp)
3451 {
3452 	struct T_unitdata_ind	*tudi;
3453 	uchar_t			*rptr;
3454 	int			hdr_length;
3455 	int			udi_size;	/* Size of T_unitdata_ind */
3456 	udp_t			*udp;
3457 	udpha_t			*udpha;
3458 	int			ipversion;
3459 	ip6_pkt_t		ipp;
3460 	ip6_t			*ip6h;
3461 	ip6i_t			*ip6i;
3462 	mblk_t			*mp1;
3463 	mblk_t			*options_mp = NULL;
3464 	in_pktinfo_t		*pinfo = NULL;
3465 	size_t			mp_size = MBLKL(mp);
3466 	cred_t			*cr = NULL;
3467 	pid_t			cpid;
3468 
3469 	TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START,
3470 	    "udp_rput_start: q %p mp %p", q, mp);
3471 
3472 	udp = (udp_t *)q->q_ptr;
3473 	rptr = mp->b_rptr;
3474 
3475 	switch (mp->b_datap->db_type) {
3476 	case M_DATA:
3477 		/*
3478 		 * M_DATA messages contain IP datagrams.  They are handled
3479 		 * after this switch.
3480 		 */
3481 		break;
3482 	case M_PROTO:
3483 	case M_PCPROTO:
3484 		/* M_PROTO messages contain some type of TPI message. */
3485 		if ((mp->b_wptr - rptr) < sizeof (t_scalar_t)) {
3486 			freemsg(mp);
3487 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3488 				"udp_rput_end: q %p (%S)", q, "protoshort");
3489 			return;
3490 		}
3491 		qwriter(q, mp, udp_rput_other, PERIM_INNER);
3492 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3493 			"udp_rput_end: q %p (%S)", q, "proto");
3494 		return;
3495 	case M_FLUSH:
3496 		if (*mp->b_rptr & FLUSHR)
3497 			flushq(q, FLUSHDATA);
3498 		putnext(q, mp);
3499 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3500 			"udp_rput_end: q %p (%S)", q, "flush");
3501 		return;
3502 	case M_CTL:
3503 		if (udp->udp_recvif || udp->udp_recvslla ||
3504 		    udp->udp_ipv6_recvpktinfo) {
3505 			/*
3506 			 * IP should have prepended the options data in an M_CTL
3507 			 * Check M_CTL "type" to make sure are not here bcos of
3508 			 * a valid ICMP message
3509 			 */
3510 			if (mp_size == sizeof (in_pktinfo_t) &&
3511 			    ((in_pktinfo_t *)mp->b_rptr)->in_pkt_ulp_type ==
3512 			    IN_PKTINFO) {
3513 				pinfo = (in_pktinfo_t *)mp->b_rptr;
3514 				/*
3515 				 * Jump to normal data processing, this is not
3516 				 * an ICMP message
3517 				 */
3518 				break;
3519 			}
3520 		}
3521 		/*
3522 		 * ICMP messages.
3523 		 */
3524 		udp_icmp_error(q, mp);
3525 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3526 			"udp_rput_end: q %p (%S)", q, "m_ctl");
3527 		return;
3528 	default:
3529 		putnext(q, mp);
3530 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3531 			"udp_rput_end: q %p (%S)", q, "default");
3532 		return;
3533 	}
3534 
3535 	/*
3536 	 * If we are here bcos the IP_RECVIF or IP_RECVSLLA then we need to
3537 	 * extract the mblk and adjust the rptr
3538 	 */
3539 	if (pinfo != NULL) {
3540 		ASSERT(mp->b_datap->db_type == M_CTL);
3541 		options_mp = mp;
3542 		mp = mp->b_cont;
3543 		rptr = mp->b_rptr;
3544 		mp_size = MBLKL(mp);
3545 	}
3546 	/*
3547 	 * This is the inbound data path.
3548 	 * First, we check to make sure the IP version number is correct,
3549 	 * and then pull the IP and UDP headers into the first mblk.
3550 	 */
3551 	/*
3552 	 * Assume IP provides aligned packets - otherwise toss.
3553 	 * Also, check if we have a complete IP header.
3554 	 */
3555 	if (!OK_32PTR(rptr) || (mp_size < sizeof (ipha_t))) {
3556 tossit:
3557 		freemsg(mp);
3558 		if (options_mp != NULL)
3559 			freeb(options_mp);
3560 		BUMP_MIB(&udp_mib, udpInErrors);
3561 		return;
3562 	}
3563 
3564 	/* Initialize regardless if ipversion is IPv4 or IPv6 */
3565 	ipp.ipp_fields = 0;
3566 
3567 	ipversion = IPH_HDR_VERSION(rptr);
3568 	switch (ipversion) {
3569 	case IPV4_VERSION:
3570 		hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE;
3571 		/* Verify this is a UDP packet */
3572 		if (((ipha_t *)rptr)->ipha_protocol != IPPROTO_UDP)
3573 			goto tossit;
3574 		if ((hdr_length > IP_SIMPLE_HDR_LENGTH + UDPH_SIZE) ||
3575 		    (udp->udp_ip_rcv_options_len)) {
3576 			/*
3577 			 * Handle IPv4 packets with options outside of the
3578 			 * main data path. Not needed for AF_INET6 sockets
3579 			 * since they don't support a getsockopt of IP_OPTIONS.
3580 			 */
3581 			if (udp->udp_family == AF_INET6)
3582 				break;
3583 			/*
3584 			 * UDP length check performed for IPv4 packets with
3585 			 * options to check whether UDP length specified in
3586 			 * the header is the same as the physical length of
3587 			 * the packet.
3588 			 */
3589 			udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE));
3590 			if (msgdsize(mp) != (ntohs(udpha->uha_length) +
3591 			    hdr_length - UDPH_SIZE)) {
3592 				goto tossit;
3593 			}
3594 			/*
3595 			 * Handle the case where the packet has IP options
3596 			 * and the IP_RECVSLLA & IP_RECVIF are set
3597 			 */
3598 			if (pinfo != NULL)
3599 				mp = options_mp;
3600 			qwriter(q, mp, udp_rput_other, PERIM_INNER);
3601 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3602 				"udp_rput_end: q %p (%S)", q, "end");
3603 			return;
3604 		}
3605 
3606 		/* Handle IPV6_RECVHOPLIMIT. */
3607 		if ((udp->udp_family == AF_INET6) && (pinfo != NULL)) {
3608 			if (pinfo->in_pkt_flags & IPF_RECVIF) {
3609 				ipp.ipp_fields |= IPPF_IFINDEX;
3610 				ipp.ipp_ifindex = pinfo->in_pkt_ifindex;
3611 			}
3612 		}
3613 		break;
3614 	case IPV6_VERSION:
3615 		/*
3616 		 * IPv6 packets can only be received by applications
3617 		 * that are prepared to receive IPv6 addresses.
3618 		 * The IP fanout must ensure this.
3619 		 */
3620 		ASSERT(udp->udp_family == AF_INET6);
3621 
3622 		ip6h = (ip6_t *)rptr;
3623 		if ((uchar_t *)&ip6h[1] > mp->b_wptr)
3624 			goto tossit;
3625 
3626 		if (ip6h->ip6_nxt != IPPROTO_UDP) {
3627 			uint8_t nexthdrp;
3628 			/* Look for ifindex information */
3629 			if (ip6h->ip6_nxt == IPPROTO_RAW) {
3630 				ip6i = (ip6i_t *)ip6h;
3631 				if ((uchar_t *)&ip6i[1] > mp->b_wptr)
3632 					goto tossit;
3633 
3634 				if (ip6i->ip6i_flags & IP6I_IFINDEX) {
3635 					ASSERT(ip6i->ip6i_ifindex != 0);
3636 					ipp.ipp_fields |= IPPF_IFINDEX;
3637 					ipp.ipp_ifindex = ip6i->ip6i_ifindex;
3638 				}
3639 				rptr = (uchar_t *)&ip6i[1];
3640 				mp->b_rptr = rptr;
3641 				if (rptr == mp->b_wptr) {
3642 					mp1 = mp->b_cont;
3643 					freeb(mp);
3644 					mp = mp1;
3645 					rptr = mp->b_rptr;
3646 				}
3647 				if (MBLKL(mp) < (IPV6_HDR_LEN + UDPH_SIZE))
3648 					goto tossit;
3649 				ip6h = (ip6_t *)rptr;
3650 			}
3651 			/*
3652 			 * Find any potentially interesting extension headers
3653 			 * as well as the length of the IPv6 + extension
3654 			 * headers.
3655 			 */
3656 			hdr_length = ip_find_hdr_v6(mp, ip6h, &ipp, &nexthdrp) +
3657 			    UDPH_SIZE;
3658 			/* Verify this is a UDP packet */
3659 			if (nexthdrp != IPPROTO_UDP)
3660 				goto tossit;
3661 		} else {
3662 			hdr_length = IPV6_HDR_LEN + UDPH_SIZE;
3663 			ip6i = NULL;
3664 		}
3665 		break;
3666 	default:
3667 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3668 			"udp_rput_end: q %p (%S)", q, "Unknown IP version");
3669 		goto tossit;
3670 	}
3671 
3672 	/*
3673 	 * IP inspected the UDP header thus all of it must be in the mblk.
3674 	 * UDP length check is performed for IPv6 packets and IPv4 packets
3675 	 * without options to check if the size of the packet as specified
3676 	 * by the header is the same as the physical size of the packet.
3677 	 */
3678 	udpha = (udpha_t *)(rptr + (hdr_length - UDPH_SIZE));
3679 	if ((MBLKL(mp) < hdr_length) ||
3680 	    (msgdsize(mp) != (ntohs(udpha->uha_length) +
3681 	    hdr_length - UDPH_SIZE))) {
3682 		goto tossit;
3683 	}
3684 
3685 	/* Walk past the headers. */
3686 	if (!udp->udp_rcvhdr)
3687 		mp->b_rptr = rptr + hdr_length;
3688 
3689 	/*
3690 	 * This is the inbound data path.  Packets are passed upstream as
3691 	 * T_UNITDATA_IND messages with full IP headers still attached.
3692 	 */
3693 	if (udp->udp_family == AF_INET) {
3694 		sin_t *sin;
3695 
3696 		ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION);
3697 
3698 		/*
3699 		 * Normally only send up the address.
3700 		 * If IP_RECVDSTADDR is set we include the destination IP
3701 		 * address as an option. With IP_RECVOPTS we include all
3702 		 * the IP options. Only ip_rput_other() handles packets
3703 		 * that contain IP options.
3704 		 */
3705 		udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t);
3706 		if (udp->udp_recvdstaddr) {
3707 			udi_size += sizeof (struct T_opthdr) +
3708 			    sizeof (struct in_addr);
3709 		}
3710 
3711 		/*
3712 		 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate
3713 		 * space accordingly
3714 		 */
3715 		if (udp->udp_recvif && (pinfo != NULL) &&
3716 		    (pinfo->in_pkt_flags & IPF_RECVIF)) {
3717 			udi_size += sizeof (struct T_opthdr) +
3718 				sizeof (uint_t);
3719 		}
3720 
3721 		if (udp->udp_recvslla && (pinfo != NULL) &&
3722 		    (pinfo->in_pkt_flags & IPF_RECVSLLA)) {
3723 			udi_size += sizeof (struct T_opthdr) +
3724 				sizeof (struct sockaddr_dl);
3725 		}
3726 
3727 		if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) {
3728 			udi_size += sizeof (struct T_opthdr) + ucredsize;
3729 			cpid = DB_CPID(mp);
3730 		}
3731 		/*
3732 		 * If IP_RECVTTL is set allocate the appropriate sized buffer
3733 		 */
3734 		if (udp->udp_recvttl) {
3735 			udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t);
3736 		}
3737 
3738 		ASSERT(IPH_HDR_LENGTH((ipha_t *)rptr) == IP_SIMPLE_HDR_LENGTH);
3739 
3740 		/* Allocate a message block for the T_UNITDATA_IND structure. */
3741 		mp1 = allocb(udi_size, BPRI_MED);
3742 		if (mp1 == NULL) {
3743 			freemsg(mp);
3744 			if (options_mp != NULL)
3745 				freeb(options_mp);
3746 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3747 				"udp_rput_end: q %p (%S)", q, "allocbfail");
3748 			BUMP_MIB(&udp_mib, udpInErrors);
3749 			return;
3750 		}
3751 		mp1->b_cont = mp;
3752 		mp = mp1;
3753 		mp->b_datap->db_type = M_PROTO;
3754 		tudi = (struct T_unitdata_ind *)mp->b_rptr;
3755 		mp->b_wptr = (uchar_t *)tudi + udi_size;
3756 		tudi->PRIM_type = T_UNITDATA_IND;
3757 		tudi->SRC_length = sizeof (sin_t);
3758 		tudi->SRC_offset = sizeof (struct T_unitdata_ind);
3759 		tudi->OPT_offset = sizeof (struct T_unitdata_ind) +
3760 		    sizeof (sin_t);
3761 		udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t));
3762 		tudi->OPT_length = udi_size;
3763 		sin = (sin_t *)&tudi[1];
3764 		sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src;
3765 		sin->sin_port =	udpha->uha_src_port;
3766 		sin->sin_family = udp->udp_family;
3767 		*(uint32_t *)&sin->sin_zero[0] = 0;
3768 		*(uint32_t *)&sin->sin_zero[4] = 0;
3769 
3770 		/*
3771 		 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or
3772 		 * IP_RECVTTL has been set.
3773 		 */
3774 		if (udi_size != 0) {
3775 			/*
3776 			 * Copy in destination address before options to avoid
3777 			 * any padding issues.
3778 			 */
3779 			char *dstopt;
3780 
3781 			dstopt = (char *)&sin[1];
3782 			if (udp->udp_recvdstaddr) {
3783 				struct T_opthdr *toh;
3784 				ipaddr_t *dstptr;
3785 
3786 				toh = (struct T_opthdr *)dstopt;
3787 				toh->level = IPPROTO_IP;
3788 				toh->name = IP_RECVDSTADDR;
3789 				toh->len = sizeof (struct T_opthdr) +
3790 				    sizeof (ipaddr_t);
3791 				toh->status = 0;
3792 				dstopt += sizeof (struct T_opthdr);
3793 				dstptr = (ipaddr_t *)dstopt;
3794 				*dstptr = ((ipha_t *)rptr)->ipha_dst;
3795 				dstopt += sizeof (ipaddr_t);
3796 				udi_size -= toh->len;
3797 			}
3798 
3799 			if (udp->udp_recvslla && (pinfo != NULL) &&
3800 			    (pinfo->in_pkt_flags & IPF_RECVSLLA)) {
3801 
3802 				struct T_opthdr *toh;
3803 				struct sockaddr_dl	*dstptr;
3804 
3805 				toh = (struct T_opthdr *)dstopt;
3806 				toh->level = IPPROTO_IP;
3807 				toh->name = IP_RECVSLLA;
3808 				toh->len = sizeof (struct T_opthdr) +
3809 					sizeof (struct sockaddr_dl);
3810 				toh->status = 0;
3811 				dstopt += sizeof (struct T_opthdr);
3812 				dstptr = (struct sockaddr_dl *)dstopt;
3813 				bcopy(&pinfo->in_pkt_slla, dstptr,
3814 				    sizeof (struct sockaddr_dl));
3815 				dstopt += sizeof (struct sockaddr_dl);
3816 				udi_size -= toh->len;
3817 			}
3818 
3819 			if (udp->udp_recvif && (pinfo != NULL) &&
3820 			    (pinfo->in_pkt_flags & IPF_RECVIF)) {
3821 
3822 				struct T_opthdr *toh;
3823 				uint_t		*dstptr;
3824 
3825 				toh = (struct T_opthdr *)dstopt;
3826 				toh->level = IPPROTO_IP;
3827 				toh->name = IP_RECVIF;
3828 				toh->len = sizeof (struct T_opthdr) +
3829 					sizeof (uint_t);
3830 				toh->status = 0;
3831 				dstopt += sizeof (struct T_opthdr);
3832 				dstptr = (uint_t *)dstopt;
3833 				*dstptr = pinfo->in_pkt_ifindex;
3834 				dstopt += sizeof (uint_t);
3835 				udi_size -= toh->len;
3836 			}
3837 
3838 			if (cr != NULL) {
3839 				struct T_opthdr *toh;
3840 
3841 				toh = (struct T_opthdr *)dstopt;
3842 				toh->level = SOL_SOCKET;
3843 				toh->name = SCM_UCRED;
3844 				toh->len = sizeof (struct T_opthdr) + ucredsize;
3845 				toh->status = 0;
3846 				(void) cred2ucred(cr, cpid, &toh[1]);
3847 				dstopt += toh->len;
3848 				udi_size -= toh->len;
3849 			}
3850 
3851 			if (udp->udp_recvttl) {
3852 				struct	T_opthdr *toh;
3853 				uint8_t	*dstptr;
3854 
3855 				toh = (struct T_opthdr *)dstopt;
3856 				toh->level = IPPROTO_IP;
3857 				toh->name = IP_RECVTTL;
3858 				toh->len = sizeof (struct T_opthdr) +
3859 				    sizeof (uint8_t);
3860 				toh->status = 0;
3861 				dstopt += sizeof (struct T_opthdr);
3862 				dstptr = (uint8_t *)dstopt;
3863 				*dstptr = ((ipha_t *)rptr)->ipha_ttl;
3864 				dstopt += sizeof (uint8_t);
3865 				udi_size -= toh->len;
3866 			}
3867 
3868 			/* Consumed all of allocated space */
3869 			ASSERT(udi_size == 0);
3870 		}
3871 	} else {
3872 		sin6_t *sin6;
3873 
3874 		/*
3875 		 * Handle both IPv4 and IPv6 packets for IPv6 sockets.
3876 		 *
3877 		 * Normally we only send up the address. If receiving of any
3878 		 * optional receive side information is enabled, we also send
3879 		 * that up as options.
3880 		 * [ Only udp_rput_other() handles packets that contain IP
3881 		 * options so code to account for does not appear immediately
3882 		 * below but elsewhere ]
3883 		 */
3884 		udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin6_t);
3885 
3886 		if (ipp.ipp_fields & (IPPF_HOPOPTS|IPPF_DSTOPTS|IPPF_RTDSTOPTS|
3887 		    IPPF_RTHDR|IPPF_IFINDEX)) {
3888 			if (udp->udp_ipv6_recvhopopts &&
3889 			    (ipp.ipp_fields & IPPF_HOPOPTS)) {
3890 				udi_size += sizeof (struct T_opthdr) +
3891 				    ipp.ipp_hopoptslen;
3892 			}
3893 			if ((udp->udp_ipv6_recvdstopts ||
3894 				udp->udp_old_ipv6_recvdstopts) &&
3895 			    (ipp.ipp_fields & IPPF_DSTOPTS)) {
3896 				udi_size += sizeof (struct T_opthdr) +
3897 				    ipp.ipp_dstoptslen;
3898 			}
3899 			if (((udp->udp_ipv6_recvdstopts &&
3900 			    udp->udp_ipv6_recvrthdr &&
3901 			    (ipp.ipp_fields & IPPF_RTHDR)) ||
3902 			    udp->udp_ipv6_recvrthdrdstopts) &&
3903 			    (ipp.ipp_fields & IPPF_RTDSTOPTS)) {
3904 				udi_size += sizeof (struct T_opthdr) +
3905 				    ipp.ipp_rtdstoptslen;
3906 			}
3907 			if (udp->udp_ipv6_recvrthdr &&
3908 			    (ipp.ipp_fields & IPPF_RTHDR)) {
3909 				udi_size += sizeof (struct T_opthdr) +
3910 				    ipp.ipp_rthdrlen;
3911 			}
3912 			if (udp->udp_ipv6_recvpktinfo &&
3913 			    (ipp.ipp_fields & IPPF_IFINDEX)) {
3914 				udi_size += sizeof (struct T_opthdr) +
3915 				    sizeof (struct in6_pktinfo);
3916 			}
3917 
3918 		}
3919 		if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) {
3920 			udi_size += sizeof (struct T_opthdr) + ucredsize;
3921 			cpid = DB_CPID(mp);
3922 		}
3923 
3924 		if (udp->udp_ipv6_recvhoplimit)
3925 			udi_size += sizeof (struct T_opthdr) + sizeof (int);
3926 
3927 		if (udp->udp_ipv6_recvtclass)
3928 			udi_size += sizeof (struct T_opthdr) + sizeof (int);
3929 
3930 		mp1 = allocb(udi_size, BPRI_MED);
3931 		if (mp1 == NULL) {
3932 			freemsg(mp);
3933 			if (options_mp != NULL)
3934 				freeb(options_mp);
3935 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
3936 				"udp_rput_end: q %p (%S)", q, "allocbfail");
3937 			BUMP_MIB(&udp_mib, udpInErrors);
3938 			return;
3939 		}
3940 		mp1->b_cont = mp;
3941 		mp = mp1;
3942 		mp->b_datap->db_type = M_PROTO;
3943 		tudi = (struct T_unitdata_ind *)mp->b_rptr;
3944 		mp->b_wptr = (uchar_t *)tudi + udi_size;
3945 		tudi->PRIM_type = T_UNITDATA_IND;
3946 		tudi->SRC_length = sizeof (sin6_t);
3947 		tudi->SRC_offset = sizeof (struct T_unitdata_ind);
3948 		tudi->OPT_offset = sizeof (struct T_unitdata_ind) +
3949 		    sizeof (sin6_t);
3950 		udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin6_t));
3951 		tudi->OPT_length = udi_size;
3952 		sin6 = (sin6_t *)&tudi[1];
3953 		if (ipversion == IPV4_VERSION) {
3954 			in6_addr_t v6dst;
3955 
3956 			IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_src,
3957 			    &sin6->sin6_addr);
3958 			IN6_IPADDR_TO_V4MAPPED(((ipha_t *)rptr)->ipha_dst,
3959 			    &v6dst);
3960 			sin6->sin6_flowinfo = 0;
3961 			sin6->sin6_scope_id = 0;
3962 			sin6->__sin6_src_id = ip_srcid_find_addr(&v6dst,
3963 			    udp->udp_zoneid);
3964 		} else {
3965 			sin6->sin6_addr = ip6h->ip6_src;
3966 			/* No sin6_flowinfo per API */
3967 			sin6->sin6_flowinfo = 0;
3968 			/* For link-scope source pass up scope id */
3969 			if ((ipp.ipp_fields & IPPF_IFINDEX) &&
3970 			    IN6_IS_ADDR_LINKSCOPE(&ip6h->ip6_src))
3971 				sin6->sin6_scope_id = ipp.ipp_ifindex;
3972 			else
3973 				sin6->sin6_scope_id = 0;
3974 			sin6->__sin6_src_id =
3975 			    ip_srcid_find_addr(&ip6h->ip6_dst, udp->udp_zoneid);
3976 		}
3977 		sin6->sin6_port = udpha->uha_src_port;
3978 		sin6->sin6_family = udp->udp_family;
3979 
3980 		if (udi_size != 0) {
3981 			uchar_t *dstopt;
3982 
3983 			dstopt = (uchar_t *)&sin6[1];
3984 			if (udp->udp_ipv6_recvpktinfo &&
3985 			    (ipp.ipp_fields & IPPF_IFINDEX)) {
3986 				struct T_opthdr *toh;
3987 				struct in6_pktinfo *pkti;
3988 
3989 				toh = (struct T_opthdr *)dstopt;
3990 				toh->level = IPPROTO_IPV6;
3991 				toh->name = IPV6_PKTINFO;
3992 				toh->len = sizeof (struct T_opthdr) +
3993 				    sizeof (*pkti);
3994 				toh->status = 0;
3995 				dstopt += sizeof (struct T_opthdr);
3996 				pkti = (struct in6_pktinfo *)dstopt;
3997 				if (ipversion == IPV6_VERSION)
3998 					pkti->ipi6_addr = ip6h->ip6_dst;
3999 				else
4000 					IN6_IPADDR_TO_V4MAPPED(
4001 						((ipha_t *)rptr)->ipha_dst,
4002 						    &pkti->ipi6_addr);
4003 				pkti->ipi6_ifindex = ipp.ipp_ifindex;
4004 				dstopt += sizeof (*pkti);
4005 				udi_size -= toh->len;
4006 			}
4007 			if (udp->udp_ipv6_recvhoplimit) {
4008 				struct T_opthdr *toh;
4009 
4010 				toh = (struct T_opthdr *)dstopt;
4011 				toh->level = IPPROTO_IPV6;
4012 				toh->name = IPV6_HOPLIMIT;
4013 				toh->len = sizeof (struct T_opthdr) +
4014 				    sizeof (uint_t);
4015 				toh->status = 0;
4016 				dstopt += sizeof (struct T_opthdr);
4017 				if (ipversion == IPV6_VERSION)
4018 					*(uint_t *)dstopt = ip6h->ip6_hops;
4019 				else
4020 					*(uint_t *)dstopt =
4021 					    ((ipha_t *)rptr)->ipha_ttl;
4022 				dstopt += sizeof (uint_t);
4023 				udi_size -= toh->len;
4024 			}
4025 			if (udp->udp_ipv6_recvtclass) {
4026 				struct T_opthdr *toh;
4027 
4028 				toh = (struct T_opthdr *)dstopt;
4029 				toh->level = IPPROTO_IPV6;
4030 				toh->name = IPV6_TCLASS;
4031 				toh->len = sizeof (struct T_opthdr) +
4032 				    sizeof (uint_t);
4033 				toh->status = 0;
4034 				dstopt += sizeof (struct T_opthdr);
4035 				if (ipversion == IPV6_VERSION) {
4036 					*(uint_t *)dstopt =
4037 					IPV6_FLOW_TCLASS(ip6h->ip6_flow);
4038 				} else {
4039 					ipha_t *ipha = (ipha_t *)rptr;
4040 					*(uint_t *)dstopt =
4041 					    ipha->ipha_type_of_service;
4042 				}
4043 				dstopt += sizeof (uint_t);
4044 				udi_size -= toh->len;
4045 			}
4046 			if (udp->udp_ipv6_recvhopopts &&
4047 			    (ipp.ipp_fields & IPPF_HOPOPTS)) {
4048 				struct T_opthdr *toh;
4049 
4050 				toh = (struct T_opthdr *)dstopt;
4051 				toh->level = IPPROTO_IPV6;
4052 				toh->name = IPV6_HOPOPTS;
4053 				toh->len = sizeof (struct T_opthdr) +
4054 				    ipp.ipp_hopoptslen;
4055 				toh->status = 0;
4056 				dstopt += sizeof (struct T_opthdr);
4057 				bcopy(ipp.ipp_hopopts, dstopt,
4058 				    ipp.ipp_hopoptslen);
4059 				dstopt += ipp.ipp_hopoptslen;
4060 				udi_size -= toh->len;
4061 			}
4062 			if (udp->udp_ipv6_recvdstopts &&
4063 			    udp->udp_ipv6_recvrthdr &&
4064 			    (ipp.ipp_fields & IPPF_RTHDR) &&
4065 			    (ipp.ipp_fields & IPPF_RTDSTOPTS)) {
4066 				struct T_opthdr *toh;
4067 
4068 				toh = (struct T_opthdr *)dstopt;
4069 				toh->level = IPPROTO_IPV6;
4070 				toh->name = IPV6_DSTOPTS;
4071 				toh->len = sizeof (struct T_opthdr) +
4072 				    ipp.ipp_rtdstoptslen;
4073 				toh->status = 0;
4074 				dstopt += sizeof (struct T_opthdr);
4075 				bcopy(ipp.ipp_rtdstopts, dstopt,
4076 				    ipp.ipp_rtdstoptslen);
4077 				dstopt += ipp.ipp_rtdstoptslen;
4078 				udi_size -= toh->len;
4079 			}
4080 			if (udp->udp_ipv6_recvrthdr &&
4081 			    (ipp.ipp_fields & IPPF_RTHDR)) {
4082 				struct T_opthdr *toh;
4083 
4084 				toh = (struct T_opthdr *)dstopt;
4085 				toh->level = IPPROTO_IPV6;
4086 				toh->name = IPV6_RTHDR;
4087 				toh->len = sizeof (struct T_opthdr) +
4088 				    ipp.ipp_rthdrlen;
4089 				toh->status = 0;
4090 				dstopt += sizeof (struct T_opthdr);
4091 				bcopy(ipp.ipp_rthdr, dstopt, ipp.ipp_rthdrlen);
4092 				dstopt += ipp.ipp_rthdrlen;
4093 				udi_size -= toh->len;
4094 			}
4095 			if (udp->udp_ipv6_recvdstopts &&
4096 			    (ipp.ipp_fields & IPPF_DSTOPTS)) {
4097 				struct T_opthdr *toh;
4098 
4099 				toh = (struct T_opthdr *)dstopt;
4100 				toh->level = IPPROTO_IPV6;
4101 				toh->name = IPV6_DSTOPTS;
4102 				toh->len = sizeof (struct T_opthdr) +
4103 				    ipp.ipp_dstoptslen;
4104 				toh->status = 0;
4105 				dstopt += sizeof (struct T_opthdr);
4106 				bcopy(ipp.ipp_dstopts, dstopt,
4107 				    ipp.ipp_dstoptslen);
4108 				dstopt += ipp.ipp_dstoptslen;
4109 				udi_size -= toh->len;
4110 			}
4111 
4112 			if (cr != NULL) {
4113 				struct T_opthdr *toh;
4114 
4115 				toh = (struct T_opthdr *)dstopt;
4116 				toh->level = SOL_SOCKET;
4117 				toh->name = SCM_UCRED;
4118 				toh->len = sizeof (struct T_opthdr) + ucredsize;
4119 				toh->status = 0;
4120 				(void) cred2ucred(cr, cpid, &toh[1]);
4121 				dstopt += toh->len;
4122 				udi_size -= toh->len;
4123 			}
4124 			/* Consumed all of allocated space */
4125 			ASSERT(udi_size == 0);
4126 		}
4127 #undef	sin6
4128 		/* No IP_RECVDSTADDR for IPv6. */
4129 	}
4130 
4131 	BUMP_MIB(&udp_mib, udpInDatagrams);
4132 	TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
4133 		"udp_rput_end: q %p (%S)", q, "end");
4134 	if (options_mp != NULL)
4135 		freeb(options_mp);
4136 	putnext(q, mp);
4137 }
4138 
4139 /*
4140  * Process non-M_DATA messages as well as M_DATA messages that requires
4141  * modifications to udp_ip_rcv_options i.e. IPv4 packets with IP options.
4142  */
4143 static void
4144 udp_rput_other(queue_t *q, mblk_t *mp)
4145 {
4146 	struct T_unitdata_ind	*tudi;
4147 	mblk_t			*mp1;
4148 	uchar_t			*rptr;
4149 	uchar_t			*new_rptr;
4150 	int			hdr_length;
4151 	int			udi_size;	/* Size of T_unitdata_ind */
4152 	int			opt_len;	/* Length of IP options */
4153 	sin_t			*sin;
4154 	struct T_error_ack	*tea;
4155 	udp_t			*udp;
4156 	mblk_t			*options_mp = NULL;
4157 	in_pktinfo_t		*pinfo;
4158 	boolean_t		recv_on = B_FALSE;
4159 	cred_t			*cr = NULL;
4160 	pid_t			cpid;
4161 
4162 	TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_START,
4163 	    "udp_rput_other: q %p mp %p", q, mp);
4164 
4165 	ASSERT(OK_32PTR(mp->b_rptr));
4166 	udp = (udp_t *)q->q_ptr;
4167 	rptr = mp->b_rptr;
4168 
4169 	switch (mp->b_datap->db_type) {
4170 	case M_CTL:
4171 		/*
4172 		 * We are here only if IP_RECVSLLA and/or IP_RECVIF are set
4173 		 */
4174 		recv_on = B_TRUE;
4175 		options_mp = mp;
4176 		pinfo = (in_pktinfo_t *)options_mp->b_rptr;
4177 
4178 		/*
4179 		 * The actual data is in mp->b_cont
4180 		 */
4181 		mp = mp->b_cont;
4182 		ASSERT(OK_32PTR(mp->b_rptr));
4183 		rptr = mp->b_rptr;
4184 		break;
4185 	case M_DATA:
4186 		/*
4187 		 * M_DATA messages contain IPv4 datagrams.  They are handled
4188 		 * after this switch.
4189 		 */
4190 		break;
4191 	case M_PROTO:
4192 	case M_PCPROTO:
4193 		/* M_PROTO messages contain some type of TPI message. */
4194 		ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
4195 		if (mp->b_wptr - rptr < sizeof (t_scalar_t)) {
4196 			freemsg(mp);
4197 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
4198 			    "udp_rput_other_end: q %p (%S)", q, "protoshort");
4199 			return;
4200 		}
4201 		tea = (struct T_error_ack *)rptr;
4202 
4203 		switch (tea->PRIM_type) {
4204 		case T_ERROR_ACK:
4205 			switch (tea->ERROR_prim) {
4206 			case O_T_BIND_REQ:
4207 			case T_BIND_REQ: {
4208 				/*
4209 				 * If our O_T_BIND_REQ/T_BIND_REQ fails,
4210 				 * clear out the associated port and source
4211 				 * address before passing the message
4212 				 * upstream. If this was caused by a T_CONN_REQ
4213 				 * revert back to bound state.
4214 				 */
4215 				udp_fanout_t	*udpf;
4216 
4217 				udpf = &udp_bind_fanout[
4218 				    UDP_BIND_HASH(udp->udp_port)];
4219 				mutex_enter(&udpf->uf_lock);
4220 				if (udp->udp_state == TS_DATA_XFER) {
4221 					/* Connect failed */
4222 					tea->ERROR_prim = T_CONN_REQ;
4223 					/* Revert back to the bound source */
4224 					udp->udp_v6src = udp->udp_bound_v6src;
4225 					udp->udp_state = TS_IDLE;
4226 					mutex_exit(&udpf->uf_lock);
4227 					if (udp->udp_family == AF_INET6)
4228 						(void) udp_build_hdrs(q, udp);
4229 					break;
4230 				}
4231 
4232 				if (udp->udp_discon_pending) {
4233 					tea->ERROR_prim = T_DISCON_REQ;
4234 					udp->udp_discon_pending = 0;
4235 				}
4236 				V6_SET_ZERO(udp->udp_v6src);
4237 				V6_SET_ZERO(udp->udp_bound_v6src);
4238 				udp->udp_state = TS_UNBND;
4239 				udp_bind_hash_remove(udp, B_TRUE);
4240 				udp->udp_port = 0;
4241 				mutex_exit(&udpf->uf_lock);
4242 				if (udp->udp_family == AF_INET6)
4243 					(void) udp_build_hdrs(q, udp);
4244 				break;
4245 			}
4246 			default:
4247 				break;
4248 			}
4249 			break;
4250 		case T_BIND_ACK:
4251 			udp_rput_bind_ack(q, mp);
4252 			return;
4253 
4254 		case T_OPTMGMT_ACK:
4255 		case T_OK_ACK:
4256 			break;
4257 		default:
4258 			freemsg(mp);
4259 			return;
4260 		}
4261 		putnext(q, mp);
4262 		return;
4263 	}
4264 
4265 	/*
4266 	 * This is the inbound data path.
4267 	 * First, we make sure the data contains both IP and UDP headers.
4268 	 *
4269 	 * This handle IPv4 packets for only AF_INET sockets.
4270 	 * AF_INET6 sockets can never access udp_ip_rcv_options thus there
4271 	 * is no need saving the options.
4272 	 */
4273 	ASSERT(IPH_HDR_VERSION((ipha_t *)rptr) == IPV4_VERSION);
4274 	hdr_length = IPH_HDR_LENGTH(rptr) + UDPH_SIZE;
4275 	if (mp->b_wptr - rptr < hdr_length) {
4276 		if (!pullupmsg(mp, hdr_length)) {
4277 			freemsg(mp);
4278 			if (options_mp != NULL)
4279 				freeb(options_mp);
4280 			BUMP_MIB(&udp_mib, udpInErrors);
4281 			TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
4282 			    "udp_rput_other_end: q %p (%S)", q, "hdrshort");
4283 			BUMP_MIB(&udp_mib, udpInErrors);
4284 			return;
4285 		}
4286 		rptr = mp->b_rptr;
4287 	}
4288 	/* Walk past the headers. */
4289 	new_rptr = rptr + hdr_length;
4290 	if (!udp->udp_rcvhdr)
4291 		mp->b_rptr = new_rptr;
4292 
4293 	/* Save the options if any */
4294 	opt_len = hdr_length - (IP_SIMPLE_HDR_LENGTH + UDPH_SIZE);
4295 	if (opt_len > 0) {
4296 		if (opt_len > udp->udp_ip_rcv_options_len) {
4297 			if (udp->udp_ip_rcv_options_len)
4298 				mi_free((char *)udp->udp_ip_rcv_options);
4299 			udp->udp_ip_rcv_options_len = 0;
4300 			udp->udp_ip_rcv_options =
4301 			    (uchar_t *)mi_alloc(opt_len, BPRI_HI);
4302 			if (udp->udp_ip_rcv_options)
4303 				udp->udp_ip_rcv_options_len = opt_len;
4304 		}
4305 		if (udp->udp_ip_rcv_options_len) {
4306 			bcopy(rptr + IP_SIMPLE_HDR_LENGTH,
4307 			    udp->udp_ip_rcv_options, opt_len);
4308 			/* Adjust length if we are resusing the space */
4309 			udp->udp_ip_rcv_options_len = opt_len;
4310 		}
4311 	} else if (udp->udp_ip_rcv_options_len) {
4312 		mi_free((char *)udp->udp_ip_rcv_options);
4313 		udp->udp_ip_rcv_options = NULL;
4314 		udp->udp_ip_rcv_options_len = 0;
4315 	}
4316 
4317 	/*
4318 	 * Normally only send up the address.
4319 	 * If IP_RECVDSTADDR is set we include the destination IP
4320 	 * address as an option. With IP_RECVOPTS we include all
4321 	 * the IP options.
4322 	 */
4323 	udi_size = sizeof (struct T_unitdata_ind) + sizeof (sin_t);
4324 	if (udp->udp_recvdstaddr) {
4325 		udi_size += sizeof (struct T_opthdr) + sizeof (struct in_addr);
4326 	}
4327 	if (udp->udp_recvopts && opt_len > 0)
4328 		udi_size += sizeof (struct T_opthdr) + opt_len;
4329 
4330 	/*
4331 	 * If the IP_RECVSLLA or the IP_RECVIF is set then allocate
4332 	 * space accordingly
4333 	 */
4334 	if (udp->udp_recvif && recv_on &&
4335 	    (pinfo->in_pkt_flags & IPF_RECVIF)) {
4336 		udi_size += sizeof (struct T_opthdr) +
4337 		    sizeof (uint_t);
4338 	}
4339 
4340 	if (udp->udp_recvslla && recv_on &&
4341 	    (pinfo->in_pkt_flags & IPF_RECVSLLA)) {
4342 		udi_size += sizeof (struct T_opthdr) +
4343 		    sizeof (struct sockaddr_dl);
4344 	}
4345 
4346 	if (udp->udp_recvucred && (cr = DB_CRED(mp)) != NULL) {
4347 		udi_size += sizeof (struct T_opthdr) + ucredsize;
4348 		cpid = DB_CPID(mp);
4349 	}
4350 	/*
4351 	 * If IP_RECVTTL is set allocate the appropriate sized buffer
4352 	 */
4353 	if (udp->udp_recvttl) {
4354 		udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t);
4355 	}
4356 
4357 	/* Allocate a message block for the T_UNITDATA_IND structure. */
4358 	mp1 = allocb(udi_size, BPRI_MED);
4359 	if (mp1 == NULL) {
4360 		freemsg(mp);
4361 		if (options_mp != NULL)
4362 			freeb(options_mp);
4363 		TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
4364 			"udp_rput_other_end: q %p (%S)", q, "allocbfail");
4365 		BUMP_MIB(&udp_mib, udpInErrors);
4366 		return;
4367 	}
4368 	mp1->b_cont = mp;
4369 	mp = mp1;
4370 	mp->b_datap->db_type = M_PROTO;
4371 	tudi = (struct T_unitdata_ind *)mp->b_rptr;
4372 	mp->b_wptr = (uchar_t *)tudi + udi_size;
4373 	tudi->PRIM_type = T_UNITDATA_IND;
4374 	tudi->SRC_length = sizeof (sin_t);
4375 	tudi->SRC_offset = sizeof (struct T_unitdata_ind);
4376 	tudi->OPT_offset = sizeof (struct T_unitdata_ind) + sizeof (sin_t);
4377 	udi_size -= (sizeof (struct T_unitdata_ind) + sizeof (sin_t));
4378 	tudi->OPT_length = udi_size;
4379 
4380 	sin = (sin_t *)&tudi[1];
4381 	sin->sin_addr.s_addr = ((ipha_t *)rptr)->ipha_src;
4382 	sin->sin_port =	((in_port_t *)
4383 	    new_rptr)[-(UDPH_SIZE/sizeof (in_port_t))];
4384 	sin->sin_family = AF_INET;
4385 	*(uint32_t *)&sin->sin_zero[0] = 0;
4386 	*(uint32_t *)&sin->sin_zero[4] = 0;
4387 
4388 	/*
4389 	 * Add options if IP_RECVDSTADDR, IP_RECVIF, IP_RECVSLLA or
4390 	 * IP_RECVTTL has been set.
4391 	 */
4392 	if (udi_size != 0) {
4393 		/*
4394 		 * Copy in destination address before options to avoid any
4395 		 * padding issues.
4396 		 */
4397 		char *dstopt;
4398 
4399 		dstopt = (char *)&sin[1];
4400 		if (udp->udp_recvdstaddr) {
4401 			struct T_opthdr *toh;
4402 			ipaddr_t *dstptr;
4403 
4404 			toh = (struct T_opthdr *)dstopt;
4405 			toh->level = IPPROTO_IP;
4406 			toh->name = IP_RECVDSTADDR;
4407 			toh->len = sizeof (struct T_opthdr) + sizeof (ipaddr_t);
4408 			toh->status = 0;
4409 			dstopt += sizeof (struct T_opthdr);
4410 			dstptr = (ipaddr_t *)dstopt;
4411 			*dstptr = (((ipaddr_t *)rptr)[4]);
4412 			dstopt += sizeof (ipaddr_t);
4413 			udi_size -= toh->len;
4414 		}
4415 		if (udp->udp_recvopts && udi_size != 0) {
4416 			struct T_opthdr *toh;
4417 
4418 			toh = (struct T_opthdr *)dstopt;
4419 			toh->level = IPPROTO_IP;
4420 			toh->name = IP_RECVOPTS;
4421 			toh->len = sizeof (struct T_opthdr) + opt_len;
4422 			toh->status = 0;
4423 			dstopt += sizeof (struct T_opthdr);
4424 			bcopy(rptr + IP_SIMPLE_HDR_LENGTH, dstopt, opt_len);
4425 			dstopt += opt_len;
4426 			udi_size -= toh->len;
4427 		}
4428 
4429 		if (udp->udp_recvslla && recv_on &&
4430 		    (pinfo->in_pkt_flags & IPF_RECVSLLA)) {
4431 
4432 			struct T_opthdr *toh;
4433 			struct sockaddr_dl	*dstptr;
4434 
4435 			toh = (struct T_opthdr *)dstopt;
4436 			toh->level = IPPROTO_IP;
4437 			toh->name = IP_RECVSLLA;
4438 			toh->len = sizeof (struct T_opthdr) +
4439 			    sizeof (struct sockaddr_dl);
4440 			toh->status = 0;
4441 			dstopt += sizeof (struct T_opthdr);
4442 			dstptr = (struct sockaddr_dl *)dstopt;
4443 			bcopy(&pinfo->in_pkt_slla, dstptr,
4444 			    sizeof (struct sockaddr_dl));
4445 			dstopt += sizeof (struct sockaddr_dl);
4446 			udi_size -= toh->len;
4447 		}
4448 
4449 		if (udp->udp_recvif && recv_on &&
4450 		    (pinfo->in_pkt_flags & IPF_RECVIF)) {
4451 
4452 			struct T_opthdr *toh;
4453 			uint_t		*dstptr;
4454 
4455 			toh = (struct T_opthdr *)dstopt;
4456 			toh->level = IPPROTO_IP;
4457 			toh->name = IP_RECVIF;
4458 			toh->len = sizeof (struct T_opthdr) +
4459 			    sizeof (uint_t);
4460 			toh->status = 0;
4461 			dstopt += sizeof (struct T_opthdr);
4462 			dstptr = (uint_t *)dstopt;
4463 			*dstptr = pinfo->in_pkt_ifindex;
4464 			dstopt += sizeof (uint_t);
4465 			udi_size -= toh->len;
4466 		}
4467 
4468 		if (cr != NULL) {
4469 			struct T_opthdr *toh;
4470 
4471 			toh = (struct T_opthdr *)dstopt;
4472 			toh->level = SOL_SOCKET;
4473 			toh->name = SCM_UCRED;
4474 			toh->len = sizeof (struct T_opthdr) + ucredsize;
4475 			toh->status = 0;
4476 			(void) cred2ucred(cr, cpid, &toh[1]);
4477 			dstopt += toh->len;
4478 			udi_size -= toh->len;
4479 		}
4480 
4481 		if (udp->udp_recvttl) {
4482 			struct	T_opthdr *toh;
4483 			uint8_t	*dstptr;
4484 
4485 			toh = (struct T_opthdr *)dstopt;
4486 			toh->level = IPPROTO_IP;
4487 			toh->name = IP_RECVTTL;
4488 			toh->len = sizeof (struct T_opthdr) +
4489 			    sizeof (uint8_t);
4490 			toh->status = 0;
4491 			dstopt += sizeof (struct T_opthdr);
4492 			dstptr = (uint8_t *)dstopt;
4493 			*dstptr = ((ipha_t *)rptr)->ipha_ttl;
4494 			dstopt += sizeof (uint8_t);
4495 			udi_size -= toh->len;
4496 		}
4497 
4498 		ASSERT(udi_size == 0);	/* "Consumed" all of allocated space */
4499 	}
4500 	BUMP_MIB(&udp_mib, udpInDatagrams);
4501 	TRACE_2(TR_FAC_UDP, TR_UDP_RPUT_END,
4502 	    "udp_rput_other_end: q %p (%S)", q, "end");
4503 	if (options_mp != NULL)
4504 		freeb(options_mp);
4505 	putnext(q, mp);
4506 }
4507 
4508 /*
4509  * Process a T_BIND_ACK
4510  */
4511 static void
4512 udp_rput_bind_ack(queue_t *q, mblk_t *mp)
4513 {
4514 	udp_t	*udp = (udp_t *)q->q_ptr;
4515 	mblk_t	*mp1;
4516 	ire_t	*ire;
4517 	struct T_bind_ack *tba;
4518 	uchar_t *addrp;
4519 	ipa_conn_t	*ac;
4520 	ipa6_conn_t	*ac6;
4521 
4522 	if (udp->udp_discon_pending)
4523 		udp->udp_discon_pending = 0;
4524 
4525 	/*
4526 	 * If a broadcast/multicast address was bound set
4527 	 * the source address to 0.
4528 	 * This ensures no datagrams with broadcast address
4529 	 * as source address are emitted (which would violate
4530 	 * RFC1122 - Hosts requirements)
4531 	 *
4532 	 * Note that when connecting the returned IRE is
4533 	 * for the destination address and we only perform
4534 	 * the broadcast check for the source address (it
4535 	 * is OK to connect to a broadcast/multicast address.)
4536 	 */
4537 	mp1 = mp->b_cont;
4538 	if (mp1 != NULL && mp1->b_datap->db_type == IRE_DB_TYPE) {
4539 		ire = (ire_t *)mp1->b_rptr;
4540 
4541 		/*
4542 		 * Note: we get IRE_BROADCAST for IPv6 to "mark" a multicast
4543 		 * local address.
4544 		 */
4545 		if (ire->ire_type == IRE_BROADCAST &&
4546 		    udp->udp_state != TS_DATA_XFER) {
4547 			/* This was just a local bind to a broadcast addr */
4548 			V6_SET_ZERO(udp->udp_v6src);
4549 			if (udp->udp_family == AF_INET6)
4550 				(void) udp_build_hdrs(q, udp);
4551 		} else if (V6_OR_V4_INADDR_ANY(udp->udp_v6src)) {
4552 			/*
4553 			 * Local address not yet set - pick it from the
4554 			 * T_bind_ack
4555 			 */
4556 			tba = (struct T_bind_ack *)mp->b_rptr;
4557 			addrp = &mp->b_rptr[tba->ADDR_offset];
4558 			switch (udp->udp_family) {
4559 			case AF_INET:
4560 				if (tba->ADDR_length == sizeof (ipa_conn_t)) {
4561 					ac = (ipa_conn_t *)addrp;
4562 				} else {
4563 					ASSERT(tba->ADDR_length ==
4564 					    sizeof (ipa_conn_x_t));
4565 					ac = &((ipa_conn_x_t *)addrp)->acx_conn;
4566 				}
4567 				IN6_IPADDR_TO_V4MAPPED(ac->ac_laddr,
4568 				    &udp->udp_v6src);
4569 				break;
4570 			case AF_INET6:
4571 				if (tba->ADDR_length == sizeof (ipa6_conn_t)) {
4572 					ac6 = (ipa6_conn_t *)addrp;
4573 				} else {
4574 					ASSERT(tba->ADDR_length ==
4575 					    sizeof (ipa6_conn_x_t));
4576 					ac6 = &((ipa6_conn_x_t *)
4577 					    addrp)->ac6x_conn;
4578 				}
4579 				udp->udp_v6src = ac6->ac6_laddr;
4580 				(void) udp_build_hdrs(q, udp);
4581 				break;
4582 			}
4583 		}
4584 		mp1 = mp1->b_cont;
4585 	}
4586 	/*
4587 	 * Look for one or more appended ACK message added by
4588 	 * udp_connect or udp_disconnect.
4589 	 * If none found just send up the T_BIND_ACK.
4590 	 * udp_connect has appended a T_OK_ACK and a T_CONN_CON.
4591 	 * udp_disconnect has appended a T_OK_ACK.
4592 	 */
4593 	if (mp1 != NULL) {
4594 		if (mp->b_cont == mp1)
4595 			mp->b_cont = NULL;
4596 		else {
4597 			ASSERT(mp->b_cont->b_cont == mp1);
4598 			mp->b_cont->b_cont = NULL;
4599 		}
4600 		freemsg(mp);
4601 		mp = mp1;
4602 		while (mp != NULL) {
4603 			mp1 = mp->b_cont;
4604 			mp->b_cont = NULL;
4605 			putnext(q, mp);
4606 			mp = mp1;
4607 		}
4608 		return;
4609 	}
4610 	freemsg(mp->b_cont);
4611 	mp->b_cont = NULL;
4612 	putnext(q, mp);
4613 }
4614 
4615 /*
4616  * return SNMP stuff in buffer in mpdata
4617  */
4618 static int
4619 udp_snmp_get(queue_t *q, mblk_t *mpctl)
4620 {
4621 	mblk_t			*mpdata;
4622 	mblk_t			*mp_conn_ctl;
4623 	mblk_t			*mp6_conn_ctl;
4624 	mblk_t			*mp_conn_data;
4625 	mblk_t			*mp6_conn_data;
4626 	mblk_t			*mp_conn_tail = NULL;
4627 	mblk_t			*mp6_conn_tail = NULL;
4628 	struct opthdr		*optp;
4629 	IDP			idp;
4630 	udp_t			*udp;
4631 	mib2_udpEntry_t		ude;
4632 	mib2_udp6Entry_t	ude6;
4633 	int			state;
4634 	zoneid_t		zoneid;
4635 
4636 	if (mpctl == NULL ||
4637 	    (mpdata = mpctl->b_cont) == NULL ||
4638 	    (mp_conn_ctl = copymsg(mpctl)) == NULL ||
4639 	    (mp6_conn_ctl = copymsg(mpctl)) == NULL) {
4640 		freemsg(mp_conn_ctl);
4641 		return (0);
4642 	}
4643 
4644 	mp_conn_data = mp_conn_ctl->b_cont;
4645 	mp6_conn_data = mp6_conn_ctl->b_cont;
4646 
4647 	udp = (udp_t *)q->q_ptr;
4648 	zoneid = udp->udp_zoneid;
4649 
4650 	/* fixed length structure for IPv4 and IPv6 counters */
4651 	SET_MIB(udp_mib.udpEntrySize, sizeof (mib2_udpEntry_t));
4652 	SET_MIB(udp_mib.udp6EntrySize, sizeof (mib2_udp6Entry_t));
4653 	optp = (struct opthdr *)&mpctl->b_rptr[sizeof (struct T_optmgmt_ack)];
4654 	optp->level = MIB2_UDP;
4655 	optp->name = 0;
4656 	(void) snmp_append_data(mpdata, (char *)&udp_mib, sizeof (udp_mib));
4657 	optp->len = msgdsize(mpdata);
4658 	qreply(q, mpctl);
4659 
4660 	mutex_enter(&udp_g_lock);
4661 	for (idp = mi_first_ptr(&udp_g_head);
4662 	    (udp = (udp_t *)idp) != 0;
4663 	    idp = mi_next_ptr(&udp_g_head, idp)) {
4664 
4665 		if (zoneid != udp->udp_zoneid)
4666 			continue;
4667 
4668 		/* Note that the port numbers are sent in host byte order */
4669 
4670 		if (udp->udp_state == TS_UNBND)
4671 			state = MIB2_UDP_unbound;
4672 		else if (udp->udp_state == TS_IDLE)
4673 			state = MIB2_UDP_idle;
4674 		else if (udp->udp_state == TS_DATA_XFER)
4675 			state = MIB2_UDP_connected;
4676 		else
4677 			state = MIB2_UDP_unknown;
4678 
4679 		/*
4680 		 * Create an IPv4 table entry for IPv4 entries and also
4681 		 * any IPv6 entries which are bound to in6addr_any
4682 		 * (i.e. anything a IPv4 peer could connect/send to).
4683 		 */
4684 		if (udp->udp_ipversion == IPV4_VERSION ||
4685 		    (udp->udp_state <= TS_IDLE &&
4686 		    IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src))) {
4687 			ude.udpEntryInfo.ue_state = state;
4688 			/* If in6addr_any this will set it to INADDR_ANY */
4689 			ude.udpLocalAddress = V4_PART_OF_V6(udp->udp_v6src);
4690 			ude.udpLocalPort = ntohs(udp->udp_port);
4691 			if (udp->udp_state == TS_DATA_XFER) {
4692 				/*
4693 				 * Can potentially get here for v6 socket
4694 				 * if another process (say, ping) has just
4695 				 * done a sendto(), changing the state
4696 				 * from the TS_IDLE above to TS_DATA_XFER
4697 				 * by the time we hit this part of the code.
4698 				 */
4699 				ude.udpEntryInfo.ue_RemoteAddress =
4700 				    V4_PART_OF_V6(udp->udp_v6dst);
4701 				ude.udpEntryInfo.ue_RemotePort =
4702 				    ntohs(udp->udp_dstport);
4703 			} else {
4704 				ude.udpEntryInfo.ue_RemoteAddress = 0;
4705 				ude.udpEntryInfo.ue_RemotePort = 0;
4706 			}
4707 			(void) snmp_append_data2(mp_conn_data, &mp_conn_tail,
4708 			    (char *)&ude, sizeof (ude));
4709 		}
4710 		if (udp->udp_ipversion == IPV6_VERSION) {
4711 			ude6.udp6EntryInfo.ue_state  = state;
4712 			ude6.udp6LocalAddress = udp->udp_v6src;
4713 			ude6.udp6LocalPort = ntohs(udp->udp_port);
4714 			ude6.udp6IfIndex = udp->udp_bound_if;
4715 			if (udp->udp_state == TS_DATA_XFER) {
4716 				ude6.udp6EntryInfo.ue_RemoteAddress =
4717 				    udp->udp_v6dst;
4718 				ude6.udp6EntryInfo.ue_RemotePort =
4719 				    ntohs(udp->udp_dstport);
4720 			} else {
4721 				ude6.udp6EntryInfo.ue_RemoteAddress =
4722 				    sin6_null.sin6_addr;
4723 				ude6.udp6EntryInfo.ue_RemotePort = 0;
4724 			}
4725 			(void) snmp_append_data2(mp6_conn_data, &mp6_conn_tail,
4726 			    (char *)&ude6, sizeof (ude6));
4727 		}
4728 	}
4729 	mutex_exit(&udp_g_lock);
4730 
4731 	/* IPv4 UDP endpoints */
4732 	optp = (struct opthdr *)&mp_conn_ctl->b_rptr[
4733 	    sizeof (struct T_optmgmt_ack)];
4734 	optp->level = MIB2_UDP;
4735 	optp->name = MIB2_UDP_ENTRY;
4736 	optp->len = msgdsize(mp_conn_data);
4737 	qreply(q, mp_conn_ctl);
4738 
4739 	/* IPv6 UDP endpoints */
4740 	optp = (struct opthdr *)&mp6_conn_ctl->b_rptr[
4741 	    sizeof (struct T_optmgmt_ack)];
4742 	optp->level = MIB2_UDP6;
4743 	optp->name = MIB2_UDP6_ENTRY;
4744 	optp->len = msgdsize(mp6_conn_data);
4745 	qreply(q, mp6_conn_ctl);
4746 
4747 	return (1);
4748 }
4749 
4750 /*
4751  * Return 0 if invalid set request, 1 otherwise, including non-udp requests.
4752  * NOTE: Per MIB-II, UDP has no writable data.
4753  * TODO:  If this ever actually tries to set anything, it needs to be
4754  * to do the appropriate locking.
4755  */
4756 /* ARGSUSED */
4757 static int
4758 udp_snmp_set(queue_t *q, t_scalar_t level, t_scalar_t name,
4759     uchar_t *ptr, int len)
4760 {
4761 	switch (level) {
4762 	case MIB2_UDP:
4763 		return (0);
4764 	default:
4765 		return (1);
4766 	}
4767 }
4768 
4769 static void
4770 udp_report_item(mblk_t *mp, udp_t *udp)
4771 {
4772 	char *state;
4773 	char addrbuf1[INET6_ADDRSTRLEN];
4774 	char addrbuf2[INET6_ADDRSTRLEN];
4775 	uint_t print_len, buf_len;
4776 
4777 	buf_len = mp->b_datap->db_lim - mp->b_wptr;
4778 	ASSERT(buf_len >= 0);
4779 	if (buf_len == 0)
4780 		return;
4781 
4782 	if (udp->udp_state == TS_UNBND)
4783 		state = "UNBOUND";
4784 	else if (udp->udp_state == TS_IDLE)
4785 		state = "IDLE";
4786 	else if (udp->udp_state == TS_DATA_XFER)
4787 		state = "CONNECTED";
4788 	else
4789 		state = "UnkState";
4790 	print_len = snprintf((char *)mp->b_wptr, buf_len,
4791 	    MI_COL_PTRFMT_STR "%4d %5u %s %s %5u %s\n",
4792 	    (void *)udp, udp->udp_zoneid, ntohs(udp->udp_port),
4793 	    inet_ntop(AF_INET6, &udp->udp_v6src,
4794 		addrbuf1, sizeof (addrbuf1)),
4795 	    inet_ntop(AF_INET6, &udp->udp_v6dst,
4796 		addrbuf2, sizeof (addrbuf2)),
4797 	    ntohs(udp->udp_dstport), state);
4798 	if (print_len < buf_len) {
4799 		mp->b_wptr += print_len;
4800 	} else {
4801 		mp->b_wptr += buf_len;
4802 	}
4803 }
4804 
4805 /* Report for ndd "udp_status" */
4806 /* ARGSUSED */
4807 static int
4808 udp_status_report(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *cr)
4809 {
4810 	IDP	idp;
4811 	udp_t	*udp;
4812 	zoneid_t zoneid;
4813 
4814 	/*
4815 	 * Because of the ndd constraint, at most we can have 64K buffer
4816 	 * to put in all UDP info.  So to be more efficient, just
4817 	 * allocate a 64K buffer here, assuming we need that large buffer.
4818 	 * This may be a problem as any user can read udp_status.  Therefore
4819 	 * we limit the rate of doing this using udp_ndd_get_info_interval.
4820 	 * This should be OK as normal users should not do this too often.
4821 	 */
4822 	if (cr == NULL || secpolicy_net_config(cr, B_TRUE) != 0) {
4823 		if (ddi_get_lbolt() - udp_last_ndd_get_info_time <
4824 		    drv_usectohz(udp_ndd_get_info_interval * 1000)) {
4825 			(void) mi_mpprintf(mp, NDD_TOO_QUICK_MSG);
4826 			return (0);
4827 		}
4828 	}
4829 	if ((mp->b_cont = allocb(ND_MAX_BUF_LEN, BPRI_HI)) == NULL) {
4830 		/* The following may work even if we cannot get a large buf. */
4831 		(void) mi_mpprintf(mp, NDD_OUT_OF_BUF_MSG);
4832 		return (0);
4833 	}
4834 	(void) mi_mpprintf(mp,
4835 	    "UDP     " MI_COL_HDRPAD_STR
4836 	/*   12345678[89ABCDEF] */
4837 	    " zone lport src addr        dest addr       port  state");
4838 	/*    1234 12345 xxx.xxx.xxx.xxx xxx.xxx.xxx.xxx 12345 UNBOUND */
4839 
4840 	udp = (udp_t *)q->q_ptr;
4841 	zoneid = udp->udp_zoneid;
4842 
4843 	mutex_enter(&udp_g_lock);
4844 	for (idp = mi_first_ptr(&udp_g_head);
4845 	    (udp = (udp_t *)idp) != 0;
4846 	    idp = mi_next_ptr(&udp_g_head, idp)) {
4847 
4848 		if (zoneid != GLOBAL_ZONEID &&
4849 		    zoneid != udp->udp_zoneid)
4850 			continue;
4851 
4852 		udp_report_item(mp->b_cont, udp);
4853 	}
4854 	mutex_exit(&udp_g_lock);
4855 	udp_last_ndd_get_info_time = ddi_get_lbolt();
4856 	return (0);
4857 }
4858 
4859 /*
4860  * This routine creates a T_UDERROR_IND message and passes it upstream.
4861  * The address and options are copied from the T_UNITDATA_REQ message
4862  * passed in mp.  This message is freed.
4863  */
4864 static void
4865 udp_ud_err(queue_t *q, mblk_t *mp, t_scalar_t err)
4866 {
4867 	mblk_t	*mp1;
4868 	struct T_unitdata_req	*tudr = (struct T_unitdata_req *)mp->b_rptr;
4869 	uchar_t	*destaddr, *optaddr;
4870 
4871 	if ((mp->b_wptr < mp->b_rptr) ||
4872 	    (mp->b_wptr - mp->b_rptr) < sizeof (struct T_unitdata_req)) {
4873 		goto done;
4874 	}
4875 	destaddr = mp->b_rptr + tudr->DEST_offset;
4876 	if (destaddr < mp->b_rptr || destaddr >= mp->b_wptr ||
4877 	    destaddr + tudr->DEST_length < mp->b_rptr ||
4878 	    destaddr + tudr->DEST_length > mp->b_wptr) {
4879 		goto done;
4880 	}
4881 	optaddr = mp->b_rptr + tudr->OPT_offset;
4882 	if (optaddr < mp->b_rptr || optaddr >= mp->b_wptr ||
4883 	    optaddr + tudr->OPT_length < mp->b_rptr ||
4884 	    optaddr + tudr->OPT_length > mp->b_wptr) {
4885 		goto done;
4886 	}
4887 	mp1 = mi_tpi_uderror_ind((char *)destaddr, tudr->DEST_length,
4888 	    (char *)optaddr, tudr->OPT_length, err);
4889 	if (mp1)
4890 		qreply(q, mp1);
4891 
4892 done:
4893 	freemsg(mp);
4894 }
4895 
4896 /*
4897  * This routine removes a port number association from a stream.  It
4898  * is called by udp_wput to handle T_UNBIND_REQ messages.
4899  */
4900 static void
4901 udp_unbind(queue_t *q, mblk_t *mp)
4902 {
4903 	udp_t	*udp;
4904 
4905 	udp = (udp_t *)q->q_ptr;
4906 	/* If a bind has not been done, we can't unbind. */
4907 	if (udp->udp_state == TS_UNBND) {
4908 		udp_err_ack(q, mp, TOUTSTATE, 0);
4909 		return;
4910 	}
4911 	if (cl_inet_unbind != NULL) {
4912 		/*
4913 		 * Running in cluster mode - register unbind information
4914 		 */
4915 		if (udp->udp_ipversion == IPV4_VERSION) {
4916 			(*cl_inet_unbind)(IPPROTO_UDP, AF_INET,
4917 			    (uint8_t *)(&V4_PART_OF_V6(udp->udp_v6src)),
4918 			    (in_port_t)udp->udp_port);
4919 		} else {
4920 			(*cl_inet_unbind)(IPPROTO_UDP, AF_INET6,
4921 			    (uint8_t *)&(udp->udp_v6src),
4922 			    (in_port_t)udp->udp_port);
4923 		}
4924 	}
4925 
4926 	udp_bind_hash_remove(udp, B_FALSE);
4927 	V6_SET_ZERO(udp->udp_v6src);
4928 	V6_SET_ZERO(udp->udp_bound_v6src);
4929 	udp->udp_port = 0;
4930 	udp->udp_state = TS_UNBND;
4931 
4932 	if (udp->udp_family == AF_INET6) {
4933 		int error;
4934 
4935 		/* Rebuild the header template */
4936 		error = udp_build_hdrs(q, udp);
4937 		if (error != 0) {
4938 			udp_err_ack(q, mp, TSYSERR, error);
4939 			return;
4940 		}
4941 	}
4942 	/* Pass the unbind to IP */
4943 	putnext(q, mp);
4944 }
4945 
4946 /*
4947  * Don't let port fall into the privileged range.
4948  * Since the extra priviledged ports can be arbitrary we also
4949  * ensure that we exclude those from consideration.
4950  * udp_g_epriv_ports is not sorted thus we loop over it until
4951  * there are no changes.
4952  */
4953 static in_port_t
4954 udp_update_next_port(in_port_t port, boolean_t random)
4955 {
4956 	int i;
4957 
4958 	if (random && udp_random_anon_port != 0) {
4959 		(void) random_get_pseudo_bytes((uint8_t *)&port,
4960 		    sizeof (in_port_t));
4961 		/*
4962 		 * Unless changed by a sys admin, the smallest anon port
4963 		 * is 32768 and the largest anon port is 65535.  It is
4964 		 * very likely (50%) for the random port to be smaller
4965 		 * than the smallest anon port.  When that happens,
4966 		 * add port % (anon port range) to the smallest anon
4967 		 * port to get the random port.  It should fall into the
4968 		 * valid anon port range.
4969 		 */
4970 		if (port < udp_smallest_anon_port) {
4971 			port = udp_smallest_anon_port +
4972 			    port % (udp_largest_anon_port -
4973 			    udp_smallest_anon_port);
4974 		}
4975 	}
4976 
4977 retry:
4978 	if (port < udp_smallest_anon_port || port > udp_largest_anon_port)
4979 		port = udp_smallest_anon_port;
4980 
4981 	if (port < udp_smallest_nonpriv_port)
4982 		port = udp_smallest_nonpriv_port;
4983 
4984 	for (i = 0; i < udp_g_num_epriv_ports; i++) {
4985 		if (port == udp_g_epriv_ports[i]) {
4986 			port++;
4987 			/*
4988 			 * Make sure that the port is in the
4989 			 * valid range.
4990 			 */
4991 			goto retry;
4992 		}
4993 	}
4994 	return (port);
4995 }
4996 
4997 /*
4998  * This routine handles all messages passed downstream.  It either
4999  * consumes the message or passes it downstream; it never queues a
5000  * a message.
5001  */
5002 static void
5003 udp_wput(queue_t *q, mblk_t *mp)
5004 {
5005 	uchar_t		*rptr = mp->b_rptr;
5006 	struct 		datab *db;
5007 	ipha_t		*ipha;
5008 	udpha_t		*udpha;
5009 	mblk_t		*mp1;
5010 	int		ip_hdr_length;
5011 #define	tudr ((struct T_unitdata_req *)rptr)
5012 	uint32_t	ip_len;
5013 	udp_t		*udp;
5014 	sin6_t		*sin6;
5015 	sin_t		*sin;
5016 	ipaddr_t	v4dst;
5017 	uint16_t	port;
5018 	uint_t		srcid;
5019 
5020 	TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_START,
5021 		"udp_wput_start: q %p mp %p", q, mp);
5022 
5023 	db = mp->b_datap;
5024 	switch (db->db_type) {
5025 	case M_PROTO:
5026 	case M_PCPROTO:
5027 		ASSERT((uintptr_t)(mp->b_wptr - rptr) <= (uintptr_t)INT_MAX);
5028 		if (mp->b_wptr - rptr >= sizeof (struct T_unitdata_req)) {
5029 			/* Detect valid T_UNITDATA_REQ here */
5030 			if (((union T_primitives *)rptr)->type
5031 			    == T_UNITDATA_REQ)
5032 				break;
5033 		}
5034 		/* FALLTHRU */
5035 	default:
5036 		qwriter(q, mp, udp_wput_other, PERIM_INNER);
5037 		return;
5038 	}
5039 
5040 	udp = (udp_t *)q->q_ptr;
5041 
5042 	/* Handle UNITDATA_REQ messages here */
5043 	if (udp->udp_state == TS_UNBND) {
5044 		/* If a port has not been bound to the stream, fail. */
5045 		BUMP_MIB(&udp_mib, udpOutErrors);
5046 		udp_ud_err(q, mp, EPROTO);
5047 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5048 			"udp_wput_end: q %p (%S)", q, "outstate");
5049 		return;
5050 	}
5051 	mp1 = mp->b_cont;
5052 	if (mp1 == NULL) {
5053 		BUMP_MIB(&udp_mib, udpOutErrors);
5054 		udp_ud_err(q, mp, EPROTO);
5055 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5056 			"udp_wput_end: q %p (%S)", q, "badaddr");
5057 		return;
5058 	}
5059 
5060 	if ((rptr + tudr->DEST_offset + tudr->DEST_length) > mp->b_wptr) {
5061 		BUMP_MIB(&udp_mib, udpOutErrors);
5062 		udp_ud_err(q, mp, EADDRNOTAVAIL);
5063 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5064 			"udp_wput_end: q %p (%S)", q, "badaddr");
5065 		return;
5066 	}
5067 
5068 	switch (udp->udp_family) {
5069 	case AF_INET6:
5070 		sin6 = (sin6_t *)&rptr[tudr->DEST_offset];
5071 		if (!OK_32PTR((char *)sin6) ||
5072 		    tudr->DEST_length != sizeof (sin6_t) ||
5073 		    sin6->sin6_family != AF_INET6) {
5074 			BUMP_MIB(&udp_mib, udpOutErrors);
5075 			udp_ud_err(q, mp, EADDRNOTAVAIL);
5076 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5077 				"udp_wput_end: q %p (%S)", q, "badaddr");
5078 			return;
5079 		}
5080 
5081 		if (!IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5082 			/*
5083 			 * Destination is a non-IPv4-compatible IPv6 address.
5084 			 * Send out an IPv6 format packet.
5085 			 */
5086 			udp_wput_ipv6(q, mp, sin6, tudr->OPT_length);
5087 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5088 				"udp_wput_end: q %p (%S)", q, "udp_wput_ipv6");
5089 			return;
5090 		}
5091 		/*
5092 		 * If the local address is not zero or a mapped address return
5093 		 * an error.
5094 		 * I would be possible to send an IPv4 packet but the
5095 		 * response would never make it back to the application
5096 		 * since it is bound to a non-mapped address.
5097 		 */
5098 		if (!IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src) &&
5099 		    !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) {
5100 			BUMP_MIB(&udp_mib, udpOutErrors);
5101 			udp_ud_err(q, mp, EADDRNOTAVAIL);
5102 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5103 				"udp_wput_end: q %p (%S)", q, "badaddr");
5104 			return;
5105 		}
5106 		/* Send IPv4 packet without modifying udp_ipversion */
5107 		/* Extract port and ipaddr */
5108 		port = sin6->sin6_port;
5109 		IN6_V4MAPPED_TO_IPADDR(&sin6->sin6_addr, v4dst);
5110 		srcid = sin6->__sin6_src_id;
5111 		break;
5112 
5113 	case AF_INET:
5114 		sin = (sin_t *)&rptr[tudr->DEST_offset];
5115 		if (!OK_32PTR((char *)sin) ||
5116 		    tudr->DEST_length != sizeof (sin_t) ||
5117 		    sin->sin_family != AF_INET) {
5118 			BUMP_MIB(&udp_mib, udpOutErrors);
5119 			udp_ud_err(q, mp, EADDRNOTAVAIL);
5120 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5121 				"udp_wput_end: q %p (%S)", q, "badaddr");
5122 			return;
5123 		}
5124 		/* Extract port and ipaddr */
5125 		port = sin->sin_port;
5126 		v4dst = sin->sin_addr.s_addr;
5127 		srcid = 0;
5128 		break;
5129 	}
5130 
5131 
5132 	/*
5133 	 * If options passed in, feed it for verification and handling
5134 	 */
5135 	if (tudr->OPT_length != 0) {
5136 		int error;
5137 
5138 		if (udp_unitdata_opt_process(q, mp, &error, NULL) < 0) {
5139 			/* failure */
5140 			BUMP_MIB(&udp_mib, udpOutErrors);
5141 			udp_ud_err(q, mp, error);
5142 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5143 			    "udp_wput_end: q %p (%S)", q,
5144 			    "udp_unitdata_opt_process");
5145 			return;
5146 		}
5147 		ASSERT(error == 0);
5148 		/*
5149 		 * Note: success in processing options.
5150 		 * mp option buffer represented by
5151 		 * OPT_length/offset now potentially modified
5152 		 * and contain option setting results
5153 		 */
5154 	}
5155 
5156 	/* Add an IP header */
5157 	ip_hdr_length = IP_SIMPLE_HDR_LENGTH + UDPH_SIZE +
5158 	    udp->udp_ip_snd_options_len;
5159 	ipha = (ipha_t *)&mp1->b_rptr[-ip_hdr_length];
5160 	if ((mp1->b_datap->db_ref != 1) ||
5161 	    ((uchar_t *)ipha < mp1->b_datap->db_base) ||
5162 	    !OK_32PTR(ipha)) {
5163 		uchar_t *wptr;
5164 
5165 		mp1 = allocb(ip_hdr_length + udp_wroff_extra, BPRI_LO);
5166 		if (!mp1) {
5167 			BUMP_MIB(&udp_mib, udpOutErrors);
5168 			udp_ud_err(q, mp, ENOMEM);
5169 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5170 				"udp_wput_end: q %p (%S)", q, "allocbfail2");
5171 			return;
5172 		}
5173 		mp1->b_cont = mp->b_cont;
5174 		mp->b_cont = mp1;
5175 		wptr = mp1->b_datap->db_lim;
5176 		mp1->b_wptr = wptr;
5177 		ipha = (ipha_t *)(wptr - ip_hdr_length);
5178 	}
5179 	mp1->b_rptr = (uchar_t *)ipha;
5180 
5181 	ASSERT((uintptr_t)(mp1->b_wptr - (uchar_t *)ipha) <=
5182 	    (uintptr_t)UINT_MAX);
5183 
5184 	ip_hdr_length -= UDPH_SIZE;
5185 #ifdef	_BIG_ENDIAN
5186 	/* Set version, header length, and tos */
5187 	*(uint16_t *)&ipha->ipha_version_and_hdr_length =
5188 	    ((((IP_VERSION << 4) | (ip_hdr_length>>2)) << 8) |
5189 		udp->udp_type_of_service);
5190 	/* Set ttl and protocol */
5191 	*(uint16_t *)&ipha->ipha_ttl = (udp->udp_ttl << 8) | IPPROTO_UDP;
5192 #else
5193 	/* Set version, header length, and tos */
5194 	*(uint16_t *)&ipha->ipha_version_and_hdr_length =
5195 		((udp->udp_type_of_service << 8) |
5196 		    ((IP_VERSION << 4) | (ip_hdr_length>>2)));
5197 	/* Set ttl and protocol */
5198 	*(uint16_t *)&ipha->ipha_ttl = (IPPROTO_UDP << 8) | udp->udp_ttl;
5199 #endif
5200 	/*
5201 	 * Copy our address into the packet.  If this is zero,
5202 	 * first look at __sin6_src_id for a hint. If we leave the source
5203 	 * as INADDR_ANY then ip will fill in the real source address.
5204 	 */
5205 	IN6_V4MAPPED_TO_IPADDR(&udp->udp_v6src, ipha->ipha_src);
5206 	if (srcid != 0 && ipha->ipha_src == INADDR_ANY) {
5207 		in6_addr_t v6src;
5208 
5209 		ip_srcid_find_id(srcid, &v6src, udp->udp_zoneid);
5210 		IN6_V4MAPPED_TO_IPADDR(&v6src, ipha->ipha_src);
5211 	}
5212 
5213 	ipha->ipha_fragment_offset_and_flags = 0;
5214 	ipha->ipha_ident = 0;
5215 
5216 	/* Determine length of packet */
5217 	ip_len = (uint32_t)(mp1->b_wptr - (uchar_t *)ipha);
5218 	{
5219 		mblk_t	*mp2;
5220 		if ((mp2 = mp1->b_cont) != NULL) {
5221 			do {
5222 				ASSERT((uintptr_t)(mp2->b_wptr - mp2->b_rptr)
5223 				    <= (uintptr_t)UINT_MAX);
5224 				ip_len += (uint32_t)(mp2->b_wptr - mp2->b_rptr);
5225 			} while ((mp2 = mp2->b_cont) != NULL);
5226 		}
5227 	}
5228 	/*
5229 	 * If the size of the packet is greater than the maximum allowed by
5230 	 * ip, return an error. Passing this down could cause panics because
5231 	 * the size will have wrapped and be inconsistent with the msg size.
5232 	 */
5233 	if (ip_len > IP_MAXPACKET) {
5234 		BUMP_MIB(&udp_mib, udpOutErrors);
5235 		udp_ud_err(q, mp, EMSGSIZE);
5236 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5237 		    "udp_wput_end: q %p (%S)", q, "IP length exceeded");
5238 		return;
5239 	}
5240 	ipha->ipha_length = htons((uint16_t)ip_len);
5241 	ip_len -= ip_hdr_length;
5242 	ip_len = htons((uint16_t)ip_len);
5243 	udpha = (udpha_t *)(((uchar_t *)ipha) + ip_hdr_length);
5244 	/*
5245 	 * Copy in the destination address and port from the T_UNITDATA
5246 	 * request
5247 	 */
5248 	if (v4dst == INADDR_ANY)
5249 		ipha->ipha_dst = htonl(INADDR_LOOPBACK);
5250 	else
5251 		ipha->ipha_dst = v4dst;
5252 
5253 	/*
5254 	 * Set ttl based on IP_MULTICAST_TTL to match IPv6 logic.
5255 	 */
5256 	if (CLASSD(v4dst))
5257 		ipha->ipha_ttl = udp->udp_multicast_ttl;
5258 
5259 	udpha->uha_dst_port = port;
5260 	udpha->uha_src_port = udp->udp_port;
5261 
5262 	if (ip_hdr_length > IP_SIMPLE_HDR_LENGTH) {
5263 		uint32_t	cksum;
5264 
5265 		bcopy(udp->udp_ip_snd_options, &ipha[1],
5266 		    udp->udp_ip_snd_options_len);
5267 		/*
5268 		 * Massage source route putting first source route in ipha_dst.
5269 		 * Ignore the destination in T_unitdata_req.
5270 		 * Create a checksum adjustment for a source route, if any.
5271 		 */
5272 		cksum = ip_massage_options(ipha);
5273 		cksum = (cksum & 0xFFFF) + (cksum >> 16);
5274 		cksum -= ((ipha->ipha_dst >> 16) & 0xFFFF) +
5275 		    (ipha->ipha_dst & 0xFFFF);
5276 		if ((int)cksum < 0)
5277 			cksum--;
5278 		cksum = (cksum & 0xFFFF) + (cksum >> 16);
5279 		/*
5280 		 * IP does the checksum if uha_checksum is non-zero,
5281 		 * We make it easy for IP to include our pseudo header
5282 		 * by putting our length in uha_checksum.
5283 		 */
5284 		cksum += ip_len;
5285 		cksum = (cksum & 0xFFFF) + (cksum >> 16);
5286 		/* There might be a carry. */
5287 		cksum = (cksum & 0xFFFF) + (cksum >> 16);
5288 #ifdef _LITTLE_ENDIAN
5289 		if (udp_do_checksum)
5290 			ip_len = (cksum << 16) | ip_len;
5291 #else
5292 		if (udp_do_checksum)
5293 			ip_len = (ip_len << 16) | cksum;
5294 		else
5295 			ip_len <<= 16;
5296 #endif
5297 	} else {
5298 		/*
5299 		 * IP does the checksum if uha_checksum is non-zero,
5300 		 * We make it easy for IP to include our pseudo header
5301 		 * by putting our length in uha_checksum.
5302 		 */
5303 		if (udp_do_checksum)
5304 			ip_len |= (ip_len << 16);
5305 #ifndef _LITTLE_ENDIAN
5306 		else
5307 			ip_len <<= 16;
5308 #endif
5309 	}
5310 	/* Set UDP length and checksum */
5311 	*((uint32_t *)&udpha->uha_length) = ip_len;
5312 
5313 	freeb(mp);
5314 
5315 	/* We're done.  Pass the packet to ip. */
5316 	BUMP_MIB(&udp_mib, udpOutDatagrams);
5317 	TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_END,
5318 		"udp_wput_end: q %p (%S)", q, "end");
5319 	putnext(q, mp1);
5320 #undef tudr
5321 }
5322 
5323 /*
5324  * udp_wput_ipv6():
5325  * Assumes that udp_wput did some sanity checking on the destination
5326  * address.
5327  */
5328 static void
5329 udp_wput_ipv6(queue_t *q, mblk_t *mp, sin6_t *sin6, t_scalar_t tudr_optlen)
5330 {
5331 	ip6_t			*ip6h;
5332 	ip6i_t			*ip6i;	/* mp1->b_rptr even if no ip6i_t */
5333 	mblk_t			*mp1;
5334 	int			udp_ip_hdr_len = IPV6_HDR_LEN + UDPH_SIZE;
5335 	size_t			ip_len;
5336 	udpha_t			*udph;
5337 	udp_t			*udp;
5338 	ip6_pkt_t		ipp_s;	/* For ancillary data options */
5339 	ip6_pkt_t		*ipp = &ipp_s;
5340 	ip6_pkt_t		*tipp;	/* temporary ipp */
5341 	uint32_t		csum = 0;
5342 	uint_t			ignore = 0;
5343 	uint_t			option_exists = 0, is_sticky = 0;
5344 	uint8_t			*cp;
5345 	uint8_t			*nxthdr_ptr;
5346 
5347 	udp = (udp_t *)q->q_ptr;
5348 
5349 	/*
5350 	 * If the local address is a mapped address return
5351 	 * an error.
5352 	 * It would be possible to send an IPv6 packet but the
5353 	 * response would never make it back to the application
5354 	 * since it is bound to a mapped address.
5355 	 */
5356 	if (IN6_IS_ADDR_V4MAPPED(&udp->udp_v6src)) {
5357 		BUMP_MIB(&udp_mib, udpOutErrors);
5358 		udp_ud_err(q, mp, EADDRNOTAVAIL);
5359 		return;
5360 	}
5361 
5362 	ipp->ipp_fields = 0;
5363 	ipp->ipp_sticky_ignored = 0;
5364 
5365 	/*
5366 	 * If TPI options passed in, feed it for verification and handling
5367 	 */
5368 	if (tudr_optlen != 0) {
5369 		int 		error;
5370 
5371 		if (udp_unitdata_opt_process(q, mp, &error,
5372 		    (void *)ipp) < 0) {
5373 			/* failure */
5374 			BUMP_MIB(&udp_mib, udpOutErrors);
5375 			udp_ud_err(q, mp, error);
5376 			return;
5377 		}
5378 		ignore = ipp->ipp_sticky_ignored;
5379 		ASSERT(error == 0);
5380 	}
5381 
5382 	if (sin6->sin6_scope_id != 0 &&
5383 	    IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
5384 		/*
5385 		 * IPPF_SCOPE_ID is special.  It's neither a sticky
5386 		 * option nor ancillary data.  It needs to be
5387 		 * explicitly set in options_exists.
5388 		 */
5389 		option_exists |= IPPF_SCOPE_ID;
5390 	}
5391 
5392 	if ((udp->udp_sticky_ipp.ipp_fields == 0) &&
5393 	    (ipp->ipp_fields == 0)) {
5394 		/* No sticky options nor ancillary data. */
5395 		goto no_options;
5396 	}
5397 
5398 	/*
5399 	 * Go through the options figuring out where each is going to
5400 	 * come from and build two masks.  The first mask indicates if
5401 	 * the option exists at all.  The second mask indicates if the
5402 	 * option is sticky or ancillary.
5403 	 */
5404 	if (!(ignore & IPPF_HOPOPTS)) {
5405 		if (ipp->ipp_fields & IPPF_HOPOPTS) {
5406 			option_exists |= IPPF_HOPOPTS;
5407 			udp_ip_hdr_len += ipp->ipp_hopoptslen;
5408 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_HOPOPTS) {
5409 			option_exists |= IPPF_HOPOPTS;
5410 			is_sticky |= IPPF_HOPOPTS;
5411 			udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_hopoptslen;
5412 		}
5413 	}
5414 
5415 	if (!(ignore & IPPF_RTHDR)) {
5416 		if (ipp->ipp_fields & IPPF_RTHDR) {
5417 			option_exists |= IPPF_RTHDR;
5418 			udp_ip_hdr_len += ipp->ipp_rthdrlen;
5419 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTHDR) {
5420 			option_exists |= IPPF_RTHDR;
5421 			is_sticky |= IPPF_RTHDR;
5422 			udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rthdrlen;
5423 		}
5424 	}
5425 
5426 	if (!(ignore & IPPF_RTDSTOPTS) && (option_exists & IPPF_RTHDR)) {
5427 		if (ipp->ipp_fields & IPPF_RTDSTOPTS) {
5428 			option_exists |= IPPF_RTDSTOPTS;
5429 			udp_ip_hdr_len += ipp->ipp_rtdstoptslen;
5430 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_RTDSTOPTS) {
5431 			option_exists |= IPPF_RTDSTOPTS;
5432 			is_sticky |= IPPF_RTDSTOPTS;
5433 			udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_rtdstoptslen;
5434 		}
5435 	}
5436 
5437 	if (!(ignore & IPPF_DSTOPTS)) {
5438 		if (ipp->ipp_fields & IPPF_DSTOPTS) {
5439 			option_exists |= IPPF_DSTOPTS;
5440 			udp_ip_hdr_len += ipp->ipp_dstoptslen;
5441 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DSTOPTS) {
5442 			option_exists |= IPPF_DSTOPTS;
5443 			is_sticky |= IPPF_DSTOPTS;
5444 			udp_ip_hdr_len += udp->udp_sticky_ipp.ipp_dstoptslen;
5445 		}
5446 	}
5447 
5448 	if (!(ignore & IPPF_IFINDEX)) {
5449 		if (ipp->ipp_fields & IPPF_IFINDEX) {
5450 			option_exists |= IPPF_IFINDEX;
5451 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_IFINDEX) {
5452 			option_exists |= IPPF_IFINDEX;
5453 			is_sticky |= IPPF_IFINDEX;
5454 		}
5455 	}
5456 
5457 	if (!(ignore & IPPF_ADDR)) {
5458 		if (ipp->ipp_fields & IPPF_ADDR) {
5459 			option_exists |= IPPF_ADDR;
5460 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_ADDR) {
5461 			option_exists |= IPPF_ADDR;
5462 			is_sticky |= IPPF_ADDR;
5463 		}
5464 	}
5465 
5466 	if (!(ignore & IPPF_DONTFRAG)) {
5467 		if (ipp->ipp_fields & IPPF_DONTFRAG) {
5468 			option_exists |= IPPF_DONTFRAG;
5469 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_DONTFRAG) {
5470 			option_exists |= IPPF_DONTFRAG;
5471 			is_sticky |= IPPF_DONTFRAG;
5472 		}
5473 	}
5474 
5475 	if (!(ignore & IPPF_USE_MIN_MTU)) {
5476 		if (ipp->ipp_fields & IPPF_USE_MIN_MTU) {
5477 			option_exists |= IPPF_USE_MIN_MTU;
5478 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_USE_MIN_MTU) {
5479 			option_exists |= IPPF_USE_MIN_MTU;
5480 			is_sticky |= IPPF_USE_MIN_MTU;
5481 		}
5482 	}
5483 
5484 	if (!(ignore & IPPF_HOPLIMIT) && (ipp->ipp_fields & IPPF_HOPLIMIT))
5485 		option_exists |= IPPF_HOPLIMIT;
5486 	/* IPV6_HOPLIMIT can never be sticky */
5487 	ASSERT(!(udp->udp_sticky_ipp.ipp_fields & IPPF_HOPLIMIT));
5488 
5489 	if (!(ignore & IPPF_UNICAST_HOPS) &&
5490 	    (udp->udp_sticky_ipp.ipp_fields & IPPF_UNICAST_HOPS)) {
5491 		option_exists |= IPPF_UNICAST_HOPS;
5492 		is_sticky |= IPPF_UNICAST_HOPS;
5493 	}
5494 
5495 	if (!(ignore & IPPF_MULTICAST_HOPS) &&
5496 	    (udp->udp_sticky_ipp.ipp_fields & IPPF_MULTICAST_HOPS)) {
5497 		option_exists |= IPPF_MULTICAST_HOPS;
5498 		is_sticky |= IPPF_MULTICAST_HOPS;
5499 	}
5500 
5501 	if (!(ignore & IPPF_TCLASS)) {
5502 		if (ipp->ipp_fields & IPPF_TCLASS) {
5503 			option_exists |= IPPF_TCLASS;
5504 		} else if (udp->udp_sticky_ipp.ipp_fields & IPPF_TCLASS) {
5505 			option_exists |= IPPF_TCLASS;
5506 			is_sticky |= IPPF_TCLASS;
5507 		}
5508 	}
5509 
5510 no_options:
5511 
5512 	/*
5513 	 * If any options carried in the ip6i_t were specified, we
5514 	 * need to account for the ip6i_t in the data we'll be sending
5515 	 * down.
5516 	 */
5517 	if (option_exists & IPPF_HAS_IP6I)
5518 		udp_ip_hdr_len += sizeof (ip6i_t);
5519 
5520 	/* check/fix buffer config, setup pointers into it */
5521 	mp1 = mp->b_cont;
5522 	ip6h = (ip6_t *)&mp1->b_rptr[-udp_ip_hdr_len];
5523 	if ((mp1->b_datap->db_ref != 1) ||
5524 	    ((unsigned char *)ip6h < mp1->b_datap->db_base) ||
5525 	    !OK_32PTR(ip6h)) {
5526 		/* Try to get everything in a single mblk next time */
5527 		if (udp_ip_hdr_len > udp->udp_max_hdr_len) {
5528 			udp->udp_max_hdr_len = udp_ip_hdr_len;
5529 			(void) mi_set_sth_wroff(RD(q),
5530 			    udp->udp_max_hdr_len + udp_wroff_extra);
5531 		}
5532 		mp1 = allocb(udp_ip_hdr_len + udp_wroff_extra, BPRI_LO);
5533 		if (!mp1) {
5534 			BUMP_MIB(&udp_mib, udpOutErrors);
5535 			udp_ud_err(q, mp, ENOMEM);
5536 			return;
5537 		}
5538 		mp1->b_cont = mp->b_cont;
5539 		mp->b_cont = mp1;
5540 		mp1->b_wptr = mp1->b_datap->db_lim;
5541 		ip6h = (ip6_t *)(mp1->b_wptr - udp_ip_hdr_len);
5542 	}
5543 	mp1->b_rptr = (unsigned char *)ip6h;
5544 	ip6i = (ip6i_t *)ip6h;
5545 
5546 #define	ANCIL_OR_STICKY_PTR(f) ((is_sticky & f) ? &udp->udp_sticky_ipp : ipp)
5547 	if (option_exists & IPPF_HAS_IP6I) {
5548 		ip6h = (ip6_t *)&ip6i[1];
5549 		ip6i->ip6i_flags = 0;
5550 		ip6i->ip6i_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
5551 
5552 		/* sin6_scope_id takes precendence over IPPF_IFINDEX */
5553 		if (option_exists & IPPF_SCOPE_ID) {
5554 			ip6i->ip6i_flags |= IP6I_IFINDEX;
5555 			ip6i->ip6i_ifindex = sin6->sin6_scope_id;
5556 		} else if (option_exists & IPPF_IFINDEX) {
5557 			tipp = ANCIL_OR_STICKY_PTR(IPPF_IFINDEX);
5558 			ASSERT(tipp->ipp_ifindex != 0);
5559 			ip6i->ip6i_flags |= IP6I_IFINDEX;
5560 			ip6i->ip6i_ifindex = tipp->ipp_ifindex;
5561 		}
5562 
5563 		if (option_exists & IPPF_ADDR) {
5564 			/*
5565 			 * Enable per-packet source address verification if
5566 			 * IPV6_PKTINFO specified the source address.
5567 			 * ip6_src is set in the transport's _wput function.
5568 			 */
5569 			ip6i->ip6i_flags |= IP6I_VERIFY_SRC;
5570 		}
5571 
5572 		if (option_exists & IPPF_DONTFRAG) {
5573 			ip6i->ip6i_flags |= IP6I_DONTFRAG;
5574 		}
5575 
5576 		if (option_exists & IPPF_USE_MIN_MTU) {
5577 			ip6i->ip6i_flags = IP6I_API_USE_MIN_MTU(
5578 			    ip6i->ip6i_flags, ipp->ipp_use_min_mtu);
5579 		}
5580 
5581 		if (option_exists & IPPF_NEXTHOP) {
5582 			tipp = ANCIL_OR_STICKY_PTR(IPPF_NEXTHOP);
5583 			ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_nexthop));
5584 			ip6i->ip6i_flags |= IP6I_NEXTHOP;
5585 			ip6i->ip6i_nexthop = tipp->ipp_nexthop;
5586 		}
5587 
5588 		/*
5589 		 * tell IP this is an ip6i_t private header
5590 		 */
5591 		ip6i->ip6i_nxt = IPPROTO_RAW;
5592 	}
5593 
5594 	/* Initialize IPv6 header */
5595 	ip6h->ip6_vcf = IPV6_DEFAULT_VERS_AND_FLOW;
5596 	bzero(&ip6h->ip6_src, sizeof (ip6h->ip6_src));
5597 
5598 	/* Set the hoplimit of the outgoing packet. */
5599 	if (option_exists & IPPF_HOPLIMIT) {
5600 		/* IPV6_HOPLIMIT ancillary data overrides all other settings. */
5601 		ip6h->ip6_hops = ipp->ipp_hoplimit;
5602 		ip6i->ip6i_flags |= IP6I_HOPLIMIT;
5603 	} else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) {
5604 		ip6h->ip6_hops = udp->udp_multicast_ttl;
5605 		if (option_exists & IPPF_MULTICAST_HOPS)
5606 			ip6i->ip6i_flags |= IP6I_HOPLIMIT;
5607 	} else {
5608 		ip6h->ip6_hops = udp->udp_ttl;
5609 		if (option_exists & IPPF_UNICAST_HOPS)
5610 			ip6i->ip6i_flags |= IP6I_HOPLIMIT;
5611 	}
5612 
5613 	if (option_exists & IPPF_ADDR) {
5614 		tipp = ANCIL_OR_STICKY_PTR(IPPF_ADDR);
5615 		ASSERT(!IN6_IS_ADDR_UNSPECIFIED(&tipp->ipp_addr));
5616 		ip6h->ip6_src = tipp->ipp_addr;
5617 	} else {
5618 		/*
5619 		 * The source address was not set using IPV6_PKTINFO.
5620 		 * First look at the bound source.
5621 		 * If unspecified fallback to __sin6_src_id.
5622 		 */
5623 		ip6h->ip6_src = udp->udp_v6src;
5624 		if (sin6->__sin6_src_id != 0 &&
5625 		    IN6_IS_ADDR_UNSPECIFIED(&ip6h->ip6_src)) {
5626 			ip_srcid_find_id(sin6->__sin6_src_id,
5627 			    &ip6h->ip6_src, udp->udp_zoneid);
5628 		}
5629 	}
5630 
5631 	nxthdr_ptr = (uint8_t *)&ip6h->ip6_nxt;
5632 	cp = (uint8_t *)&ip6h[1];
5633 
5634 	/*
5635 	 * Here's where we have to start stringing together
5636 	 * any extension headers in the right order:
5637 	 * Hop-by-hop, destination, routing, and final destination opts.
5638 	 */
5639 	if (option_exists & IPPF_HOPOPTS) {
5640 		/* Hop-by-hop options */
5641 		ip6_hbh_t *hbh = (ip6_hbh_t *)cp;
5642 		tipp = ANCIL_OR_STICKY_PTR(IPPF_HOPOPTS);
5643 
5644 		*nxthdr_ptr = IPPROTO_HOPOPTS;
5645 		nxthdr_ptr = &hbh->ip6h_nxt;
5646 
5647 		bcopy(tipp->ipp_hopopts, cp, tipp->ipp_hopoptslen);
5648 		cp += tipp->ipp_hopoptslen;
5649 	}
5650 	/*
5651 	 * En-route destination options
5652 	 * Only do them if there's a routing header as well
5653 	 */
5654 	if (option_exists & IPPF_RTDSTOPTS) {
5655 		ip6_dest_t *dst = (ip6_dest_t *)cp;
5656 		tipp = ANCIL_OR_STICKY_PTR(IPPF_RTDSTOPTS);
5657 
5658 		*nxthdr_ptr = IPPROTO_DSTOPTS;
5659 		nxthdr_ptr = &dst->ip6d_nxt;
5660 
5661 		bcopy(tipp->ipp_rtdstopts, cp, tipp->ipp_rtdstoptslen);
5662 		cp += tipp->ipp_rtdstoptslen;
5663 	}
5664 	/*
5665 	 * Routing header next
5666 	 */
5667 	if (option_exists & IPPF_RTHDR) {
5668 		ip6_rthdr_t *rt = (ip6_rthdr_t *)cp;
5669 		tipp = ANCIL_OR_STICKY_PTR(IPPF_RTHDR);
5670 
5671 		*nxthdr_ptr = IPPROTO_ROUTING;
5672 		nxthdr_ptr = &rt->ip6r_nxt;
5673 
5674 		bcopy(tipp->ipp_rthdr, cp, tipp->ipp_rthdrlen);
5675 		cp += tipp->ipp_rthdrlen;
5676 	}
5677 	/*
5678 	 * Do ultimate destination options
5679 	 */
5680 	if (option_exists & IPPF_DSTOPTS) {
5681 		ip6_dest_t *dest = (ip6_dest_t *)cp;
5682 		tipp = ANCIL_OR_STICKY_PTR(IPPF_DSTOPTS);
5683 
5684 		*nxthdr_ptr = IPPROTO_DSTOPTS;
5685 		nxthdr_ptr = &dest->ip6d_nxt;
5686 
5687 		bcopy(tipp->ipp_dstopts, cp, tipp->ipp_dstoptslen);
5688 		cp += tipp->ipp_dstoptslen;
5689 	}
5690 	/*
5691 	 * Now set the last header pointer to the proto passed in
5692 	 */
5693 	ASSERT((int)(cp - (uint8_t *)ip6i) == (udp_ip_hdr_len - UDPH_SIZE));
5694 	*nxthdr_ptr = IPPROTO_UDP;
5695 
5696 	/* Update UDP header */
5697 	udph = (udpha_t *)((uchar_t *)ip6i + udp_ip_hdr_len - UDPH_SIZE);
5698 	udph->uha_dst_port = sin6->sin6_port;
5699 	udph->uha_src_port = udp->udp_port;
5700 
5701 	/*
5702 	 * Copy in the destination address
5703 	 */
5704 	if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr))
5705 		ip6h->ip6_dst = ipv6_loopback;
5706 	else
5707 		ip6h->ip6_dst = sin6->sin6_addr;
5708 
5709 	ip6h->ip6_vcf =
5710 	    (IPV6_DEFAULT_VERS_AND_FLOW & IPV6_VERS_AND_FLOW_MASK) |
5711 	    (sin6->sin6_flowinfo & ~IPV6_VERS_AND_FLOW_MASK);
5712 
5713 	if (option_exists & IPPF_TCLASS) {
5714 		tipp = ANCIL_OR_STICKY_PTR(IPPF_TCLASS);
5715 		ip6h->ip6_vcf = IPV6_TCLASS_FLOW(ip6h->ip6_vcf,
5716 		    tipp->ipp_tclass);
5717 	}
5718 
5719 	if (option_exists & IPPF_RTHDR) {
5720 		ip6_rthdr_t	*rth;
5721 
5722 		/*
5723 		 * Perform any processing needed for source routing.
5724 		 * We know that all extension headers will be in the same mblk
5725 		 * as the IPv6 header.
5726 		 */
5727 		rth = ip_find_rthdr_v6(ip6h, mp1->b_wptr);
5728 		if (rth != NULL && rth->ip6r_segleft != 0) {
5729 			if (rth->ip6r_type != IPV6_RTHDR_TYPE_0) {
5730 				/*
5731 				 * Drop packet - only support Type 0 routing.
5732 				 * Notify the application as well.
5733 				 */
5734 				udp_ud_err(q, mp, EPROTO);
5735 				BUMP_MIB(&udp_mib, udpOutErrors);
5736 				return;
5737 			}
5738 
5739 			/*
5740 			 * rth->ip6r_len is twice the number of
5741 			 * addresses in the header. Thus it must be even.
5742 			 */
5743 			if (rth->ip6r_len & 0x1) {
5744 				udp_ud_err(q, mp, EPROTO);
5745 				BUMP_MIB(&udp_mib, udpOutErrors);
5746 				return;
5747 			}
5748 			/*
5749 			 * Shuffle the routing header and ip6_dst
5750 			 * addresses, and get the checksum difference
5751 			 * between the first hop (in ip6_dst) and
5752 			 * the destination (in the last routing hdr entry).
5753 			 */
5754 			csum = ip_massage_options_v6(ip6h, rth);
5755 			/*
5756 			 * Verify that the first hop isn't a mapped address.
5757 			 * Routers along the path need to do this verification
5758 			 * for subsequent hops.
5759 			 */
5760 			if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst)) {
5761 				udp_ud_err(q, mp, EADDRNOTAVAIL);
5762 				BUMP_MIB(&udp_mib, udpOutErrors);
5763 				return;
5764 			}
5765 
5766 			cp += (rth->ip6r_len + 1)*8;
5767 		}
5768 	}
5769 
5770 	/* count up length of UDP packet */
5771 	ip_len = (mp1->b_wptr - (unsigned char *)ip6h) - IPV6_HDR_LEN;
5772 	{
5773 		mblk_t *mp2;
5774 
5775 		if ((mp2 = mp1->b_cont) != NULL) {
5776 			do {
5777 				ip_len += mp2->b_wptr - mp2->b_rptr;
5778 			} while ((mp2 = mp2->b_cont) != NULL);
5779 		}
5780 	}
5781 
5782 	/*
5783 	 * If the size of the packet is greater than the maximum allowed by
5784 	 * ip, return an error. Passing this down could cause panics because
5785 	 * the size will have wrapped and be inconsistent with the msg size.
5786 	 */
5787 	if (ip_len > IP_MAXPACKET) {
5788 		BUMP_MIB(&udp_mib, udpOutErrors);
5789 		udp_ud_err(q, mp, EMSGSIZE);
5790 		return;
5791 	}
5792 
5793 	/* Store the UDP length. Subtract length of extension hdrs */
5794 	udph->uha_length = htons(ip_len + IPV6_HDR_LEN -
5795 	    (int)((uchar_t *)udph - (uchar_t *)ip6h));
5796 
5797 	/*
5798 	 * We make it easy for IP to include our pseudo header
5799 	 * by putting our length in uh_checksum, modified (if
5800 	 * we have a routing header) by the checksum difference
5801 	 * between the ultimate destination and first hop addresses.
5802 	 * Note: UDP over IPv6 must always checksum the packet.
5803 	 */
5804 	csum += udph->uha_length;
5805 	csum = (csum & 0xFFFF) + (csum >> 16);
5806 	udph->uha_checksum = (uint16_t)csum;
5807 
5808 #ifdef _LITTLE_ENDIAN
5809 	ip_len = htons(ip_len);
5810 #endif
5811 	ip6h->ip6_plen = ip_len;
5812 
5813 	freeb(mp);
5814 
5815 	/* We're done. Pass the packet to IP */
5816 	BUMP_MIB(&udp_mib, udpOutDatagrams);
5817 	putnext(q, mp1);
5818 }
5819 
5820 static void
5821 udp_wput_other(queue_t *q, mblk_t *mp)
5822 {
5823 	uchar_t	*rptr = mp->b_rptr;
5824 	struct datab *db;
5825 	struct iocblk *iocp;
5826 	udp_t	*udp;
5827 	cred_t	*cr;
5828 
5829 	TRACE_1(TR_FAC_UDP, TR_UDP_WPUT_OTHER_START,
5830 		"udp_wput_other_start: q %p", q);
5831 
5832 	udp = (udp_t *)q->q_ptr;
5833 	db = mp->b_datap;
5834 
5835 	cr = DB_CREDDEF(mp, udp->udp_credp);
5836 
5837 	switch (db->db_type) {
5838 	case M_DATA:
5839 		/* Not connected */
5840 		BUMP_MIB(&udp_mib, udpOutErrors);
5841 		freemsg(mp);
5842 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5843 			"udp_wput_other_end: q %p (%S)",
5844 			q, "not-connected");
5845 		return;
5846 	case M_PROTO:
5847 	case M_PCPROTO:
5848 		if (mp->b_wptr - rptr < sizeof (t_scalar_t)) {
5849 			freemsg(mp);
5850 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5851 				"udp_wput_other_end: q %p (%S)",
5852 				q, "protoshort");
5853 			return;
5854 		}
5855 		switch (((union T_primitives *)rptr)->type) {
5856 		case T_ADDR_REQ:
5857 			udp_addr_req(q, mp);
5858 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5859 				"udp_wput_other_end: q %p (%S)", q, "addrreq");
5860 			return;
5861 		case O_T_BIND_REQ:
5862 		case T_BIND_REQ:
5863 			udp_bind(q, mp);
5864 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5865 				"udp_wput_other_end: q %p (%S)", q, "bindreq");
5866 			return;
5867 		case T_CONN_REQ:
5868 			udp_connect(q, mp);
5869 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5870 				"udp_wput_other_end: q %p (%S)", q, "connreq");
5871 			return;
5872 		case T_CAPABILITY_REQ:
5873 			udp_capability_req(q, mp);
5874 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5875 				"udp_wput_other_end: q %p (%S)", q, "capabreq");
5876 			return;
5877 		case T_INFO_REQ:
5878 			udp_info_req(q, mp);
5879 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5880 				"udp_wput_other_end: q %p (%S)", q, "inforeq");
5881 			return;
5882 		case T_UNITDATA_REQ:
5883 			/*
5884 			 * If a T_UNITDATA_REQ gets here, the address must
5885 			 * be bad.  Valid T_UNITDATA_REQs are handled
5886 			 * in udp_wput.
5887 			 */
5888 			udp_ud_err(q, mp, EADDRNOTAVAIL);
5889 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5890 				"udp_wput_other_end: q %p (%S)",
5891 				q, "unitdatareq");
5892 			return;
5893 		case T_UNBIND_REQ:
5894 			udp_unbind(q, mp);
5895 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5896 			    "udp_wput_other_end: q %p (%S)", q, "unbindreq");
5897 			return;
5898 		case T_SVR4_OPTMGMT_REQ:
5899 			if (!snmpcom_req(q, mp, udp_snmp_set, udp_snmp_get, cr))
5900 				(void) svr4_optcom_req(q, mp, cr, &udp_opt_obj);
5901 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5902 			    "udp_wput_other_end: q %p (%S)",
5903 			    q, "optmgmtreq");
5904 			return;
5905 
5906 		case T_OPTMGMT_REQ:
5907 			(void) tpi_optcom_req(q, mp, cr, &udp_opt_obj);
5908 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5909 				"udp_wput_other_end: q %p (%S)",
5910 				q, "optmgmtreq");
5911 			return;
5912 
5913 		case T_DISCON_REQ:
5914 			udp_disconnect(q, mp);
5915 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5916 				"udp_wput_other_end: q %p (%S)",
5917 				q, "disconreq");
5918 			return;
5919 
5920 		/* The following TPI message is not supported by udp. */
5921 		case O_T_CONN_RES:
5922 		case T_CONN_RES:
5923 			udp_err_ack(q, mp, TNOTSUPPORT, 0);
5924 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5925 				"udp_wput_other_end: q %p (%S)",
5926 				q, "connres/disconreq");
5927 			return;
5928 
5929 		/* The following 3 TPI messages are illegal for udp. */
5930 		case T_DATA_REQ:
5931 		case T_EXDATA_REQ:
5932 		case T_ORDREL_REQ:
5933 			udp_err_ack(q, mp, TNOTSUPPORT, 0);
5934 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5935 				"udp_wput_other_end: q %p (%S)",
5936 				q, "data/exdata/ordrel");
5937 			return;
5938 		default:
5939 			break;
5940 		}
5941 		break;
5942 	case M_FLUSH:
5943 		if (*rptr & FLUSHW)
5944 			flushq(q, FLUSHDATA);
5945 		break;
5946 	case M_IOCTL:
5947 		iocp = (struct iocblk *)mp->b_rptr;
5948 		switch (iocp->ioc_cmd) {
5949 		case TI_GETPEERNAME:
5950 			if (udp->udp_state != TS_DATA_XFER) {
5951 				/*
5952 				 * If a default destination address has not
5953 				 * been associated with the stream, then we
5954 				 * don't know the peer's name.
5955 				 */
5956 				iocp->ioc_error = ENOTCONN;
5957 err_ret:;
5958 				iocp->ioc_count = 0;
5959 				mp->b_datap->db_type = M_IOCACK;
5960 				qreply(q, mp);
5961 				TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5962 					"udp_wput_other_end: q %p (%S)",
5963 					q, "getpeername");
5964 				return;
5965 			}
5966 			/* FALLTHRU */
5967 		case TI_GETMYNAME: {
5968 			/*
5969 			 * For TI_GETPEERNAME and TI_GETMYNAME, we first
5970 			 * need to copyin the user's strbuf structure.
5971 			 * Processing will continue in the M_IOCDATA case
5972 			 * below.
5973 			 */
5974 			mi_copyin(q, mp, NULL,
5975 			    SIZEOF_STRUCT(strbuf, iocp->ioc_flag));
5976 			TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5977 				"udp_wput_other_end: q %p (%S)",
5978 				q, "getmyname");
5979 			return;
5980 			}
5981 		case ND_SET:
5982 			/* nd_getset performs the necessary checking */
5983 		case ND_GET:
5984 			if (nd_getset(q, udp_g_nd, mp)) {
5985 				qreply(q, mp);
5986 				TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5987 					"udp_wput_other_end: q %p (%S)",
5988 					q, "get");
5989 				return;
5990 			}
5991 			break;
5992 		default:
5993 			break;
5994 		}
5995 		break;
5996 	case M_IOCDATA:
5997 		udp_wput_iocdata(q, mp);
5998 		TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
5999 			"udp_wput_other_end: q %p (%S)", q, "iocdata");
6000 		return;
6001 	default:
6002 		/* Unrecognized messages are passed through without change. */
6003 		break;
6004 	}
6005 	TRACE_2(TR_FAC_UDP, TR_UDP_WPUT_OTHER_END,
6006 		"udp_wput_other_end: q %p (%S)", q, "end");
6007 	putnext(q, mp);
6008 }
6009 
6010 /*
6011  * udp_wput_iocdata is called by udp_wput_other to handle all M_IOCDATA
6012  * messages.
6013  */
6014 static void
6015 udp_wput_iocdata(queue_t *q, mblk_t *mp)
6016 {
6017 	mblk_t	*mp1;
6018 	STRUCT_HANDLE(strbuf, sb);
6019 	uint16_t port;
6020 	udp_t	*udp;
6021 	in6_addr_t	v6addr;
6022 	ipaddr_t	v4addr;
6023 	uint32_t	flowinfo = 0;
6024 	int		addrlen;
6025 
6026 	/* Make sure it is one of ours. */
6027 	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
6028 	case TI_GETMYNAME:
6029 	case TI_GETPEERNAME:
6030 		break;
6031 	default:
6032 		putnext(q, mp);
6033 		return;
6034 	}
6035 	switch (mi_copy_state(q, mp, &mp1)) {
6036 	case -1:
6037 		return;
6038 	case MI_COPY_CASE(MI_COPY_IN, 1):
6039 		break;
6040 	case MI_COPY_CASE(MI_COPY_OUT, 1):
6041 		/*
6042 		 * The address has been copied out, so now
6043 		 * copyout the strbuf.
6044 		 */
6045 		mi_copyout(q, mp);
6046 		return;
6047 	case MI_COPY_CASE(MI_COPY_OUT, 2):
6048 		/*
6049 		 * The address and strbuf have been copied out.
6050 		 * We're done, so just acknowledge the original
6051 		 * M_IOCTL.
6052 		 */
6053 		mi_copy_done(q, mp, 0);
6054 		return;
6055 	default:
6056 		/*
6057 		 * Something strange has happened, so acknowledge
6058 		 * the original M_IOCTL with an EPROTO error.
6059 		 */
6060 		mi_copy_done(q, mp, EPROTO);
6061 		return;
6062 	}
6063 
6064 	/*
6065 	 * Now we have the strbuf structure for TI_GETMYNAME
6066 	 * and TI_GETPEERNAME.  Next we copyout the requested
6067 	 * address and then we'll copyout the strbuf.
6068 	 */
6069 	STRUCT_SET_HANDLE(sb, ((struct iocblk *)mp->b_rptr)->ioc_flag,
6070 	    (void *)mp1->b_rptr);
6071 	udp = (udp_t *)q->q_ptr;
6072 	if (udp->udp_family == AF_INET)
6073 		addrlen = sizeof (sin_t);
6074 	else
6075 		addrlen = sizeof (sin6_t);
6076 
6077 	if (STRUCT_FGET(sb, maxlen) < addrlen) {
6078 		mi_copy_done(q, mp, EINVAL);
6079 		return;
6080 	}
6081 	switch (((struct iocblk *)mp->b_rptr)->ioc_cmd) {
6082 	case TI_GETMYNAME:
6083 		if (udp->udp_family == AF_INET) {
6084 			ASSERT(udp->udp_ipversion == IPV4_VERSION);
6085 			if (!IN6_IS_ADDR_V4MAPPED_ANY(&udp->udp_v6src) &&
6086 			    !IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) {
6087 				v4addr = V4_PART_OF_V6(udp->udp_v6src);
6088 			} else {
6089 				/*
6090 				 * INADDR_ANY
6091 				 * udp_v6src is not set, we might be bound to
6092 				 * broadcast/multicast. Use udp_bound_v6src as
6093 				 * local address instead (that could
6094 				 * also still be INADDR_ANY)
6095 				 */
6096 				v4addr = V4_PART_OF_V6(udp->udp_bound_v6src);
6097 			}
6098 		} else {
6099 			/* udp->udp_family == AF_INET6 */
6100 			if (!IN6_IS_ADDR_UNSPECIFIED(&udp->udp_v6src)) {
6101 				v6addr = udp->udp_v6src;
6102 			} else {
6103 				/*
6104 				 * UNSPECIFIED
6105 				 * udp_v6src is not set, we might be bound to
6106 				 * broadcast/multicast. Use udp_bound_v6src as
6107 				 * local address instead (that could
6108 				 * also still be UNSPECIFIED)
6109 				 */
6110 				v6addr = udp->udp_bound_v6src;
6111 			}
6112 		}
6113 		port = udp->udp_port;
6114 		break;
6115 	case TI_GETPEERNAME:
6116 		if (udp->udp_family == AF_INET) {
6117 			ASSERT(udp->udp_ipversion == IPV4_VERSION);
6118 			v4addr = V4_PART_OF_V6(udp->udp_v6dst);
6119 		} else {
6120 			/* udp->udp_family == AF_INET6) */
6121 			v6addr = udp->udp_v6dst;
6122 			flowinfo = udp->udp_flowinfo;
6123 		}
6124 		port = udp->udp_dstport;
6125 		break;
6126 	default:
6127 		mi_copy_done(q, mp, EPROTO);
6128 		return;
6129 	}
6130 	mp1 = mi_copyout_alloc(q, mp, STRUCT_FGETP(sb, buf), addrlen, B_TRUE);
6131 	if (!mp1)
6132 		return;
6133 
6134 	if (udp->udp_family == AF_INET) {
6135 		sin_t *sin;
6136 
6137 		STRUCT_FSET(sb, len, (int)sizeof (sin_t));
6138 		sin = (sin_t *)mp1->b_rptr;
6139 		mp1->b_wptr = (uchar_t *)&sin[1];
6140 		*sin = sin_null;
6141 		sin->sin_family = AF_INET;
6142 		sin->sin_addr.s_addr = v4addr;
6143 		sin->sin_port = port;
6144 	} else {
6145 		/* udp->udp_family == AF_INET6 */
6146 		sin6_t *sin6;
6147 
6148 		STRUCT_FSET(sb, len, (int)sizeof (sin6_t));
6149 		sin6 = (sin6_t *)mp1->b_rptr;
6150 		mp1->b_wptr = (uchar_t *)&sin6[1];
6151 		*sin6 = sin6_null;
6152 		sin6->sin6_family = AF_INET6;
6153 		sin6->sin6_flowinfo = flowinfo;
6154 		sin6->sin6_addr = v6addr;
6155 		sin6->sin6_port = port;
6156 	}
6157 	/* Copy out the address */
6158 	mi_copyout(q, mp);
6159 }
6160 
6161 
6162 static int
6163 udp_unitdata_opt_process(queue_t *q, mblk_t *mp, int *errorp,
6164     void *thisdg_attrs)
6165 {
6166 	udp_t	*udp;
6167 	struct T_unitdata_req *udreqp;
6168 	int is_absreq_failure;
6169 	cred_t *cr;
6170 
6171 	ASSERT(((union T_primitives *)mp->b_rptr)->type);
6172 
6173 	udp = (udp_t *)q->q_ptr;
6174 
6175 	cr = DB_CREDDEF(mp, udp->udp_credp);
6176 
6177 	udreqp = (struct T_unitdata_req *)mp->b_rptr;
6178 	*errorp = 0;
6179 
6180 	*errorp = tpi_optcom_buf(q, mp, &udreqp->OPT_length,
6181 	    udreqp->OPT_offset, cr, &udp_opt_obj,
6182 	    thisdg_attrs, &is_absreq_failure);
6183 
6184 	if (*errorp != 0) {
6185 		/*
6186 		 * Note: No special action needed in this
6187 		 * module for "is_absreq_failure"
6188 		 */
6189 		return (-1);		/* failure */
6190 	}
6191 	ASSERT(is_absreq_failure == 0);
6192 	return (0);	/* success */
6193 }
6194 
6195 void
6196 udp_ddi_init(void)
6197 {
6198 	int i;
6199 
6200 	UDP6_MAJ = ddi_name_to_major(UDP6);
6201 	mutex_init(&udp_g_lock, NULL, MUTEX_DEFAULT, NULL);
6202 
6203 	udp_max_optsize = optcom_max_optsize(udp_opt_obj.odb_opt_des_arr,
6204 	    udp_opt_obj.odb_opt_arr_cnt);
6205 
6206 	if (udp_bind_fanout_size & (udp_bind_fanout_size - 1)) {
6207 		/* Not a power of two. Round up to nearest power of two */
6208 		for (i = 0; i < 31; i++) {
6209 			if (udp_bind_fanout_size < (1 << i))
6210 				break;
6211 		}
6212 		udp_bind_fanout_size = 1 << i;
6213 	}
6214 	udp_bind_fanout = kmem_zalloc(udp_bind_fanout_size *
6215 	    sizeof (udp_fanout_t), KM_SLEEP);
6216 	for (i = 0; i < udp_bind_fanout_size; i++) {
6217 		mutex_init(&udp_bind_fanout[i].uf_lock, NULL, MUTEX_DEFAULT,
6218 		    NULL);
6219 	}
6220 	(void) udp_param_register(udp_param_arr, A_CNT(udp_param_arr));
6221 	udp_kstat_init();
6222 }
6223 
6224 void
6225 udp_ddi_destroy(void)
6226 {
6227 	int i;
6228 
6229 	nd_free(&udp_g_nd);
6230 
6231 	mutex_destroy(&udp_g_lock);
6232 	for (i = 0; i < udp_bind_fanout_size; i++) {
6233 		mutex_destroy(&udp_bind_fanout[i].uf_lock);
6234 	}
6235 	kmem_free(udp_bind_fanout, udp_bind_fanout_size *
6236 	    sizeof (udp_fanout_t));
6237 	udp_kstat_fini();
6238 
6239 }
6240 
6241 static void
6242 udp_kstat_init(void)
6243 {
6244 	udp_named_kstat_t template = {
6245 		{ "inDatagrams",	KSTAT_DATA_UINT32, 0 },
6246 		{ "inErrors",		KSTAT_DATA_UINT32, 0 },
6247 		{ "outDatagrams",	KSTAT_DATA_UINT32, 0 },
6248 		{ "entrySize",		KSTAT_DATA_INT32, 0 },
6249 		{ "entry6Size",		KSTAT_DATA_INT32, 0 },
6250 		{ "outErrors",		KSTAT_DATA_UINT32, 0 },
6251 	};
6252 
6253 	udp_mibkp = kstat_create("udp", 0, "udp", "mib2", KSTAT_TYPE_NAMED,
6254 					NUM_OF_FIELDS(udp_named_kstat_t),
6255 					0);
6256 	if (udp_mibkp == NULL)
6257 		return;
6258 
6259 	template.entrySize.value.ui32 = sizeof (mib2_udpEntry_t);
6260 	template.entry6Size.value.ui32 = sizeof (mib2_udp6Entry_t);
6261 
6262 	bcopy(&template, udp_mibkp->ks_data, sizeof (template));
6263 
6264 	udp_mibkp->ks_update = udp_kstat_update;
6265 
6266 	kstat_install(udp_mibkp);
6267 }
6268 
6269 static void
6270 udp_kstat_fini(void)
6271 {
6272 	if (udp_mibkp) {
6273 		kstat_delete(udp_mibkp);
6274 		udp_mibkp = NULL;
6275 	}
6276 }
6277 
6278 static int
6279 udp_kstat_update(kstat_t *kp, int rw)
6280 {
6281 	udp_named_kstat_t *udpkp;
6282 
6283 	if ((kp == NULL) || (kp->ks_data == NULL))
6284 		return (EIO);
6285 
6286 	if (rw == KSTAT_WRITE)
6287 		return (EACCES);
6288 
6289 	udpkp = (udp_named_kstat_t *)kp->ks_data;
6290 
6291 	udpkp->inDatagrams.value.ui32 =	udp_mib.udpInDatagrams;
6292 	udpkp->inErrors.value.ui32 =	udp_mib.udpInErrors;
6293 	udpkp->outDatagrams.value.ui32 = udp_mib.udpOutDatagrams;
6294 	udpkp->outErrors.value.ui32 =	udp_mib.udpOutErrors;
6295 
6296 	return (0);
6297 }
6298 
6299 /*
6300  * Little helper for IPsec's NAT-T processing.
6301  */
6302 boolean_t
6303 udp_compute_checksum(void)
6304 {
6305 	return (udp_do_checksum);
6306 }
6307