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


   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) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright 2019 Joyent, Inc.
  26  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.

  27  */
  28 
  29 /* This file contains all TCP input processing functions. */
  30 
  31 #include <sys/types.h>
  32 #include <sys/stream.h>
  33 #include <sys/strsun.h>
  34 #include <sys/strsubr.h>
  35 #include <sys/stropts.h>
  36 #include <sys/strlog.h>
  37 #define _SUN_TPI_VERSION 2
  38 #include <sys/tihdr.h>
  39 #include <sys/suntpi.h>
  40 #include <sys/xti_inet.h>
  41 #include <sys/squeue_impl.h>
  42 #include <sys/squeue.h>
  43 #include <sys/tsol/tnet.h>
  44 
  45 #include <inet/common.h>
  46 #include <inet/ip.h>


5091  * ancillary pieces requested by the application that are
5092  * different than they were in the previous data segment.
5093  *
5094  * Save the "current" values once memory allocation is ok so that
5095  * when memory allocation fails we can just wait for the next data segment.
5096  */
5097 static mblk_t *
5098 tcp_input_add_ancillary(tcp_t *tcp, mblk_t *mp, ip_pkt_t *ipp,
5099     ip_recv_attr_t *ira)
5100 {
5101         struct T_optdata_ind *todi;
5102         int optlen;
5103         uchar_t *optptr;
5104         struct T_opthdr *toh;
5105         crb_t addflag;  /* Which pieces to add */
5106         mblk_t *mp1;
5107         conn_t  *connp = tcp->tcp_connp;
5108 
5109         optlen = 0;
5110         addflag.crb_all = 0;









5111         /* If app asked for pktinfo and the index has changed ... */
5112         if (connp->conn_recv_ancillary.crb_ip_recvpktinfo &&
5113             ira->ira_ruifindex != tcp->tcp_recvifindex) {
5114                 optlen += sizeof (struct T_opthdr) +
5115                     sizeof (struct in6_pktinfo);
5116                 addflag.crb_ip_recvpktinfo = 1;
5117         }
5118         /* If app asked for hoplimit and it has changed ... */
5119         if (connp->conn_recv_ancillary.crb_ipv6_recvhoplimit &&
5120             ipp->ipp_hoplimit != tcp->tcp_recvhops) {
5121                 optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
5122                 addflag.crb_ipv6_recvhoplimit = 1;
5123         }
5124         /* If app asked for tclass and it has changed ... */
5125         if (connp->conn_recv_ancillary.crb_ipv6_recvtclass &&
5126             ipp->ipp_tclass != tcp->tcp_recvtclass) {
5127                 optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
5128                 addflag.crb_ipv6_recvtclass = 1;
5129         }

5130         /*
5131          * If app asked for hopbyhop headers and it has changed ...
5132          * For security labels, note that (1) security labels can't change on
5133          * a connected socket at all, (2) we're connected to at most one peer,
5134          * (3) if anything changes, then it must be some other extra option.
5135          */
5136         if (connp->conn_recv_ancillary.crb_ipv6_recvhopopts &&
5137             ip_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
5138             (ipp->ipp_fields & IPPF_HOPOPTS),
5139             ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
5140                 optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
5141                 addflag.crb_ipv6_recvhopopts = 1;
5142                 if (!ip_allocbuf((void **)&tcp->tcp_hopopts,
5143                     &tcp->tcp_hopoptslen, (ipp->ipp_fields & IPPF_HOPOPTS),
5144                     ipp->ipp_hopopts, ipp->ipp_hopoptslen))
5145                         return (mp);
5146         }
5147         /* If app asked for dst headers before routing headers ... */
5148         if (connp->conn_recv_ancillary.crb_ipv6_recvrthdrdstopts &&
5149             ip_cmpbuf(tcp->tcp_rthdrdstopts, tcp->tcp_rthdrdstoptslen,
5150             (ipp->ipp_fields & IPPF_RTHDRDSTOPTS),
5151             ipp->ipp_rthdrdstopts, ipp->ipp_rthdrdstoptslen)) {


5189                 return (mp);
5190         }
5191         mp1 = allocb(sizeof (struct T_optdata_ind) + optlen, BPRI_MED);
5192         if (mp1 == NULL) {
5193                 /*
5194                  * Defer sending ancillary data until the next TCP segment
5195                  * arrives.
5196                  */
5197                 return (mp);
5198         }
5199         mp1->b_cont = mp;
5200         mp = mp1;
5201         mp->b_wptr += sizeof (*todi) + optlen;
5202         mp->b_datap->db_type = M_PROTO;
5203         todi = (struct T_optdata_ind *)mp->b_rptr;
5204         todi->PRIM_type = T_OPTDATA_IND;
5205         todi->DATA_flag = 1; /* MORE data */
5206         todi->OPT_length = optlen;
5207         todi->OPT_offset = sizeof (*todi);
5208         optptr = (uchar_t *)&todi[1];

















5209         /*
5210          * If app asked for pktinfo and the index has changed ...
5211          * Note that the local address never changes for the connection.
5212          */
5213         if (addflag.crb_ip_recvpktinfo) {
5214                 struct in6_pktinfo *pkti;
5215                 uint_t ifindex;
5216 
5217                 ifindex = ira->ira_ruifindex;
5218                 toh = (struct T_opthdr *)optptr;
5219                 toh->level = IPPROTO_IPV6;
5220                 toh->name = IPV6_PKTINFO;
5221                 toh->len = sizeof (*toh) + sizeof (*pkti);
5222                 toh->status = 0;
5223                 optptr += sizeof (*toh);
5224                 pkti = (struct in6_pktinfo *)optptr;
5225                 pkti->ipi6_addr = connp->conn_laddr_v6;
5226                 pkti->ipi6_ifindex = ifindex;
5227                 optptr += sizeof (*pkti);
5228                 ASSERT(OK_32PTR(optptr));




   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) 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
  25  * Copyright 2019 Joyent, Inc.
  26  * Copyright (c) 2014, 2016 by Delphix. All rights reserved.
  27  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
  28  */
  29 
  30 /* This file contains all TCP input processing functions. */
  31 
  32 #include <sys/types.h>
  33 #include <sys/stream.h>
  34 #include <sys/strsun.h>
  35 #include <sys/strsubr.h>
  36 #include <sys/stropts.h>
  37 #include <sys/strlog.h>
  38 #define _SUN_TPI_VERSION 2
  39 #include <sys/tihdr.h>
  40 #include <sys/suntpi.h>
  41 #include <sys/xti_inet.h>
  42 #include <sys/squeue_impl.h>
  43 #include <sys/squeue.h>
  44 #include <sys/tsol/tnet.h>
  45 
  46 #include <inet/common.h>
  47 #include <inet/ip.h>


5092  * ancillary pieces requested by the application that are
5093  * different than they were in the previous data segment.
5094  *
5095  * Save the "current" values once memory allocation is ok so that
5096  * when memory allocation fails we can just wait for the next data segment.
5097  */
5098 static mblk_t *
5099 tcp_input_add_ancillary(tcp_t *tcp, mblk_t *mp, ip_pkt_t *ipp,
5100     ip_recv_attr_t *ira)
5101 {
5102         struct T_optdata_ind *todi;
5103         int optlen;
5104         uchar_t *optptr;
5105         struct T_opthdr *toh;
5106         crb_t addflag;  /* Which pieces to add */
5107         mblk_t *mp1;
5108         conn_t  *connp = tcp->tcp_connp;
5109 
5110         optlen = 0;
5111         addflag.crb_all = 0;
5112 
5113         /* If app asked for TOS and it has changed ... */
5114         if (connp->conn_recv_ancillary.crb_recvtos &&
5115             ipp->ipp_type_of_service != tcp->tcp_recvtos &&
5116             (ira->ira_flags & IRAF_IS_IPV4)) {
5117                 optlen += sizeof (struct T_opthdr) +
5118                     P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
5119                 addflag.crb_recvtos = 1;
5120         }
5121         /* If app asked for pktinfo and the index has changed ... */
5122         if (connp->conn_recv_ancillary.crb_ip_recvpktinfo &&
5123             ira->ira_ruifindex != tcp->tcp_recvifindex) {
5124                 optlen += sizeof (struct T_opthdr) +
5125                     sizeof (struct in6_pktinfo);
5126                 addflag.crb_ip_recvpktinfo = 1;
5127         }
5128         /* If app asked for hoplimit and it has changed ... */
5129         if (connp->conn_recv_ancillary.crb_ipv6_recvhoplimit &&
5130             ipp->ipp_hoplimit != tcp->tcp_recvhops) {
5131                 optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
5132                 addflag.crb_ipv6_recvhoplimit = 1;
5133         }
5134         /* If app asked for tclass and it has changed ... */
5135         if (connp->conn_recv_ancillary.crb_ipv6_recvtclass &&
5136             ipp->ipp_tclass != tcp->tcp_recvtclass) {
5137                 optlen += sizeof (struct T_opthdr) + sizeof (uint_t);
5138                 addflag.crb_ipv6_recvtclass = 1;
5139         }
5140 
5141         /*
5142          * If app asked for hop-by-hop headers and it has changed ...
5143          * For security labels, note that (1) security labels can't change on
5144          * a connected socket at all, (2) we're connected to at most one peer,
5145          * (3) if anything changes, then it must be some other extra option.
5146          */
5147         if (connp->conn_recv_ancillary.crb_ipv6_recvhopopts &&
5148             ip_cmpbuf(tcp->tcp_hopopts, tcp->tcp_hopoptslen,
5149             (ipp->ipp_fields & IPPF_HOPOPTS),
5150             ipp->ipp_hopopts, ipp->ipp_hopoptslen)) {
5151                 optlen += sizeof (struct T_opthdr) + ipp->ipp_hopoptslen;
5152                 addflag.crb_ipv6_recvhopopts = 1;
5153                 if (!ip_allocbuf((void **)&tcp->tcp_hopopts,
5154                     &tcp->tcp_hopoptslen, (ipp->ipp_fields & IPPF_HOPOPTS),
5155                     ipp->ipp_hopopts, ipp->ipp_hopoptslen))
5156                         return (mp);
5157         }
5158         /* If app asked for dst headers before routing headers ... */
5159         if (connp->conn_recv_ancillary.crb_ipv6_recvrthdrdstopts &&
5160             ip_cmpbuf(tcp->tcp_rthdrdstopts, tcp->tcp_rthdrdstoptslen,
5161             (ipp->ipp_fields & IPPF_RTHDRDSTOPTS),
5162             ipp->ipp_rthdrdstopts, ipp->ipp_rthdrdstoptslen)) {


5200                 return (mp);
5201         }
5202         mp1 = allocb(sizeof (struct T_optdata_ind) + optlen, BPRI_MED);
5203         if (mp1 == NULL) {
5204                 /*
5205                  * Defer sending ancillary data until the next TCP segment
5206                  * arrives.
5207                  */
5208                 return (mp);
5209         }
5210         mp1->b_cont = mp;
5211         mp = mp1;
5212         mp->b_wptr += sizeof (*todi) + optlen;
5213         mp->b_datap->db_type = M_PROTO;
5214         todi = (struct T_optdata_ind *)mp->b_rptr;
5215         todi->PRIM_type = T_OPTDATA_IND;
5216         todi->DATA_flag = 1; /* MORE data */
5217         todi->OPT_length = optlen;
5218         todi->OPT_offset = sizeof (*todi);
5219         optptr = (uchar_t *)&todi[1];
5220 
5221         /* If app asked for TOS and it has changed ... */
5222         if (addflag.crb_recvtos) {
5223                 toh = (struct T_opthdr *)optptr;
5224                 toh->level = IPPROTO_IP;
5225                 toh->name = IP_RECVTOS;
5226                 toh->len = sizeof (*toh) +
5227                     P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
5228                 toh->status = 0;
5229                 optptr += sizeof (*toh);
5230                 *(uint8_t *)optptr = ipp->ipp_type_of_service;
5231                 optptr = (uchar_t *)toh + toh->len;
5232                 ASSERT(__TPI_TOPT_ISALIGNED(optptr));
5233                 /* Save as "last" value */
5234                 tcp->tcp_recvtos = ipp->ipp_type_of_service;
5235         }
5236 
5237         /*
5238          * If app asked for pktinfo and the index has changed ...
5239          * Note that the local address never changes for the connection.
5240          */
5241         if (addflag.crb_ip_recvpktinfo) {
5242                 struct in6_pktinfo *pkti;
5243                 uint_t ifindex;
5244 
5245                 ifindex = ira->ira_ruifindex;
5246                 toh = (struct T_opthdr *)optptr;
5247                 toh->level = IPPROTO_IPV6;
5248                 toh->name = IPV6_PKTINFO;
5249                 toh->len = sizeof (*toh) + sizeof (*pkti);
5250                 toh->status = 0;
5251                 optptr += sizeof (*toh);
5252                 pkti = (struct in6_pktinfo *)optptr;
5253                 pkti->ipi6_addr = connp->conn_laddr_v6;
5254                 pkti->ipi6_ifindex = ifindex;
5255                 optptr += sizeof (*pkti);
5256                 ASSERT(OK_32PTR(optptr));