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