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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/types.h> 30 #include <sys/stream.h> 31 #include <sys/ddi.h> 32 #include <sys/sunddi.h> 33 34 #include <netinet/in.h> 35 #include <netinet/ip6.h> 36 37 #include <inet/common.h> 38 #include <inet/ipclassifier.h> 39 #include <inet/ip.h> 40 #include <inet/ip6.h> 41 #include <inet/mib2.h> 42 #include <inet/nd.h> 43 #include <inet/optcom.h> 44 #include <inet/ipclassifier.h> 45 #include "sctp_impl.h" 46 #include "sctp_addr.h" 47 48 /* 49 * This will compute the checksum over the SCTP packet, so this 50 * function should only be called after the whole packet has been 51 * built. 52 * 53 * rptr should point to the IP / SCTP composite header. 54 * len should be the length of the entire packet, including the IP 55 * header. 56 */ 57 void 58 sctp_add_hdr(sctp_t *sctp, uchar_t *rptr, size_t len) 59 { 60 ipha_t *iphdr; 61 short iplen; 62 63 ASSERT(len >= sctp->sctp_hdr_len); 64 65 /* Copy the common header from the template */ 66 bcopy(sctp->sctp_iphc, rptr, sctp->sctp_hdr_len); 67 68 /* Set the total length in the IP hdr */ 69 iplen = (short)len; 70 iphdr = (ipha_t *)rptr; 71 U16_TO_ABE16(iplen, &iphdr->ipha_length); 72 } 73 74 /*ARGSUSED*/ 75 size_t 76 sctp_supaddr_param_len(sctp_t *sctp) 77 { 78 return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 79 } 80 81 size_t 82 sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 83 { 84 sctp_parm_hdr_t *sph; 85 uint16_t *addrtype; 86 87 sph = (sctp_parm_hdr_t *)p; 88 sph->sph_type = htons(PARM_SUPP_ADDRS); 89 addrtype = (uint16_t *)(sph + 1); 90 switch (sctp->sctp_ipversion) { 91 case IPV4_VERSION: 92 *addrtype++ = htons(PARM_ADDR4); 93 *addrtype = 0; 94 sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 95 break; 96 case IPV6_VERSION: 97 *addrtype++ = htons(PARM_ADDR6); 98 if (!sctp->sctp_connp->conn_ipv6_v6only) { 99 *addrtype = htons(PARM_ADDR4); 100 sph->sph_len = htons(sizeof (*sph) + 101 sizeof (*addrtype) * 2); 102 } else { 103 *addrtype = 0; 104 sph->sph_len = htons(sizeof (*sph) + 105 sizeof (*addrtype)); 106 } 107 break; 108 default: 109 break; 110 } 111 return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 112 } 113 114 /* 115 * Currently, we support on PRSCTP option, there is more to come. 116 */ 117 /*ARGSUSED*/ 118 size_t 119 sctp_options_param_len(const sctp_t *sctp, int option) 120 { 121 size_t optlen; 122 123 switch (option) { 124 case SCTP_PRSCTP_OPTION: 125 optlen = sizeof (sctp_parm_hdr_t); 126 break; 127 default: 128 ASSERT(0); 129 } 130 131 return (optlen); 132 } 133 134 /*ARGSUSED*/ 135 size_t 136 sctp_options_param(const sctp_t *sctp, void *p, int option) 137 { 138 sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 139 140 switch (option) { 141 case SCTP_PRSCTP_OPTION: 142 sph->sph_type = htons(PARM_FORWARD_TSN); 143 sph->sph_len = htons(sizeof (*sph)); 144 break; 145 default: 146 ASSERT(0); 147 } 148 149 return (sizeof (*sph)); 150 151 } 152 153 size_t 154 sctp_adaption_code_param(sctp_t *sctp, uchar_t *p) 155 { 156 sctp_parm_hdr_t *sph; 157 158 if (!sctp->sctp_send_adaption) { 159 return (0); 160 } 161 sph = (sctp_parm_hdr_t *)p; 162 sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 163 sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 164 *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaption_code); 165 166 return (sizeof (*sph) + sizeof (uint32_t)); 167 } 168 169 mblk_t * 170 sctp_init_mp(sctp_t *sctp) 171 { 172 mblk_t *mp; 173 uchar_t *p; 174 size_t initlen; 175 sctp_init_chunk_t *icp; 176 sctp_chunk_hdr_t *chp; 177 uint16_t schlen; 178 int supp_af; 179 sctp_stack_t *sctps = sctp->sctp_sctps; 180 181 if (sctp->sctp_family == AF_INET) { 182 supp_af = PARM_SUPP_V4; 183 } else { 184 /* Assume here that a v6 endpoint supports v4 address. */ 185 if (sctp->sctp_connp->conn_ipv6_v6only) 186 supp_af = PARM_SUPP_V6; 187 else 188 supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 189 } 190 initlen = sizeof (*chp) + sizeof (*icp); 191 if (sctp->sctp_send_adaption) { 192 initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 193 } 194 initlen += sctp_supaddr_param_len(sctp); 195 initlen += sctp_addr_params_len(sctp, supp_af, B_TRUE); 196 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 197 initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 198 199 /* 200 * This could be a INIT retransmission in which case sh_verf may 201 * be non-zero, zero it out just to be sure. 202 */ 203 sctp->sctp_sctph->sh_verf = 0; 204 sctp->sctp_sctph6->sh_verf = 0; 205 206 mp = sctp_make_mp(sctp, NULL, initlen); 207 if (mp == NULL) { 208 SCTP_KSTAT(sctps, sctp_send_init_failed); 209 return (NULL); 210 } 211 212 /* Lay in a new INIT chunk, starting with the chunk header */ 213 chp = (sctp_chunk_hdr_t *)mp->b_wptr; 214 chp->sch_id = CHUNK_INIT; 215 chp->sch_flags = 0; 216 schlen = (uint16_t)initlen; 217 U16_TO_ABE16(schlen, &(chp->sch_len)); 218 219 mp->b_wptr += initlen; 220 221 icp = (sctp_init_chunk_t *)(chp + 1); 222 icp->sic_inittag = sctp->sctp_lvtag; 223 U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 224 U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 225 U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 226 U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 227 228 p = (uchar_t *)(icp + 1); 229 230 /* Adaption layer param */ 231 p += sctp_adaption_code_param(sctp, p); 232 233 /* Add supported address types parameter */ 234 p += sctp_supaddr_param(sctp, p); 235 236 /* Add address parameters */ 237 p += sctp_addr_params(sctp, supp_af, p); 238 239 /* Add Forward-TSN-Supported param */ 240 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 241 p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 242 243 BUMP_LOCAL(sctp->sctp_obchunks); 244 245 sctp_set_iplen(sctp, mp); 246 247 return (mp); 248 } 249 250 /* 251 * Extracts the verification tag from an INIT chunk. If the INIT 252 * chunk is truncated or malformed, returns 0. 253 */ 254 uint32_t 255 sctp_init2vtag(sctp_chunk_hdr_t *initch) 256 { 257 sctp_init_chunk_t *init; 258 259 init = (sctp_init_chunk_t *)(initch + 1); 260 return (init->sic_inittag); 261 } 262 263 size_t 264 sctp_addr_params_len(sctp_t *sctp, int af, boolean_t modify) 265 { 266 ASSERT(sctp->sctp_nsaddrs > 0); 267 268 /* 269 * If we have only one local address or it is a loopback or linklocal 270 * association, we let the peer pull the address from the IP header. 271 */ 272 if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback || 273 sctp->sctp_linklocal) { 274 return (0); 275 } 276 277 return (sctp_saddr_info(sctp, af, NULL, modify)); 278 } 279 280 size_t 281 sctp_addr_params(sctp_t *sctp, int af, uchar_t *p) 282 { 283 /* 284 * If we have only one local address or it is a loopback or linklocal 285 * association, we let the peer pull the address from the IP header. 286 */ 287 if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback || 288 sctp->sctp_linklocal) { 289 return (0); 290 } 291 return (sctp_saddr_info(sctp, af, p, B_FALSE)); 292 } 293