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