1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/types.h> 30*0Sstevel@tonic-gate #include <sys/systm.h> 31*0Sstevel@tonic-gate #include <sys/stream.h> 32*0Sstevel@tonic-gate #include <sys/cmn_err.h> 33*0Sstevel@tonic-gate #include <sys/md5.h> 34*0Sstevel@tonic-gate #include <sys/kmem.h> 35*0Sstevel@tonic-gate #include <sys/strsubr.h> 36*0Sstevel@tonic-gate #include <sys/random.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate #include <netinet/in.h> 39*0Sstevel@tonic-gate #include <netinet/ip6.h> 40*0Sstevel@tonic-gate 41*0Sstevel@tonic-gate #include <inet/common.h> 42*0Sstevel@tonic-gate #include <inet/ip.h> 43*0Sstevel@tonic-gate #include <inet/ip6.h> 44*0Sstevel@tonic-gate #include <inet/sctp_ip.h> 45*0Sstevel@tonic-gate #include <inet/ipclassifier.h> 46*0Sstevel@tonic-gate #include "sctp_impl.h" 47*0Sstevel@tonic-gate 48*0Sstevel@tonic-gate /* 49*0Sstevel@tonic-gate * From RFC 2104. This should probably go into libmd5 (and while 50*0Sstevel@tonic-gate * we're at it, maybe we should make a libdigest so we can later 51*0Sstevel@tonic-gate * add SHA1 and others, esp. since some weaknesses have been found 52*0Sstevel@tonic-gate * with MD5). 53*0Sstevel@tonic-gate * 54*0Sstevel@tonic-gate * text IN pointer to data stream 55*0Sstevel@tonic-gate * text_len IN length of data stream 56*0Sstevel@tonic-gate * key IN pointer to authentication key 57*0Sstevel@tonic-gate * key_len IN length of authentication key 58*0Sstevel@tonic-gate * digest OUT caller digest to be filled in 59*0Sstevel@tonic-gate */ 60*0Sstevel@tonic-gate static void 61*0Sstevel@tonic-gate hmac_md5(uchar_t *text, size_t text_len, uchar_t *key, size_t key_len, 62*0Sstevel@tonic-gate uchar_t *digest) 63*0Sstevel@tonic-gate { 64*0Sstevel@tonic-gate MD5_CTX context; 65*0Sstevel@tonic-gate uchar_t k_ipad[65]; /* inner padding - key XORd with ipad */ 66*0Sstevel@tonic-gate uchar_t k_opad[65]; /* outer padding - key XORd with opad */ 67*0Sstevel@tonic-gate uchar_t tk[16]; 68*0Sstevel@tonic-gate int i; 69*0Sstevel@tonic-gate 70*0Sstevel@tonic-gate /* if key is longer than 64 bytes reset it to key=MD5(key) */ 71*0Sstevel@tonic-gate if (key_len > 64) { 72*0Sstevel@tonic-gate MD5_CTX tctx; 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate MD5Init(&tctx); 75*0Sstevel@tonic-gate MD5Update(&tctx, key, key_len); 76*0Sstevel@tonic-gate MD5Final(tk, &tctx); 77*0Sstevel@tonic-gate 78*0Sstevel@tonic-gate key = tk; 79*0Sstevel@tonic-gate key_len = 16; 80*0Sstevel@tonic-gate } 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate /* 83*0Sstevel@tonic-gate * the HMAC_MD5 transform looks like: 84*0Sstevel@tonic-gate * 85*0Sstevel@tonic-gate * MD5(K XOR opad, MD5(K XOR ipad, text)) 86*0Sstevel@tonic-gate * 87*0Sstevel@tonic-gate * where K is an n byte key 88*0Sstevel@tonic-gate * ipad is the byte 0x36 repeated 64 times 89*0Sstevel@tonic-gate * opad is the byte 0x5c repeated 64 times 90*0Sstevel@tonic-gate * and text is the data being protected 91*0Sstevel@tonic-gate */ 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gate /* start out by storing key in pads */ 94*0Sstevel@tonic-gate bzero(k_ipad, sizeof (k_ipad)); 95*0Sstevel@tonic-gate bzero(k_opad, sizeof (k_opad)); 96*0Sstevel@tonic-gate bcopy(key, k_ipad, key_len); 97*0Sstevel@tonic-gate bcopy(key, k_opad, key_len); 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate /* XOR key with ipad and opad values */ 100*0Sstevel@tonic-gate for (i = 0; i < 64; i++) { 101*0Sstevel@tonic-gate k_ipad[i] ^= 0x36; 102*0Sstevel@tonic-gate k_opad[i] ^= 0x5c; 103*0Sstevel@tonic-gate } 104*0Sstevel@tonic-gate /* 105*0Sstevel@tonic-gate * perform inner MD5 106*0Sstevel@tonic-gate */ 107*0Sstevel@tonic-gate MD5Init(&context); /* init context for 1st */ 108*0Sstevel@tonic-gate /* pass */ 109*0Sstevel@tonic-gate MD5Update(&context, k_ipad, 64); /* start with inner pad */ 110*0Sstevel@tonic-gate MD5Update(&context, text, text_len); /* then text of datagram */ 111*0Sstevel@tonic-gate MD5Final(digest, &context); /* finish up 1st pass */ 112*0Sstevel@tonic-gate /* 113*0Sstevel@tonic-gate * perform outer MD5 114*0Sstevel@tonic-gate */ 115*0Sstevel@tonic-gate MD5Init(&context); /* init context for 2nd */ 116*0Sstevel@tonic-gate /* pass */ 117*0Sstevel@tonic-gate MD5Update(&context, k_opad, 64); /* start with outer pad */ 118*0Sstevel@tonic-gate MD5Update(&context, digest, 16); /* then results of 1st */ 119*0Sstevel@tonic-gate /* hash */ 120*0Sstevel@tonic-gate MD5Final(digest, &context); /* finish up 2nd pass */ 121*0Sstevel@tonic-gate } 122*0Sstevel@tonic-gate 123*0Sstevel@tonic-gate /* 124*0Sstevel@tonic-gate * If inmp is non-NULL, and we need to abort, it will use the IP/SCTP 125*0Sstevel@tonic-gate * info in initmp to send the abort. Otherwise, no abort will be sent. 126*0Sstevel@tonic-gate * If errmp is non-NULL, a chain of unrecognized parameters will 127*0Sstevel@tonic-gate * be created and returned via *errmp. 128*0Sstevel@tonic-gate * 129*0Sstevel@tonic-gate * Returns 1 if the parameters are OK (or there are no parameters), or 130*0Sstevel@tonic-gate * 0 if not. 131*0Sstevel@tonic-gate */ 132*0Sstevel@tonic-gate static int 133*0Sstevel@tonic-gate validate_init_params(sctp_t *sctp, sctp_chunk_hdr_t *ch, 134*0Sstevel@tonic-gate sctp_init_chunk_t *init, mblk_t *inmp, sctp_parm_hdr_t **want_cookie, 135*0Sstevel@tonic-gate mblk_t **errmp, int *supp_af, uint_t *sctp_options) 136*0Sstevel@tonic-gate { 137*0Sstevel@tonic-gate sctp_parm_hdr_t *cph; 138*0Sstevel@tonic-gate sctp_init_chunk_t *ic; 139*0Sstevel@tonic-gate ssize_t remaining; 140*0Sstevel@tonic-gate uint16_t serror = 0; 141*0Sstevel@tonic-gate char *details = NULL; 142*0Sstevel@tonic-gate size_t errlen = 0; 143*0Sstevel@tonic-gate boolean_t got_cookie = B_FALSE; 144*0Sstevel@tonic-gate uint16_t ptype; 145*0Sstevel@tonic-gate 146*0Sstevel@tonic-gate *supp_af = 0; 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (sctp_options != NULL) 149*0Sstevel@tonic-gate *sctp_options = 0; 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate /* First validate stream parameters */ 152*0Sstevel@tonic-gate if (init->sic_instr == 0 || init->sic_outstr == 0) { 153*0Sstevel@tonic-gate serror = SCTP_ERR_BAD_MANDPARM; 154*0Sstevel@tonic-gate dprint(1, 155*0Sstevel@tonic-gate ("validate_init_params: bad sid, is=%d os=%d\n", 156*0Sstevel@tonic-gate htons(init->sic_instr), htons(init->sic_outstr))); 157*0Sstevel@tonic-gate goto abort; 158*0Sstevel@tonic-gate } 159*0Sstevel@tonic-gate if (ntohl(init->sic_inittag) == 0) { 160*0Sstevel@tonic-gate serror = SCTP_ERR_BAD_MANDPARM; 161*0Sstevel@tonic-gate dprint(1, ("validate_init_params: inittag = 0\n")); 162*0Sstevel@tonic-gate goto abort; 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate remaining = ntohs(ch->sch_len) - sizeof (*ch); 166*0Sstevel@tonic-gate ic = (sctp_init_chunk_t *)(ch + 1); 167*0Sstevel@tonic-gate remaining -= sizeof (*ic); 168*0Sstevel@tonic-gate if (remaining < sizeof (*cph)) { 169*0Sstevel@tonic-gate /* Nothing to validate */ 170*0Sstevel@tonic-gate if (want_cookie != NULL) 171*0Sstevel@tonic-gate goto cookie_abort; 172*0Sstevel@tonic-gate return (1); 173*0Sstevel@tonic-gate } 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate cph = (sctp_parm_hdr_t *)(ic + 1); 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate while (cph != NULL) { 178*0Sstevel@tonic-gate ptype = ntohs(cph->sph_type); 179*0Sstevel@tonic-gate switch (ptype) { 180*0Sstevel@tonic-gate case PARM_HBINFO: 181*0Sstevel@tonic-gate case PARM_UNRECOGNIZED: 182*0Sstevel@tonic-gate case PARM_ECN: 183*0Sstevel@tonic-gate /* just ignore them */ 184*0Sstevel@tonic-gate break; 185*0Sstevel@tonic-gate case PARM_FORWARD_TSN: 186*0Sstevel@tonic-gate if (sctp_options != NULL) 187*0Sstevel@tonic-gate *sctp_options |= SCTP_PRSCTP_OPTION; 188*0Sstevel@tonic-gate break; 189*0Sstevel@tonic-gate case PARM_COOKIE: 190*0Sstevel@tonic-gate got_cookie = B_TRUE; 191*0Sstevel@tonic-gate if (want_cookie != NULL) { 192*0Sstevel@tonic-gate *want_cookie = cph; 193*0Sstevel@tonic-gate } 194*0Sstevel@tonic-gate break; 195*0Sstevel@tonic-gate case PARM_ADDR4: 196*0Sstevel@tonic-gate case PARM_ADDR6: 197*0Sstevel@tonic-gate case PARM_COOKIE_PRESERVE: 198*0Sstevel@tonic-gate case PARM_ADAPT_LAYER_IND: 199*0Sstevel@tonic-gate /* These are OK */ 200*0Sstevel@tonic-gate break; 201*0Sstevel@tonic-gate case PARM_ADDR_HOST_NAME: 202*0Sstevel@tonic-gate /* Don't support this; abort the association */ 203*0Sstevel@tonic-gate serror = SCTP_ERR_BAD_ADDR; 204*0Sstevel@tonic-gate details = (char *)cph; 205*0Sstevel@tonic-gate errlen = ntohs(cph->sph_len); 206*0Sstevel@tonic-gate dprint(1, ("sctp:validate_init_params: host addr\n")); 207*0Sstevel@tonic-gate goto abort; 208*0Sstevel@tonic-gate case PARM_SUPP_ADDRS: { 209*0Sstevel@tonic-gate /* Make sure we have a supported addr intersection */ 210*0Sstevel@tonic-gate uint16_t *p, addrtype; 211*0Sstevel@tonic-gate int plen; 212*0Sstevel@tonic-gate 213*0Sstevel@tonic-gate plen = ntohs(cph->sph_len); 214*0Sstevel@tonic-gate p = (uint16_t *)(cph + 1); 215*0Sstevel@tonic-gate while (plen > 0) { 216*0Sstevel@tonic-gate addrtype = ntohs(*p); 217*0Sstevel@tonic-gate switch (addrtype) { 218*0Sstevel@tonic-gate case PARM_ADDR6: 219*0Sstevel@tonic-gate *supp_af |= PARM_SUPP_V6; 220*0Sstevel@tonic-gate break; 221*0Sstevel@tonic-gate case PARM_ADDR4: 222*0Sstevel@tonic-gate *supp_af |= PARM_SUPP_V4; 223*0Sstevel@tonic-gate break; 224*0Sstevel@tonic-gate default: 225*0Sstevel@tonic-gate /* 226*0Sstevel@tonic-gate * Do nothing, silently ignore hostname 227*0Sstevel@tonic-gate * address. 228*0Sstevel@tonic-gate */ 229*0Sstevel@tonic-gate break; 230*0Sstevel@tonic-gate } 231*0Sstevel@tonic-gate p++; 232*0Sstevel@tonic-gate plen -= sizeof (*p); 233*0Sstevel@tonic-gate } 234*0Sstevel@tonic-gate /* 235*0Sstevel@tonic-gate * Some sanity checks. The following should not 236*0Sstevel@tonic-gate * fail unless the other side is broken. 237*0Sstevel@tonic-gate * 238*0Sstevel@tonic-gate * 1. If there is no supported address type yet the 239*0Sstevel@tonic-gate * supported address parameter is present, abort. 240*0Sstevel@tonic-gate * 2. If this is a V4 endpoint but V4 address is not 241*0Sstevel@tonic-gate * supported, abort. 242*0Sstevel@tonic-gate * 3. If this is a V6 only endpoint but V6 address is 243*0Sstevel@tonic-gate * not supported, abort. This assumes that a V6 244*0Sstevel@tonic-gate * endpoint can use both V4 and V6 addresses. 245*0Sstevel@tonic-gate */ 246*0Sstevel@tonic-gate if (*supp_af == 0 || 247*0Sstevel@tonic-gate (sctp->sctp_family == AF_INET && 248*0Sstevel@tonic-gate !(*supp_af & PARM_SUPP_V4)) || 249*0Sstevel@tonic-gate (sctp->sctp_family == AF_INET6 && 250*0Sstevel@tonic-gate !(*supp_af & PARM_SUPP_V6) && 251*0Sstevel@tonic-gate sctp->sctp_connp->conn_ipv6_v6only)) { 252*0Sstevel@tonic-gate dprint(1, 253*0Sstevel@tonic-gate ("sctp:validate_init_params: no supp addr\n")); 254*0Sstevel@tonic-gate serror = SCTP_ERR_BAD_ADDR; 255*0Sstevel@tonic-gate goto abort; 256*0Sstevel@tonic-gate } 257*0Sstevel@tonic-gate break; 258*0Sstevel@tonic-gate } 259*0Sstevel@tonic-gate default: 260*0Sstevel@tonic-gate /* Unrecognized param; check the high order bits */ 261*0Sstevel@tonic-gate if ((ptype & 0xc000) == 0xc000) { 262*0Sstevel@tonic-gate /* 263*0Sstevel@tonic-gate * report unrecognized param, and 264*0Sstevel@tonic-gate * keep processing 265*0Sstevel@tonic-gate */ 266*0Sstevel@tonic-gate if (errmp != NULL) { 267*0Sstevel@tonic-gate if (want_cookie != NULL) { 268*0Sstevel@tonic-gate *errmp = sctp_make_err(sctp, 269*0Sstevel@tonic-gate PARM_UNRECOGNIZED, 270*0Sstevel@tonic-gate (void *)cph, 271*0Sstevel@tonic-gate ntohs(cph->sph_len)); 272*0Sstevel@tonic-gate } else { 273*0Sstevel@tonic-gate sctp_add_unrec_parm(cph, errmp); 274*0Sstevel@tonic-gate } 275*0Sstevel@tonic-gate } 276*0Sstevel@tonic-gate break; 277*0Sstevel@tonic-gate } 278*0Sstevel@tonic-gate if (ptype & 0x4000) { 279*0Sstevel@tonic-gate /* 280*0Sstevel@tonic-gate * Stop processing and drop; report 281*0Sstevel@tonic-gate * unrecognized param 282*0Sstevel@tonic-gate */ 283*0Sstevel@tonic-gate serror = SCTP_ERR_UNREC_PARM; 284*0Sstevel@tonic-gate details = (char *)cph; 285*0Sstevel@tonic-gate errlen = ntohs(cph->sph_len); 286*0Sstevel@tonic-gate goto abort; 287*0Sstevel@tonic-gate } 288*0Sstevel@tonic-gate if (ptype & 0x8000) { 289*0Sstevel@tonic-gate /* skip and continue processing */ 290*0Sstevel@tonic-gate break; 291*0Sstevel@tonic-gate } 292*0Sstevel@tonic-gate 293*0Sstevel@tonic-gate /* 294*0Sstevel@tonic-gate * 2 high bits are clear; stop processing and 295*0Sstevel@tonic-gate * drop packet 296*0Sstevel@tonic-gate */ 297*0Sstevel@tonic-gate return (0); 298*0Sstevel@tonic-gate } 299*0Sstevel@tonic-gate 300*0Sstevel@tonic-gate cph = sctp_next_parm(cph, &remaining); 301*0Sstevel@tonic-gate } 302*0Sstevel@tonic-gate 303*0Sstevel@tonic-gate if (want_cookie != NULL && !got_cookie) { 304*0Sstevel@tonic-gate cookie_abort: 305*0Sstevel@tonic-gate dprint(1, ("validate_init_params: cookie absent\n")); 306*0Sstevel@tonic-gate sctp_send_abort(sctp, sctp_init2vtag(ch), SCTP_ERR_MISSING_PARM, 307*0Sstevel@tonic-gate details, errlen, inmp, 0, B_FALSE); 308*0Sstevel@tonic-gate return (0); 309*0Sstevel@tonic-gate } 310*0Sstevel@tonic-gate 311*0Sstevel@tonic-gate /* OK */ 312*0Sstevel@tonic-gate return (1); 313*0Sstevel@tonic-gate 314*0Sstevel@tonic-gate abort: 315*0Sstevel@tonic-gate if (want_cookie != NULL) 316*0Sstevel@tonic-gate return (0); 317*0Sstevel@tonic-gate 318*0Sstevel@tonic-gate sctp_send_abort(sctp, sctp_init2vtag(ch), serror, details, 319*0Sstevel@tonic-gate errlen, inmp, 0, B_FALSE); 320*0Sstevel@tonic-gate return (0); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate 323*0Sstevel@tonic-gate /* 324*0Sstevel@tonic-gate * Initialize params from the INIT and INIT-ACK when the assoc. is 325*0Sstevel@tonic-gate * established. 326*0Sstevel@tonic-gate */ 327*0Sstevel@tonic-gate boolean_t 328*0Sstevel@tonic-gate sctp_initialize_params(sctp_t *sctp, sctp_init_chunk_t *init, 329*0Sstevel@tonic-gate sctp_init_chunk_t *iack) 330*0Sstevel@tonic-gate { 331*0Sstevel@tonic-gate /* Get initial TSN */ 332*0Sstevel@tonic-gate sctp->sctp_ftsn = ntohl(init->sic_inittsn); 333*0Sstevel@tonic-gate sctp->sctp_lastacked = sctp->sctp_ftsn - 1; 334*0Sstevel@tonic-gate 335*0Sstevel@tonic-gate /* Serial number is initialized to the same value as the TSN */ 336*0Sstevel@tonic-gate sctp->sctp_fcsn = sctp->sctp_lastacked; 337*0Sstevel@tonic-gate 338*0Sstevel@tonic-gate /* 339*0Sstevel@tonic-gate * Get verification tags; no byteordering is necessary, since 340*0Sstevel@tonic-gate * verfication tags are never processed except for byte-by-byte 341*0Sstevel@tonic-gate * comparisons. 342*0Sstevel@tonic-gate */ 343*0Sstevel@tonic-gate sctp->sctp_fvtag = init->sic_inittag; 344*0Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = init->sic_inittag; 345*0Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = init->sic_inittag; 346*0Sstevel@tonic-gate sctp->sctp_lvtag = iack->sic_inittag; 347*0Sstevel@tonic-gate 348*0Sstevel@tonic-gate /* Get the peer's rwnd */ 349*0Sstevel@tonic-gate sctp->sctp_frwnd = ntohl(init->sic_a_rwnd); 350*0Sstevel@tonic-gate 351*0Sstevel@tonic-gate /* Allocate the in/out-stream counters */ 352*0Sstevel@tonic-gate sctp->sctp_num_ostr = iack->sic_outstr; 353*0Sstevel@tonic-gate sctp->sctp_ostrcntrs = kmem_zalloc(sizeof (uint16_t) * 354*0Sstevel@tonic-gate sctp->sctp_num_ostr, KM_NOSLEEP); 355*0Sstevel@tonic-gate if (sctp->sctp_ostrcntrs == NULL) 356*0Sstevel@tonic-gate return (B_FALSE); 357*0Sstevel@tonic-gate 358*0Sstevel@tonic-gate sctp->sctp_num_istr = iack->sic_instr; 359*0Sstevel@tonic-gate sctp->sctp_instr = kmem_zalloc(sizeof (*sctp->sctp_instr) * 360*0Sstevel@tonic-gate sctp->sctp_num_istr, KM_NOSLEEP); 361*0Sstevel@tonic-gate if (sctp->sctp_instr == NULL) { 362*0Sstevel@tonic-gate kmem_free(sctp->sctp_ostrcntrs, sizeof (uint16_t) * 363*0Sstevel@tonic-gate sctp->sctp_num_ostr); 364*0Sstevel@tonic-gate sctp->sctp_ostrcntrs = NULL; 365*0Sstevel@tonic-gate return (B_FALSE); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate return (B_TRUE); 368*0Sstevel@tonic-gate } 369*0Sstevel@tonic-gate 370*0Sstevel@tonic-gate #define SCTP_CALC_COOKIE_LEN(initcp) \ 371*0Sstevel@tonic-gate sizeof (int64_t) + /* timestamp */ \ 372*0Sstevel@tonic-gate sizeof (uint32_t) + /* cookie lifetime */ \ 373*0Sstevel@tonic-gate sizeof (sctp_init_chunk_t) + /* INIT ACK */ \ 374*0Sstevel@tonic-gate sizeof (in6_addr_t) + /* peer's original source */ \ 375*0Sstevel@tonic-gate ntohs((initcp)->sch_len) + /* peer's INIT */ \ 376*0Sstevel@tonic-gate sizeof (uint32_t) + /* local tie-tag */ \ 377*0Sstevel@tonic-gate sizeof (uint32_t) + /* peer tie-tag */ \ 378*0Sstevel@tonic-gate sizeof (sctp_parm_hdr_t) + /* param header */ \ 379*0Sstevel@tonic-gate 16 /* MD5 hash */ 380*0Sstevel@tonic-gate 381*0Sstevel@tonic-gate void 382*0Sstevel@tonic-gate sctp_send_initack(sctp_t *sctp, sctp_chunk_hdr_t *ch, mblk_t *initmp) 383*0Sstevel@tonic-gate { 384*0Sstevel@tonic-gate ipha_t *initiph; 385*0Sstevel@tonic-gate ip6_t *initip6h; 386*0Sstevel@tonic-gate ipha_t *iackiph; 387*0Sstevel@tonic-gate ip6_t *iackip6h; 388*0Sstevel@tonic-gate sctp_chunk_hdr_t *iack_ch; 389*0Sstevel@tonic-gate sctp_init_chunk_t *iack; 390*0Sstevel@tonic-gate sctp_init_chunk_t *init; 391*0Sstevel@tonic-gate sctp_hdr_t *iacksh; 392*0Sstevel@tonic-gate sctp_hdr_t *initsh; 393*0Sstevel@tonic-gate size_t cookielen; 394*0Sstevel@tonic-gate size_t iacklen; 395*0Sstevel@tonic-gate size_t ipsctplen; 396*0Sstevel@tonic-gate size_t errlen = 0; 397*0Sstevel@tonic-gate sctp_parm_hdr_t *cookieph; 398*0Sstevel@tonic-gate mblk_t *iackmp; 399*0Sstevel@tonic-gate uint32_t itag; 400*0Sstevel@tonic-gate uint32_t itsn; 401*0Sstevel@tonic-gate int64_t *now; 402*0Sstevel@tonic-gate int64_t nowt; 403*0Sstevel@tonic-gate uint32_t *lifetime; 404*0Sstevel@tonic-gate char *p; 405*0Sstevel@tonic-gate boolean_t isv4; 406*0Sstevel@tonic-gate int supp_af; 407*0Sstevel@tonic-gate uint_t sctp_options; 408*0Sstevel@tonic-gate uint32_t *ttag; 409*0Sstevel@tonic-gate int pad; 410*0Sstevel@tonic-gate mblk_t *errmp = NULL; 411*0Sstevel@tonic-gate boolean_t initcollision = B_FALSE; 412*0Sstevel@tonic-gate 413*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_ibchunks); 414*0Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(initmp->b_rptr) == IPV4_VERSION); 415*0Sstevel@tonic-gate 416*0Sstevel@tonic-gate /* Extract the INIT chunk */ 417*0Sstevel@tonic-gate if (isv4) { 418*0Sstevel@tonic-gate initiph = (ipha_t *)initmp->b_rptr; 419*0Sstevel@tonic-gate initsh = (sctp_hdr_t *)((char *)initiph + 420*0Sstevel@tonic-gate IPH_HDR_LENGTH(initmp->b_rptr)); 421*0Sstevel@tonic-gate ipsctplen = sctp->sctp_ip_hdr_len; 422*0Sstevel@tonic-gate } else { 423*0Sstevel@tonic-gate initip6h = (ip6_t *)initmp->b_rptr; 424*0Sstevel@tonic-gate initsh = (sctp_hdr_t *)(initip6h + 1); 425*0Sstevel@tonic-gate ipsctplen = sctp->sctp_ip_hdr6_len; 426*0Sstevel@tonic-gate } 427*0Sstevel@tonic-gate ASSERT(OK_32PTR(initsh)); 428*0Sstevel@tonic-gate init = (sctp_init_chunk_t *)((char *)(initsh + 1) + sizeof (*iack_ch)); 429*0Sstevel@tonic-gate 430*0Sstevel@tonic-gate /* Make sure we like the peer's parameters */ 431*0Sstevel@tonic-gate if (validate_init_params(sctp, ch, init, initmp, NULL, &errmp, 432*0Sstevel@tonic-gate &supp_af, &sctp_options) == 0) { 433*0Sstevel@tonic-gate return; 434*0Sstevel@tonic-gate } 435*0Sstevel@tonic-gate if (errmp != NULL) 436*0Sstevel@tonic-gate errlen = msgdsize(errmp); 437*0Sstevel@tonic-gate if (sctp->sctp_family == AF_INET) { 438*0Sstevel@tonic-gate /* 439*0Sstevel@tonic-gate * Irregardless of the supported address in the INIT, v4 440*0Sstevel@tonic-gate * must be supported. 441*0Sstevel@tonic-gate */ 442*0Sstevel@tonic-gate supp_af = PARM_SUPP_V4; 443*0Sstevel@tonic-gate } else { 444*0Sstevel@tonic-gate /* 445*0Sstevel@tonic-gate * No supported addresses parameter in INIT. Assume 446*0Sstevel@tonic-gate * both v4 and v6 are supported. 447*0Sstevel@tonic-gate */ 448*0Sstevel@tonic-gate if (supp_af == 0) { 449*0Sstevel@tonic-gate supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 450*0Sstevel@tonic-gate } 451*0Sstevel@tonic-gate } 452*0Sstevel@tonic-gate if (sctp->sctp_state <= SCTPS_LISTEN) { 453*0Sstevel@tonic-gate /* normal, expected INIT: generate new vtag and itsn */ 454*0Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)&itag, sizeof (itag)); 455*0Sstevel@tonic-gate if (itag == 0) 456*0Sstevel@tonic-gate itag = (uint32_t)gethrtime(); 457*0Sstevel@tonic-gate itsn = itag + 1; 458*0Sstevel@tonic-gate itag = htonl(itag); 459*0Sstevel@tonic-gate } else if (sctp->sctp_state == SCTPS_COOKIE_WAIT || 460*0Sstevel@tonic-gate sctp->sctp_state == SCTPS_COOKIE_ECHOED) { 461*0Sstevel@tonic-gate /* init collision; copy vtag and itsn from sctp */ 462*0Sstevel@tonic-gate itag = sctp->sctp_lvtag; 463*0Sstevel@tonic-gate itsn = sctp->sctp_ltsn; 464*0Sstevel@tonic-gate /* 465*0Sstevel@tonic-gate * In addition we need to send all the params that was sent 466*0Sstevel@tonic-gate * in our INIT chunk. Essentially, it is only the supported 467*0Sstevel@tonic-gate * address params that we need to add. 468*0Sstevel@tonic-gate */ 469*0Sstevel@tonic-gate initcollision = B_TRUE; 470*0Sstevel@tonic-gate } else { 471*0Sstevel@tonic-gate /* peer restart; generate new vtag but keep everything else */ 472*0Sstevel@tonic-gate (void) random_get_pseudo_bytes((uint8_t *)&itag, sizeof (itag)); 473*0Sstevel@tonic-gate if (itag == 0) 474*0Sstevel@tonic-gate itag = (uint32_t)gethrtime(); 475*0Sstevel@tonic-gate itag = htonl(itag); 476*0Sstevel@tonic-gate itsn = sctp->sctp_ltsn; 477*0Sstevel@tonic-gate } 478*0Sstevel@tonic-gate 479*0Sstevel@tonic-gate /* 480*0Sstevel@tonic-gate * Allocate a mblk for the INIT ACK, consisting of the link layer 481*0Sstevel@tonic-gate * header, the IP header, the SCTP common header, and INIT ACK chunk, 482*0Sstevel@tonic-gate * and finally the COOKIE parameter. 483*0Sstevel@tonic-gate */ 484*0Sstevel@tonic-gate cookielen = SCTP_CALC_COOKIE_LEN(ch); 485*0Sstevel@tonic-gate iacklen = sizeof (*iack_ch) + sizeof (*iack) + cookielen; 486*0Sstevel@tonic-gate if (sctp->sctp_send_adaption) 487*0Sstevel@tonic-gate iacklen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 488*0Sstevel@tonic-gate if (((sctp_options & SCTP_PRSCTP_OPTION) || initcollision) && 489*0Sstevel@tonic-gate sctp->sctp_prsctp_aware && sctp_prsctp_enabled) { 490*0Sstevel@tonic-gate iacklen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 491*0Sstevel@tonic-gate } 492*0Sstevel@tonic-gate if (initcollision) 493*0Sstevel@tonic-gate iacklen += sctp_supaddr_param_len(sctp); 494*0Sstevel@tonic-gate iacklen += sctp_addr_params_len(sctp, supp_af); 495*0Sstevel@tonic-gate ipsctplen += sizeof (*iacksh) + iacklen; 496*0Sstevel@tonic-gate iacklen += errlen; 497*0Sstevel@tonic-gate if ((pad = ipsctplen % 4) != 0) { 498*0Sstevel@tonic-gate pad = 4 - pad; 499*0Sstevel@tonic-gate ipsctplen += pad; 500*0Sstevel@tonic-gate } 501*0Sstevel@tonic-gate iackmp = allocb(ipsctplen + sctp_wroff_xtra, BPRI_MED); 502*0Sstevel@tonic-gate if (iackmp == NULL) { 503*0Sstevel@tonic-gate sctp_send_abort(sctp, sctp_init2vtag(ch), 504*0Sstevel@tonic-gate SCTP_ERR_NO_RESOURCES, NULL, 0, initmp, 0, B_FALSE); 505*0Sstevel@tonic-gate return; 506*0Sstevel@tonic-gate } 507*0Sstevel@tonic-gate 508*0Sstevel@tonic-gate /* Copy in the [imcomplete] IP/SCTP composite header */ 509*0Sstevel@tonic-gate p = (char *)(iackmp->b_rptr + sctp_wroff_xtra); 510*0Sstevel@tonic-gate iackmp->b_rptr = (uchar_t *)p; 511*0Sstevel@tonic-gate if (isv4) { 512*0Sstevel@tonic-gate bcopy(sctp->sctp_iphc, p, sctp->sctp_hdr_len); 513*0Sstevel@tonic-gate iackiph = (ipha_t *)p; 514*0Sstevel@tonic-gate 515*0Sstevel@tonic-gate /* Copy the peer's IP addr */ 516*0Sstevel@tonic-gate iackiph->ipha_dst = initiph->ipha_src; 517*0Sstevel@tonic-gate iackiph->ipha_src = initiph->ipha_dst; 518*0Sstevel@tonic-gate iackiph->ipha_length = htons(ipsctplen + errlen); 519*0Sstevel@tonic-gate iacksh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr_len); 520*0Sstevel@tonic-gate } else { 521*0Sstevel@tonic-gate bcopy(sctp->sctp_iphc6, p, sctp->sctp_hdr6_len); 522*0Sstevel@tonic-gate iackip6h = (ip6_t *)p; 523*0Sstevel@tonic-gate 524*0Sstevel@tonic-gate /* Copy the peer's IP addr */ 525*0Sstevel@tonic-gate iackip6h->ip6_dst = initip6h->ip6_src; 526*0Sstevel@tonic-gate iackip6h->ip6_src = initip6h->ip6_dst; 527*0Sstevel@tonic-gate iackip6h->ip6_plen = htons(ipsctplen - sizeof (*iackip6h) + 528*0Sstevel@tonic-gate errlen); 529*0Sstevel@tonic-gate iacksh = (sctp_hdr_t *)(p + sctp->sctp_ip_hdr6_len); 530*0Sstevel@tonic-gate } 531*0Sstevel@tonic-gate ASSERT(OK_32PTR(iacksh)); 532*0Sstevel@tonic-gate 533*0Sstevel@tonic-gate /* Fill in the holes in the SCTP common header */ 534*0Sstevel@tonic-gate iacksh->sh_sport = initsh->sh_dport; 535*0Sstevel@tonic-gate iacksh->sh_dport = initsh->sh_sport; 536*0Sstevel@tonic-gate iacksh->sh_verf = init->sic_inittag; 537*0Sstevel@tonic-gate 538*0Sstevel@tonic-gate /* INIT ACK chunk header */ 539*0Sstevel@tonic-gate iack_ch = (sctp_chunk_hdr_t *)(iacksh + 1); 540*0Sstevel@tonic-gate iack_ch->sch_id = CHUNK_INIT_ACK; 541*0Sstevel@tonic-gate iack_ch->sch_flags = 0; 542*0Sstevel@tonic-gate iack_ch->sch_len = htons(iacklen); 543*0Sstevel@tonic-gate 544*0Sstevel@tonic-gate /* The INIT ACK itself */ 545*0Sstevel@tonic-gate iack = (sctp_init_chunk_t *)(iack_ch + 1); 546*0Sstevel@tonic-gate iack->sic_inittag = itag; /* already in network byteorder */ 547*0Sstevel@tonic-gate iack->sic_inittsn = htonl(itsn); 548*0Sstevel@tonic-gate 549*0Sstevel@tonic-gate iack->sic_a_rwnd = htonl(sctp->sctp_rwnd); 550*0Sstevel@tonic-gate /* Advertise what we would want to have as stream #'s */ 551*0Sstevel@tonic-gate iack->sic_outstr = htons(MIN(sctp->sctp_num_ostr, 552*0Sstevel@tonic-gate ntohs(init->sic_instr))); 553*0Sstevel@tonic-gate iack->sic_instr = htons(sctp->sctp_num_istr); 554*0Sstevel@tonic-gate 555*0Sstevel@tonic-gate p = (char *)(iack + 1); 556*0Sstevel@tonic-gate p += sctp_adaption_code_param(sctp, (uchar_t *)p); 557*0Sstevel@tonic-gate if (initcollision) 558*0Sstevel@tonic-gate p += sctp_supaddr_param(sctp, (uchar_t *)p); 559*0Sstevel@tonic-gate p += sctp_addr_params(sctp, supp_af, (uchar_t *)p); 560*0Sstevel@tonic-gate if (((sctp_options & SCTP_PRSCTP_OPTION) || initcollision) && 561*0Sstevel@tonic-gate sctp->sctp_prsctp_aware && sctp_prsctp_enabled) { 562*0Sstevel@tonic-gate p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 563*0Sstevel@tonic-gate } 564*0Sstevel@tonic-gate /* 565*0Sstevel@tonic-gate * Generate and lay in the COOKIE parameter. 566*0Sstevel@tonic-gate * 567*0Sstevel@tonic-gate * The cookie consists of: 568*0Sstevel@tonic-gate * 1. The relative timestamp for the cookie (lbolt64) 569*0Sstevel@tonic-gate * 2. The cookie lifetime (uint32_t) in tick 570*0Sstevel@tonic-gate * 3. The local tie-tag 571*0Sstevel@tonic-gate * 4. The peer tie-tag 572*0Sstevel@tonic-gate * 5. Peer's original src, used to confirm the validity of address. 573*0Sstevel@tonic-gate * 6. Our INIT ACK chunk, less any parameters 574*0Sstevel@tonic-gate * 7. The INIT chunk (may contain parameters) 575*0Sstevel@tonic-gate * 8. 128-bit MD5 signature. 576*0Sstevel@tonic-gate * 577*0Sstevel@tonic-gate * Since the timestamp values will only be evaluated locally, we 578*0Sstevel@tonic-gate * don't need to worry about byte-ordering them. 579*0Sstevel@tonic-gate */ 580*0Sstevel@tonic-gate cookieph = (sctp_parm_hdr_t *)p; 581*0Sstevel@tonic-gate cookieph->sph_type = htons(PARM_COOKIE); 582*0Sstevel@tonic-gate cookieph->sph_len = htons(cookielen); 583*0Sstevel@tonic-gate 584*0Sstevel@tonic-gate /* timestamp */ 585*0Sstevel@tonic-gate now = (int64_t *)(cookieph + 1); 586*0Sstevel@tonic-gate nowt = lbolt64; 587*0Sstevel@tonic-gate bcopy(&nowt, now, sizeof (*now)); 588*0Sstevel@tonic-gate 589*0Sstevel@tonic-gate /* cookie lifetime -- need configuration */ 590*0Sstevel@tonic-gate lifetime = (uint32_t *)(now + 1); 591*0Sstevel@tonic-gate *lifetime = sctp->sctp_cookie_lifetime; 592*0Sstevel@tonic-gate 593*0Sstevel@tonic-gate /* Set the tie-tags */ 594*0Sstevel@tonic-gate ttag = (uint32_t *)(lifetime + 1); 595*0Sstevel@tonic-gate if (sctp->sctp_state <= SCTPS_COOKIE_WAIT) { 596*0Sstevel@tonic-gate *ttag = 0; 597*0Sstevel@tonic-gate ttag++; 598*0Sstevel@tonic-gate *ttag = 0; 599*0Sstevel@tonic-gate ttag++; 600*0Sstevel@tonic-gate } else { 601*0Sstevel@tonic-gate /* local tie-tag (network byte-order) */ 602*0Sstevel@tonic-gate *ttag = sctp->sctp_lvtag; 603*0Sstevel@tonic-gate ttag++; 604*0Sstevel@tonic-gate /* peer tie-tag (network byte-order) */ 605*0Sstevel@tonic-gate *ttag = sctp->sctp_fvtag; 606*0Sstevel@tonic-gate ttag++; 607*0Sstevel@tonic-gate } 608*0Sstevel@tonic-gate /* 609*0Sstevel@tonic-gate * Copy in peer's original source address so that we can confirm 610*0Sstevel@tonic-gate * the reachability later. 611*0Sstevel@tonic-gate */ 612*0Sstevel@tonic-gate p = (char *)ttag; 613*0Sstevel@tonic-gate if (isv4) { 614*0Sstevel@tonic-gate in6_addr_t peer_addr; 615*0Sstevel@tonic-gate 616*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(iackiph->ipha_dst, &peer_addr); 617*0Sstevel@tonic-gate bcopy(&peer_addr, p, sizeof (in6_addr_t)); 618*0Sstevel@tonic-gate } else { 619*0Sstevel@tonic-gate bcopy(&iackip6h->ip6_dst, p, sizeof (in6_addr_t)); 620*0Sstevel@tonic-gate } 621*0Sstevel@tonic-gate p += sizeof (in6_addr_t); 622*0Sstevel@tonic-gate /* Copy in our INIT ACK chunk */ 623*0Sstevel@tonic-gate bcopy(iack, p, sizeof (*iack)); 624*0Sstevel@tonic-gate iack = (sctp_init_chunk_t *)p; 625*0Sstevel@tonic-gate /* Set the # of streams we'll end up using */ 626*0Sstevel@tonic-gate iack->sic_outstr = MIN(sctp->sctp_num_ostr, ntohs(init->sic_instr)); 627*0Sstevel@tonic-gate iack->sic_instr = MIN(sctp->sctp_num_istr, ntohs(init->sic_outstr)); 628*0Sstevel@tonic-gate p += sizeof (*iack); 629*0Sstevel@tonic-gate 630*0Sstevel@tonic-gate /* Copy in the peer's INIT chunk */ 631*0Sstevel@tonic-gate bcopy(ch, p, ntohs(ch->sch_len)); 632*0Sstevel@tonic-gate p += ntohs(ch->sch_len); 633*0Sstevel@tonic-gate 634*0Sstevel@tonic-gate /* 635*0Sstevel@tonic-gate * Calculate the HMAC ICV into the digest slot in buf. 636*0Sstevel@tonic-gate * First, generate a new secret if the current secret is 637*0Sstevel@tonic-gate * older than the new secret lifetime parameter permits, 638*0Sstevel@tonic-gate * copying the current secret to sctp_old_secret. 639*0Sstevel@tonic-gate */ 640*0Sstevel@tonic-gate if (sctp_new_secret_interval > 0 && 641*0Sstevel@tonic-gate (sctp->sctp_last_secret_update + 642*0Sstevel@tonic-gate MSEC_TO_TICK(sctp_new_secret_interval)) <= nowt) { 643*0Sstevel@tonic-gate bcopy(sctp->sctp_secret, sctp->sctp_old_secret, 644*0Sstevel@tonic-gate SCTP_SECRET_LEN); 645*0Sstevel@tonic-gate (void) random_get_pseudo_bytes(sctp->sctp_secret, 646*0Sstevel@tonic-gate SCTP_SECRET_LEN); 647*0Sstevel@tonic-gate sctp->sctp_last_secret_update = nowt; 648*0Sstevel@tonic-gate } 649*0Sstevel@tonic-gate 650*0Sstevel@tonic-gate hmac_md5((uchar_t *)now, cookielen - sizeof (*cookieph) - 16, 651*0Sstevel@tonic-gate (uchar_t *)sctp->sctp_secret, SCTP_SECRET_LEN, (uchar_t *)p); 652*0Sstevel@tonic-gate 653*0Sstevel@tonic-gate iackmp->b_wptr = iackmp->b_rptr + ipsctplen; 654*0Sstevel@tonic-gate iackmp->b_cont = errmp; /* OK if NULL */ 655*0Sstevel@tonic-gate 656*0Sstevel@tonic-gate /* 657*0Sstevel@tonic-gate * Stash the conn ptr info. for IP only as e don't have any 658*0Sstevel@tonic-gate * cached IRE. 659*0Sstevel@tonic-gate */ 660*0Sstevel@tonic-gate SCTP_STASH_IPINFO(iackmp, (ire_t *)NULL); 661*0Sstevel@tonic-gate 662*0Sstevel@tonic-gate /* XXX sctp == sctp_g_q, so using its obchunks is valid */ 663*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_opkts); 664*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 665*0Sstevel@tonic-gate 666*0Sstevel@tonic-gate /* OK to call IP_PUT() here instead of sctp_add_sendq(). */ 667*0Sstevel@tonic-gate CONN_INC_REF(sctp->sctp_connp); 668*0Sstevel@tonic-gate iackmp->b_flag |= MSGHASREF; 669*0Sstevel@tonic-gate IP_PUT(iackmp, sctp->sctp_connp, isv4); 670*0Sstevel@tonic-gate } 671*0Sstevel@tonic-gate 672*0Sstevel@tonic-gate void 673*0Sstevel@tonic-gate sctp_send_cookie_ack(sctp_t *sctp) 674*0Sstevel@tonic-gate { 675*0Sstevel@tonic-gate sctp_chunk_hdr_t *cach; 676*0Sstevel@tonic-gate mblk_t *camp; 677*0Sstevel@tonic-gate 678*0Sstevel@tonic-gate camp = sctp_make_mp(sctp, NULL, sizeof (*cach)); 679*0Sstevel@tonic-gate if (camp == NULL) { 680*0Sstevel@tonic-gate /* XXX should abort, but don't have the inmp anymore */ 681*0Sstevel@tonic-gate return; 682*0Sstevel@tonic-gate } 683*0Sstevel@tonic-gate 684*0Sstevel@tonic-gate cach = (sctp_chunk_hdr_t *)camp->b_wptr; 685*0Sstevel@tonic-gate camp->b_wptr = (uchar_t *)(cach + 1); 686*0Sstevel@tonic-gate cach->sch_id = CHUNK_COOKIE_ACK; 687*0Sstevel@tonic-gate cach->sch_flags = 0; 688*0Sstevel@tonic-gate cach->sch_len = htons(sizeof (*cach)); 689*0Sstevel@tonic-gate 690*0Sstevel@tonic-gate sctp_set_iplen(sctp, camp); 691*0Sstevel@tonic-gate 692*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 693*0Sstevel@tonic-gate 694*0Sstevel@tonic-gate sctp_add_sendq(sctp, camp); 695*0Sstevel@tonic-gate } 696*0Sstevel@tonic-gate 697*0Sstevel@tonic-gate static int 698*0Sstevel@tonic-gate sctp_find_al_ind(sctp_parm_hdr_t *sph, ssize_t len, uint32_t *adaption_code) 699*0Sstevel@tonic-gate { 700*0Sstevel@tonic-gate 701*0Sstevel@tonic-gate if (len < sizeof (*sph)) 702*0Sstevel@tonic-gate return (-1); 703*0Sstevel@tonic-gate while (sph != NULL) { 704*0Sstevel@tonic-gate if (sph->sph_type == htons(PARM_ADAPT_LAYER_IND) && 705*0Sstevel@tonic-gate ntohs(sph->sph_len) >= (sizeof (*sph) + 706*0Sstevel@tonic-gate sizeof (uint32_t))) { 707*0Sstevel@tonic-gate *adaption_code = *(uint32_t *)(sph + 1); 708*0Sstevel@tonic-gate return (0); 709*0Sstevel@tonic-gate } 710*0Sstevel@tonic-gate sph = sctp_next_parm(sph, &len); 711*0Sstevel@tonic-gate } 712*0Sstevel@tonic-gate return (-1); 713*0Sstevel@tonic-gate } 714*0Sstevel@tonic-gate 715*0Sstevel@tonic-gate void 716*0Sstevel@tonic-gate sctp_send_cookie_echo(sctp_t *sctp, sctp_chunk_hdr_t *iackch, mblk_t *iackmp) 717*0Sstevel@tonic-gate { 718*0Sstevel@tonic-gate mblk_t *cemp; 719*0Sstevel@tonic-gate mblk_t *mp = NULL; 720*0Sstevel@tonic-gate mblk_t *head; 721*0Sstevel@tonic-gate mblk_t *meta; 722*0Sstevel@tonic-gate sctp_faddr_t *fp; 723*0Sstevel@tonic-gate sctp_chunk_hdr_t *cech; 724*0Sstevel@tonic-gate sctp_init_chunk_t *iack; 725*0Sstevel@tonic-gate int32_t cansend; 726*0Sstevel@tonic-gate int32_t seglen; 727*0Sstevel@tonic-gate size_t ceclen; 728*0Sstevel@tonic-gate sctp_parm_hdr_t *cph; 729*0Sstevel@tonic-gate sctp_data_hdr_t *sdc; 730*0Sstevel@tonic-gate sctp_tf_t *tf; 731*0Sstevel@tonic-gate int pad; 732*0Sstevel@tonic-gate int hdrlen; 733*0Sstevel@tonic-gate mblk_t *errmp = NULL; 734*0Sstevel@tonic-gate uint_t sctp_options; 735*0Sstevel@tonic-gate int error; 736*0Sstevel@tonic-gate uint16_t old_num_str; 737*0Sstevel@tonic-gate 738*0Sstevel@tonic-gate iack = (sctp_init_chunk_t *)(iackch + 1); 739*0Sstevel@tonic-gate 740*0Sstevel@tonic-gate cph = NULL; 741*0Sstevel@tonic-gate if (validate_init_params(sctp, iackch, iack, iackmp, &cph, &errmp, 742*0Sstevel@tonic-gate &pad, &sctp_options) == 0) { /* result in 'pad' ignored */ 743*0Sstevel@tonic-gate BUMP_MIB(&sctp_mib, sctpAborted); 744*0Sstevel@tonic-gate sctp_assoc_event(sctp, SCTP_CANT_STR_ASSOC, 0, NULL); 745*0Sstevel@tonic-gate sctp_clean_death(sctp, ECONNABORTED); 746*0Sstevel@tonic-gate return; 747*0Sstevel@tonic-gate } 748*0Sstevel@tonic-gate ASSERT(cph != NULL); 749*0Sstevel@tonic-gate 750*0Sstevel@tonic-gate ASSERT(sctp->sctp_cookie_mp == NULL); 751*0Sstevel@tonic-gate 752*0Sstevel@tonic-gate /* Got a cookie to echo back; allocate an mblk */ 753*0Sstevel@tonic-gate ceclen = sizeof (*cech) + ntohs(cph->sph_len) - sizeof (*cph); 754*0Sstevel@tonic-gate if ((pad = ceclen & (SCTP_ALIGN - 1)) != 0) 755*0Sstevel@tonic-gate pad = SCTP_ALIGN - pad; 756*0Sstevel@tonic-gate 757*0Sstevel@tonic-gate if (IPH_HDR_VERSION(iackmp->b_rptr) == IPV4_VERSION) 758*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr_len; 759*0Sstevel@tonic-gate else 760*0Sstevel@tonic-gate hdrlen = sctp->sctp_hdr6_len; 761*0Sstevel@tonic-gate 762*0Sstevel@tonic-gate cemp = allocb(sctp_wroff_xtra + hdrlen + ceclen + pad, BPRI_MED); 763*0Sstevel@tonic-gate if (cemp == NULL) { 764*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, sctp->sctp_current, 765*0Sstevel@tonic-gate sctp->sctp_current->rto); 766*0Sstevel@tonic-gate if (errmp != NULL) 767*0Sstevel@tonic-gate freeb(errmp); 768*0Sstevel@tonic-gate return; 769*0Sstevel@tonic-gate } 770*0Sstevel@tonic-gate cemp->b_rptr += (sctp_wroff_xtra + hdrlen); 771*0Sstevel@tonic-gate 772*0Sstevel@tonic-gate /* Process the INIT ACK */ 773*0Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = iack->sic_inittag; 774*0Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = iack->sic_inittag; 775*0Sstevel@tonic-gate sctp->sctp_fvtag = iack->sic_inittag; 776*0Sstevel@tonic-gate sctp->sctp_ftsn = ntohl(iack->sic_inittsn); 777*0Sstevel@tonic-gate sctp->sctp_lastacked = sctp->sctp_ftsn - 1; 778*0Sstevel@tonic-gate sctp->sctp_fcsn = sctp->sctp_lastacked; 779*0Sstevel@tonic-gate sctp->sctp_frwnd = ntohl(iack->sic_a_rwnd); 780*0Sstevel@tonic-gate 781*0Sstevel@tonic-gate /* 782*0Sstevel@tonic-gate * Populate sctp with addresses given in the INIT ACK or IP header. 783*0Sstevel@tonic-gate * Need to set the df bit in the current fp as it has been cleared 784*0Sstevel@tonic-gate * in sctp_connect(). 785*0Sstevel@tonic-gate */ 786*0Sstevel@tonic-gate sctp->sctp_current->df = B_TRUE; 787*0Sstevel@tonic-gate /* 788*0Sstevel@tonic-gate * Since IP uses this info during the fanout process, we need to hold 789*0Sstevel@tonic-gate * the lock for this hash line while performing this operation. 790*0Sstevel@tonic-gate */ 791*0Sstevel@tonic-gate /* XXX sctp_conn_fanout + SCTP_CONN_HASH(sctp->sctp_ports); */ 792*0Sstevel@tonic-gate ASSERT(sctp->sctp_conn_tfp != NULL); 793*0Sstevel@tonic-gate tf = sctp->sctp_conn_tfp; 794*0Sstevel@tonic-gate /* sctp isn't a listener so only need to hold conn fanout lock */ 795*0Sstevel@tonic-gate mutex_enter(&tf->tf_lock); 796*0Sstevel@tonic-gate if (sctp_get_addrparams(sctp, NULL, iackmp, iackch, NULL) != 0) { 797*0Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 798*0Sstevel@tonic-gate freeb(cemp); 799*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, sctp->sctp_current, 800*0Sstevel@tonic-gate sctp->sctp_current->rto); 801*0Sstevel@tonic-gate if (errmp != NULL) 802*0Sstevel@tonic-gate freeb(errmp); 803*0Sstevel@tonic-gate return; 804*0Sstevel@tonic-gate } 805*0Sstevel@tonic-gate mutex_exit(&tf->tf_lock); 806*0Sstevel@tonic-gate 807*0Sstevel@tonic-gate fp = sctp->sctp_current; 808*0Sstevel@tonic-gate 809*0Sstevel@tonic-gate /* 810*0Sstevel@tonic-gate * There could be a case when we get an INIT-ACK again, if the INIT 811*0Sstevel@tonic-gate * is re-transmitted, for e.g., which means we would have already 812*0Sstevel@tonic-gate * allocated this resource earlier (also for sctp_instr). In this 813*0Sstevel@tonic-gate * case we check and re-allocate, if necessary. 814*0Sstevel@tonic-gate */ 815*0Sstevel@tonic-gate old_num_str = sctp->sctp_num_ostr; 816*0Sstevel@tonic-gate if (ntohs(iack->sic_instr) < sctp->sctp_num_ostr) 817*0Sstevel@tonic-gate sctp->sctp_num_ostr = ntohs(iack->sic_instr); 818*0Sstevel@tonic-gate if (sctp->sctp_ostrcntrs == NULL) { 819*0Sstevel@tonic-gate sctp->sctp_ostrcntrs = kmem_zalloc(sizeof (uint16_t) * 820*0Sstevel@tonic-gate sctp->sctp_num_ostr, KM_NOSLEEP); 821*0Sstevel@tonic-gate } else { 822*0Sstevel@tonic-gate ASSERT(old_num_str > 0); 823*0Sstevel@tonic-gate if (old_num_str != sctp->sctp_num_ostr) { 824*0Sstevel@tonic-gate kmem_free(sctp->sctp_ostrcntrs, sizeof (uint16_t) * 825*0Sstevel@tonic-gate old_num_str); 826*0Sstevel@tonic-gate sctp->sctp_ostrcntrs = kmem_zalloc(sizeof (uint16_t) * 827*0Sstevel@tonic-gate sctp->sctp_num_ostr, KM_NOSLEEP); 828*0Sstevel@tonic-gate } 829*0Sstevel@tonic-gate } 830*0Sstevel@tonic-gate if (sctp->sctp_ostrcntrs == NULL) { 831*0Sstevel@tonic-gate freeb(cemp); 832*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto); 833*0Sstevel@tonic-gate if (errmp != NULL) 834*0Sstevel@tonic-gate freeb(errmp); 835*0Sstevel@tonic-gate return; 836*0Sstevel@tonic-gate } 837*0Sstevel@tonic-gate 838*0Sstevel@tonic-gate /* 839*0Sstevel@tonic-gate * Allocate the in stream tracking array. Comments for sctp_ostrcntrs 840*0Sstevel@tonic-gate * hold here too. 841*0Sstevel@tonic-gate */ 842*0Sstevel@tonic-gate old_num_str = sctp->sctp_num_istr; 843*0Sstevel@tonic-gate if (ntohs(iack->sic_outstr) < sctp->sctp_num_istr) 844*0Sstevel@tonic-gate sctp->sctp_num_istr = ntohs(iack->sic_outstr); 845*0Sstevel@tonic-gate if (sctp->sctp_instr == NULL) { 846*0Sstevel@tonic-gate sctp->sctp_instr = kmem_zalloc(sizeof (*sctp->sctp_instr) * 847*0Sstevel@tonic-gate sctp->sctp_num_istr, KM_NOSLEEP); 848*0Sstevel@tonic-gate } else { 849*0Sstevel@tonic-gate ASSERT(old_num_str > 0); 850*0Sstevel@tonic-gate if (old_num_str != sctp->sctp_num_istr) { 851*0Sstevel@tonic-gate kmem_free(sctp->sctp_instr, 852*0Sstevel@tonic-gate sizeof (*sctp->sctp_instr) * old_num_str); 853*0Sstevel@tonic-gate sctp->sctp_instr = kmem_zalloc( 854*0Sstevel@tonic-gate sizeof (*sctp->sctp_instr) * sctp->sctp_num_istr, 855*0Sstevel@tonic-gate KM_NOSLEEP); 856*0Sstevel@tonic-gate } 857*0Sstevel@tonic-gate } 858*0Sstevel@tonic-gate if (sctp->sctp_instr == NULL) { 859*0Sstevel@tonic-gate kmem_free(sctp->sctp_ostrcntrs, 860*0Sstevel@tonic-gate sizeof (uint16_t) * sctp->sctp_num_ostr); 861*0Sstevel@tonic-gate freeb(cemp); 862*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto); 863*0Sstevel@tonic-gate if (errmp != NULL) 864*0Sstevel@tonic-gate freeb(errmp); 865*0Sstevel@tonic-gate return; 866*0Sstevel@tonic-gate } 867*0Sstevel@tonic-gate 868*0Sstevel@tonic-gate if (!(sctp_options & SCTP_PRSCTP_OPTION) && sctp->sctp_prsctp_aware) 869*0Sstevel@tonic-gate sctp->sctp_prsctp_aware = B_FALSE; 870*0Sstevel@tonic-gate 871*0Sstevel@tonic-gate if (sctp_find_al_ind((sctp_parm_hdr_t *)(iack + 1), 872*0Sstevel@tonic-gate ntohs(iackch->sch_len) - (sizeof (*iackch) + sizeof (*iack)), 873*0Sstevel@tonic-gate &sctp->sctp_rx_adaption_code) == 0) { 874*0Sstevel@tonic-gate sctp->sctp_recv_adaption = 1; 875*0Sstevel@tonic-gate } 876*0Sstevel@tonic-gate 877*0Sstevel@tonic-gate cech = (sctp_chunk_hdr_t *)cemp->b_rptr; 878*0Sstevel@tonic-gate ASSERT(OK_32PTR(cech)); 879*0Sstevel@tonic-gate cech->sch_id = CHUNK_COOKIE; 880*0Sstevel@tonic-gate cech->sch_flags = 0; 881*0Sstevel@tonic-gate cech->sch_len = htons(ceclen); 882*0Sstevel@tonic-gate 883*0Sstevel@tonic-gate /* Copy the cookie (less the parm hdr) to the chunk */ 884*0Sstevel@tonic-gate bcopy(cph + 1, cech + 1, ceclen - sizeof (*cph)); 885*0Sstevel@tonic-gate 886*0Sstevel@tonic-gate cemp->b_wptr = cemp->b_rptr + ceclen; 887*0Sstevel@tonic-gate 888*0Sstevel@tonic-gate if (sctp->sctp_unsent != NULL) { 889*0Sstevel@tonic-gate sctp_msg_hdr_t *smh; 890*0Sstevel@tonic-gate mblk_t *prev = NULL; 891*0Sstevel@tonic-gate uint32_t unsent = 0; 892*0Sstevel@tonic-gate 893*0Sstevel@tonic-gate mp = sctp->sctp_xmit_unsent; 894*0Sstevel@tonic-gate do { 895*0Sstevel@tonic-gate smh = (sctp_msg_hdr_t *)mp->b_rptr; 896*0Sstevel@tonic-gate if (smh->smh_sid >= sctp->sctp_num_ostr) { 897*0Sstevel@tonic-gate unsent += smh->smh_msglen; 898*0Sstevel@tonic-gate if (prev != NULL) 899*0Sstevel@tonic-gate prev->b_next = mp->b_next; 900*0Sstevel@tonic-gate else 901*0Sstevel@tonic-gate sctp->sctp_xmit_unsent = mp->b_next; 902*0Sstevel@tonic-gate mp->b_next = NULL; 903*0Sstevel@tonic-gate sctp_sendfail_event(sctp, mp, SCTP_ERR_BAD_SID, 904*0Sstevel@tonic-gate B_FALSE); 905*0Sstevel@tonic-gate if (prev != NULL) 906*0Sstevel@tonic-gate mp = prev->b_next; 907*0Sstevel@tonic-gate else 908*0Sstevel@tonic-gate mp = sctp->sctp_xmit_unsent; 909*0Sstevel@tonic-gate } else { 910*0Sstevel@tonic-gate prev = mp; 911*0Sstevel@tonic-gate mp = mp->b_next; 912*0Sstevel@tonic-gate } 913*0Sstevel@tonic-gate } while (mp != NULL); 914*0Sstevel@tonic-gate if (unsent > 0) { 915*0Sstevel@tonic-gate ASSERT(sctp->sctp_unsent >= unsent); 916*0Sstevel@tonic-gate sctp->sctp_unsent -= unsent; 917*0Sstevel@tonic-gate /* 918*0Sstevel@tonic-gate * Update ULP the amount of queued data, which is 919*0Sstevel@tonic-gate * sent-unack'ed + unsent. 920*0Sstevel@tonic-gate * This is not necessary, but doesn't harm, we 921*0Sstevel@tonic-gate * just use unsent instead of sent-unack'ed + 922*0Sstevel@tonic-gate * unsent, since there won't be any sent-unack'ed 923*0Sstevel@tonic-gate * here. 924*0Sstevel@tonic-gate */ 925*0Sstevel@tonic-gate if (!SCTP_IS_DETACHED(sctp)) { 926*0Sstevel@tonic-gate sctp->sctp_ulp_xmitted(sctp->sctp_ulpd, 927*0Sstevel@tonic-gate sctp->sctp_unsent); 928*0Sstevel@tonic-gate } 929*0Sstevel@tonic-gate } 930*0Sstevel@tonic-gate if (sctp->sctp_xmit_unsent == NULL) 931*0Sstevel@tonic-gate sctp->sctp_xmit_unsent_tail = NULL; 932*0Sstevel@tonic-gate } 933*0Sstevel@tonic-gate ceclen += pad; 934*0Sstevel@tonic-gate cansend = MIN(sctp->sctp_unsent, sctp->sctp_frwnd); 935*0Sstevel@tonic-gate meta = sctp_get_msg_to_send(sctp, &mp, NULL, &error, ceclen, 936*0Sstevel@tonic-gate cansend, NULL); 937*0Sstevel@tonic-gate /* 938*0Sstevel@tonic-gate * The error cannot be anything else since we could have an non-zero 939*0Sstevel@tonic-gate * error only if sctp_get_msg_to_send() tries to send a Forward 940*0Sstevel@tonic-gate * TSN which will not happen here. 941*0Sstevel@tonic-gate */ 942*0Sstevel@tonic-gate ASSERT(error == 0); 943*0Sstevel@tonic-gate if (meta == NULL) 944*0Sstevel@tonic-gate goto sendcookie; 945*0Sstevel@tonic-gate sctp->sctp_xmit_tail = meta; 946*0Sstevel@tonic-gate sdc = (sctp_data_hdr_t *)mp->b_rptr; 947*0Sstevel@tonic-gate seglen = ntohs(sdc->sdh_len); 948*0Sstevel@tonic-gate if ((ceclen + seglen) > fp->sfa_pmss || 949*0Sstevel@tonic-gate (seglen - sizeof (*sdc)) > cansend) { 950*0Sstevel@tonic-gate goto sendcookie; 951*0Sstevel@tonic-gate } 952*0Sstevel@tonic-gate /* OK, if this fails */ 953*0Sstevel@tonic-gate cemp->b_cont = dupmsg(mp); 954*0Sstevel@tonic-gate sendcookie: 955*0Sstevel@tonic-gate head = sctp_add_proto_hdr(sctp, fp, cemp, 0); 956*0Sstevel@tonic-gate ASSERT(head != NULL); 957*0Sstevel@tonic-gate /* 958*0Sstevel@tonic-gate * Even if cookie-echo exceeds MTU for one of the hops, it'll 959*0Sstevel@tonic-gate * have a chance of getting there. 960*0Sstevel@tonic-gate */ 961*0Sstevel@tonic-gate if (fp->isv4) { 962*0Sstevel@tonic-gate ipha_t *iph = (ipha_t *)head->b_rptr; 963*0Sstevel@tonic-gate iph->ipha_fragment_offset_and_flags = 0; 964*0Sstevel@tonic-gate } 965*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 966*0Sstevel@tonic-gate 967*0Sstevel@tonic-gate sctp->sctp_cookie_mp = dupmsg(head); 968*0Sstevel@tonic-gate /* Don't bundle, we will just resend init if this cookie is lost. */ 969*0Sstevel@tonic-gate if (sctp->sctp_cookie_mp == NULL) { 970*0Sstevel@tonic-gate if (cemp->b_cont != NULL) { 971*0Sstevel@tonic-gate freemsg(cemp->b_cont); 972*0Sstevel@tonic-gate cemp->b_cont = NULL; 973*0Sstevel@tonic-gate } 974*0Sstevel@tonic-gate } else if (cemp->b_cont != NULL) { 975*0Sstevel@tonic-gate ASSERT(mp != NULL && mp == meta->b_cont); 976*0Sstevel@tonic-gate SCTP_CHUNK_CLEAR_FLAGS(cemp->b_cont); 977*0Sstevel@tonic-gate cemp->b_wptr += pad; 978*0Sstevel@tonic-gate seglen -= sizeof (*sdc); 979*0Sstevel@tonic-gate SCTP_CHUNK_SENT(sctp, mp, sdc, fp, seglen, meta); 980*0Sstevel@tonic-gate } 981*0Sstevel@tonic-gate if (errmp != NULL) 982*0Sstevel@tonic-gate linkb(head, errmp); 983*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_COOKIE_ECHOED; 984*0Sstevel@tonic-gate SCTP_FADDR_TIMER_RESTART(sctp, fp, fp->rto); 985*0Sstevel@tonic-gate 986*0Sstevel@tonic-gate sctp_set_iplen(sctp, head); 987*0Sstevel@tonic-gate sctp_add_sendq(sctp, head); 988*0Sstevel@tonic-gate } 989*0Sstevel@tonic-gate 990*0Sstevel@tonic-gate int 991*0Sstevel@tonic-gate sctp_process_cookie(sctp_t *sctp, sctp_chunk_hdr_t *ch, mblk_t *cmp, 992*0Sstevel@tonic-gate sctp_init_chunk_t **iackpp, sctp_hdr_t *insctph, int *recv_adaption, 993*0Sstevel@tonic-gate in6_addr_t *peer_addr) 994*0Sstevel@tonic-gate { 995*0Sstevel@tonic-gate int32_t clen; 996*0Sstevel@tonic-gate size_t initplen; 997*0Sstevel@tonic-gate uchar_t *p; 998*0Sstevel@tonic-gate uchar_t *given_hash; 999*0Sstevel@tonic-gate uchar_t needed_hash[16]; 1000*0Sstevel@tonic-gate int64_t ts; 1001*0Sstevel@tonic-gate int64_t diff; 1002*0Sstevel@tonic-gate uint32_t *lt; 1003*0Sstevel@tonic-gate sctp_init_chunk_t *iack; 1004*0Sstevel@tonic-gate sctp_chunk_hdr_t *initch; 1005*0Sstevel@tonic-gate sctp_init_chunk_t *init; 1006*0Sstevel@tonic-gate uint32_t *lttag; 1007*0Sstevel@tonic-gate uint32_t *fttag; 1008*0Sstevel@tonic-gate uint32_t ports; 1009*0Sstevel@tonic-gate 1010*0Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_ibchunks); 1011*0Sstevel@tonic-gate /* Verify the ICV */ 1012*0Sstevel@tonic-gate clen = ntohs(ch->sch_len) - sizeof (*ch) - 16; 1013*0Sstevel@tonic-gate if (clen < 0) { 1014*0Sstevel@tonic-gate dprint(1, ("invalid cookie chunk length %d\n", 1015*0Sstevel@tonic-gate ntohs(ch->sch_len))); 1016*0Sstevel@tonic-gate 1017*0Sstevel@tonic-gate return (-1); 1018*0Sstevel@tonic-gate } 1019*0Sstevel@tonic-gate p = (uchar_t *)(ch + 1); 1020*0Sstevel@tonic-gate 1021*0Sstevel@tonic-gate hmac_md5(p, clen, (uchar_t *)sctp->sctp_secret, SCTP_SECRET_LEN, 1022*0Sstevel@tonic-gate needed_hash); 1023*0Sstevel@tonic-gate 1024*0Sstevel@tonic-gate /* The given hash follows the cookie data */ 1025*0Sstevel@tonic-gate given_hash = p + clen; 1026*0Sstevel@tonic-gate 1027*0Sstevel@tonic-gate if (bcmp(given_hash, needed_hash, 16) != 0) { 1028*0Sstevel@tonic-gate /* The secret may have changed; try the old secret */ 1029*0Sstevel@tonic-gate hmac_md5(p, clen, (uchar_t *)sctp->sctp_old_secret, 1030*0Sstevel@tonic-gate SCTP_SECRET_LEN, needed_hash); 1031*0Sstevel@tonic-gate if (bcmp(given_hash, needed_hash, 16) != 0) { 1032*0Sstevel@tonic-gate return (-1); 1033*0Sstevel@tonic-gate } 1034*0Sstevel@tonic-gate } 1035*0Sstevel@tonic-gate 1036*0Sstevel@tonic-gate /* Timestamp is int64_t, and we only guarantee 32-bit alignment */ 1037*0Sstevel@tonic-gate bcopy(p, &ts, sizeof (ts)); 1038*0Sstevel@tonic-gate /* Cookie life time, int32_t */ 1039*0Sstevel@tonic-gate lt = (uint32_t *)(p + sizeof (ts)); 1040*0Sstevel@tonic-gate 1041*0Sstevel@tonic-gate /* 1042*0Sstevel@tonic-gate * To quote PRC, "this is our baby", so let's continue. 1043*0Sstevel@tonic-gate * We need to pull out the encapsulated INIT ACK and 1044*0Sstevel@tonic-gate * INIT chunks. Note that we don't process these until 1045*0Sstevel@tonic-gate * we have verified the timestamp, but we need them before 1046*0Sstevel@tonic-gate * processing the timestamp since if the time check fails, 1047*0Sstevel@tonic-gate * we need to get the verification tag from the INIT in order 1048*0Sstevel@tonic-gate * to send a stale cookie error. 1049*0Sstevel@tonic-gate */ 1050*0Sstevel@tonic-gate lttag = (uint32_t *)(lt + 1); 1051*0Sstevel@tonic-gate fttag = lttag + 1; 1052*0Sstevel@tonic-gate if (peer_addr != NULL) 1053*0Sstevel@tonic-gate bcopy(fttag + 1, peer_addr, sizeof (in6_addr_t)); 1054*0Sstevel@tonic-gate iack = (sctp_init_chunk_t *)((char *)(fttag + 1) + sizeof (in6_addr_t)); 1055*0Sstevel@tonic-gate initch = (sctp_chunk_hdr_t *)(iack + 1); 1056*0Sstevel@tonic-gate init = (sctp_init_chunk_t *)(initch + 1); 1057*0Sstevel@tonic-gate initplen = ntohs(initch->sch_len) - (sizeof (*init) + sizeof (*initch)); 1058*0Sstevel@tonic-gate *iackpp = iack; 1059*0Sstevel@tonic-gate *recv_adaption = 0; 1060*0Sstevel@tonic-gate 1061*0Sstevel@tonic-gate /* Check the timestamp */ 1062*0Sstevel@tonic-gate diff = lbolt64 - ts; 1063*0Sstevel@tonic-gate if (diff > *lt && (init->sic_inittag != sctp->sctp_fvtag || 1064*0Sstevel@tonic-gate iack->sic_inittag != sctp->sctp_lvtag)) { 1065*0Sstevel@tonic-gate 1066*0Sstevel@tonic-gate uint32_t staleness; 1067*0Sstevel@tonic-gate 1068*0Sstevel@tonic-gate staleness = TICK_TO_USEC(diff); 1069*0Sstevel@tonic-gate staleness = htonl(staleness); 1070*0Sstevel@tonic-gate sctp_send_abort(sctp, init->sic_inittag, SCTP_ERR_STALE_COOKIE, 1071*0Sstevel@tonic-gate (char *)&staleness, sizeof (staleness), cmp, 1, B_FALSE); 1072*0Sstevel@tonic-gate 1073*0Sstevel@tonic-gate dprint(1, ("stale cookie %d\n", staleness)); 1074*0Sstevel@tonic-gate 1075*0Sstevel@tonic-gate return (-1); 1076*0Sstevel@tonic-gate } 1077*0Sstevel@tonic-gate 1078*0Sstevel@tonic-gate /* Check for attack by adding addresses to a restart */ 1079*0Sstevel@tonic-gate bcopy(insctph, &ports, sizeof (ports)); 1080*0Sstevel@tonic-gate if (sctp_secure_restart_check(cmp, initch, ports, KM_NOSLEEP) != 1) { 1081*0Sstevel@tonic-gate return (-1); 1082*0Sstevel@tonic-gate } 1083*0Sstevel@tonic-gate 1084*0Sstevel@tonic-gate /* Look for adaptation code if there any parms in the INIT chunk */ 1085*0Sstevel@tonic-gate if ((initplen >= sizeof (sctp_parm_hdr_t)) && 1086*0Sstevel@tonic-gate (sctp_find_al_ind((sctp_parm_hdr_t *)(init + 1), initplen, 1087*0Sstevel@tonic-gate &sctp->sctp_rx_adaption_code) == 0)) { 1088*0Sstevel@tonic-gate *recv_adaption = 1; 1089*0Sstevel@tonic-gate } 1090*0Sstevel@tonic-gate 1091*0Sstevel@tonic-gate /* Examine tie-tags */ 1092*0Sstevel@tonic-gate 1093*0Sstevel@tonic-gate if (sctp->sctp_state >= SCTPS_COOKIE_WAIT) { 1094*0Sstevel@tonic-gate if (sctp->sctp_state == SCTPS_ESTABLISHED && 1095*0Sstevel@tonic-gate init->sic_inittag == sctp->sctp_fvtag && 1096*0Sstevel@tonic-gate iack->sic_inittag == sctp->sctp_lvtag && 1097*0Sstevel@tonic-gate *fttag == 0 && *lttag == 0) { 1098*0Sstevel@tonic-gate 1099*0Sstevel@tonic-gate dprint(1, ("duplicate cookie from %x:%x:%x:%x (%d)\n", 1100*0Sstevel@tonic-gate SCTP_PRINTADDR(sctp->sctp_current->faddr), 1101*0Sstevel@tonic-gate (int)(sctp->sctp_fport))); 1102*0Sstevel@tonic-gate return (-1); 1103*0Sstevel@tonic-gate } 1104*0Sstevel@tonic-gate 1105*0Sstevel@tonic-gate if (init->sic_inittag != sctp->sctp_fvtag && 1106*0Sstevel@tonic-gate iack->sic_inittag != sctp->sctp_lvtag && 1107*0Sstevel@tonic-gate *fttag == sctp->sctp_fvtag && 1108*0Sstevel@tonic-gate *lttag == sctp->sctp_lvtag) { 1109*0Sstevel@tonic-gate int i; 1110*0Sstevel@tonic-gate 1111*0Sstevel@tonic-gate /* Section 5.2.4 case A: restart */ 1112*0Sstevel@tonic-gate sctp->sctp_fvtag = init->sic_inittag; 1113*0Sstevel@tonic-gate sctp->sctp_lvtag = iack->sic_inittag; 1114*0Sstevel@tonic-gate 1115*0Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = init->sic_inittag; 1116*0Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = init->sic_inittag; 1117*0Sstevel@tonic-gate 1118*0Sstevel@tonic-gate sctp->sctp_ftsn = ntohl(init->sic_inittsn); 1119*0Sstevel@tonic-gate sctp->sctp_lastacked = sctp->sctp_ftsn - 1; 1120*0Sstevel@tonic-gate sctp->sctp_frwnd = ntohl(init->sic_a_rwnd); 1121*0Sstevel@tonic-gate sctp->sctp_fcsn = sctp->sctp_lastacked; 1122*0Sstevel@tonic-gate 1123*0Sstevel@tonic-gate if (sctp->sctp_state < SCTPS_ESTABLISHED) { 1124*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_ESTABLISHED; 1125*0Sstevel@tonic-gate sctp->sctp_assoc_start_time = (uint32_t)lbolt; 1126*0Sstevel@tonic-gate } 1127*0Sstevel@tonic-gate 1128*0Sstevel@tonic-gate dprint(1, ("sctp peer %x:%x:%x:%x (%d) restarted\n", 1129*0Sstevel@tonic-gate SCTP_PRINTADDR(sctp->sctp_current->faddr), 1130*0Sstevel@tonic-gate (int)(sctp->sctp_fport))); 1131*0Sstevel@tonic-gate /* reset parameters */ 1132*0Sstevel@tonic-gate sctp_congest_reset(sctp); 1133*0Sstevel@tonic-gate 1134*0Sstevel@tonic-gate /* reset stream bookkeeping */ 1135*0Sstevel@tonic-gate sctp_instream_cleanup(sctp, B_FALSE); 1136*0Sstevel@tonic-gate 1137*0Sstevel@tonic-gate sctp->sctp_istr_nmsgs = 0; 1138*0Sstevel@tonic-gate sctp->sctp_rxqueued = 0; 1139*0Sstevel@tonic-gate for (i = 0; i < sctp->sctp_num_ostr; i++) { 1140*0Sstevel@tonic-gate sctp->sctp_ostrcntrs[i] = 0; 1141*0Sstevel@tonic-gate } 1142*0Sstevel@tonic-gate /* XXX flush xmit_list? */ 1143*0Sstevel@tonic-gate 1144*0Sstevel@tonic-gate return (0); 1145*0Sstevel@tonic-gate } else if (init->sic_inittag != sctp->sctp_fvtag && 1146*0Sstevel@tonic-gate iack->sic_inittag == sctp->sctp_lvtag) { 1147*0Sstevel@tonic-gate 1148*0Sstevel@tonic-gate /* Section 5.2.4 case B: INIT collision */ 1149*0Sstevel@tonic-gate if (sctp->sctp_state < SCTPS_ESTABLISHED) { 1150*0Sstevel@tonic-gate if (!sctp_initialize_params(sctp, init, iack)) 1151*0Sstevel@tonic-gate return (-1); /* Drop? */ 1152*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_ESTABLISHED; 1153*0Sstevel@tonic-gate sctp->sctp_assoc_start_time = (uint32_t)lbolt; 1154*0Sstevel@tonic-gate } 1155*0Sstevel@tonic-gate 1156*0Sstevel@tonic-gate dprint(1, ("init collision with %x:%x:%x:%x (%d)\n", 1157*0Sstevel@tonic-gate SCTP_PRINTADDR(sctp->sctp_current->faddr), 1158*0Sstevel@tonic-gate (int)(sctp->sctp_fport))); 1159*0Sstevel@tonic-gate 1160*0Sstevel@tonic-gate return (0); 1161*0Sstevel@tonic-gate } else if (iack->sic_inittag != sctp->sctp_lvtag && 1162*0Sstevel@tonic-gate init->sic_inittag == sctp->sctp_fvtag && 1163*0Sstevel@tonic-gate *fttag == 0 && *lttag == 0) { 1164*0Sstevel@tonic-gate 1165*0Sstevel@tonic-gate /* Section 5.2.4 case C: late COOKIE */ 1166*0Sstevel@tonic-gate dprint(1, ("late cookie from %x:%x:%x:%x (%d)\n", 1167*0Sstevel@tonic-gate SCTP_PRINTADDR(sctp->sctp_current->faddr), 1168*0Sstevel@tonic-gate (int)(sctp->sctp_fport))); 1169*0Sstevel@tonic-gate return (-1); 1170*0Sstevel@tonic-gate } else if (init->sic_inittag == sctp->sctp_fvtag && 1171*0Sstevel@tonic-gate iack->sic_inittag == sctp->sctp_lvtag) { 1172*0Sstevel@tonic-gate 1173*0Sstevel@tonic-gate /* 1174*0Sstevel@tonic-gate * Section 5.2.4 case D: COOKIE ECHO retransmit 1175*0Sstevel@tonic-gate * Don't check cookie lifetime 1176*0Sstevel@tonic-gate */ 1177*0Sstevel@tonic-gate dprint(1, ("cookie tags match from %x:%x:%x:%x (%d)\n", 1178*0Sstevel@tonic-gate SCTP_PRINTADDR(sctp->sctp_current->faddr), 1179*0Sstevel@tonic-gate (int)(sctp->sctp_fport))); 1180*0Sstevel@tonic-gate if (sctp->sctp_state < SCTPS_ESTABLISHED) { 1181*0Sstevel@tonic-gate if (!sctp_initialize_params(sctp, init, iack)) 1182*0Sstevel@tonic-gate return (-1); /* Drop? */ 1183*0Sstevel@tonic-gate sctp->sctp_state = SCTPS_ESTABLISHED; 1184*0Sstevel@tonic-gate sctp->sctp_assoc_start_time = (uint32_t)lbolt; 1185*0Sstevel@tonic-gate } 1186*0Sstevel@tonic-gate return (0); 1187*0Sstevel@tonic-gate } else { 1188*0Sstevel@tonic-gate /* unrecognized case -- silently drop it */ 1189*0Sstevel@tonic-gate return (-1); 1190*0Sstevel@tonic-gate } 1191*0Sstevel@tonic-gate } 1192*0Sstevel@tonic-gate 1193*0Sstevel@tonic-gate return (0); 1194*0Sstevel@tonic-gate } 1195*0Sstevel@tonic-gate 1196*0Sstevel@tonic-gate /* 1197*0Sstevel@tonic-gate * Similar to ip_fanout_sctp, except that the src addr(s) are drawn 1198*0Sstevel@tonic-gate * from address parameters in an INIT ACK's address list. This 1199*0Sstevel@tonic-gate * function is used when an INIT ACK is received but IP's fanout 1200*0Sstevel@tonic-gate * function could not find a sctp via the normal lookup routine. 1201*0Sstevel@tonic-gate * This can happen when a host sends an INIT ACK from a different 1202*0Sstevel@tonic-gate * address than the INIT was sent to. 1203*0Sstevel@tonic-gate * 1204*0Sstevel@tonic-gate * Returns the sctp_t if found, or NULL if not found. 1205*0Sstevel@tonic-gate */ 1206*0Sstevel@tonic-gate sctp_t * 1207*0Sstevel@tonic-gate sctp_addrlist2sctp(mblk_t *mp, sctp_hdr_t *sctph, sctp_chunk_hdr_t *ich, 1208*0Sstevel@tonic-gate uint_t ipif_seqid, zoneid_t zoneid) 1209*0Sstevel@tonic-gate { 1210*0Sstevel@tonic-gate int isv4; 1211*0Sstevel@tonic-gate ipha_t *iph; 1212*0Sstevel@tonic-gate ip6_t *ip6h; 1213*0Sstevel@tonic-gate in6_addr_t dst; 1214*0Sstevel@tonic-gate in6_addr_t src; 1215*0Sstevel@tonic-gate sctp_parm_hdr_t *ph; 1216*0Sstevel@tonic-gate ssize_t remaining; 1217*0Sstevel@tonic-gate sctp_init_chunk_t *iack; 1218*0Sstevel@tonic-gate uint32_t ports; 1219*0Sstevel@tonic-gate sctp_t *sctp = NULL; 1220*0Sstevel@tonic-gate 1221*0Sstevel@tonic-gate ASSERT(ich->sch_id == CHUNK_INIT_ACK); 1222*0Sstevel@tonic-gate 1223*0Sstevel@tonic-gate isv4 = (IPH_HDR_VERSION(mp->b_rptr) == IPV4_VERSION); 1224*0Sstevel@tonic-gate if (isv4) { 1225*0Sstevel@tonic-gate iph = (ipha_t *)mp->b_rptr; 1226*0Sstevel@tonic-gate IN6_IPADDR_TO_V4MAPPED(iph->ipha_dst, &dst); 1227*0Sstevel@tonic-gate } else { 1228*0Sstevel@tonic-gate ip6h = (ip6_t *)mp->b_rptr; 1229*0Sstevel@tonic-gate dst = ip6h->ip6_dst; 1230*0Sstevel@tonic-gate } 1231*0Sstevel@tonic-gate 1232*0Sstevel@tonic-gate ports = *(uint32_t *)sctph; 1233*0Sstevel@tonic-gate 1234*0Sstevel@tonic-gate dprint(1, ("sctp_addrlist2sctp: ports=%u, dst = %x:%x:%x:%x\n", 1235*0Sstevel@tonic-gate ports, SCTP_PRINTADDR(dst))); 1236*0Sstevel@tonic-gate 1237*0Sstevel@tonic-gate /* pull out any address parameters */ 1238*0Sstevel@tonic-gate remaining = ntohs(ich->sch_len) - sizeof (*ich) - sizeof (*iack); 1239*0Sstevel@tonic-gate if (remaining < sizeof (*ph)) { 1240*0Sstevel@tonic-gate return (NULL); 1241*0Sstevel@tonic-gate } 1242*0Sstevel@tonic-gate 1243*0Sstevel@tonic-gate iack = (sctp_init_chunk_t *)(ich + 1); 1244*0Sstevel@tonic-gate ph = (sctp_parm_hdr_t *)(iack + 1); 1245*0Sstevel@tonic-gate 1246*0Sstevel@tonic-gate while (ph != NULL) { 1247*0Sstevel@tonic-gate /* 1248*0Sstevel@tonic-gate * params have been put in host byteorder by 1249*0Sstevel@tonic-gate * sctp_check_input() 1250*0Sstevel@tonic-gate */ 1251*0Sstevel@tonic-gate if (ph->sph_type == PARM_ADDR4) { 1252*0Sstevel@tonic-gate IN6_INADDR_TO_V4MAPPED((struct in_addr *)(ph + 1), 1253*0Sstevel@tonic-gate &src); 1254*0Sstevel@tonic-gate 1255*0Sstevel@tonic-gate sctp = sctp_conn_match(&src, &dst, ports, ipif_seqid, 1256*0Sstevel@tonic-gate zoneid); 1257*0Sstevel@tonic-gate 1258*0Sstevel@tonic-gate dprint(1, 1259*0Sstevel@tonic-gate ("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n", 1260*0Sstevel@tonic-gate SCTP_PRINTADDR(src), sctp)); 1261*0Sstevel@tonic-gate 1262*0Sstevel@tonic-gate 1263*0Sstevel@tonic-gate if (sctp != NULL) { 1264*0Sstevel@tonic-gate return (sctp); 1265*0Sstevel@tonic-gate } 1266*0Sstevel@tonic-gate } else if (ph->sph_type == PARM_ADDR6) { 1267*0Sstevel@tonic-gate src = *(in6_addr_t *)(ph + 1); 1268*0Sstevel@tonic-gate sctp = sctp_conn_match(&src, &dst, ports, ipif_seqid, 1269*0Sstevel@tonic-gate zoneid); 1270*0Sstevel@tonic-gate 1271*0Sstevel@tonic-gate dprint(1, 1272*0Sstevel@tonic-gate ("sctp_addrlist2sctp: src=%x:%x:%x:%x, sctp=%p\n", 1273*0Sstevel@tonic-gate SCTP_PRINTADDR(src), sctp)); 1274*0Sstevel@tonic-gate 1275*0Sstevel@tonic-gate if (sctp != NULL) { 1276*0Sstevel@tonic-gate return (sctp); 1277*0Sstevel@tonic-gate } 1278*0Sstevel@tonic-gate } 1279*0Sstevel@tonic-gate 1280*0Sstevel@tonic-gate ph = sctp_next_parm(ph, &remaining); 1281*0Sstevel@tonic-gate } 1282*0Sstevel@tonic-gate 1283*0Sstevel@tonic-gate return (NULL); 1284*0Sstevel@tonic-gate } 1285