4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25 /* Copyright (c) 1990 Mentat Inc. */
26
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #include <sys/strsun.h>
30 #define _SUN_TPI_VERSION 2
31 #include <sys/tihdr.h>
32 #include <sys/xti_inet.h>
33 #include <sys/ucred.h>
34 #include <sys/zone.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/cmn_err.h>
38 #include <sys/debug.h>
39 #include <sys/atomic.h>
40 #include <sys/policy.h>
41
42 #include <sys/systm.h>
43 #include <sys/param.h>
218 }
219 if (recv_ancillary.crb_recvucred && ira->ira_cred != NULL) {
220 ancil_size += sizeof (struct T_opthdr) +
221 ucredminsize(ira->ira_cred);
222 IP_STAT(ipst, conn_in_recvucred);
223 }
224
225 /*
226 * If SO_TIMESTAMP is set allocate the appropriate sized
227 * buffer. Since gethrestime() expects a pointer aligned
228 * argument, we allocate space necessary for extra
229 * alignment (even though it might not be used).
230 */
231 if (recv_ancillary.crb_timestamp) {
232 ancil_size += sizeof (struct T_opthdr) +
233 sizeof (timestruc_t) + _POINTER_ALIGNMENT;
234 IP_STAT(ipst, conn_in_timestamp);
235 }
236
237 /*
238 * If IP_RECVTTL is set allocate the appropriate sized buffer
239 */
240 if (recv_ancillary.crb_recvttl &&
241 (ira->ira_flags & IRAF_IS_IPV4)) {
242 ancil_size += sizeof (struct T_opthdr) + sizeof (uint8_t);
243 IP_STAT(ipst, conn_in_recvttl);
244 }
245
246 return (ancil_size);
247 }
248
249 /*
250 * Lay down the ancillary data items at "ancil_buf".
251 * Assumes caller has used conn_recvancillary_size to allocate a sufficiently
252 * large buffer - ancil_size.
253 */
254 void
255 conn_recvancillary_add(conn_t *connp, crb_t recv_ancillary,
256 ip_recv_attr_t *ira, ip_pkt_t *ipp, uchar_t *ancil_buf, uint_t ancil_size)
257 {
258 /*
259 * Copy in destination address before options to avoid
260 * any padding issues.
261 */
262 if (recv_ancillary.crb_recvdstaddr &&
532 ancil_size -= toh->len;
533 }
534 if (recv_ancillary.crb_timestamp) {
535 struct T_opthdr *toh;
536
537 toh = (struct T_opthdr *)ancil_buf;
538 toh->level = SOL_SOCKET;
539 toh->name = SCM_TIMESTAMP;
540 toh->len = sizeof (struct T_opthdr) +
541 sizeof (timestruc_t) + _POINTER_ALIGNMENT;
542 toh->status = 0;
543 ancil_buf += sizeof (struct T_opthdr);
544 /* Align for gethrestime() */
545 ancil_buf = (uchar_t *)P2ROUNDUP((intptr_t)ancil_buf,
546 sizeof (intptr_t));
547 gethrestime((timestruc_t *)ancil_buf);
548 ancil_buf = (uchar_t *)toh + toh->len;
549 ancil_size -= toh->len;
550 }
551
552 /*
553 * CAUTION:
554 * Due to aligment issues
555 * Processing of IP_RECVTTL option
556 * should always be the last. Adding
557 * any option processing after this will
558 * cause alignment panic.
559 */
560 if (recv_ancillary.crb_recvttl &&
561 (ira->ira_flags & IRAF_IS_IPV4)) {
562 struct T_opthdr *toh;
563 uint8_t *dstptr;
564
565 toh = (struct T_opthdr *)ancil_buf;
566 toh->level = IPPROTO_IP;
567 toh->name = IP_RECVTTL;
568 toh->len = sizeof (struct T_opthdr) + sizeof (uint8_t);
569 toh->status = 0;
570 ancil_buf += sizeof (struct T_opthdr);
571 dstptr = (uint8_t *)ancil_buf;
572 *dstptr = ipp->ipp_hoplimit;
573 ancil_buf += sizeof (uint8_t);
574 ancil_size -= toh->len;
575 }
576
577 /* Consumed all of allocated space */
578 ASSERT(ancil_size == 0);
579
580 }
581
582 /*
583 * This routine retrieves the current status of socket options.
584 * It returns the size of the option retrieved, or -1.
585 */
586 int
587 conn_opt_get(conn_opt_arg_t *coa, t_scalar_t level, t_scalar_t name,
588 uchar_t *ptr)
589 {
590 int *i1 = (int *)ptr;
591 conn_t *connp = coa->coa_connp;
592 ip_xmit_attr_t *ixa = coa->coa_ixa;
593 ip_pkt_t *ipp = coa->coa_ipp;
594 ip_stack_t *ipst = ixa->ixa_ipst;
756 *(uchar_t *)ptr = ixa->ixa_multicast_ttl;
757 return (sizeof (uchar_t));
758 case IP_MULTICAST_LOOP:
759 *ptr = (ixa->ixa_flags & IXAF_MULTICAST_LOOP) ? 1 : 0;
760 return (sizeof (uint8_t));
761 case IP_RECVOPTS:
762 *i1 = connp->conn_recv_ancillary.crb_recvopts;
763 break; /* goto sizeof (int) option return */
764 case IP_RECVDSTADDR:
765 *i1 = connp->conn_recv_ancillary.crb_recvdstaddr;
766 break; /* goto sizeof (int) option return */
767 case IP_RECVIF:
768 *i1 = connp->conn_recv_ancillary.crb_recvif;
769 break; /* goto sizeof (int) option return */
770 case IP_RECVSLLA:
771 *i1 = connp->conn_recv_ancillary.crb_recvslla;
772 break; /* goto sizeof (int) option return */
773 case IP_RECVTTL:
774 *i1 = connp->conn_recv_ancillary.crb_recvttl;
775 break; /* goto sizeof (int) option return */
776 case IP_ADD_MEMBERSHIP:
777 case IP_DROP_MEMBERSHIP:
778 case MCAST_JOIN_GROUP:
779 case MCAST_LEAVE_GROUP:
780 case IP_BLOCK_SOURCE:
781 case IP_UNBLOCK_SOURCE:
782 case IP_ADD_SOURCE_MEMBERSHIP:
783 case IP_DROP_SOURCE_MEMBERSHIP:
784 case MCAST_BLOCK_SOURCE:
785 case MCAST_UNBLOCK_SOURCE:
786 case MCAST_JOIN_SOURCE_GROUP:
787 case MCAST_LEAVE_SOURCE_GROUP:
788 case MRT_INIT:
789 case MRT_DONE:
790 case MRT_ADD_VIF:
791 case MRT_DEL_VIF:
792 case MRT_ADD_MFC:
793 case MRT_DEL_MFC:
794 /* cannot "get" the value for these */
795 return (-1);
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);
|
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
25 */
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>
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_RECVTOS is set allocate the appropriately sized buffer
240 */
241 if (recv_ancillary.crb_recvtos &&
242 (ira->ira_flags & IRAF_IS_IPV4)) {
243 ancil_size += sizeof (struct T_opthdr) +
244 P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
245 IP_STAT(ipst, conn_in_recvtos);
246 }
247
248 /*
249 * If IP_RECVTTL is set allocate the appropriate sized buffer
250 */
251 if (recv_ancillary.crb_recvttl &&
252 (ira->ira_flags & IRAF_IS_IPV4)) {
253 ancil_size += sizeof (struct T_opthdr) +
254 P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
255 IP_STAT(ipst, conn_in_recvttl);
256 }
257
258 return (ancil_size);
259 }
260
261 /*
262 * Lay down the ancillary data items at "ancil_buf".
263 * Assumes caller has used conn_recvancillary_size to allocate a sufficiently
264 * large buffer - ancil_size.
265 */
266 void
267 conn_recvancillary_add(conn_t *connp, crb_t recv_ancillary,
268 ip_recv_attr_t *ira, ip_pkt_t *ipp, uchar_t *ancil_buf, uint_t ancil_size)
269 {
270 /*
271 * Copy in destination address before options to avoid
272 * any padding issues.
273 */
274 if (recv_ancillary.crb_recvdstaddr &&
544 ancil_size -= toh->len;
545 }
546 if (recv_ancillary.crb_timestamp) {
547 struct T_opthdr *toh;
548
549 toh = (struct T_opthdr *)ancil_buf;
550 toh->level = SOL_SOCKET;
551 toh->name = SCM_TIMESTAMP;
552 toh->len = sizeof (struct T_opthdr) +
553 sizeof (timestruc_t) + _POINTER_ALIGNMENT;
554 toh->status = 0;
555 ancil_buf += sizeof (struct T_opthdr);
556 /* Align for gethrestime() */
557 ancil_buf = (uchar_t *)P2ROUNDUP((intptr_t)ancil_buf,
558 sizeof (intptr_t));
559 gethrestime((timestruc_t *)ancil_buf);
560 ancil_buf = (uchar_t *)toh + toh->len;
561 ancil_size -= toh->len;
562 }
563
564 if (recv_ancillary.crb_recvtos &&
565 (ira->ira_flags & IRAF_IS_IPV4)) {
566 struct T_opthdr *toh;
567 uint8_t *dstptr;
568
569 toh = (struct T_opthdr *)ancil_buf;
570 toh->level = IPPROTO_IP;
571 toh->name = IP_RECVTOS;
572 toh->len = sizeof (struct T_opthdr) +
573 P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
574 toh->status = 0;
575 ancil_buf += sizeof (struct T_opthdr);
576 dstptr = (uint8_t *)ancil_buf;
577 *dstptr = ipp->ipp_type_of_service;
578 ancil_buf = (uchar_t *)toh + toh->len;
579 ancil_size -= toh->len;
580 ASSERT(__TPI_TOPT_ISALIGNED(toh));
581 }
582
583 if (recv_ancillary.crb_recvttl &&
584 (ira->ira_flags & IRAF_IS_IPV4)) {
585 struct T_opthdr *toh;
586 uint8_t *dstptr;
587
588 toh = (struct T_opthdr *)ancil_buf;
589 toh->level = IPPROTO_IP;
590 toh->name = IP_RECVTTL;
591 toh->len = sizeof (struct T_opthdr) +
592 P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
593 toh->status = 0;
594 ancil_buf += sizeof (struct T_opthdr);
595 dstptr = (uint8_t *)ancil_buf;
596 *dstptr = ipp->ipp_hoplimit;
597 ancil_buf = (uchar_t *)toh + toh->len;
598 ancil_size -= toh->len;
599 ASSERT(__TPI_TOPT_ISALIGNED(toh));
600 }
601
602 /* Consumed all of allocated space */
603 ASSERT(ancil_size == 0);
604
605 }
606
607 /*
608 * This routine retrieves the current status of socket options.
609 * It returns the size of the option retrieved, or -1.
610 */
611 int
612 conn_opt_get(conn_opt_arg_t *coa, t_scalar_t level, t_scalar_t name,
613 uchar_t *ptr)
614 {
615 int *i1 = (int *)ptr;
616 conn_t *connp = coa->coa_connp;
617 ip_xmit_attr_t *ixa = coa->coa_ixa;
618 ip_pkt_t *ipp = coa->coa_ipp;
619 ip_stack_t *ipst = ixa->ixa_ipst;
781 *(uchar_t *)ptr = ixa->ixa_multicast_ttl;
782 return (sizeof (uchar_t));
783 case IP_MULTICAST_LOOP:
784 *ptr = (ixa->ixa_flags & IXAF_MULTICAST_LOOP) ? 1 : 0;
785 return (sizeof (uint8_t));
786 case IP_RECVOPTS:
787 *i1 = connp->conn_recv_ancillary.crb_recvopts;
788 break; /* goto sizeof (int) option return */
789 case IP_RECVDSTADDR:
790 *i1 = connp->conn_recv_ancillary.crb_recvdstaddr;
791 break; /* goto sizeof (int) option return */
792 case IP_RECVIF:
793 *i1 = connp->conn_recv_ancillary.crb_recvif;
794 break; /* goto sizeof (int) option return */
795 case IP_RECVSLLA:
796 *i1 = connp->conn_recv_ancillary.crb_recvslla;
797 break; /* goto sizeof (int) option return */
798 case IP_RECVTTL:
799 *i1 = connp->conn_recv_ancillary.crb_recvttl;
800 break; /* goto sizeof (int) option return */
801 case IP_RECVTOS:
802 *i1 = connp->conn_recv_ancillary.crb_recvtos;
803 break; /* goto sizeof (int) option return */
804 case IP_ADD_MEMBERSHIP:
805 case IP_DROP_MEMBERSHIP:
806 case MCAST_JOIN_GROUP:
807 case MCAST_LEAVE_GROUP:
808 case IP_BLOCK_SOURCE:
809 case IP_UNBLOCK_SOURCE:
810 case IP_ADD_SOURCE_MEMBERSHIP:
811 case IP_DROP_SOURCE_MEMBERSHIP:
812 case MCAST_BLOCK_SOURCE:
813 case MCAST_UNBLOCK_SOURCE:
814 case MCAST_JOIN_SOURCE_GROUP:
815 case MCAST_LEAVE_SOURCE_GROUP:
816 case MRT_INIT:
817 case MRT_DONE:
818 case MRT_ADD_VIF:
819 case MRT_DEL_VIF:
820 case MRT_ADD_MFC:
821 case MRT_DEL_MFC:
822 /* cannot "get" the value for these */
823 return (-1);
1376 case IP_RECVDSTADDR:
1377 mutex_enter(&connp->conn_lock);
1378 connp->conn_recv_ancillary.crb_recvdstaddr = onoff;
1379 mutex_exit(&connp->conn_lock);
1380 break;
1381 case IP_RECVIF:
1382 mutex_enter(&connp->conn_lock);
1383 connp->conn_recv_ancillary.crb_recvif = onoff;
1384 mutex_exit(&connp->conn_lock);
1385 break;
1386 case IP_RECVSLLA:
1387 mutex_enter(&connp->conn_lock);
1388 connp->conn_recv_ancillary.crb_recvslla = onoff;
1389 mutex_exit(&connp->conn_lock);
1390 break;
1391 case IP_RECVTTL:
1392 mutex_enter(&connp->conn_lock);
1393 connp->conn_recv_ancillary.crb_recvttl = onoff;
1394 mutex_exit(&connp->conn_lock);
1395 break;
1396 case IP_RECVTOS:
1397 mutex_enter(&connp->conn_lock);
1398 connp->conn_recv_ancillary.crb_recvtos = onoff;
1399 mutex_exit(&connp->conn_lock);
1400 break;
1401 case IP_PKTINFO: {
1402 /*
1403 * This also handles IP_RECVPKTINFO.
1404 * IP_PKTINFO and IP_RECVPKTINFO have same value.
1405 * Differentiation is based on the size of the
1406 * argument passed in.
1407 */
1408 struct in_pktinfo *pktinfo;
1409
1410 if (inlen == sizeof (int)) {
1411 /* This is IP_RECVPKTINFO option. */
1412 mutex_enter(&connp->conn_lock);
1413 connp->conn_recv_ancillary.crb_ip_recvpktinfo =
1414 onoff;
1415 mutex_exit(&connp->conn_lock);
1416 break;
1417 }
1418
1419 /* This is IP_PKTINFO option. */
1420 mutex_enter(&connp->conn_lock);
|