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