Print this page
13175 Add support for IP_RECVTOS
13182 CMSG_ macros should have man pages
Change-ID: I784aa36cfd3c17e3cccbf1fd329fa7e69b663ef9


   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);