xref: /illumos-gate/usr/src/uts/common/inet/ip/conn_opt.c (revision ac2250cb76bb32944fd2c8a3ba2cd3f79747748d)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
25  * Copyright 2024 Oxide Computer Company
26  * Copyright 2026 Bill Sommerfeld <sommerfeld@hamachi.org>
27  */
28 /* Copyright (c) 1990 Mentat Inc. */
29 
30 #include <sys/types.h>
31 #include <sys/stream.h>
32 #include <sys/strsun.h>
33 #define	_SUN_TPI_VERSION 2
34 #include <sys/tihdr.h>
35 #include <sys/xti_inet.h>
36 #include <sys/ucred.h>
37 #include <sys/zone.h>
38 #include <sys/ddi.h>
39 #include <sys/sunddi.h>
40 #include <sys/cmn_err.h>
41 #include <sys/debug.h>
42 #include <sys/atomic.h>
43 #include <sys/policy.h>
44 
45 #include <sys/systm.h>
46 #include <sys/param.h>
47 #include <sys/kmem.h>
48 #include <sys/sdt.h>
49 #include <sys/socket.h>
50 #include <sys/ethernet.h>
51 #include <sys/mac.h>
52 #include <net/if.h>
53 #include <net/if_types.h>
54 #include <net/if_arp.h>
55 #include <net/route.h>
56 #include <sys/sockio.h>
57 #include <netinet/in.h>
58 #include <net/if_dl.h>
59 
60 #include <inet/common.h>
61 #include <inet/mi.h>
62 #include <inet/mib2.h>
63 #include <inet/nd.h>
64 #include <inet/arp.h>
65 #include <inet/snmpcom.h>
66 #include <inet/kstatcom.h>
67 
68 #include <netinet/igmp_var.h>
69 #include <netinet/ip6.h>
70 #include <netinet/icmp6.h>
71 #include <netinet/sctp.h>
72 
73 #include <inet/ip.h>
74 #include <inet/ip_impl.h>
75 #include <inet/ip6.h>
76 #include <inet/ip6_asp.h>
77 #include <inet/tcp.h>
78 #include <inet/ip_multi.h>
79 #include <inet/ip_if.h>
80 #include <inet/ip_ire.h>
81 #include <inet/ip_ftable.h>
82 #include <inet/ip_rts.h>
83 #include <inet/optcom.h>
84 #include <inet/ip_ndp.h>
85 #include <inet/ip_listutils.h>
86 #include <netinet/igmp.h>
87 #include <netinet/ip_mroute.h>
88 #include <netinet/udp.h>
89 #include <inet/ipp_common.h>
90 
91 #include <net/pfkeyv2.h>
92 #include <inet/sadb.h>
93 #include <inet/ipsec_impl.h>
94 #include <inet/ipdrop.h>
95 #include <inet/ip_netinfo.h>
96 
97 #include <inet/ipclassifier.h>
98 #include <inet/sctp_ip.h>
99 #include <inet/sctp/sctp_impl.h>
100 #include <inet/udp_impl.h>
101 #include <sys/sunddi.h>
102 
103 #include <sys/tsol/label.h>
104 #include <sys/tsol/tnet.h>
105 
106 /*
107  * Return how much size is needed for the different ancillary data items
108  */
109 uint_t
110 conn_recvancillary_size(conn_t *connp, crb_t recv_ancillary,
111     ip_recv_attr_t *ira, mblk_t *mp, ip_pkt_t *ipp)
112 {
113 	uint_t		ancil_size;
114 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
115 
116 	/*
117 	 * If IP_RECVDSTADDR is set we include the destination IP
118 	 * address as an option. With IP_RECVOPTS we include all
119 	 * the IP options.
120 	 */
121 	ancil_size = 0;
122 	if (recv_ancillary.crb_recvdstaddr &&
123 	    (ira->ira_flags & IRAF_IS_IPV4)) {
124 		ancil_size += sizeof (struct T_opthdr) +
125 		    sizeof (struct in_addr);
126 		IP_STAT(ipst, conn_in_recvdstaddr);
127 	}
128 
129 	/*
130 	 * ip_recvpktinfo is used for both AF_INET and AF_INET6 but
131 	 * are different
132 	 */
133 	if (recv_ancillary.crb_ip_recvpktinfo &&
134 	    connp->conn_family == AF_INET) {
135 		ancil_size += sizeof (struct T_opthdr) +
136 		    sizeof (struct in_pktinfo);
137 		IP_STAT(ipst, conn_in_recvpktinfo);
138 	}
139 
140 	if ((recv_ancillary.crb_recvopts) &&
141 	    (ipp->ipp_fields & IPPF_IPV4_OPTIONS)) {
142 		ancil_size += sizeof (struct T_opthdr) +
143 		    ipp->ipp_ipv4_options_len;
144 		IP_STAT(ipst, conn_in_recvopts);
145 	}
146 
147 	if (recv_ancillary.crb_recvslla) {
148 		ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
149 		ill_t *ill;
150 
151 		/* Make sure ira_l2src is setup if not already */
152 		if (!(ira->ira_flags & IRAF_L2SRC_SET)) {
153 			ill = ill_lookup_on_ifindex(ira->ira_rifindex, B_FALSE,
154 			    ipst);
155 			if (ill != NULL) {
156 				ip_setl2src(mp, ira, ill);
157 				ill_refrele(ill);
158 			}
159 		}
160 		ancil_size += sizeof (struct T_opthdr) +
161 		    sizeof (struct sockaddr_dl);
162 		IP_STAT(ipst, conn_in_recvslla);
163 	}
164 
165 	if (recv_ancillary.crb_recvif) {
166 		ancil_size += sizeof (struct T_opthdr) + sizeof (uint_t);
167 		IP_STAT(ipst, conn_in_recvif);
168 	}
169 
170 	/*
171 	 * ip_recvpktinfo is used for both AF_INET and AF_INET6 but
172 	 * are different
173 	 */
174 	if (recv_ancillary.crb_ip_recvpktinfo &&
175 	    connp->conn_family == AF_INET6) {
176 		ancil_size += sizeof (struct T_opthdr) +
177 		    sizeof (struct in6_pktinfo);
178 		IP_STAT(ipst, conn_in_recvpktinfo);
179 	}
180 
181 	if (recv_ancillary.crb_ipv6_recvhoplimit) {
182 		ancil_size += sizeof (struct T_opthdr) + sizeof (int);
183 		IP_STAT(ipst, conn_in_recvhoplimit);
184 	}
185 
186 	if (recv_ancillary.crb_ipv6_recvtclass) {
187 		ancil_size += sizeof (struct T_opthdr) + sizeof (int);
188 		IP_STAT(ipst, conn_in_recvtclass);
189 	}
190 
191 	if (recv_ancillary.crb_ipv6_recvhopopts &&
192 	    (ipp->ipp_fields & IPPF_HOPOPTS)) {
193 		ancil_size += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
194 		IP_STAT(ipst, conn_in_recvhopopts);
195 	}
196 	/*
197 	 * To honor RFC3542 when an application asks for both IPV6_RECVDSTOPTS
198 	 * and IPV6_RECVRTHDR, we pass up the item rthdrdstopts (the destination
199 	 * options that appear before a routing header.
200 	 * We also pass them up if IPV6_RECVRTHDRDSTOPTS is set.
201 	 */
202 	if (ipp->ipp_fields & IPPF_RTHDRDSTOPTS) {
203 		if (recv_ancillary.crb_ipv6_recvrthdrdstopts ||
204 		    (recv_ancillary.crb_ipv6_recvdstopts &&
205 		    recv_ancillary.crb_ipv6_recvrthdr)) {
206 			ancil_size += sizeof (struct T_opthdr) +
207 			    ipp->ipp_rthdrdstoptslen;
208 			IP_STAT(ipst, conn_in_recvrthdrdstopts);
209 		}
210 	}
211 	if ((recv_ancillary.crb_ipv6_recvrthdr) &&
212 	    (ipp->ipp_fields & IPPF_RTHDR)) {
213 		ancil_size += sizeof (struct T_opthdr) + ipp->ipp_rthdrlen;
214 		IP_STAT(ipst, conn_in_recvrthdr);
215 	}
216 	if ((recv_ancillary.crb_ipv6_recvdstopts ||
217 	    recv_ancillary.crb_old_ipv6_recvdstopts) &&
218 	    (ipp->ipp_fields & IPPF_DSTOPTS)) {
219 		ancil_size += sizeof (struct T_opthdr) + ipp->ipp_dstoptslen;
220 		IP_STAT(ipst, conn_in_recvdstopts);
221 	}
222 	if (recv_ancillary.crb_recvucred && ira->ira_cred != NULL) {
223 		ancil_size += sizeof (struct T_opthdr) +
224 		    ucredminsize(ira->ira_cred);
225 		IP_STAT(ipst, conn_in_recvucred);
226 	}
227 
228 	/*
229 	 * If SO_TIMESTAMP is set allocate the appropriate sized
230 	 * buffer. Since gethrestime() expects a pointer aligned
231 	 * argument, we allocate space necessary for extra
232 	 * alignment (even though it might not be used).
233 	 */
234 	if (recv_ancillary.crb_timestamp) {
235 		ancil_size += sizeof (struct T_opthdr) +
236 		    sizeof (timestruc_t) + _POINTER_ALIGNMENT;
237 		IP_STAT(ipst, conn_in_timestamp);
238 	}
239 
240 	/*
241 	 * If IP_RECVTOS is set allocate the appropriately sized buffer
242 	 */
243 	if (recv_ancillary.crb_recvtos &&
244 	    (ira->ira_flags & IRAF_IS_IPV4)) {
245 		ancil_size += sizeof (struct T_opthdr) +
246 		    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
247 		IP_STAT(ipst, conn_in_recvtos);
248 	}
249 
250 	/*
251 	 * If IP_RECVTTL is set allocate the appropriate sized buffer
252 	 */
253 	if (recv_ancillary.crb_recvttl &&
254 	    (ira->ira_flags & IRAF_IS_IPV4)) {
255 		ancil_size += sizeof (struct T_opthdr) +
256 		    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
257 		IP_STAT(ipst, conn_in_recvttl);
258 	}
259 
260 	return (ancil_size);
261 }
262 
263 /*
264  * Lay down the ancillary data items at "ancil_buf".
265  * Assumes caller has used conn_recvancillary_size to allocate a sufficiently
266  * large buffer - ancil_size.
267  */
268 void
269 conn_recvancillary_add(conn_t *connp, crb_t recv_ancillary,
270     ip_recv_attr_t *ira, ip_pkt_t *ipp, uchar_t *ancil_buf, uint_t ancil_size)
271 {
272 	/*
273 	 * Copy in destination address before options to avoid
274 	 * any padding issues.
275 	 */
276 	if (recv_ancillary.crb_recvdstaddr &&
277 	    (ira->ira_flags & IRAF_IS_IPV4)) {
278 		struct T_opthdr *toh;
279 		ipaddr_t *dstptr;
280 
281 		toh = (struct T_opthdr *)ancil_buf;
282 		toh->level = IPPROTO_IP;
283 		toh->name = IP_RECVDSTADDR;
284 		toh->len = sizeof (struct T_opthdr) + sizeof (ipaddr_t);
285 		toh->status = 0;
286 		ancil_buf += sizeof (struct T_opthdr);
287 		dstptr = (ipaddr_t *)ancil_buf;
288 		*dstptr = ipp->ipp_addr_v4;
289 		ancil_buf += sizeof (ipaddr_t);
290 		ancil_size -= toh->len;
291 	}
292 
293 	/*
294 	 * ip_recvpktinfo is used for both AF_INET and AF_INET6 but
295 	 * are different
296 	 */
297 	if (recv_ancillary.crb_ip_recvpktinfo &&
298 	    connp->conn_family == AF_INET) {
299 		ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
300 		struct T_opthdr *toh;
301 		struct in_pktinfo *pktinfop;
302 		ill_t *ill;
303 		ipif_t *ipif;
304 
305 		toh = (struct T_opthdr *)ancil_buf;
306 		toh->level = IPPROTO_IP;
307 		toh->name = IP_PKTINFO;
308 		toh->len = sizeof (struct T_opthdr) + sizeof (*pktinfop);
309 		toh->status = 0;
310 		ancil_buf += sizeof (struct T_opthdr);
311 		pktinfop = (struct in_pktinfo *)ancil_buf;
312 
313 		pktinfop->ipi_ifindex = ira->ira_ruifindex;
314 		pktinfop->ipi_spec_dst.s_addr = INADDR_ANY;
315 
316 		/* Find a good address to report */
317 		ill = ill_lookup_on_ifindex(ira->ira_ruifindex, B_FALSE, ipst);
318 		if (ill != NULL) {
319 			ipif = ipif_good_addr(ill, IPCL_ZONEID(connp));
320 			if (ipif != NULL) {
321 				pktinfop->ipi_spec_dst.s_addr =
322 				    ipif->ipif_lcl_addr;
323 				ipif_refrele(ipif);
324 			}
325 			ill_refrele(ill);
326 		}
327 		pktinfop->ipi_addr.s_addr = ipp->ipp_addr_v4;
328 		ancil_buf += sizeof (struct in_pktinfo);
329 		ancil_size -= toh->len;
330 	}
331 
332 	if ((recv_ancillary.crb_recvopts) &&
333 	    (ipp->ipp_fields & IPPF_IPV4_OPTIONS)) {
334 		struct T_opthdr *toh;
335 
336 		toh = (struct T_opthdr *)ancil_buf;
337 		toh->level = IPPROTO_IP;
338 		toh->name = IP_RECVOPTS;
339 		toh->len = sizeof (struct T_opthdr) + ipp->ipp_ipv4_options_len;
340 		toh->status = 0;
341 		ancil_buf += sizeof (struct T_opthdr);
342 		bcopy(ipp->ipp_ipv4_options, ancil_buf,
343 		    ipp->ipp_ipv4_options_len);
344 		ancil_buf += ipp->ipp_ipv4_options_len;
345 		ancil_size -= toh->len;
346 	}
347 
348 	if (recv_ancillary.crb_recvslla) {
349 		ip_stack_t *ipst = connp->conn_netstack->netstack_ip;
350 		struct T_opthdr *toh;
351 		struct sockaddr_dl *dstptr;
352 		ill_t *ill;
353 		int alen = 0;
354 
355 		ill = ill_lookup_on_ifindex(ira->ira_rifindex, B_FALSE, ipst);
356 		if (ill != NULL)
357 			alen = ill->ill_phys_addr_length;
358 
359 		/*
360 		 * For loopback multicast and broadcast the packet arrives
361 		 * with ira_ruifdex being the physical interface, but
362 		 * ira_l2src is all zero since ip_postfrag_loopback doesn't
363 		 * know our l2src. We don't report the address in that case.
364 		 */
365 		if (ira->ira_flags & IRAF_LOOPBACK)
366 			alen = 0;
367 
368 		toh = (struct T_opthdr *)ancil_buf;
369 		toh->level = IPPROTO_IP;
370 		toh->name = IP_RECVSLLA;
371 		toh->len = sizeof (struct T_opthdr) +
372 		    sizeof (struct sockaddr_dl);
373 		toh->status = 0;
374 		ancil_buf += sizeof (struct T_opthdr);
375 		dstptr = (struct sockaddr_dl *)ancil_buf;
376 		dstptr->sdl_family = AF_LINK;
377 		dstptr->sdl_index = ira->ira_ruifindex;
378 		if (ill != NULL)
379 			dstptr->sdl_type = ill->ill_type;
380 		else
381 			dstptr->sdl_type = 0;
382 		dstptr->sdl_nlen = 0;
383 		dstptr->sdl_alen = alen;
384 		dstptr->sdl_slen = 0;
385 		bcopy(ira->ira_l2src, dstptr->sdl_data, alen);
386 		ancil_buf += sizeof (struct sockaddr_dl);
387 		ancil_size -= toh->len;
388 		if (ill != NULL)
389 			ill_refrele(ill);
390 	}
391 
392 	if (recv_ancillary.crb_recvif) {
393 		struct T_opthdr *toh;
394 		uint_t		*dstptr;
395 
396 		toh = (struct T_opthdr *)ancil_buf;
397 		toh->level = IPPROTO_IP;
398 		toh->name = IP_RECVIF;
399 		toh->len = sizeof (struct T_opthdr) + sizeof (uint_t);
400 		toh->status = 0;
401 		ancil_buf += sizeof (struct T_opthdr);
402 		dstptr = (uint_t *)ancil_buf;
403 		*dstptr = ira->ira_ruifindex;
404 		ancil_buf += sizeof (uint_t);
405 		ancil_size -= toh->len;
406 	}
407 
408 	/*
409 	 * ip_recvpktinfo is used for both AF_INET and AF_INET6 but
410 	 * are different
411 	 */
412 	if (recv_ancillary.crb_ip_recvpktinfo &&
413 	    connp->conn_family == AF_INET6) {
414 		struct T_opthdr *toh;
415 		struct in6_pktinfo *pkti;
416 
417 		toh = (struct T_opthdr *)ancil_buf;
418 		toh->level = IPPROTO_IPV6;
419 		toh->name = IPV6_PKTINFO;
420 		toh->len = sizeof (struct T_opthdr) + sizeof (*pkti);
421 		toh->status = 0;
422 		ancil_buf += sizeof (struct T_opthdr);
423 		pkti = (struct in6_pktinfo *)ancil_buf;
424 		if (ira->ira_flags & IRAF_IS_IPV4) {
425 			IN6_IPADDR_TO_V4MAPPED(ipp->ipp_addr_v4,
426 			    &pkti->ipi6_addr);
427 		} else {
428 			pkti->ipi6_addr = ipp->ipp_addr;
429 		}
430 		pkti->ipi6_ifindex = ira->ira_ruifindex;
431 
432 		ancil_buf += sizeof (*pkti);
433 		ancil_size -= toh->len;
434 	}
435 	if (recv_ancillary.crb_ipv6_recvhoplimit) {
436 		struct T_opthdr *toh;
437 
438 		toh = (struct T_opthdr *)ancil_buf;
439 		toh->level = IPPROTO_IPV6;
440 		toh->name = IPV6_HOPLIMIT;
441 		toh->len = sizeof (struct T_opthdr) + sizeof (uint_t);
442 		toh->status = 0;
443 		ancil_buf += sizeof (struct T_opthdr);
444 		*(uint_t *)ancil_buf = ipp->ipp_hoplimit;
445 		ancil_buf += sizeof (uint_t);
446 		ancil_size -= toh->len;
447 	}
448 	if (recv_ancillary.crb_ipv6_recvtclass) {
449 		struct T_opthdr *toh;
450 
451 		toh = (struct T_opthdr *)ancil_buf;
452 		toh->level = IPPROTO_IPV6;
453 		toh->name = IPV6_TCLASS;
454 		toh->len = sizeof (struct T_opthdr) + sizeof (uint_t);
455 		toh->status = 0;
456 		ancil_buf += sizeof (struct T_opthdr);
457 
458 		if (ira->ira_flags & IRAF_IS_IPV4)
459 			*(uint_t *)ancil_buf = ipp->ipp_type_of_service;
460 		else
461 			*(uint_t *)ancil_buf = ipp->ipp_tclass;
462 		ancil_buf += sizeof (uint_t);
463 		ancil_size -= toh->len;
464 	}
465 	if (recv_ancillary.crb_ipv6_recvhopopts &&
466 	    (ipp->ipp_fields & IPPF_HOPOPTS)) {
467 		struct T_opthdr *toh;
468 
469 		toh = (struct T_opthdr *)ancil_buf;
470 		toh->level = IPPROTO_IPV6;
471 		toh->name = IPV6_HOPOPTS;
472 		toh->len = sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
473 		toh->status = 0;
474 		ancil_buf += sizeof (struct T_opthdr);
475 		bcopy(ipp->ipp_hopopts, ancil_buf, ipp->ipp_hopoptslen);
476 		ancil_buf += ipp->ipp_hopoptslen;
477 		ancil_size -= toh->len;
478 	}
479 	/*
480 	 * To honor RFC3542 when an application asks for both IPV6_RECVDSTOPTS
481 	 * and IPV6_RECVRTHDR, we pass up the item rthdrdstopts (the destination
482 	 * options that appear before a routing header.
483 	 * We also pass them up if IPV6_RECVRTHDRDSTOPTS is set.
484 	 */
485 	if (ipp->ipp_fields & IPPF_RTHDRDSTOPTS) {
486 		if (recv_ancillary.crb_ipv6_recvrthdrdstopts ||
487 		    (recv_ancillary.crb_ipv6_recvdstopts &&
488 		    recv_ancillary.crb_ipv6_recvrthdr)) {
489 			struct T_opthdr *toh;
490 
491 			toh = (struct T_opthdr *)ancil_buf;
492 			toh->level = IPPROTO_IPV6;
493 			toh->name = IPV6_DSTOPTS;
494 			toh->len = sizeof (struct T_opthdr) +
495 			    ipp->ipp_rthdrdstoptslen;
496 			toh->status = 0;
497 			ancil_buf += sizeof (struct T_opthdr);
498 			bcopy(ipp->ipp_rthdrdstopts, ancil_buf,
499 			    ipp->ipp_rthdrdstoptslen);
500 			ancil_buf += ipp->ipp_rthdrdstoptslen;
501 			ancil_size -= toh->len;
502 		}
503 	}
504 	if (recv_ancillary.crb_ipv6_recvrthdr &&
505 	    (ipp->ipp_fields & IPPF_RTHDR)) {
506 		struct T_opthdr *toh;
507 
508 		toh = (struct T_opthdr *)ancil_buf;
509 		toh->level = IPPROTO_IPV6;
510 		toh->name = IPV6_RTHDR;
511 		toh->len = sizeof (struct T_opthdr) + ipp->ipp_rthdrlen;
512 		toh->status = 0;
513 		ancil_buf += sizeof (struct T_opthdr);
514 		bcopy(ipp->ipp_rthdr, ancil_buf, ipp->ipp_rthdrlen);
515 		ancil_buf += ipp->ipp_rthdrlen;
516 		ancil_size -= toh->len;
517 	}
518 	if ((recv_ancillary.crb_ipv6_recvdstopts ||
519 	    recv_ancillary.crb_old_ipv6_recvdstopts) &&
520 	    (ipp->ipp_fields & IPPF_DSTOPTS)) {
521 		struct T_opthdr *toh;
522 
523 		toh = (struct T_opthdr *)ancil_buf;
524 		toh->level = IPPROTO_IPV6;
525 		toh->name = IPV6_DSTOPTS;
526 		toh->len = sizeof (struct T_opthdr) + ipp->ipp_dstoptslen;
527 		toh->status = 0;
528 		ancil_buf += sizeof (struct T_opthdr);
529 		bcopy(ipp->ipp_dstopts, ancil_buf, ipp->ipp_dstoptslen);
530 		ancil_buf += ipp->ipp_dstoptslen;
531 		ancil_size -= toh->len;
532 	}
533 
534 	if (recv_ancillary.crb_recvucred && ira->ira_cred != NULL) {
535 		struct T_opthdr *toh;
536 		cred_t		*rcr = connp->conn_cred;
537 
538 		toh = (struct T_opthdr *)ancil_buf;
539 		toh->level = SOL_SOCKET;
540 		toh->name = SCM_UCRED;
541 		toh->len = sizeof (struct T_opthdr) +
542 		    ucredminsize(ira->ira_cred);
543 		toh->status = 0;
544 		(void) cred2ucred(ira->ira_cred, ira->ira_cpid, &toh[1], rcr);
545 		ancil_buf += toh->len;
546 		ancil_size -= toh->len;
547 	}
548 	if (recv_ancillary.crb_timestamp) {
549 		struct	T_opthdr *toh;
550 
551 		toh = (struct T_opthdr *)ancil_buf;
552 		toh->level = SOL_SOCKET;
553 		toh->name = SCM_TIMESTAMP;
554 		toh->len = sizeof (struct T_opthdr) +
555 		    sizeof (timestruc_t) + _POINTER_ALIGNMENT;
556 		toh->status = 0;
557 		ancil_buf += sizeof (struct T_opthdr);
558 		/* Align for gethrestime() */
559 		ancil_buf = (uchar_t *)P2ROUNDUP((intptr_t)ancil_buf,
560 		    sizeof (intptr_t));
561 		gethrestime((timestruc_t *)ancil_buf);
562 		ancil_buf = (uchar_t *)toh + toh->len;
563 		ancil_size -= toh->len;
564 	}
565 
566 	if (recv_ancillary.crb_recvtos &&
567 	    (ira->ira_flags & IRAF_IS_IPV4)) {
568 		struct	T_opthdr *toh;
569 		uint8_t	*dstptr;
570 
571 		toh = (struct T_opthdr *)ancil_buf;
572 		toh->level = IPPROTO_IP;
573 		toh->name = IP_RECVTOS;
574 		toh->len = sizeof (struct T_opthdr) +
575 		    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
576 		toh->status = 0;
577 		ancil_buf += sizeof (struct T_opthdr);
578 		dstptr = (uint8_t *)ancil_buf;
579 		*dstptr = ipp->ipp_type_of_service;
580 		ancil_buf = (uchar_t *)toh + toh->len;
581 		ancil_size -= toh->len;
582 		ASSERT(__TPI_TOPT_ISALIGNED(toh));
583 	}
584 
585 	if (recv_ancillary.crb_recvttl &&
586 	    (ira->ira_flags & IRAF_IS_IPV4)) {
587 		struct	T_opthdr *toh;
588 		uint8_t	*dstptr;
589 
590 		toh = (struct T_opthdr *)ancil_buf;
591 		toh->level = IPPROTO_IP;
592 		toh->name = IP_RECVTTL;
593 		toh->len = sizeof (struct T_opthdr) +
594 		    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
595 		toh->status = 0;
596 		ancil_buf += sizeof (struct T_opthdr);
597 		dstptr = (uint8_t *)ancil_buf;
598 		*dstptr = ipp->ipp_hoplimit;
599 		ancil_buf = (uchar_t *)toh + toh->len;
600 		ancil_size -= toh->len;
601 		ASSERT(__TPI_TOPT_ISALIGNED(toh));
602 	}
603 
604 	/* Consumed all of allocated space */
605 	ASSERT(ancil_size == 0);
606 
607 }
608 
609 /*
610  * This routine retrieves the current status of socket options.
611  * It returns the size of the option retrieved, or -1.
612  */
613 int
614 conn_opt_get(conn_opt_arg_t *coa, t_scalar_t level, t_scalar_t name,
615     uchar_t *ptr)
616 {
617 	int		*i1 = (int *)ptr;
618 	conn_t		*connp = coa->coa_connp;
619 	ip_xmit_attr_t	*ixa = coa->coa_ixa;
620 	ip_pkt_t	*ipp = coa->coa_ipp;
621 	ip_stack_t	*ipst = ixa->ixa_ipst;
622 	uint_t		len;
623 
624 	ASSERT(MUTEX_HELD(&coa->coa_connp->conn_lock));
625 
626 	switch (level) {
627 	case SOL_SOCKET:
628 		switch (name) {
629 		case SO_DEBUG:
630 			*i1 = connp->conn_debug ? SO_DEBUG : 0;
631 			break;	/* goto sizeof (int) option return */
632 		case SO_KEEPALIVE:
633 			*i1 = connp->conn_keepalive ? SO_KEEPALIVE : 0;
634 			break;
635 		case SO_LINGER:	{
636 			struct linger *lgr = (struct linger *)ptr;
637 
638 			lgr->l_onoff = connp->conn_linger ? SO_LINGER : 0;
639 			lgr->l_linger = connp->conn_lingertime;
640 			}
641 			return (sizeof (struct linger));
642 
643 		case SO_OOBINLINE:
644 			*i1 = connp->conn_oobinline ? SO_OOBINLINE : 0;
645 			break;
646 		case SO_REUSEADDR:
647 			*i1 = connp->conn_reuseaddr ? SO_REUSEADDR : 0;
648 			break;	/* goto sizeof (int) option return */
649 		case SO_TYPE:
650 			*i1 = connp->conn_so_type;
651 			break;	/* goto sizeof (int) option return */
652 		case SO_DONTROUTE:
653 			*i1 = (ixa->ixa_flags & IXAF_DONTROUTE) ?
654 			    SO_DONTROUTE : 0;
655 			break;	/* goto sizeof (int) option return */
656 		case SO_USELOOPBACK:
657 			*i1 = connp->conn_useloopback ? SO_USELOOPBACK : 0;
658 			break;	/* goto sizeof (int) option return */
659 		case SO_BROADCAST:
660 			*i1 = connp->conn_broadcast ? SO_BROADCAST : 0;
661 			break;	/* goto sizeof (int) option return */
662 
663 		case SO_SNDBUF:
664 			*i1 = connp->conn_sndbuf;
665 			break;	/* goto sizeof (int) option return */
666 		case SO_RCVBUF:
667 			*i1 = connp->conn_rcvbuf;
668 			break;	/* goto sizeof (int) option return */
669 		case SO_RCVTIMEO:
670 		case SO_SNDTIMEO:
671 			/*
672 			 * Pass these two options in order for third part
673 			 * protocol usage. Here just return directly.
674 			 */
675 			*i1 = 0;
676 			break;
677 		case SO_DGRAM_ERRIND:
678 			*i1 = connp->conn_dgram_errind ? SO_DGRAM_ERRIND : 0;
679 			break;	/* goto sizeof (int) option return */
680 		case SO_RECVUCRED:
681 			*i1 = connp->conn_recv_ancillary.crb_recvucred;
682 			break;	/* goto sizeof (int) option return */
683 		case SO_TIMESTAMP:
684 			*i1 = connp->conn_recv_ancillary.crb_timestamp;
685 			break;	/* goto sizeof (int) option return */
686 		case SO_VRRP:
687 			*i1 = connp->conn_isvrrp;
688 			break;	/* goto sizeof (int) option return */
689 		case SO_ANON_MLP:
690 			*i1 = connp->conn_anon_mlp;
691 			break;	/* goto sizeof (int) option return */
692 		case SO_MAC_EXEMPT:
693 			*i1 = (connp->conn_mac_mode == CONN_MAC_AWARE);
694 			break;	/* goto sizeof (int) option return */
695 		case SO_MAC_IMPLICIT:
696 			*i1 = (connp->conn_mac_mode == CONN_MAC_IMPLICIT);
697 			break;	/* goto sizeof (int) option return */
698 		case SO_ALLZONES:
699 			*i1 = connp->conn_allzones;
700 			break;	/* goto sizeof (int) option return */
701 		case SO_EXCLBIND:
702 			*i1 = connp->conn_exclbind ? SO_EXCLBIND : 0;
703 			break;
704 		case SO_PROTOTYPE:
705 			*i1 = connp->conn_proto;
706 			break;
707 
708 		case SO_DOMAIN:
709 			*i1 = connp->conn_family;
710 			break;
711 		default:
712 			return (-1);
713 		}
714 		break;
715 	case IPPROTO_IP:
716 		if (connp->conn_family != AF_INET)
717 			return (-1);
718 		switch (name) {
719 		case IP_OPTIONS:
720 		case T_IP_OPTIONS:
721 			if (!(ipp->ipp_fields & IPPF_IPV4_OPTIONS))
722 				return (0);
723 
724 			len = ipp->ipp_ipv4_options_len;
725 			if (len > 0) {
726 				bcopy(ipp->ipp_ipv4_options, ptr, len);
727 			}
728 			return (len);
729 
730 		case IP_PKTINFO: {
731 			/*
732 			 * This also handles IP_RECVPKTINFO.
733 			 * IP_PKTINFO and IP_RECVPKTINFO have same value.
734 			 * Differentiation is based on the size of the
735 			 * argument passed in.
736 			 */
737 			struct in_pktinfo *pktinfo;
738 
739 #ifdef notdef
740 			/* optcom doesn't provide a length with "get" */
741 			if (inlen == sizeof (int)) {
742 				/* This is IP_RECVPKTINFO option. */
743 				*i1 = connp->conn_recv_ancillary.
744 				    crb_ip_recvpktinfo;
745 				return (sizeof (int));
746 			}
747 #endif
748 			/* XXX assumes that caller has room for max size! */
749 
750 			pktinfo = (struct in_pktinfo *)ptr;
751 			pktinfo->ipi_ifindex = ixa->ixa_ifindex;
752 			if (ipp->ipp_fields & IPPF_ADDR)
753 				pktinfo->ipi_spec_dst.s_addr = ipp->ipp_addr_v4;
754 			else
755 				pktinfo->ipi_spec_dst.s_addr = INADDR_ANY;
756 			return (sizeof (struct in_pktinfo));
757 		}
758 		case IP_DONTFRAG:
759 			*i1 = (ixa->ixa_flags & IXAF_DONTFRAG) != 0;
760 			return (sizeof (int));
761 		case IP_TOS:
762 		case T_IP_TOS:
763 			*i1 = (int)ipp->ipp_type_of_service;
764 			break;	/* goto sizeof (int) option return */
765 		case IP_TTL:
766 			*i1 = (int)ipp->ipp_unicast_hops;
767 			break;	/* goto sizeof (int) option return */
768 		case IP_DHCPINIT_IF:
769 			return (-1);
770 		case IP_NEXTHOP:
771 			if (ixa->ixa_flags & IXAF_NEXTHOP_SET) {
772 				*(ipaddr_t *)ptr = ixa->ixa_nexthop_v4;
773 				return (sizeof (ipaddr_t));
774 			} else {
775 				return (0);
776 			}
777 
778 		case IP_MULTICAST_IF:
779 			/* 0 address if not set */
780 			*(ipaddr_t *)ptr = ixa->ixa_multicast_ifaddr;
781 			return (sizeof (ipaddr_t));
782 		case IP_MULTICAST_TTL:
783 			*(uchar_t *)ptr = ixa->ixa_multicast_ttl;
784 			return (sizeof (uchar_t));
785 		case IP_MULTICAST_LOOP:
786 			*ptr = (ixa->ixa_flags & IXAF_MULTICAST_LOOP) ? 1 : 0;
787 			return (sizeof (uint8_t));
788 		case IP_RECVOPTS:
789 			*i1 = connp->conn_recv_ancillary.crb_recvopts;
790 			break;	/* goto sizeof (int) option return */
791 		case IP_RECVDSTADDR:
792 			*i1 = connp->conn_recv_ancillary.crb_recvdstaddr;
793 			break;	/* goto sizeof (int) option return */
794 		case IP_RECVIF:
795 			*i1 = connp->conn_recv_ancillary.crb_recvif;
796 			break;	/* goto sizeof (int) option return */
797 		case IP_RECVSLLA:
798 			*i1 = connp->conn_recv_ancillary.crb_recvslla;
799 			break;	/* goto sizeof (int) option return */
800 		case IP_RECVTTL:
801 			*i1 = connp->conn_recv_ancillary.crb_recvttl;
802 			break;	/* goto sizeof (int) option return */
803 		case IP_RECVTOS:
804 			*i1 = connp->conn_recv_ancillary.crb_recvtos;
805 			break;	/* goto sizeof (int) option return */
806 		case IP_ADD_MEMBERSHIP:
807 		case IP_DROP_MEMBERSHIP:
808 		case MCAST_JOIN_GROUP:
809 		case MCAST_LEAVE_GROUP:
810 		case IP_BLOCK_SOURCE:
811 		case IP_UNBLOCK_SOURCE:
812 		case IP_ADD_SOURCE_MEMBERSHIP:
813 		case IP_DROP_SOURCE_MEMBERSHIP:
814 		case MCAST_BLOCK_SOURCE:
815 		case MCAST_UNBLOCK_SOURCE:
816 		case MCAST_JOIN_SOURCE_GROUP:
817 		case MCAST_LEAVE_SOURCE_GROUP:
818 		case MRT_INIT:
819 		case MRT_DONE:
820 		case MRT_ADD_VIF:
821 		case MRT_DEL_VIF:
822 		case MRT_ADD_MFC:
823 		case MRT_DEL_MFC:
824 			/* cannot "get" the value for these */
825 			return (-1);
826 		case MRT_VERSION:
827 		case MRT_ASSERT:
828 			(void) ip_mrouter_get(name, connp, ptr);
829 			return (sizeof (int));
830 		case IP_SEC_OPT:
831 			return (ipsec_req_from_conn(connp, (ipsec_req_t	*)ptr,
832 			    IPSEC_AF_V4));
833 		case IP_BOUND_IF:
834 			/* Zero if not set */
835 			*i1 = connp->conn_bound_if;
836 			break;	/* goto sizeof (int) option return */
837 		case IP_UNSPEC_SRC:
838 			*i1 = connp->conn_unspec_src;
839 			break;	/* goto sizeof (int) option return */
840 		case IP_BROADCAST_TTL:
841 			if (ixa->ixa_flags & IXAF_BROADCAST_TTL_SET)
842 				*(uchar_t *)ptr = ixa->ixa_broadcast_ttl;
843 			else
844 				*(uchar_t *)ptr = ipst->ips_ip_broadcast_ttl;
845 			return (sizeof (uchar_t));
846 		case IP_MINTTL:
847 			*i1 = connp->conn_min_ttl;
848 			return (sizeof (int));
849 		default:
850 			return (-1);
851 		}
852 		break;
853 	case IPPROTO_IPV6:
854 		if (connp->conn_family != AF_INET6)
855 			return (-1);
856 		switch (name) {
857 		case IPV6_UNICAST_HOPS:
858 			*i1 = (int)ipp->ipp_unicast_hops;
859 			break;	/* goto sizeof (int) option return */
860 		case IPV6_MULTICAST_IF:
861 			/* 0 index if not set */
862 			*i1 = ixa->ixa_multicast_ifindex;
863 			break;	/* goto sizeof (int) option return */
864 		case IPV6_MULTICAST_HOPS:
865 			*i1 = ixa->ixa_multicast_ttl;
866 			break;	/* goto sizeof (int) option return */
867 		case IPV6_MULTICAST_LOOP:
868 			*i1 = (ixa->ixa_flags & IXAF_MULTICAST_LOOP) ? 1 : 0;
869 			break;	/* goto sizeof (int) option return */
870 		case IPV6_JOIN_GROUP:
871 		case IPV6_LEAVE_GROUP:
872 		case MCAST_JOIN_GROUP:
873 		case MCAST_LEAVE_GROUP:
874 		case MCAST_BLOCK_SOURCE:
875 		case MCAST_UNBLOCK_SOURCE:
876 		case MCAST_JOIN_SOURCE_GROUP:
877 		case MCAST_LEAVE_SOURCE_GROUP:
878 			/* cannot "get" the value for these */
879 			return (-1);
880 		case IPV6_BOUND_IF:
881 			/* Zero if not set */
882 			*i1 = connp->conn_bound_if;
883 			break;	/* goto sizeof (int) option return */
884 		case IPV6_UNSPEC_SRC:
885 			*i1 = connp->conn_unspec_src;
886 			break;	/* goto sizeof (int) option return */
887 		case IPV6_RECVPKTINFO:
888 			*i1 = connp->conn_recv_ancillary.crb_ip_recvpktinfo;
889 			break;	/* goto sizeof (int) option return */
890 		case IPV6_RECVTCLASS:
891 			*i1 = connp->conn_recv_ancillary.crb_ipv6_recvtclass;
892 			break;	/* goto sizeof (int) option return */
893 		case IPV6_RECVPATHMTU:
894 			*i1 = connp->conn_ipv6_recvpathmtu;
895 			break;	/* goto sizeof (int) option return */
896 		case IPV6_RECVHOPLIMIT:
897 			*i1 = connp->conn_recv_ancillary.crb_ipv6_recvhoplimit;
898 			break;	/* goto sizeof (int) option return */
899 		case IPV6_RECVHOPOPTS:
900 			*i1 = connp->conn_recv_ancillary.crb_ipv6_recvhopopts;
901 			break;	/* goto sizeof (int) option return */
902 		case IPV6_RECVDSTOPTS:
903 			*i1 = connp->conn_recv_ancillary.crb_ipv6_recvdstopts;
904 			break;	/* goto sizeof (int) option return */
905 		case _OLD_IPV6_RECVDSTOPTS:
906 			*i1 =
907 			    connp->conn_recv_ancillary.crb_old_ipv6_recvdstopts;
908 			break;	/* goto sizeof (int) option return */
909 		case IPV6_RECVRTHDRDSTOPTS:
910 			*i1 = connp->conn_recv_ancillary.
911 			    crb_ipv6_recvrthdrdstopts;
912 			break;	/* goto sizeof (int) option return */
913 		case IPV6_RECVRTHDR:
914 			*i1 = connp->conn_recv_ancillary.crb_ipv6_recvrthdr;
915 			break;	/* goto sizeof (int) option return */
916 		case IPV6_PKTINFO: {
917 			/* XXX assumes that caller has room for max size! */
918 			struct in6_pktinfo *pkti;
919 
920 			pkti = (struct in6_pktinfo *)ptr;
921 			pkti->ipi6_ifindex = ixa->ixa_ifindex;
922 			if (ipp->ipp_fields & IPPF_ADDR)
923 				pkti->ipi6_addr = ipp->ipp_addr;
924 			else
925 				pkti->ipi6_addr = ipv6_all_zeros;
926 			return (sizeof (struct in6_pktinfo));
927 		}
928 		case IPV6_TCLASS:
929 			*i1 = ipp->ipp_tclass;
930 			break;	/* goto sizeof (int) option return */
931 		case IPV6_NEXTHOP: {
932 			sin6_t *sin6 = (sin6_t *)ptr;
933 
934 			if (ixa->ixa_flags & IXAF_NEXTHOP_SET)
935 				return (0);
936 
937 			*sin6 = sin6_null;
938 			sin6->sin6_family = AF_INET6;
939 			sin6->sin6_addr = ixa->ixa_nexthop_v6;
940 
941 			return (sizeof (sin6_t));
942 		}
943 		case IPV6_HOPOPTS:
944 			if (!(ipp->ipp_fields & IPPF_HOPOPTS))
945 				return (0);
946 			bcopy(ipp->ipp_hopopts, ptr,
947 			    ipp->ipp_hopoptslen);
948 			return (ipp->ipp_hopoptslen);
949 		case IPV6_RTHDRDSTOPTS:
950 			if (!(ipp->ipp_fields & IPPF_RTHDRDSTOPTS))
951 				return (0);
952 			bcopy(ipp->ipp_rthdrdstopts, ptr,
953 			    ipp->ipp_rthdrdstoptslen);
954 			return (ipp->ipp_rthdrdstoptslen);
955 		case IPV6_RTHDR:
956 			if (!(ipp->ipp_fields & IPPF_RTHDR))
957 				return (0);
958 			bcopy(ipp->ipp_rthdr, ptr, ipp->ipp_rthdrlen);
959 			return (ipp->ipp_rthdrlen);
960 		case IPV6_DSTOPTS:
961 			if (!(ipp->ipp_fields & IPPF_DSTOPTS))
962 				return (0);
963 			bcopy(ipp->ipp_dstopts, ptr, ipp->ipp_dstoptslen);
964 			return (ipp->ipp_dstoptslen);
965 		case IPV6_PATHMTU:
966 			return (ip_fill_mtuinfo(connp, ixa,
967 			    (struct ip6_mtuinfo *)ptr));
968 		case IPV6_SEC_OPT:
969 			return (ipsec_req_from_conn(connp, (ipsec_req_t	*)ptr,
970 			    IPSEC_AF_V6));
971 		case IPV6_SRC_PREFERENCES:
972 			return (ip6_get_src_preferences(ixa, (uint32_t *)ptr));
973 		case IPV6_DONTFRAG:
974 			*i1 = (ixa->ixa_flags & IXAF_DONTFRAG) != 0;
975 			return (sizeof (int));
976 		case IPV6_USE_MIN_MTU:
977 			if (ixa->ixa_flags & IXAF_USE_MIN_MTU)
978 				*i1 = ixa->ixa_use_min_mtu;
979 			else
980 				*i1 = IPV6_USE_MIN_MTU_MULTICAST;
981 			break;
982 		case IPV6_V6ONLY:
983 			*i1 = connp->conn_ipv6_v6only;
984 			return (sizeof (int));
985 		case IPV6_MINHOPCOUNT:
986 			*i1 = connp->conn_min_ttl;
987 			return (sizeof (int));
988 		default:
989 			return (-1);
990 		}
991 		break;
992 	case IPPROTO_UDP:
993 		switch (name) {
994 		case UDP_ANONPRIVBIND:
995 			*i1 = connp->conn_anon_priv_bind;
996 			break;
997 		case UDP_EXCLBIND:
998 			*i1 = connp->conn_exclbind ? UDP_EXCLBIND : 0;
999 			break;
1000 		default:
1001 			return (-1);
1002 		}
1003 		break;
1004 	case IPPROTO_TCP:
1005 		switch (name) {
1006 		case TCP_RECVDSTADDR:
1007 			*i1 = connp->conn_recv_ancillary.crb_recvdstaddr;
1008 			break;
1009 		case TCP_ANONPRIVBIND:
1010 			*i1 = connp->conn_anon_priv_bind;
1011 			break;
1012 		case TCP_EXCLBIND:
1013 			*i1 = connp->conn_exclbind ? TCP_EXCLBIND : 0;
1014 			break;
1015 		default:
1016 			return (-1);
1017 		}
1018 		break;
1019 	default:
1020 		return (-1);
1021 	}
1022 	return (sizeof (int));
1023 }
1024 
1025 static int conn_opt_set_socket(conn_opt_arg_t *coa, t_scalar_t name,
1026     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr);
1027 static int conn_opt_set_ip(conn_opt_arg_t *coa, t_scalar_t name,
1028     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr);
1029 static int conn_opt_set_ipv6(conn_opt_arg_t *coa, t_scalar_t name,
1030     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr);
1031 static int conn_opt_set_udp(conn_opt_arg_t *coa, t_scalar_t name,
1032     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr);
1033 static int conn_opt_set_tcp(conn_opt_arg_t *coa, t_scalar_t name,
1034     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr);
1035 
1036 /*
1037  * This routine sets the most common socket options including some
1038  * that are transport/ULP specific.
1039  * It returns errno or zero.
1040  *
1041  * For fixed length options, there is no sanity check
1042  * of passed in length is done. It is assumed *_optcom_req()
1043  * routines do the right thing.
1044  */
1045 int
1046 conn_opt_set(conn_opt_arg_t *coa, t_scalar_t level, t_scalar_t name,
1047     uint_t inlen, uchar_t *invalp, boolean_t checkonly, cred_t *cr)
1048 {
1049 	ASSERT(MUTEX_NOT_HELD(&coa->coa_connp->conn_lock));
1050 
1051 	/* We have different functions for different levels */
1052 	switch (level) {
1053 	case SOL_SOCKET:
1054 		return (conn_opt_set_socket(coa, name, inlen, invalp,
1055 		    checkonly, cr));
1056 	case IPPROTO_IP:
1057 		return (conn_opt_set_ip(coa, name, inlen, invalp,
1058 		    checkonly, cr));
1059 	case IPPROTO_IPV6:
1060 		return (conn_opt_set_ipv6(coa, name, inlen, invalp,
1061 		    checkonly, cr));
1062 	case IPPROTO_UDP:
1063 		return (conn_opt_set_udp(coa, name, inlen, invalp,
1064 		    checkonly, cr));
1065 	case IPPROTO_TCP:
1066 		return (conn_opt_set_tcp(coa, name, inlen, invalp,
1067 		    checkonly, cr));
1068 	default:
1069 		return (0);
1070 	}
1071 }
1072 
1073 /*
1074  * Handle SOL_SOCKET
1075  * Note that we do not handle SO_PROTOTYPE here. The ULPs that support
1076  * it implement their own checks and setting of conn_proto.
1077  */
1078 /* ARGSUSED1 */
1079 static int
1080 conn_opt_set_socket(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen,
1081     uchar_t *invalp, boolean_t checkonly, cred_t *cr)
1082 {
1083 	conn_t		*connp = coa->coa_connp;
1084 	ip_xmit_attr_t	*ixa = coa->coa_ixa;
1085 	int		*i1 = (int *)invalp;
1086 	boolean_t	onoff = (*i1 == 0) ? 0 : 1;
1087 
1088 	switch (name) {
1089 	case SO_ALLZONES:
1090 		if (IPCL_IS_BOUND(connp))
1091 			return (EINVAL);
1092 		break;
1093 	case SO_VRRP:
1094 		if (secpolicy_ip_config(cr, checkonly) != 0)
1095 			return (EACCES);
1096 		break;
1097 	case SO_MAC_EXEMPT:
1098 		if (secpolicy_net_mac_aware(cr) != 0)
1099 			return (EACCES);
1100 		if (IPCL_IS_BOUND(connp))
1101 			return (EINVAL);
1102 		break;
1103 	case SO_MAC_IMPLICIT:
1104 		if (secpolicy_net_mac_implicit(cr) != 0)
1105 			return (EACCES);
1106 		break;
1107 	}
1108 	if (checkonly)
1109 		return (0);
1110 
1111 	mutex_enter(&connp->conn_lock);
1112 	/* Here we set the actual option value */
1113 	switch (name) {
1114 	case SO_DEBUG:
1115 		connp->conn_debug = onoff;
1116 		break;
1117 	case SO_KEEPALIVE:
1118 		connp->conn_keepalive = onoff;
1119 		break;
1120 	case SO_LINGER: {
1121 		struct linger *lgr = (struct linger *)invalp;
1122 
1123 		if (lgr->l_onoff) {
1124 			connp->conn_linger = 1;
1125 			connp->conn_lingertime = lgr->l_linger;
1126 		} else {
1127 			connp->conn_linger = 0;
1128 			connp->conn_lingertime = 0;
1129 		}
1130 		break;
1131 	}
1132 	case SO_OOBINLINE:
1133 		connp->conn_oobinline = onoff;
1134 		coa->coa_changed |= COA_OOBINLINE_CHANGED;
1135 		break;
1136 	case SO_REUSEADDR:
1137 		connp->conn_reuseaddr = onoff;
1138 		break;
1139 	case SO_DONTROUTE:
1140 		if (onoff)
1141 			ixa->ixa_flags |= IXAF_DONTROUTE;
1142 		else
1143 			ixa->ixa_flags &= ~IXAF_DONTROUTE;
1144 		coa->coa_changed |= COA_ROUTE_CHANGED;
1145 		break;
1146 	case SO_USELOOPBACK:
1147 		connp->conn_useloopback = onoff;
1148 		break;
1149 	case SO_BROADCAST:
1150 		connp->conn_broadcast = onoff;
1151 		break;
1152 	case SO_SNDBUF:
1153 		/* ULP has range checked the value */
1154 		connp->conn_sndbuf = *i1;
1155 		coa->coa_changed |= COA_SNDBUF_CHANGED;
1156 		break;
1157 	case SO_RCVBUF:
1158 		/* ULP has range checked the value */
1159 		connp->conn_rcvbuf = *i1;
1160 		coa->coa_changed |= COA_RCVBUF_CHANGED;
1161 		break;
1162 	case SO_RCVTIMEO:
1163 	case SO_SNDTIMEO:
1164 		/*
1165 		 * Pass these two options in order for third part
1166 		 * protocol usage.
1167 		 */
1168 		break;
1169 	case SO_DGRAM_ERRIND:
1170 		connp->conn_dgram_errind = onoff;
1171 		break;
1172 	case SO_RECVUCRED:
1173 		connp->conn_recv_ancillary.crb_recvucred = onoff;
1174 		break;
1175 	case SO_ALLZONES:
1176 		connp->conn_allzones = onoff;
1177 		coa->coa_changed |= COA_ROUTE_CHANGED;
1178 		if (onoff)
1179 			ixa->ixa_zoneid = ALL_ZONES;
1180 		else
1181 			ixa->ixa_zoneid = connp->conn_zoneid;
1182 		break;
1183 	case SO_TIMESTAMP:
1184 		connp->conn_recv_ancillary.crb_timestamp = onoff;
1185 		break;
1186 	case SO_VRRP:
1187 		connp->conn_isvrrp = onoff;
1188 		break;
1189 	case SO_ANON_MLP:
1190 		connp->conn_anon_mlp = onoff;
1191 		break;
1192 	case SO_MAC_EXEMPT:
1193 		connp->conn_mac_mode = onoff ?
1194 		    CONN_MAC_AWARE : CONN_MAC_DEFAULT;
1195 		break;
1196 	case SO_MAC_IMPLICIT:
1197 		connp->conn_mac_mode = onoff ?
1198 		    CONN_MAC_IMPLICIT : CONN_MAC_DEFAULT;
1199 		break;
1200 	case SO_EXCLBIND:
1201 		connp->conn_exclbind = onoff;
1202 		break;
1203 	}
1204 	mutex_exit(&connp->conn_lock);
1205 	return (0);
1206 }
1207 
1208 /* Handle IPPROTO_IP */
1209 static int
1210 conn_opt_set_ip(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen,
1211     uchar_t *invalp, boolean_t checkonly, cred_t *cr)
1212 {
1213 	conn_t		*connp = coa->coa_connp;
1214 	ip_xmit_attr_t	*ixa = coa->coa_ixa;
1215 	ip_pkt_t	*ipp = coa->coa_ipp;
1216 	int		*i1 = (int *)invalp;
1217 	boolean_t	onoff = (*i1 == 0) ? 0 : 1;
1218 	ipaddr_t	addr = (ipaddr_t)*i1;
1219 	uint_t		ifindex;
1220 	zoneid_t	zoneid = IPCL_ZONEID(connp);
1221 	ipif_t		*ipif;
1222 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1223 	int		error;
1224 
1225 	if (connp->conn_family != AF_INET)
1226 		return (EINVAL);
1227 
1228 	ifindex = UINT_MAX;
1229 	switch (name) {
1230 	case IP_TTL:
1231 		/* Don't allow zero */
1232 		if (*i1 < 1 || *i1 > MAXTTL)
1233 			return (EINVAL);
1234 		break;
1235 	case IP_MULTICAST_IF:
1236 		if (addr == INADDR_ANY) {
1237 			/* Clear */
1238 			ifindex = 0;
1239 			break;
1240 		}
1241 		ipif = ipif_lookup_addr(addr, NULL, zoneid, ipst);
1242 		if (ipif == NULL)
1243 			return (EHOSTUNREACH);
1244 		/* not supported by the virtual network iface */
1245 		if (IS_VNI(ipif->ipif_ill)) {
1246 			ipif_refrele(ipif);
1247 			return (EINVAL);
1248 		}
1249 		ifindex = ipif->ipif_ill->ill_phyint->phyint_ifindex;
1250 		ipif_refrele(ipif);
1251 		break;
1252 	case IP_NEXTHOP: {
1253 		ire_t	*ire;
1254 
1255 		if (addr == INADDR_ANY) {
1256 			/* Clear */
1257 			break;
1258 		}
1259 		/* Verify that the next-hop is on-link */
1260 		ire = ire_ftable_lookup_v4(addr, 0, 0, IRE_ONLINK, NULL, zoneid,
1261 		    NULL, MATCH_IRE_TYPE, 0, ipst, NULL);
1262 		if (ire == NULL)
1263 			return (EHOSTUNREACH);
1264 		ire_refrele(ire);
1265 		break;
1266 	}
1267 	case IP_OPTIONS:
1268 	case T_IP_OPTIONS: {
1269 		uint_t newlen;
1270 
1271 		if (ipp->ipp_fields & IPPF_LABEL_V4)
1272 			newlen = inlen + (ipp->ipp_label_len_v4 + 3) & ~3;
1273 		else
1274 			newlen = inlen;
1275 		if ((inlen & 0x3) || newlen > IP_MAX_OPT_LENGTH) {
1276 			return (EINVAL);
1277 		}
1278 		break;
1279 	}
1280 	case IP_PKTINFO: {
1281 		struct in_pktinfo *pktinfo;
1282 
1283 		/* Two different valid lengths */
1284 		if (inlen != sizeof (int) &&
1285 		    inlen != sizeof (struct in_pktinfo))
1286 			return (EINVAL);
1287 		if (inlen == sizeof (int))
1288 			break;
1289 
1290 		pktinfo = (struct in_pktinfo *)invalp;
1291 		if (pktinfo->ipi_spec_dst.s_addr != INADDR_ANY) {
1292 			switch (ip_laddr_verify_v4(pktinfo->ipi_spec_dst.s_addr,
1293 			    zoneid, ipst, B_FALSE)) {
1294 			case IPVL_UNICAST_UP:
1295 			case IPVL_UNICAST_DOWN:
1296 				break;
1297 			default:
1298 				return (EADDRNOTAVAIL);
1299 			}
1300 		}
1301 		if (!ip_xmit_ifindex_valid(pktinfo->ipi_ifindex, zoneid,
1302 		    B_FALSE, ipst))
1303 			return (ENXIO);
1304 		break;
1305 	}
1306 	case IP_BOUND_IF:
1307 		ifindex = *(uint_t *)i1;
1308 
1309 		/* Just check it is ok. */
1310 		if (!ip_xmit_ifindex_valid(ifindex, zoneid, B_FALSE, ipst))
1311 			return (ENXIO);
1312 		break;
1313 	case IP_MINTTL:
1314 		if (*i1 < 0 || *i1 > MAXTTL)
1315 			return (EINVAL);
1316 		break;
1317 	}
1318 	if (checkonly)
1319 		return (0);
1320 
1321 	/* Here we set the actual option value */
1322 	/*
1323 	 * conn_lock protects the bitfields, and is used to
1324 	 * set the fields atomically. Not needed for ixa settings since
1325 	 * the caller has an exclusive copy of the ixa.
1326 	 * We can not hold conn_lock across the multicast options though.
1327 	 */
1328 	switch (name) {
1329 	case IP_OPTIONS:
1330 	case T_IP_OPTIONS:
1331 		/* Save options for use by IP. */
1332 		mutex_enter(&connp->conn_lock);
1333 		error = optcom_pkt_set(invalp, inlen,
1334 		    (uchar_t **)&ipp->ipp_ipv4_options,
1335 		    &ipp->ipp_ipv4_options_len);
1336 		if (error != 0) {
1337 			mutex_exit(&connp->conn_lock);
1338 			return (error);
1339 		}
1340 		if (ipp->ipp_ipv4_options_len == 0) {
1341 			ipp->ipp_fields &= ~IPPF_IPV4_OPTIONS;
1342 		} else {
1343 			ipp->ipp_fields |= IPPF_IPV4_OPTIONS;
1344 		}
1345 		mutex_exit(&connp->conn_lock);
1346 		coa->coa_changed |= COA_HEADER_CHANGED;
1347 		coa->coa_changed |= COA_WROFF_CHANGED;
1348 		break;
1349 
1350 	case IP_TTL:
1351 		mutex_enter(&connp->conn_lock);
1352 		ipp->ipp_unicast_hops = *i1;
1353 		mutex_exit(&connp->conn_lock);
1354 		coa->coa_changed |= COA_HEADER_CHANGED;
1355 		break;
1356 	case IP_TOS:
1357 	case T_IP_TOS:
1358 		mutex_enter(&connp->conn_lock);
1359 		if (*i1 == -1) {
1360 			ipp->ipp_type_of_service = 0;
1361 		} else {
1362 			ipp->ipp_type_of_service = *i1;
1363 		}
1364 		mutex_exit(&connp->conn_lock);
1365 		coa->coa_changed |= COA_HEADER_CHANGED;
1366 		break;
1367 	case IP_MULTICAST_IF:
1368 		ixa->ixa_multicast_ifindex = ifindex;
1369 		ixa->ixa_multicast_ifaddr = addr;
1370 		coa->coa_changed |= COA_ROUTE_CHANGED;
1371 		break;
1372 	case IP_MULTICAST_TTL:
1373 		ixa->ixa_multicast_ttl = *invalp;
1374 		/* Handled automatically by ip_output */
1375 		break;
1376 	case IP_MULTICAST_LOOP:
1377 		if (*invalp != 0)
1378 			ixa->ixa_flags |= IXAF_MULTICAST_LOOP;
1379 		else
1380 			ixa->ixa_flags &= ~IXAF_MULTICAST_LOOP;
1381 		/* Handled automatically by ip_output */
1382 		break;
1383 	case IP_RECVOPTS:
1384 		mutex_enter(&connp->conn_lock);
1385 		connp->conn_recv_ancillary.crb_recvopts = onoff;
1386 		mutex_exit(&connp->conn_lock);
1387 		break;
1388 	case IP_RECVDSTADDR:
1389 		mutex_enter(&connp->conn_lock);
1390 		connp->conn_recv_ancillary.crb_recvdstaddr = onoff;
1391 		mutex_exit(&connp->conn_lock);
1392 		break;
1393 	case IP_RECVIF:
1394 		mutex_enter(&connp->conn_lock);
1395 		connp->conn_recv_ancillary.crb_recvif = onoff;
1396 		mutex_exit(&connp->conn_lock);
1397 		break;
1398 	case IP_RECVSLLA:
1399 		mutex_enter(&connp->conn_lock);
1400 		connp->conn_recv_ancillary.crb_recvslla = onoff;
1401 		mutex_exit(&connp->conn_lock);
1402 		break;
1403 	case IP_RECVTTL:
1404 		mutex_enter(&connp->conn_lock);
1405 		connp->conn_recv_ancillary.crb_recvttl = onoff;
1406 		mutex_exit(&connp->conn_lock);
1407 		break;
1408 	case IP_RECVTOS:
1409 		mutex_enter(&connp->conn_lock);
1410 		connp->conn_recv_ancillary.crb_recvtos = onoff;
1411 		mutex_exit(&connp->conn_lock);
1412 		break;
1413 	case IP_PKTINFO: {
1414 		/*
1415 		 * This also handles IP_RECVPKTINFO.
1416 		 * IP_PKTINFO and IP_RECVPKTINFO have same value.
1417 		 * Differentiation is based on the size of the
1418 		 * argument passed in.
1419 		 */
1420 		struct in_pktinfo *pktinfo;
1421 
1422 		if (inlen == sizeof (int)) {
1423 			/* This is IP_RECVPKTINFO option. */
1424 			mutex_enter(&connp->conn_lock);
1425 			connp->conn_recv_ancillary.crb_ip_recvpktinfo =
1426 			    onoff;
1427 			mutex_exit(&connp->conn_lock);
1428 			break;
1429 		}
1430 
1431 		/* This is IP_PKTINFO option. */
1432 		mutex_enter(&connp->conn_lock);
1433 		pktinfo = (struct in_pktinfo *)invalp;
1434 		if (pktinfo->ipi_spec_dst.s_addr != INADDR_ANY) {
1435 			ipp->ipp_fields |= IPPF_ADDR;
1436 			IN6_INADDR_TO_V4MAPPED(&pktinfo->ipi_spec_dst,
1437 			    &ipp->ipp_addr);
1438 		} else {
1439 			ipp->ipp_fields &= ~IPPF_ADDR;
1440 			ipp->ipp_addr = ipv6_all_zeros;
1441 		}
1442 		mutex_exit(&connp->conn_lock);
1443 		ixa->ixa_ifindex = pktinfo->ipi_ifindex;
1444 		coa->coa_changed |= COA_ROUTE_CHANGED;
1445 		coa->coa_changed |= COA_HEADER_CHANGED;
1446 		break;
1447 	}
1448 	case IP_DONTFRAG:
1449 		if (onoff) {
1450 			ixa->ixa_flags |= (IXAF_DONTFRAG | IXAF_PMTU_IPV4_DF);
1451 			ixa->ixa_flags &= ~IXAF_PMTU_DISCOVERY;
1452 		} else {
1453 			ixa->ixa_flags &= ~(IXAF_DONTFRAG | IXAF_PMTU_IPV4_DF);
1454 			ixa->ixa_flags |= IXAF_PMTU_DISCOVERY;
1455 		}
1456 		/* Need to redo ip_attr_connect */
1457 		coa->coa_changed |= COA_ROUTE_CHANGED;
1458 		break;
1459 	case IP_ADD_MEMBERSHIP:
1460 	case IP_DROP_MEMBERSHIP:
1461 	case MCAST_JOIN_GROUP:
1462 	case MCAST_LEAVE_GROUP:
1463 		return (ip_opt_set_multicast_group(connp, name,
1464 		    invalp, B_FALSE, checkonly));
1465 
1466 	case IP_BLOCK_SOURCE:
1467 	case IP_UNBLOCK_SOURCE:
1468 	case IP_ADD_SOURCE_MEMBERSHIP:
1469 	case IP_DROP_SOURCE_MEMBERSHIP:
1470 	case MCAST_BLOCK_SOURCE:
1471 	case MCAST_UNBLOCK_SOURCE:
1472 	case MCAST_JOIN_SOURCE_GROUP:
1473 	case MCAST_LEAVE_SOURCE_GROUP:
1474 		return (ip_opt_set_multicast_sources(connp, name,
1475 		    invalp, B_FALSE, checkonly));
1476 
1477 	case IP_SEC_OPT:
1478 		mutex_enter(&connp->conn_lock);
1479 		error = ipsec_set_req(cr, connp, (ipsec_req_t *)invalp);
1480 		mutex_exit(&connp->conn_lock);
1481 		if (error != 0) {
1482 			return (error);
1483 		}
1484 		/* This is an IPsec policy change - redo ip_attr_connect */
1485 		coa->coa_changed |= COA_ROUTE_CHANGED;
1486 		break;
1487 	case IP_NEXTHOP:
1488 		ixa->ixa_nexthop_v4 = addr;
1489 		if (addr != INADDR_ANY)
1490 			ixa->ixa_flags |= IXAF_NEXTHOP_SET;
1491 		else
1492 			ixa->ixa_flags &= ~IXAF_NEXTHOP_SET;
1493 		coa->coa_changed |= COA_ROUTE_CHANGED;
1494 		break;
1495 
1496 	case IP_BOUND_IF:
1497 		ixa->ixa_ifindex = ifindex;		/* Send */
1498 		mutex_enter(&connp->conn_lock);
1499 		connp->conn_incoming_ifindex = ifindex;	/* Receive */
1500 		connp->conn_bound_if = ifindex;		/* getsockopt */
1501 		mutex_exit(&connp->conn_lock);
1502 		coa->coa_changed |= COA_ROUTE_CHANGED;
1503 		break;
1504 	case IP_UNSPEC_SRC:
1505 		mutex_enter(&connp->conn_lock);
1506 		connp->conn_unspec_src = onoff;
1507 		if (onoff)
1508 			ixa->ixa_flags &= ~IXAF_VERIFY_SOURCE;
1509 		else
1510 			ixa->ixa_flags |= IXAF_VERIFY_SOURCE;
1511 
1512 		mutex_exit(&connp->conn_lock);
1513 		break;
1514 	case IP_BROADCAST_TTL:
1515 		ixa->ixa_broadcast_ttl = *invalp;
1516 		ixa->ixa_flags |= IXAF_BROADCAST_TTL_SET;
1517 		/* Handled automatically by ip_output */
1518 		break;
1519 	case MRT_INIT:
1520 	case MRT_DONE:
1521 	case MRT_ADD_VIF:
1522 	case MRT_DEL_VIF:
1523 	case MRT_ADD_MFC:
1524 	case MRT_DEL_MFC:
1525 	case MRT_ASSERT:
1526 		if ((error = secpolicy_ip_config(cr, B_FALSE)) != 0) {
1527 			return (error);
1528 		}
1529 		error = ip_mrouter_set((int)name, connp, checkonly,
1530 		    (uchar_t *)invalp, inlen);
1531 		if (error) {
1532 			return (error);
1533 		}
1534 		return (0);
1535 	case IP_MINTTL:
1536 		mutex_enter(&connp->conn_lock);
1537 		connp->conn_min_ttl = *i1;
1538 		mutex_exit(&connp->conn_lock);
1539 		break;
1540 	}
1541 	return (0);
1542 }
1543 
1544 /* Handle IPPROTO_IPV6 */
1545 static int
1546 conn_opt_set_ipv6(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen,
1547     uchar_t *invalp, boolean_t checkonly, cred_t *cr)
1548 {
1549 	conn_t		*connp = coa->coa_connp;
1550 	ip_xmit_attr_t	*ixa = coa->coa_ixa;
1551 	ip_pkt_t	*ipp = coa->coa_ipp;
1552 	int		*i1 = (int *)invalp;
1553 	boolean_t	onoff = (*i1 == 0) ? 0 : 1;
1554 	uint_t		ifindex;
1555 	zoneid_t	zoneid = IPCL_ZONEID(connp);
1556 	ip_stack_t	*ipst = connp->conn_netstack->netstack_ip;
1557 	int		error;
1558 
1559 	if (connp->conn_family != AF_INET6)
1560 		return (EINVAL);
1561 
1562 	ifindex = UINT_MAX;
1563 	switch (name) {
1564 	case IPV6_MULTICAST_IF:
1565 		/*
1566 		 * The only possible error is EINVAL.
1567 		 * We call this option on both V4 and V6
1568 		 * If both fail, then this call returns
1569 		 * EINVAL. If at least one of them succeeds we
1570 		 * return success.
1571 		 */
1572 		ifindex = *(uint_t *)i1;
1573 
1574 		if (!ip_xmit_ifindex_valid(ifindex, zoneid, B_TRUE, ipst) &&
1575 		    !ip_xmit_ifindex_valid(ifindex, zoneid, B_FALSE, ipst))
1576 			return (EINVAL);
1577 		break;
1578 	case IPV6_UNICAST_HOPS:
1579 		/* Don't allow zero. -1 means to use default */
1580 		if (*i1 < -1 || *i1 == 0 || *i1 > IPV6_MAX_HOPS)
1581 			return (EINVAL);
1582 		break;
1583 	case IPV6_MULTICAST_HOPS:
1584 		/* -1 means use default */
1585 		if (*i1 < -1 || *i1 > IPV6_MAX_HOPS)
1586 			return (EINVAL);
1587 		break;
1588 	case IPV6_MULTICAST_LOOP:
1589 		if (*i1 != 0 && *i1 != 1)
1590 			return (EINVAL);
1591 		break;
1592 	case IPV6_BOUND_IF:
1593 		ifindex = *(uint_t *)i1;
1594 
1595 		if (!ip_xmit_ifindex_valid(ifindex, zoneid, B_TRUE, ipst))
1596 			return (ENXIO);
1597 		break;
1598 	case IPV6_PKTINFO: {
1599 		struct in6_pktinfo *pkti;
1600 		boolean_t isv6;
1601 
1602 		if (inlen != 0 && inlen != sizeof (struct in6_pktinfo))
1603 			return (EINVAL);
1604 		if (inlen == 0)
1605 			break;	/* Clear values below */
1606 
1607 		/*
1608 		 * Verify the source address and ifindex. Privileged users
1609 		 * can use any source address.
1610 		 */
1611 		pkti = (struct in6_pktinfo *)invalp;
1612 
1613 		/*
1614 		 * For link-local addresses we use the ipi6_ifindex when
1615 		 * we verify the local address.
1616 		 * If net_rawaccess then any source address can be used.
1617 		 */
1618 		if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr) &&
1619 		    secpolicy_net_rawaccess(cr) != 0) {
1620 			uint_t scopeid = 0;
1621 			in6_addr_t *v6src = &pkti->ipi6_addr;
1622 			ipaddr_t v4src;
1623 			ip_laddr_t laddr_type = IPVL_UNICAST_UP;
1624 
1625 			if (IN6_IS_ADDR_V4MAPPED(v6src)) {
1626 				IN6_V4MAPPED_TO_IPADDR(v6src, v4src);
1627 				if (v4src != INADDR_ANY) {
1628 					laddr_type = ip_laddr_verify_v4(v4src,
1629 					    zoneid, ipst, B_FALSE);
1630 				}
1631 			} else {
1632 				if (IN6_IS_ADDR_LINKSCOPE(v6src))
1633 					scopeid = pkti->ipi6_ifindex;
1634 
1635 				laddr_type = ip_laddr_verify_v6(v6src, zoneid,
1636 				    ipst, B_FALSE, scopeid);
1637 			}
1638 			switch (laddr_type) {
1639 			case IPVL_UNICAST_UP:
1640 			case IPVL_UNICAST_DOWN:
1641 				break;
1642 			default:
1643 				return (EADDRNOTAVAIL);
1644 			}
1645 			ixa->ixa_flags |= IXAF_VERIFY_SOURCE;
1646 		} else if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr)) {
1647 			/* Allow any source */
1648 			ixa->ixa_flags &= ~IXAF_VERIFY_SOURCE;
1649 		}
1650 		isv6 = !(IN6_IS_ADDR_V4MAPPED(&pkti->ipi6_addr));
1651 		if (!ip_xmit_ifindex_valid(pkti->ipi6_ifindex, zoneid, isv6,
1652 		    ipst))
1653 			return (ENXIO);
1654 		break;
1655 	}
1656 	case IPV6_HOPLIMIT:
1657 		/* It is only allowed as ancilary data */
1658 		if (!coa->coa_ancillary)
1659 			return (EINVAL);
1660 
1661 		if (inlen != 0 && inlen != sizeof (int))
1662 			return (EINVAL);
1663 		if (inlen == sizeof (int)) {
1664 			if (*i1 > IPV6_MAX_HOPS || *i1 < -1 || *i1 == 0)
1665 				return (EINVAL);
1666 		}
1667 		break;
1668 	case IPV6_TCLASS:
1669 		if (inlen != 0 && inlen != sizeof (int))
1670 			return (EINVAL);
1671 		if (inlen == sizeof (int)) {
1672 			if (*i1 > 255 || *i1 < -1)
1673 				return (EINVAL);
1674 		}
1675 		break;
1676 	case IPV6_NEXTHOP:
1677 		if (inlen != 0 && inlen != sizeof (sin6_t))
1678 			return (EINVAL);
1679 		if (inlen == sizeof (sin6_t)) {
1680 			sin6_t *sin6 = (sin6_t *)invalp;
1681 			ire_t	*ire;
1682 
1683 			if (sin6->sin6_family != AF_INET6)
1684 				return (EAFNOSUPPORT);
1685 			if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
1686 				return (EADDRNOTAVAIL);
1687 
1688 			/* Verify that the next-hop is on-link */
1689 			ire = ire_ftable_lookup_v6(&sin6->sin6_addr,
1690 			    0, 0, IRE_ONLINK, NULL, zoneid,
1691 			    NULL, MATCH_IRE_TYPE, 0, ipst, NULL);
1692 			if (ire == NULL)
1693 				return (EHOSTUNREACH);
1694 			ire_refrele(ire);
1695 			break;
1696 		}
1697 		break;
1698 	case IPV6_RTHDR:
1699 	case IPV6_DSTOPTS:
1700 	case IPV6_RTHDRDSTOPTS:
1701 	case IPV6_HOPOPTS: {
1702 		/* All have the length field in the same place */
1703 		ip6_hbh_t *hopts = (ip6_hbh_t *)invalp;
1704 		/*
1705 		 * Sanity checks - minimum size, size a multiple of
1706 		 * eight bytes, and matching size passed in.
1707 		 */
1708 		if (inlen != 0 &&
1709 		    inlen != (8 * (hopts->ip6h_len + 1)))
1710 			return (EINVAL);
1711 		break;
1712 	}
1713 	case IPV6_PATHMTU:
1714 		/* Can't be set */
1715 		return (EINVAL);
1716 
1717 	case IPV6_USE_MIN_MTU:
1718 		if (inlen != sizeof (int))
1719 			return (EINVAL);
1720 		if (*i1 < -1 || *i1 > 1)
1721 			return (EINVAL);
1722 		break;
1723 	case IPV6_SRC_PREFERENCES:
1724 		if (inlen != sizeof (uint32_t))
1725 			return (EINVAL);
1726 		break;
1727 	case IPV6_V6ONLY:
1728 		if (*i1 < 0 || *i1 > 1) {
1729 			return (EINVAL);
1730 		}
1731 		break;
1732 	case IPV6_MINHOPCOUNT:
1733 		if (*i1 < 0 || *i1 > IPV6_MAX_HOPS)
1734 			return (EINVAL);
1735 		break;
1736 	}
1737 	if (checkonly)
1738 		return (0);
1739 
1740 	/* Here we set the actual option value */
1741 	/*
1742 	 * conn_lock protects the bitfields, and is used to
1743 	 * set the fields atomically. Not needed for ixa settings since
1744 	 * the caller has an exclusive copy of the ixa.
1745 	 * We can not hold conn_lock across the multicast options though.
1746 	 */
1747 	ASSERT(MUTEX_NOT_HELD(&coa->coa_connp->conn_lock));
1748 	switch (name) {
1749 	case IPV6_MULTICAST_IF:
1750 		ixa->ixa_multicast_ifindex = ifindex;
1751 		/* Need to redo ip_attr_connect */
1752 		coa->coa_changed |= COA_ROUTE_CHANGED;
1753 		break;
1754 	case IPV6_UNICAST_HOPS:
1755 		/* -1 means use default */
1756 		mutex_enter(&connp->conn_lock);
1757 		if (*i1 == -1) {
1758 			ipp->ipp_unicast_hops = connp->conn_default_ttl;
1759 		} else {
1760 			ipp->ipp_unicast_hops = (uint8_t)*i1;
1761 		}
1762 		mutex_exit(&connp->conn_lock);
1763 		coa->coa_changed |= COA_HEADER_CHANGED;
1764 		break;
1765 	case IPV6_MULTICAST_HOPS:
1766 		/* -1 means use default */
1767 		if (*i1 == -1) {
1768 			ixa->ixa_multicast_ttl = IP_DEFAULT_MULTICAST_TTL;
1769 		} else {
1770 			ixa->ixa_multicast_ttl = (uint8_t)*i1;
1771 		}
1772 		/* Handled automatically by ip_output */
1773 		break;
1774 	case IPV6_MULTICAST_LOOP:
1775 		if (*i1 != 0)
1776 			ixa->ixa_flags |= IXAF_MULTICAST_LOOP;
1777 		else
1778 			ixa->ixa_flags &= ~IXAF_MULTICAST_LOOP;
1779 		/* Handled automatically by ip_output */
1780 		break;
1781 	case IPV6_JOIN_GROUP:
1782 	case IPV6_LEAVE_GROUP:
1783 	case MCAST_JOIN_GROUP:
1784 	case MCAST_LEAVE_GROUP:
1785 		return (ip_opt_set_multicast_group(connp, name,
1786 		    invalp, B_TRUE, checkonly));
1787 
1788 	case MCAST_BLOCK_SOURCE:
1789 	case MCAST_UNBLOCK_SOURCE:
1790 	case MCAST_JOIN_SOURCE_GROUP:
1791 	case MCAST_LEAVE_SOURCE_GROUP:
1792 		return (ip_opt_set_multicast_sources(connp, name,
1793 		    invalp, B_TRUE, checkonly));
1794 
1795 	case IPV6_BOUND_IF:
1796 		ixa->ixa_ifindex = ifindex;		/* Send */
1797 		mutex_enter(&connp->conn_lock);
1798 		connp->conn_incoming_ifindex = ifindex;	/* Receive */
1799 		connp->conn_bound_if = ifindex;		/* getsockopt */
1800 		mutex_exit(&connp->conn_lock);
1801 		coa->coa_changed |= COA_ROUTE_CHANGED;
1802 		break;
1803 	case IPV6_UNSPEC_SRC:
1804 		mutex_enter(&connp->conn_lock);
1805 		connp->conn_unspec_src = onoff;
1806 		if (onoff)
1807 			ixa->ixa_flags &= ~IXAF_VERIFY_SOURCE;
1808 		else
1809 			ixa->ixa_flags |= IXAF_VERIFY_SOURCE;
1810 		mutex_exit(&connp->conn_lock);
1811 		break;
1812 	case IPV6_RECVPKTINFO:
1813 		mutex_enter(&connp->conn_lock);
1814 		connp->conn_recv_ancillary.crb_ip_recvpktinfo = onoff;
1815 		mutex_exit(&connp->conn_lock);
1816 		break;
1817 	case IPV6_RECVTCLASS:
1818 		mutex_enter(&connp->conn_lock);
1819 		connp->conn_recv_ancillary.crb_ipv6_recvtclass = onoff;
1820 		mutex_exit(&connp->conn_lock);
1821 		break;
1822 	case IPV6_RECVPATHMTU:
1823 		mutex_enter(&connp->conn_lock);
1824 		connp->conn_ipv6_recvpathmtu = onoff;
1825 		mutex_exit(&connp->conn_lock);
1826 		break;
1827 	case IPV6_RECVHOPLIMIT:
1828 		mutex_enter(&connp->conn_lock);
1829 		connp->conn_recv_ancillary.crb_ipv6_recvhoplimit =
1830 		    onoff;
1831 		mutex_exit(&connp->conn_lock);
1832 		break;
1833 	case IPV6_RECVHOPOPTS:
1834 		mutex_enter(&connp->conn_lock);
1835 		connp->conn_recv_ancillary.crb_ipv6_recvhopopts = onoff;
1836 		mutex_exit(&connp->conn_lock);
1837 		break;
1838 	case IPV6_RECVDSTOPTS:
1839 		mutex_enter(&connp->conn_lock);
1840 		connp->conn_recv_ancillary.crb_ipv6_recvdstopts = onoff;
1841 		mutex_exit(&connp->conn_lock);
1842 		break;
1843 	case _OLD_IPV6_RECVDSTOPTS:
1844 		mutex_enter(&connp->conn_lock);
1845 		connp->conn_recv_ancillary.crb_old_ipv6_recvdstopts =
1846 		    onoff;
1847 		mutex_exit(&connp->conn_lock);
1848 		break;
1849 	case IPV6_RECVRTHDRDSTOPTS:
1850 		mutex_enter(&connp->conn_lock);
1851 		connp->conn_recv_ancillary.crb_ipv6_recvrthdrdstopts =
1852 		    onoff;
1853 		mutex_exit(&connp->conn_lock);
1854 		break;
1855 	case IPV6_RECVRTHDR:
1856 		mutex_enter(&connp->conn_lock);
1857 		connp->conn_recv_ancillary.crb_ipv6_recvrthdr = onoff;
1858 		mutex_exit(&connp->conn_lock);
1859 		break;
1860 	case IPV6_PKTINFO:
1861 		mutex_enter(&connp->conn_lock);
1862 		if (inlen == 0) {
1863 			ipp->ipp_fields &= ~IPPF_ADDR;
1864 			ipp->ipp_addr = ipv6_all_zeros;
1865 			ixa->ixa_ifindex = 0;
1866 		} else {
1867 			struct in6_pktinfo *pkti;
1868 
1869 			pkti = (struct in6_pktinfo *)invalp;
1870 			ipp->ipp_addr = pkti->ipi6_addr;
1871 			if (!IN6_IS_ADDR_UNSPECIFIED(&ipp->ipp_addr))
1872 				ipp->ipp_fields |= IPPF_ADDR;
1873 			else
1874 				ipp->ipp_fields &= ~IPPF_ADDR;
1875 			ixa->ixa_ifindex = pkti->ipi6_ifindex;
1876 		}
1877 		mutex_exit(&connp->conn_lock);
1878 		/* Source and ifindex might have changed */
1879 		coa->coa_changed |= COA_HEADER_CHANGED;
1880 		coa->coa_changed |= COA_ROUTE_CHANGED;
1881 		break;
1882 	case IPV6_HOPLIMIT:
1883 		mutex_enter(&connp->conn_lock);
1884 		if (inlen == 0 || *i1 == -1) {
1885 			/* Revert to default */
1886 			ipp->ipp_fields &= ~IPPF_HOPLIMIT;
1887 			ixa->ixa_flags &= ~IXAF_NO_TTL_CHANGE;
1888 		} else {
1889 			ipp->ipp_hoplimit = *i1;
1890 			ipp->ipp_fields |= IPPF_HOPLIMIT;
1891 			/* Ensure that it sticks for multicast packets */
1892 			ixa->ixa_flags |= IXAF_NO_TTL_CHANGE;
1893 		}
1894 		mutex_exit(&connp->conn_lock);
1895 		coa->coa_changed |= COA_HEADER_CHANGED;
1896 		break;
1897 	case IPV6_TCLASS:
1898 		/*
1899 		 * IPV6_TCLASS accepts -1 as use kernel default
1900 		 * and [0, 255] as the actualy traffic class.
1901 		 */
1902 		mutex_enter(&connp->conn_lock);
1903 		if (inlen == 0 || *i1 == -1) {
1904 			ipp->ipp_tclass = 0;
1905 			ipp->ipp_fields &= ~IPPF_TCLASS;
1906 		} else {
1907 			ipp->ipp_tclass = *i1;
1908 			ipp->ipp_fields |= IPPF_TCLASS;
1909 		}
1910 		mutex_exit(&connp->conn_lock);
1911 		coa->coa_changed |= COA_HEADER_CHANGED;
1912 		break;
1913 	case IPV6_NEXTHOP:
1914 		if (inlen == 0) {
1915 			ixa->ixa_flags &= ~IXAF_NEXTHOP_SET;
1916 		} else {
1917 			sin6_t *sin6 = (sin6_t *)invalp;
1918 
1919 			ixa->ixa_nexthop_v6 = sin6->sin6_addr;
1920 			if (!IN6_IS_ADDR_UNSPECIFIED(&ixa->ixa_nexthop_v6))
1921 				ixa->ixa_flags |= IXAF_NEXTHOP_SET;
1922 			else
1923 				ixa->ixa_flags &= ~IXAF_NEXTHOP_SET;
1924 		}
1925 		coa->coa_changed |= COA_ROUTE_CHANGED;
1926 		break;
1927 	case IPV6_HOPOPTS:
1928 		mutex_enter(&connp->conn_lock);
1929 		error = optcom_pkt_set(invalp, inlen,
1930 		    (uchar_t **)&ipp->ipp_hopopts, &ipp->ipp_hopoptslen);
1931 		if (error != 0) {
1932 			mutex_exit(&connp->conn_lock);
1933 			return (error);
1934 		}
1935 		if (ipp->ipp_hopoptslen == 0) {
1936 			ipp->ipp_fields &= ~IPPF_HOPOPTS;
1937 		} else {
1938 			ipp->ipp_fields |= IPPF_HOPOPTS;
1939 		}
1940 		mutex_exit(&connp->conn_lock);
1941 		coa->coa_changed |= COA_HEADER_CHANGED;
1942 		coa->coa_changed |= COA_WROFF_CHANGED;
1943 		break;
1944 	case IPV6_RTHDRDSTOPTS:
1945 		mutex_enter(&connp->conn_lock);
1946 		error = optcom_pkt_set(invalp, inlen,
1947 		    (uchar_t **)&ipp->ipp_rthdrdstopts,
1948 		    &ipp->ipp_rthdrdstoptslen);
1949 		if (error != 0) {
1950 			mutex_exit(&connp->conn_lock);
1951 			return (error);
1952 		}
1953 		if (ipp->ipp_rthdrdstoptslen == 0) {
1954 			ipp->ipp_fields &= ~IPPF_RTHDRDSTOPTS;
1955 		} else {
1956 			ipp->ipp_fields |= IPPF_RTHDRDSTOPTS;
1957 		}
1958 		mutex_exit(&connp->conn_lock);
1959 		coa->coa_changed |= COA_HEADER_CHANGED;
1960 		coa->coa_changed |= COA_WROFF_CHANGED;
1961 		break;
1962 	case IPV6_DSTOPTS:
1963 		mutex_enter(&connp->conn_lock);
1964 		error = optcom_pkt_set(invalp, inlen,
1965 		    (uchar_t **)&ipp->ipp_dstopts, &ipp->ipp_dstoptslen);
1966 		if (error != 0) {
1967 			mutex_exit(&connp->conn_lock);
1968 			return (error);
1969 		}
1970 		if (ipp->ipp_dstoptslen == 0) {
1971 			ipp->ipp_fields &= ~IPPF_DSTOPTS;
1972 		} else {
1973 			ipp->ipp_fields |= IPPF_DSTOPTS;
1974 		}
1975 		mutex_exit(&connp->conn_lock);
1976 		coa->coa_changed |= COA_HEADER_CHANGED;
1977 		coa->coa_changed |= COA_WROFF_CHANGED;
1978 		break;
1979 	case IPV6_RTHDR:
1980 		mutex_enter(&connp->conn_lock);
1981 		error = optcom_pkt_set(invalp, inlen,
1982 		    (uchar_t **)&ipp->ipp_rthdr, &ipp->ipp_rthdrlen);
1983 		if (error != 0) {
1984 			mutex_exit(&connp->conn_lock);
1985 			return (error);
1986 		}
1987 		if (ipp->ipp_rthdrlen == 0) {
1988 			ipp->ipp_fields &= ~IPPF_RTHDR;
1989 		} else {
1990 			ipp->ipp_fields |= IPPF_RTHDR;
1991 		}
1992 		mutex_exit(&connp->conn_lock);
1993 		coa->coa_changed |= COA_HEADER_CHANGED;
1994 		coa->coa_changed |= COA_WROFF_CHANGED;
1995 		break;
1996 
1997 	case IPV6_DONTFRAG:
1998 		if (onoff) {
1999 			ixa->ixa_flags |= IXAF_DONTFRAG;
2000 			ixa->ixa_flags &= ~IXAF_PMTU_DISCOVERY;
2001 		} else {
2002 			ixa->ixa_flags &= ~IXAF_DONTFRAG;
2003 			ixa->ixa_flags |= IXAF_PMTU_DISCOVERY;
2004 		}
2005 		/* Need to redo ip_attr_connect */
2006 		coa->coa_changed |= COA_ROUTE_CHANGED;
2007 		break;
2008 
2009 	case IPV6_USE_MIN_MTU:
2010 		ixa->ixa_flags |= IXAF_USE_MIN_MTU;
2011 		ixa->ixa_use_min_mtu = *i1;
2012 		/* Need to redo ip_attr_connect */
2013 		coa->coa_changed |= COA_ROUTE_CHANGED;
2014 		break;
2015 
2016 	case IPV6_SEC_OPT:
2017 		mutex_enter(&connp->conn_lock);
2018 		error = ipsec_set_req(cr, connp, (ipsec_req_t *)invalp);
2019 		mutex_exit(&connp->conn_lock);
2020 		if (error != 0) {
2021 			return (error);
2022 		}
2023 		/* This is an IPsec policy change - redo ip_attr_connect */
2024 		coa->coa_changed |= COA_ROUTE_CHANGED;
2025 		break;
2026 	case IPV6_SRC_PREFERENCES:
2027 		/*
2028 		 * This socket option only affects connected
2029 		 * sockets that haven't already bound to a specific
2030 		 * IPv6 address.  In other words, sockets that
2031 		 * don't call bind() with an address other than the
2032 		 * unspecified address and that call connect().
2033 		 * ip_set_destination_v6() passes these preferences
2034 		 * to the ipif_select_source_v6() function.
2035 		 */
2036 		mutex_enter(&connp->conn_lock);
2037 		error = ip6_set_src_preferences(ixa, *(uint32_t *)invalp);
2038 		mutex_exit(&connp->conn_lock);
2039 		if (error != 0) {
2040 			return (error);
2041 		}
2042 		break;
2043 	case IPV6_V6ONLY:
2044 		mutex_enter(&connp->conn_lock);
2045 		connp->conn_ipv6_v6only = onoff;
2046 		mutex_exit(&connp->conn_lock);
2047 		break;
2048 	case IPV6_MINHOPCOUNT:
2049 		mutex_enter(&connp->conn_lock);
2050 		connp->conn_min_ttl = *i1;
2051 		mutex_exit(&connp->conn_lock);
2052 		break;
2053 	}
2054 	return (0);
2055 }
2056 
2057 /* Handle IPPROTO_UDP */
2058 /* ARGSUSED1 */
2059 static int
2060 conn_opt_set_udp(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen,
2061     uchar_t *invalp, boolean_t checkonly, cred_t *cr)
2062 {
2063 	conn_t		*connp = coa->coa_connp;
2064 	int		*i1 = (int *)invalp;
2065 	boolean_t	onoff = (*i1 == 0) ? 0 : 1;
2066 	int		error;
2067 
2068 	switch (name) {
2069 	case UDP_ANONPRIVBIND:
2070 		if ((error = secpolicy_net_privaddr(cr, 0, IPPROTO_UDP)) != 0) {
2071 			return (error);
2072 		}
2073 		break;
2074 	}
2075 	if (checkonly)
2076 		return (0);
2077 
2078 	/* Here we set the actual option value */
2079 	mutex_enter(&connp->conn_lock);
2080 	switch (name) {
2081 	case UDP_ANONPRIVBIND:
2082 		connp->conn_anon_priv_bind = onoff;
2083 		break;
2084 	case UDP_EXCLBIND:
2085 		connp->conn_exclbind = onoff;
2086 		break;
2087 	}
2088 	mutex_exit(&connp->conn_lock);
2089 	return (0);
2090 }
2091 
2092 /* Handle IPPROTO_TCP */
2093 /* ARGSUSED1 */
2094 static int
2095 conn_opt_set_tcp(conn_opt_arg_t *coa, t_scalar_t name, uint_t inlen,
2096     uchar_t *invalp, boolean_t checkonly, cred_t *cr)
2097 {
2098 	conn_t		*connp = coa->coa_connp;
2099 	int		*i1 = (int *)invalp;
2100 	boolean_t	onoff = (*i1 == 0) ? 0 : 1;
2101 	int		error;
2102 
2103 	switch (name) {
2104 	case TCP_ANONPRIVBIND:
2105 		if ((error = secpolicy_net_privaddr(cr, 0, IPPROTO_TCP)) != 0) {
2106 			return (error);
2107 		}
2108 		break;
2109 	}
2110 	if (checkonly)
2111 		return (0);
2112 
2113 	/* Here we set the actual option value */
2114 	mutex_enter(&connp->conn_lock);
2115 	switch (name) {
2116 	case TCP_ANONPRIVBIND:
2117 		connp->conn_anon_priv_bind = onoff;
2118 		break;
2119 	case TCP_EXCLBIND:
2120 		connp->conn_exclbind = onoff;
2121 		break;
2122 	case TCP_RECVDSTADDR:
2123 		connp->conn_recv_ancillary.crb_recvdstaddr = onoff;
2124 		break;
2125 	}
2126 	mutex_exit(&connp->conn_lock);
2127 	return (0);
2128 }
2129 
2130 int
2131 conn_getsockname(conn_t *connp, struct sockaddr *sa, uint_t *salenp)
2132 {
2133 	sin_t		*sin;
2134 	sin6_t		*sin6;
2135 
2136 	if (connp->conn_family == AF_INET) {
2137 		if (*salenp < sizeof (sin_t))
2138 			return (EINVAL);
2139 
2140 		*salenp = sizeof (sin_t);
2141 		/* Fill zeroes and then initialize non-zero fields */
2142 		sin = (sin_t *)sa;
2143 		*sin = sin_null;
2144 		sin->sin_family = AF_INET;
2145 		if (!IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_saddr_v6) &&
2146 		    !IN6_IS_ADDR_UNSPECIFIED(&connp->conn_saddr_v6)) {
2147 			sin->sin_addr.s_addr = connp->conn_saddr_v4;
2148 		} else {
2149 			/*
2150 			 * INADDR_ANY
2151 			 * conn_saddr is not set, we might be bound to
2152 			 * broadcast/multicast. Use conn_bound_addr as
2153 			 * local address instead (that could
2154 			 * also still be INADDR_ANY)
2155 			 */
2156 			sin->sin_addr.s_addr = connp->conn_bound_addr_v4;
2157 		}
2158 		sin->sin_port = connp->conn_lport;
2159 	} else {
2160 		if (*salenp < sizeof (sin6_t))
2161 			return (EINVAL);
2162 
2163 		*salenp = sizeof (sin6_t);
2164 		/* Fill zeroes and then initialize non-zero fields */
2165 		sin6 = (sin6_t *)sa;
2166 		*sin6 = sin6_null;
2167 		sin6->sin6_family = AF_INET6;
2168 		if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_saddr_v6)) {
2169 			sin6->sin6_addr = connp->conn_saddr_v6;
2170 		} else {
2171 			/*
2172 			 * conn_saddr is not set, we might be bound to
2173 			 * broadcast/multicast. Use conn_bound_addr as
2174 			 * local address instead (which could
2175 			 * also still be unspecified)
2176 			 */
2177 			sin6->sin6_addr = connp->conn_bound_addr_v6;
2178 		}
2179 		sin6->sin6_port = connp->conn_lport;
2180 		if (IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr) &&
2181 		    (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET))
2182 			sin6->sin6_scope_id = connp->conn_ixa->ixa_scopeid;
2183 	}
2184 	return (0);
2185 }
2186 
2187 int
2188 conn_getpeername(conn_t *connp, struct sockaddr *sa, uint_t *salenp)
2189 {
2190 	struct sockaddr_in	*sin;
2191 	struct sockaddr_in6	*sin6;
2192 
2193 	if (connp->conn_family == AF_INET) {
2194 		if (*salenp < sizeof (sin_t))
2195 			return (EINVAL);
2196 
2197 		*salenp = sizeof (sin_t);
2198 		/* initialize */
2199 		sin = (sin_t *)sa;
2200 		*sin = sin_null;
2201 		sin->sin_family = AF_INET;
2202 		sin->sin_addr.s_addr = connp->conn_faddr_v4;
2203 		sin->sin_port = connp->conn_fport;
2204 	} else {
2205 		if (*salenp < sizeof (sin6_t))
2206 			return (EINVAL);
2207 
2208 		*salenp = sizeof (sin6_t);
2209 		/* initialize */
2210 		sin6 = (sin6_t *)sa;
2211 		*sin6 = sin6_null;
2212 		sin6->sin6_family = AF_INET6;
2213 		sin6->sin6_addr = connp->conn_faddr_v6;
2214 		sin6->sin6_port =  connp->conn_fport;
2215 		sin6->sin6_flowinfo = connp->conn_flowinfo;
2216 		if (IN6_IS_ADDR_LINKSCOPE(&sin6->sin6_addr) &&
2217 		    (connp->conn_ixa->ixa_flags & IXAF_SCOPEID_SET))
2218 			sin6->sin6_scope_id = connp->conn_ixa->ixa_scopeid;
2219 	}
2220 	return (0);
2221 }
2222 
2223 static uint32_t	cksum_massage_options_v4(ipha_t *, netstack_t *);
2224 static uint32_t cksum_massage_options_v6(ip6_t *, uint_t, netstack_t *);
2225 
2226 /*
2227  * Allocate and fill in conn_ht_iphc based on the current information
2228  * in the conn.
2229  * Normally used when we bind() and connect().
2230  * Returns failure if can't allocate memory, or if there is a problem
2231  * with a routing header/option.
2232  *
2233  * We allocate space for the transport header (ulp_hdr_len + extra) and
2234  * indicate the offset of the ulp header by setting ixa_ip_hdr_length.
2235  * The extra is there for transports that want some spare room for future
2236  * options. conn_ht_iphc_allocated is what was allocated; conn_ht_iphc_len
2237  * excludes the extra part.
2238  *
2239  * We massage an routing option/header and store the ckecksum difference
2240  * in conn_sum.
2241  *
2242  * Caller needs to update conn_wroff if desired.
2243  */
2244 int
2245 conn_build_hdr_template(conn_t *connp, uint_t ulp_hdr_length, uint_t extra,
2246     const in6_addr_t *v6src, const in6_addr_t *v6dst, uint32_t flowinfo)
2247 {
2248 	ip_xmit_attr_t	*ixa = connp->conn_ixa;
2249 	ip_pkt_t	*ipp = &connp->conn_xmit_ipp;
2250 	uint_t		ip_hdr_length;
2251 	uchar_t		*hdrs;
2252 	uint_t		hdrs_len;
2253 
2254 	ASSERT(MUTEX_HELD(&connp->conn_lock));
2255 
2256 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2257 		ip_hdr_length = ip_total_hdrs_len_v4(ipp);
2258 		/* In case of TX label and IP options it can be too much */
2259 		if (ip_hdr_length > IP_MAX_HDR_LENGTH) {
2260 			/* Preserves existing TX errno for this */
2261 			return (EHOSTUNREACH);
2262 		}
2263 	} else {
2264 		ip_hdr_length = ip_total_hdrs_len_v6(ipp);
2265 	}
2266 	ixa->ixa_ip_hdr_length = ip_hdr_length;
2267 	hdrs_len = ip_hdr_length + ulp_hdr_length + extra;
2268 	ASSERT(hdrs_len != 0);
2269 
2270 	if (hdrs_len != connp->conn_ht_iphc_allocated) {
2271 		/* Allocate new before we free any old */
2272 		hdrs = kmem_alloc(hdrs_len, KM_NOSLEEP);
2273 		if (hdrs == NULL)
2274 			return (ENOMEM);
2275 
2276 		if (connp->conn_ht_iphc != NULL) {
2277 			kmem_free(connp->conn_ht_iphc,
2278 			    connp->conn_ht_iphc_allocated);
2279 		}
2280 		connp->conn_ht_iphc = hdrs;
2281 		connp->conn_ht_iphc_allocated = hdrs_len;
2282 	} else {
2283 		hdrs = connp->conn_ht_iphc;
2284 	}
2285 	hdrs_len -= extra;
2286 	connp->conn_ht_iphc_len = hdrs_len;
2287 
2288 	connp->conn_ht_ulp = hdrs + ip_hdr_length;
2289 	connp->conn_ht_ulp_len = ulp_hdr_length;
2290 
2291 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2292 		ipha_t	*ipha = (ipha_t *)hdrs;
2293 
2294 		IN6_V4MAPPED_TO_IPADDR(v6src, ipha->ipha_src);
2295 		IN6_V4MAPPED_TO_IPADDR(v6dst, ipha->ipha_dst);
2296 		ip_build_hdrs_v4(hdrs, ip_hdr_length, ipp, connp->conn_proto);
2297 		ipha->ipha_length = htons(hdrs_len);
2298 		if (ixa->ixa_flags & IXAF_PMTU_IPV4_DF)
2299 			ipha->ipha_fragment_offset_and_flags |= IPH_DF_HTONS;
2300 		else
2301 			ipha->ipha_fragment_offset_and_flags &= ~IPH_DF_HTONS;
2302 
2303 		if (ipp->ipp_fields & IPPF_IPV4_OPTIONS) {
2304 			connp->conn_sum = cksum_massage_options_v4(ipha,
2305 			    connp->conn_netstack);
2306 		} else {
2307 			connp->conn_sum = 0;
2308 		}
2309 	} else {
2310 		ip6_t	*ip6h = (ip6_t *)hdrs;
2311 
2312 		ip6h->ip6_src = *v6src;
2313 		ip6h->ip6_dst = *v6dst;
2314 		ip_build_hdrs_v6(hdrs, ip_hdr_length, ipp, connp->conn_proto,
2315 		    flowinfo);
2316 		ip6h->ip6_plen = htons(hdrs_len - IPV6_HDR_LEN);
2317 
2318 		if (ipp->ipp_fields & IPPF_RTHDR) {
2319 			connp->conn_sum = cksum_massage_options_v6(ip6h,
2320 			    ip_hdr_length, connp->conn_netstack);
2321 
2322 			/*
2323 			 * Verify that the first hop isn't a mapped address.
2324 			 * Routers along the path need to do this verification
2325 			 * for subsequent hops.
2326 			 */
2327 			if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst))
2328 				return (EADDRNOTAVAIL);
2329 
2330 		} else {
2331 			connp->conn_sum = 0;
2332 		}
2333 	}
2334 	return (0);
2335 }
2336 
2337 /*
2338  * Prepend a header template to data_mp based on the ip_pkt_t
2339  * and the passed in source, destination and protocol.
2340  *
2341  * Returns failure if can't allocate memory, in which case data_mp is freed.
2342  * We allocate space for the transport header (ulp_hdr_len) and
2343  * indicate the offset of the ulp header by setting ixa_ip_hdr_length.
2344  *
2345  * We massage an routing option/header and return the ckecksum difference
2346  * in *sump. This is in host byte order.
2347  *
2348  * Caller needs to update conn_wroff if desired.
2349  */
2350 mblk_t *
2351 conn_prepend_hdr(ip_xmit_attr_t *ixa, const ip_pkt_t *ipp,
2352     const in6_addr_t *v6src, const in6_addr_t *v6dst,
2353     uint8_t protocol, uint32_t flowinfo, uint_t ulp_hdr_length, mblk_t *data_mp,
2354     uint_t data_length, uint_t wroff_extra, uint32_t *sump, int *errorp)
2355 {
2356 	uint_t		ip_hdr_length;
2357 	uchar_t		*hdrs;
2358 	uint_t		hdrs_len;
2359 	mblk_t		*mp;
2360 
2361 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2362 		ip_hdr_length = ip_total_hdrs_len_v4(ipp);
2363 		ASSERT(ip_hdr_length <= IP_MAX_HDR_LENGTH);
2364 	} else {
2365 		ip_hdr_length = ip_total_hdrs_len_v6(ipp);
2366 	}
2367 	hdrs_len = ip_hdr_length + ulp_hdr_length;
2368 	ASSERT(hdrs_len != 0);
2369 
2370 	ixa->ixa_ip_hdr_length = ip_hdr_length;
2371 
2372 	/* Can we prepend to data_mp? */
2373 	if (data_mp != NULL &&
2374 	    data_mp->b_rptr - data_mp->b_datap->db_base >= hdrs_len &&
2375 	    data_mp->b_datap->db_ref == 1) {
2376 		hdrs = data_mp->b_rptr - hdrs_len;
2377 		data_mp->b_rptr = hdrs;
2378 		mp = data_mp;
2379 	} else {
2380 		mp = allocb(hdrs_len + wroff_extra, BPRI_MED);
2381 		if (mp == NULL) {
2382 			freemsg(data_mp);
2383 			*errorp = ENOMEM;
2384 			return (NULL);
2385 		}
2386 		mp->b_wptr = mp->b_datap->db_lim;
2387 		hdrs = mp->b_rptr = mp->b_wptr - hdrs_len;
2388 		mp->b_cont = data_mp;
2389 	}
2390 
2391 	/*
2392 	 * Set the source in the header. ip_build_hdrs_v4/v6 will overwrite it
2393 	 * if PKTINFO (aka IPPF_ADDR) was set.
2394 	 */
2395 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2396 		ipha_t *ipha = (ipha_t *)hdrs;
2397 
2398 		ASSERT(IN6_IS_ADDR_V4MAPPED(v6dst));
2399 		IN6_V4MAPPED_TO_IPADDR(v6src, ipha->ipha_src);
2400 		IN6_V4MAPPED_TO_IPADDR(v6dst, ipha->ipha_dst);
2401 		ip_build_hdrs_v4(hdrs, ip_hdr_length, ipp, protocol);
2402 		ipha->ipha_length = htons(hdrs_len + data_length);
2403 		if (ixa->ixa_flags & IXAF_PMTU_IPV4_DF)
2404 			ipha->ipha_fragment_offset_and_flags |= IPH_DF_HTONS;
2405 		else
2406 			ipha->ipha_fragment_offset_and_flags &= ~IPH_DF_HTONS;
2407 
2408 		if (ipp->ipp_fields & IPPF_IPV4_OPTIONS) {
2409 			*sump = cksum_massage_options_v4(ipha,
2410 			    ixa->ixa_ipst->ips_netstack);
2411 		} else {
2412 			*sump = 0;
2413 		}
2414 	} else {
2415 		ip6_t *ip6h = (ip6_t *)hdrs;
2416 
2417 		ip6h->ip6_src = *v6src;
2418 		ip6h->ip6_dst = *v6dst;
2419 		ip_build_hdrs_v6(hdrs, ip_hdr_length, ipp, protocol, flowinfo);
2420 		ip6h->ip6_plen = htons(hdrs_len + data_length - IPV6_HDR_LEN);
2421 
2422 		if (ipp->ipp_fields & IPPF_RTHDR) {
2423 			*sump = cksum_massage_options_v6(ip6h,
2424 			    ip_hdr_length, ixa->ixa_ipst->ips_netstack);
2425 
2426 			/*
2427 			 * Verify that the first hop isn't a mapped address.
2428 			 * Routers along the path need to do this verification
2429 			 * for subsequent hops.
2430 			 */
2431 			if (IN6_IS_ADDR_V4MAPPED(&ip6h->ip6_dst)) {
2432 				*errorp = EADDRNOTAVAIL;
2433 				freemsg(mp);
2434 				return (NULL);
2435 			}
2436 		} else {
2437 			*sump = 0;
2438 		}
2439 	}
2440 	return (mp);
2441 }
2442 
2443 /*
2444  * Massage a source route if any putting the first hop
2445  * in ipha_dst. Compute a starting value for the checksum which
2446  * takes into account that the original ipha_dst should be
2447  * included in the checksum but that IP will include the
2448  * first hop from the source route in the tcp checksum.
2449  */
2450 static uint32_t
2451 cksum_massage_options_v4(ipha_t *ipha, netstack_t *ns)
2452 {
2453 	in_addr_t	dst;
2454 	uint32_t	cksum;
2455 
2456 	/* Get last hop then diff against first hop */
2457 	cksum = ip_massage_options(ipha, ns);
2458 	cksum = (cksum & 0xFFFF) + (cksum >> 16);
2459 	dst = ipha->ipha_dst;
2460 	cksum -= ((dst >> 16) + (dst & 0xffff));
2461 	if ((int)cksum < 0)
2462 		cksum--;
2463 	cksum = (cksum & 0xFFFF) + (cksum >> 16);
2464 	cksum = (cksum & 0xFFFF) + (cksum >> 16);
2465 	ASSERT(cksum < 0x10000);
2466 	return (ntohs(cksum));
2467 }
2468 
2469 static uint32_t
2470 cksum_massage_options_v6(ip6_t *ip6h, uint_t ip_hdr_len, netstack_t *ns)
2471 {
2472 	uint8_t		*end;
2473 	ip6_rthdr_t	*rth;
2474 	uint32_t	cksum;
2475 
2476 	end = (uint8_t *)ip6h + ip_hdr_len;
2477 	rth = ip_find_rthdr_v6(ip6h, end);
2478 	if (rth == NULL)
2479 		return (0);
2480 
2481 	cksum = ip_massage_options_v6(ip6h, rth, ns);
2482 	cksum = (cksum & 0xFFFF) + (cksum >> 16);
2483 	ASSERT(cksum < 0x10000);
2484 	return (ntohs(cksum));
2485 }
2486 
2487 /*
2488  * ULPs that change the destination address need to call this for each
2489  * change to discard any state about a previous destination that might
2490  * have been multicast or multirt.
2491  */
2492 void
2493 ip_attr_newdst(ip_xmit_attr_t *ixa)
2494 {
2495 	ixa->ixa_flags &= ~(IXAF_LOOPBACK_COPY | IXAF_NO_HW_CKSUM |
2496 	    IXAF_NO_TTL_CHANGE | IXAF_IPV6_ADD_FRAGHDR |
2497 	    IXAF_NO_LOOP_ZONEID_SET);
2498 }
2499 
2500 /*
2501  * Determine the nexthop which will be used.
2502  * Normally this is just the destination, but if a IPv4 source route, or
2503  * IPv6 routing header, is in the ip_pkt_t then we extract the nexthop from
2504  * there.
2505  */
2506 void
2507 ip_attr_nexthop(const ip_pkt_t *ipp, const ip_xmit_attr_t *ixa,
2508     const in6_addr_t *dst, in6_addr_t *nexthop)
2509 {
2510 	if (!(ipp->ipp_fields & (IPPF_IPV4_OPTIONS|IPPF_RTHDR))) {
2511 		*nexthop = *dst;
2512 		return;
2513 	}
2514 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2515 		ipaddr_t v4dst;
2516 		ipaddr_t v4nexthop;
2517 
2518 		IN6_V4MAPPED_TO_IPADDR(dst, v4dst);
2519 		v4nexthop = ip_pkt_source_route_v4(ipp);
2520 		if (v4nexthop == INADDR_ANY)
2521 			v4nexthop = v4dst;
2522 
2523 		IN6_IPADDR_TO_V4MAPPED(v4nexthop, nexthop);
2524 	} else {
2525 		const in6_addr_t *v6nexthop;
2526 
2527 		v6nexthop = ip_pkt_source_route_v6(ipp);
2528 		if (v6nexthop == NULL)
2529 			v6nexthop = dst;
2530 
2531 		*nexthop = *v6nexthop;
2532 	}
2533 }
2534 
2535 /*
2536  * Update the ip_xmit_attr_t based the addresses, conn_xmit_ipp and conn_ixa.
2537  * If IPDF_IPSEC is set we cache the IPsec policy to handle the unconnected
2538  * case (connected latching is done in conn_connect).
2539  * Note that IPsec policy lookup requires conn_proto and conn_laddr to be
2540  * set, but doesn't otherwise use the conn_t.
2541  *
2542  * Caller must set/clear IXAF_IS_IPV4 as appropriately.
2543  * Caller must use ip_attr_nexthop() to determine the nexthop argument.
2544  *
2545  * The caller must NOT hold conn_lock (to avoid problems with ill_refrele
2546  * causing the squeue to run doing ipcl_walk grabbing conn_lock.)
2547  *
2548  * Updates laddrp and uinfo if they are non-NULL.
2549  *
2550  * TSOL notes: The callers if ip_attr_connect must check if the destination
2551  * is different than before and in that case redo conn_update_label.
2552  * The callers of conn_connect do not need that since conn_connect
2553  * performs the conn_update_label.
2554  */
2555 int
2556 ip_attr_connect(const conn_t *connp, ip_xmit_attr_t *ixa,
2557     const in6_addr_t *v6src, const in6_addr_t *v6dst,
2558     const in6_addr_t *v6nexthop, in_port_t dstport, in6_addr_t *laddrp,
2559     iulp_t *uinfo, uint32_t flags)
2560 {
2561 	in6_addr_t		laddr = *v6src;
2562 	int			error;
2563 
2564 	ASSERT(MUTEX_NOT_HELD(&connp->conn_lock));
2565 
2566 	if (connp->conn_zone_is_global)
2567 		flags |= IPDF_ZONE_IS_GLOBAL;
2568 	else
2569 		flags &= ~IPDF_ZONE_IS_GLOBAL;
2570 
2571 	/*
2572 	 * Lookup the route to determine a source address and the uinfo.
2573 	 * If the ULP has a source route option then the caller will
2574 	 * have set v6nexthop to be the first hop.
2575 	 */
2576 	if (ixa->ixa_flags & IXAF_IS_IPV4) {
2577 		ipaddr_t v4dst;
2578 		ipaddr_t v4src, v4nexthop;
2579 
2580 		IN6_V4MAPPED_TO_IPADDR(v6dst, v4dst);
2581 		IN6_V4MAPPED_TO_IPADDR(v6nexthop, v4nexthop);
2582 		IN6_V4MAPPED_TO_IPADDR(v6src, v4src);
2583 
2584 		if (connp->conn_unspec_src || v4src != INADDR_ANY)
2585 			flags &= ~IPDF_SELECT_SRC;
2586 		else
2587 			flags |= IPDF_SELECT_SRC;
2588 
2589 		error = ip_set_destination_v4(&v4src, v4dst, v4nexthop, ixa,
2590 		    uinfo, flags, connp->conn_mac_mode);
2591 		IN6_IPADDR_TO_V4MAPPED(v4src, &laddr);
2592 	} else {
2593 		if (connp->conn_unspec_src || !IN6_IS_ADDR_UNSPECIFIED(v6src))
2594 			flags &= ~IPDF_SELECT_SRC;
2595 		else
2596 			flags |= IPDF_SELECT_SRC;
2597 
2598 		error = ip_set_destination_v6(&laddr, v6dst, v6nexthop, ixa,
2599 		    uinfo, flags, connp->conn_mac_mode);
2600 	}
2601 	/* Pass out some address even if we hit a RTF_REJECT etc */
2602 	if (laddrp != NULL)
2603 		*laddrp = laddr;
2604 
2605 	if (error != 0)
2606 		return (error);
2607 
2608 	if (flags & IPDF_IPSEC) {
2609 		/*
2610 		 * Set any IPsec policy in ixa. Routine also looks at ULP
2611 		 * ports.
2612 		 */
2613 		ipsec_cache_outbound_policy(connp, v6src, v6dst, dstport, ixa);
2614 	}
2615 	return (0);
2616 }
2617 
2618 /*
2619  * Connect the conn based on the addresses, conn_xmit_ipp and conn_ixa.
2620  * Assumes that conn_faddr and conn_fport are already set. As such it is not
2621  * usable for SCTP, since SCTP has multiple faddrs.
2622  *
2623  * Caller must hold conn_lock to provide atomic constency between the
2624  * conn_t's addresses and the ixa.
2625  * NOTE: this function drops and reaquires conn_lock since it can't be
2626  * held across ip_attr_connect/ip_set_destination.
2627  *
2628  * The caller needs to handle inserting in the receive-side fanout when
2629  * appropriate after conn_connect returns.
2630  */
2631 int
2632 conn_connect(conn_t *connp, iulp_t *uinfo, uint32_t flags)
2633 {
2634 	ip_xmit_attr_t	*ixa = connp->conn_ixa;
2635 	in6_addr_t	nexthop;
2636 	in6_addr_t	saddr, faddr;
2637 	in_port_t	fport;
2638 	int		error;
2639 
2640 	ASSERT(MUTEX_HELD(&connp->conn_lock));
2641 
2642 	if (connp->conn_ipversion == IPV4_VERSION)
2643 		ixa->ixa_flags |= IXAF_IS_IPV4;
2644 	else
2645 		ixa->ixa_flags &= ~IXAF_IS_IPV4;
2646 
2647 	/* We do IPsec latching below - hence no caching in ip_attr_connect */
2648 	flags &= ~IPDF_IPSEC;
2649 
2650 	/* In case we had previously done an ip_attr_connect */
2651 	ip_attr_newdst(ixa);
2652 
2653 	/*
2654 	 * Determine the nexthop and copy the addresses before dropping
2655 	 * conn_lock.
2656 	 */
2657 	ip_attr_nexthop(&connp->conn_xmit_ipp, connp->conn_ixa,
2658 	    &connp->conn_faddr_v6, &nexthop);
2659 	saddr = connp->conn_saddr_v6;
2660 	faddr = connp->conn_faddr_v6;
2661 	fport = connp->conn_fport;
2662 
2663 	mutex_exit(&connp->conn_lock);
2664 	error = ip_attr_connect(connp, ixa, &saddr, &faddr, &nexthop, fport,
2665 	    &saddr, uinfo, flags | IPDF_VERIFY_DST);
2666 	mutex_enter(&connp->conn_lock);
2667 
2668 	/* Could have changed even if an error */
2669 	connp->conn_saddr_v6 = saddr;
2670 	if (error != 0)
2671 		return (error);
2672 
2673 	/*
2674 	 * Check whether Trusted Solaris policy allows communication with this
2675 	 * host, and pretend that the destination is unreachable if not.
2676 	 * Compute any needed label and place it in ipp_label_v4/v6.
2677 	 *
2678 	 * Later conn_build_hdr_template() takes ipp_label_v4/v6 to form
2679 	 * the packet.
2680 	 *
2681 	 * TSOL Note: Any concurrent threads would pick a different ixa
2682 	 * (and ipp if they are to change the ipp)  so we
2683 	 * don't have to worry about concurrent threads.
2684 	 */
2685 	if (is_system_labeled()) {
2686 		if (connp->conn_mlp_type != mlptSingle)
2687 			return (ECONNREFUSED);
2688 
2689 		/*
2690 		 * conn_update_label will set ipp_label* which will later
2691 		 * be used by conn_build_hdr_template.
2692 		 */
2693 		error = conn_update_label(connp, ixa,
2694 		    &connp->conn_faddr_v6, &connp->conn_xmit_ipp);
2695 		if (error != 0)
2696 			return (error);
2697 	}
2698 
2699 	/*
2700 	 * Ensure that we match on the selected local address.
2701 	 * This overrides conn_laddr in the case we had earlier bound to a
2702 	 * multicast or broadcast address.
2703 	 */
2704 	connp->conn_laddr_v6 = connp->conn_saddr_v6;
2705 
2706 	/*
2707 	 * Allow setting new policies.
2708 	 * The addresses/ports are already set, thus the IPsec policy calls
2709 	 * can handle their passed-in conn's.
2710 	 */
2711 	connp->conn_policy_cached = B_FALSE;
2712 
2713 	/*
2714 	 * Cache IPsec policy in this conn.  If we have per-socket policy,
2715 	 * we'll cache that.  If we don't, we'll inherit global policy.
2716 	 *
2717 	 * This is done before the caller inserts in the receive-side fanout.
2718 	 * Note that conn_policy_cached is set by ipsec_conn_cache_policy() even
2719 	 * for connections where we don't have a policy. This is to prevent
2720 	 * global policy lookups in the inbound path.
2721 	 *
2722 	 * If we insert before we set conn_policy_cached,
2723 	 * CONN_INBOUND_POLICY_PRESENT() check can still evaluate true
2724 	 * because global policy cound be non-empty. We normally call
2725 	 * ipsec_check_policy() for conn_policy_cached connections only if
2726 	 * conn_in_enforce_policy is set. But in this case,
2727 	 * conn_policy_cached can get set anytime since we made the
2728 	 * CONN_INBOUND_POLICY_PRESENT() check and ipsec_check_policy() is
2729 	 * called, which will make the above assumption false.  Thus, we
2730 	 * need to insert after we set conn_policy_cached.
2731 	 */
2732 	error = ipsec_conn_cache_policy(connp,
2733 	    connp->conn_ipversion == IPV4_VERSION);
2734 	if (error != 0)
2735 		return (error);
2736 
2737 	/*
2738 	 * We defer to do LSO check until here since now we have better idea
2739 	 * whether IPsec is present. If the underlying ill is LSO capable,
2740 	 * copy its capability in so the ULP can decide whether to enable LSO
2741 	 * on this connection.
2742 	 *
2743 	 * Currently, won't enable LSO for IRE_LOOPBACK or IRE_LOCAL, because
2744 	 * the receiver can not handle it. Also won't enable LSO for MULTIRT.
2745 	 */
2746 	ixa->ixa_flags &= ~IXAF_LSO_CAPAB;
2747 
2748 	ASSERT(ixa->ixa_ire != NULL);
2749 	if (dohwcksum &&
2750 	    ixa->ixa_ipst->ips_ip_lso_outbound && (flags & IPDF_LSO) &&
2751 	    !(ixa->ixa_flags & IXAF_IPSEC_SECURE) &&
2752 	    !(ixa->ixa_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK)) &&
2753 	    !(ixa->ixa_ire->ire_flags & RTF_MULTIRT) &&
2754 	    (ixa->ixa_nce != NULL) &&
2755 	    ((ixa->ixa_flags & IXAF_IS_IPV4) ?
2756 	    ILL_LSO_TCP_IPV4_USABLE(ixa->ixa_nce->nce_ill) :
2757 	    ILL_LSO_TCP_IPV6_USABLE(ixa->ixa_nce->nce_ill))) {
2758 		ixa->ixa_lso_capab = *ixa->ixa_nce->nce_ill->ill_lso_capab;
2759 		ixa->ixa_flags |= IXAF_LSO_CAPAB;
2760 	}
2761 
2762 	/* Check whether ZEROCOPY capability is usable for this connection. */
2763 	ixa->ixa_flags &= ~IXAF_ZCOPY_CAPAB;
2764 
2765 	if ((flags & IPDF_ZCOPY) &&
2766 	    !(ixa->ixa_flags & IXAF_IPSEC_SECURE) &&
2767 	    !(ixa->ixa_ire->ire_type & (IRE_LOCAL | IRE_LOOPBACK)) &&
2768 	    !(ixa->ixa_ire->ire_flags & RTF_MULTIRT) &&
2769 	    (ixa->ixa_nce != NULL) &&
2770 	    ILL_ZCOPY_USABLE(ixa->ixa_nce->nce_ill)) {
2771 		ixa->ixa_flags |= IXAF_ZCOPY_CAPAB;
2772 	}
2773 	return (0);
2774 }
2775 
2776 /*
2777  * Predicates to check if the addresses match conn_last*
2778  */
2779 
2780 /*
2781  * Compare the conn against an address.
2782  * If using mapped addresses on AF_INET6 sockets, use the _v6 function
2783  */
2784 boolean_t
2785 conn_same_as_last_v4(conn_t *connp, sin_t *sin)
2786 {
2787 	ASSERT(connp->conn_family == AF_INET);
2788 	return (sin->sin_addr.s_addr == connp->conn_v4lastdst &&
2789 	    sin->sin_port == connp->conn_lastdstport);
2790 }
2791 
2792 /*
2793  * Compare, including for mapped addresses
2794  */
2795 boolean_t
2796 conn_same_as_last_v6(conn_t *connp, sin6_t *sin6)
2797 {
2798 	return (IN6_ARE_ADDR_EQUAL(&connp->conn_v6lastdst, &sin6->sin6_addr) &&
2799 	    sin6->sin6_port == connp->conn_lastdstport &&
2800 	    sin6->sin6_flowinfo == connp->conn_lastflowinfo &&
2801 	    sin6->sin6_scope_id == connp->conn_lastscopeid);
2802 }
2803 
2804 /*
2805  * Compute a label and place it in the ip_packet_t.
2806  * Handles IPv4 and IPv6.
2807  * The caller should have a correct ixa_tsl and ixa_zoneid and have
2808  * already called conn_connect or ip_attr_connect to ensure that tsol_check_dest
2809  * has been called.
2810  */
2811 int
2812 conn_update_label(const conn_t *connp, const ip_xmit_attr_t *ixa,
2813     const in6_addr_t *v6dst, ip_pkt_t *ipp)
2814 {
2815 	int		err;
2816 	ipaddr_t	v4dst;
2817 
2818 	if (IN6_IS_ADDR_V4MAPPED(v6dst)) {
2819 		uchar_t		opt_storage[IP_MAX_OPT_LENGTH];
2820 
2821 		IN6_V4MAPPED_TO_IPADDR(v6dst, v4dst);
2822 
2823 		err = tsol_compute_label_v4(ixa->ixa_tsl, ixa->ixa_zoneid,
2824 		    v4dst, opt_storage, ixa->ixa_ipst);
2825 		if (err == 0) {
2826 			/* Length contained in opt_storage[IPOPT_OLEN] */
2827 			err = optcom_pkt_set(opt_storage,
2828 			    opt_storage[IPOPT_OLEN],
2829 			    (uchar_t **)&ipp->ipp_label_v4,
2830 			    &ipp->ipp_label_len_v4);
2831 		}
2832 		if (err != 0) {
2833 			DTRACE_PROBE4(tx__ip__log__info__updatelabel,
2834 			    char *, "conn(1) failed to update options(2) "
2835 			    "on ixa(3)",
2836 			    conn_t *, connp, char *, opt_storage,
2837 			    ip_xmit_attr_t *, ixa);
2838 		}
2839 		if (ipp->ipp_label_len_v4 != 0)
2840 			ipp->ipp_fields |= IPPF_LABEL_V4;
2841 		else
2842 			ipp->ipp_fields &= ~IPPF_LABEL_V4;
2843 	} else {
2844 		uchar_t		opt_storage[TSOL_MAX_IPV6_OPTION];
2845 		uint_t		optlen;
2846 
2847 		err = tsol_compute_label_v6(ixa->ixa_tsl, ixa->ixa_zoneid,
2848 		    v6dst, opt_storage, ixa->ixa_ipst);
2849 		if (err == 0) {
2850 			/*
2851 			 * Note that ipp_label_v6 is just the option - not
2852 			 * the hopopts extension header.
2853 			 *
2854 			 * Length contained in opt_storage[IPOPT_OLEN], but
2855 			 * that doesn't include the two byte options header.
2856 			 */
2857 			optlen = opt_storage[IPOPT_OLEN];
2858 			if (optlen != 0)
2859 				optlen += 2;
2860 
2861 			err = optcom_pkt_set(opt_storage, optlen,
2862 			    (uchar_t **)&ipp->ipp_label_v6,
2863 			    &ipp->ipp_label_len_v6);
2864 		}
2865 		if (err != 0) {
2866 			DTRACE_PROBE4(tx__ip__log__info__updatelabel,
2867 			    char *, "conn(1) failed to update options(2) "
2868 			    "on ixa(3)",
2869 			    conn_t *, connp, char *, opt_storage,
2870 			    ip_xmit_attr_t *, ixa);
2871 		}
2872 		if (ipp->ipp_label_len_v6 != 0)
2873 			ipp->ipp_fields |= IPPF_LABEL_V6;
2874 		else
2875 			ipp->ipp_fields &= ~IPPF_LABEL_V6;
2876 	}
2877 	return (err);
2878 }
2879 
2880 /*
2881  * Inherit all options settings from the parent/listener to the eager.
2882  * Returns zero on success; ENOMEM if memory allocation failed.
2883  *
2884  * We assume that the eager has not had any work done i.e., the conn_ixa
2885  * and conn_xmit_ipp are all zero.
2886  * Furthermore we assume that no other thread can access the eager (because
2887  * it isn't inserted in any fanout list).
2888  */
2889 int
2890 conn_inherit_parent(conn_t *lconnp, conn_t *econnp)
2891 {
2892 	cred_t	*credp;
2893 	int	err;
2894 	void	*notify_cookie;
2895 	uint32_t xmit_hint;
2896 
2897 	econnp->conn_family = lconnp->conn_family;
2898 	econnp->conn_ipv6_v6only = lconnp->conn_ipv6_v6only;
2899 	econnp->conn_wq = lconnp->conn_wq;
2900 	econnp->conn_rq = lconnp->conn_rq;
2901 
2902 	/*
2903 	 * Make a safe copy of the transmit attributes.
2904 	 * conn_connect will later be used by the caller to setup the ire etc.
2905 	 */
2906 	ASSERT(econnp->conn_ixa->ixa_refcnt == 1);
2907 	ASSERT(econnp->conn_ixa->ixa_ire == NULL);
2908 	ASSERT(econnp->conn_ixa->ixa_dce == NULL);
2909 	ASSERT(econnp->conn_ixa->ixa_nce == NULL);
2910 
2911 	/* Preserve ixa_notify_cookie and xmit_hint */
2912 	notify_cookie = econnp->conn_ixa->ixa_notify_cookie;
2913 	xmit_hint = econnp->conn_ixa->ixa_xmit_hint;
2914 	ixa_safe_copy(lconnp->conn_ixa, econnp->conn_ixa);
2915 	econnp->conn_ixa->ixa_notify_cookie = notify_cookie;
2916 	econnp->conn_ixa->ixa_xmit_hint = xmit_hint;
2917 
2918 	econnp->conn_bound_if = lconnp->conn_bound_if;
2919 	econnp->conn_incoming_ifindex = lconnp->conn_incoming_ifindex;
2920 
2921 	/* Inherit all RECV options */
2922 	econnp->conn_recv_ancillary = lconnp->conn_recv_ancillary;
2923 
2924 	err = ip_pkt_copy(&lconnp->conn_xmit_ipp, &econnp->conn_xmit_ipp,
2925 	    KM_NOSLEEP);
2926 	if (err != 0)
2927 		return (err);
2928 
2929 	econnp->conn_zoneid = lconnp->conn_zoneid;
2930 	econnp->conn_allzones = lconnp->conn_allzones;
2931 
2932 	/* This is odd. Pick a flowlabel for each connection instead? */
2933 	econnp->conn_flowinfo = lconnp->conn_flowinfo;
2934 
2935 	econnp->conn_default_ttl = lconnp->conn_default_ttl;
2936 	econnp->conn_min_ttl = lconnp->conn_min_ttl;
2937 
2938 	/*
2939 	 * TSOL: tsol_input_proc() needs the eager's cred before the
2940 	 * eager is accepted
2941 	 */
2942 	ASSERT(lconnp->conn_cred != NULL);
2943 	econnp->conn_cred = credp = lconnp->conn_cred;
2944 	crhold(credp);
2945 	econnp->conn_cpid = lconnp->conn_cpid;
2946 	econnp->conn_open_time = ddi_get_lbolt64();
2947 
2948 	/*
2949 	 * Cache things in the ixa without any refhold.
2950 	 * Listener might not have set up ixa_cred
2951 	 */
2952 	ASSERT(!(econnp->conn_ixa->ixa_free_flags & IXA_FREE_CRED));
2953 	econnp->conn_ixa->ixa_cred = econnp->conn_cred;
2954 	econnp->conn_ixa->ixa_cpid = econnp->conn_cpid;
2955 	if (is_system_labeled())
2956 		econnp->conn_ixa->ixa_tsl = crgetlabel(econnp->conn_cred);
2957 
2958 	/*
2959 	 * If the caller has the process-wide flag set, then default to MAC
2960 	 * exempt mode.  This allows read-down to unlabeled hosts.
2961 	 */
2962 	if (getpflags(NET_MAC_AWARE, credp) != 0)
2963 		econnp->conn_mac_mode = CONN_MAC_AWARE;
2964 
2965 	econnp->conn_zone_is_global = lconnp->conn_zone_is_global;
2966 
2967 	/*
2968 	 * We eliminate the need for sockfs to send down a T_SVR4_OPTMGMT_REQ
2969 	 * via soaccept()->soinheritoptions() which essentially applies
2970 	 * all the listener options to the new connection. The options that we
2971 	 * need to take care of are:
2972 	 * SO_DEBUG, SO_REUSEADDR, SO_KEEPALIVE, SO_DONTROUTE, SO_BROADCAST,
2973 	 * SO_USELOOPBACK, SO_OOBINLINE, SO_DGRAM_ERRIND, SO_LINGER,
2974 	 * SO_SNDBUF, SO_RCVBUF.
2975 	 *
2976 	 * SO_RCVBUF:	conn_rcvbuf is set.
2977 	 * SO_SNDBUF:	conn_sndbuf is set.
2978 	 */
2979 
2980 	/* Could we define a struct and use a struct copy for this? */
2981 	econnp->conn_sndbuf = lconnp->conn_sndbuf;
2982 	econnp->conn_rcvbuf = lconnp->conn_rcvbuf;
2983 	econnp->conn_sndlowat = lconnp->conn_sndlowat;
2984 	econnp->conn_rcvlowat = lconnp->conn_rcvlowat;
2985 	econnp->conn_dgram_errind = lconnp->conn_dgram_errind;
2986 	econnp->conn_oobinline = lconnp->conn_oobinline;
2987 	econnp->conn_debug = lconnp->conn_debug;
2988 	econnp->conn_keepalive = lconnp->conn_keepalive;
2989 	econnp->conn_linger = lconnp->conn_linger;
2990 	econnp->conn_lingertime = lconnp->conn_lingertime;
2991 
2992 	/* Set the IP options */
2993 	econnp->conn_broadcast = lconnp->conn_broadcast;
2994 	econnp->conn_useloopback = lconnp->conn_useloopback;
2995 	econnp->conn_reuseaddr = lconnp->conn_reuseaddr;
2996 	return (0);
2997 }
2998