10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51735Skcpoon * Common Development and Distribution License (the "License"). 61735Skcpoon * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211735Skcpoon 220Sstevel@tonic-gate /* 23*11042SErik.Nordmark@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #include <sys/types.h> 280Sstevel@tonic-gate #include <sys/stream.h> 290Sstevel@tonic-gate #include <sys/ddi.h> 300Sstevel@tonic-gate #include <sys/sunddi.h> 310Sstevel@tonic-gate 320Sstevel@tonic-gate #include <netinet/in.h> 330Sstevel@tonic-gate #include <netinet/ip6.h> 340Sstevel@tonic-gate 350Sstevel@tonic-gate #include <inet/common.h> 360Sstevel@tonic-gate #include <inet/ipclassifier.h> 370Sstevel@tonic-gate #include <inet/ip.h> 380Sstevel@tonic-gate #include <inet/ip6.h> 390Sstevel@tonic-gate #include <inet/mib2.h> 400Sstevel@tonic-gate #include <inet/nd.h> 410Sstevel@tonic-gate #include <inet/optcom.h> 423448Sdh155122 #include <inet/ipclassifier.h> 430Sstevel@tonic-gate #include "sctp_impl.h" 440Sstevel@tonic-gate #include "sctp_addr.h" 450Sstevel@tonic-gate 460Sstevel@tonic-gate /*ARGSUSED*/ 470Sstevel@tonic-gate size_t 480Sstevel@tonic-gate sctp_supaddr_param_len(sctp_t *sctp) 490Sstevel@tonic-gate { 500Sstevel@tonic-gate return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 510Sstevel@tonic-gate } 520Sstevel@tonic-gate 530Sstevel@tonic-gate size_t 540Sstevel@tonic-gate sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 550Sstevel@tonic-gate { 560Sstevel@tonic-gate sctp_parm_hdr_t *sph; 570Sstevel@tonic-gate uint16_t *addrtype; 58*11042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 590Sstevel@tonic-gate 600Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 610Sstevel@tonic-gate sph->sph_type = htons(PARM_SUPP_ADDRS); 620Sstevel@tonic-gate addrtype = (uint16_t *)(sph + 1); 63*11042SErik.Nordmark@Sun.COM switch (connp->conn_family) { 64*11042SErik.Nordmark@Sun.COM case AF_INET: 650Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR4); 660Sstevel@tonic-gate *addrtype = 0; 670Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 680Sstevel@tonic-gate break; 69*11042SErik.Nordmark@Sun.COM case AF_INET6: 700Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR6); 710Sstevel@tonic-gate if (!sctp->sctp_connp->conn_ipv6_v6only) { 720Sstevel@tonic-gate *addrtype = htons(PARM_ADDR4); 730Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 740Sstevel@tonic-gate sizeof (*addrtype) * 2); 750Sstevel@tonic-gate } else { 760Sstevel@tonic-gate *addrtype = 0; 770Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 780Sstevel@tonic-gate sizeof (*addrtype)); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate break; 810Sstevel@tonic-gate default: 820Sstevel@tonic-gate break; 830Sstevel@tonic-gate } 840Sstevel@tonic-gate return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 850Sstevel@tonic-gate } 860Sstevel@tonic-gate 870Sstevel@tonic-gate /* 880Sstevel@tonic-gate * Currently, we support on PRSCTP option, there is more to come. 890Sstevel@tonic-gate */ 900Sstevel@tonic-gate /*ARGSUSED*/ 910Sstevel@tonic-gate size_t 920Sstevel@tonic-gate sctp_options_param_len(const sctp_t *sctp, int option) 930Sstevel@tonic-gate { 940Sstevel@tonic-gate size_t optlen; 950Sstevel@tonic-gate 960Sstevel@tonic-gate switch (option) { 970Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 980Sstevel@tonic-gate optlen = sizeof (sctp_parm_hdr_t); 990Sstevel@tonic-gate break; 1000Sstevel@tonic-gate default: 1010Sstevel@tonic-gate ASSERT(0); 1020Sstevel@tonic-gate } 1030Sstevel@tonic-gate 1040Sstevel@tonic-gate return (optlen); 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate /*ARGSUSED*/ 1080Sstevel@tonic-gate size_t 1090Sstevel@tonic-gate sctp_options_param(const sctp_t *sctp, void *p, int option) 1100Sstevel@tonic-gate { 1110Sstevel@tonic-gate sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate switch (option) { 1140Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1150Sstevel@tonic-gate sph->sph_type = htons(PARM_FORWARD_TSN); 1160Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph)); 1170Sstevel@tonic-gate break; 1180Sstevel@tonic-gate default: 1190Sstevel@tonic-gate ASSERT(0); 1200Sstevel@tonic-gate } 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate return (sizeof (*sph)); 1230Sstevel@tonic-gate 1240Sstevel@tonic-gate } 1250Sstevel@tonic-gate 1260Sstevel@tonic-gate size_t 1275586Skcpoon sctp_adaptation_code_param(sctp_t *sctp, uchar_t *p) 1280Sstevel@tonic-gate { 1290Sstevel@tonic-gate sctp_parm_hdr_t *sph; 1300Sstevel@tonic-gate 1315586Skcpoon if (!sctp->sctp_send_adaptation) { 1320Sstevel@tonic-gate return (0); 1330Sstevel@tonic-gate } 1340Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 1350Sstevel@tonic-gate sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 1360Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 1375586Skcpoon *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaptation_code); 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate return (sizeof (*sph) + sizeof (uint32_t)); 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate mblk_t * 143*11042SErik.Nordmark@Sun.COM sctp_init_mp(sctp_t *sctp, sctp_faddr_t *fp) 1440Sstevel@tonic-gate { 1450Sstevel@tonic-gate mblk_t *mp; 1460Sstevel@tonic-gate uchar_t *p; 1470Sstevel@tonic-gate size_t initlen; 1480Sstevel@tonic-gate sctp_init_chunk_t *icp; 1490Sstevel@tonic-gate sctp_chunk_hdr_t *chp; 1500Sstevel@tonic-gate uint16_t schlen; 1510Sstevel@tonic-gate int supp_af; 152*11042SErik.Nordmark@Sun.COM sctp_stack_t *sctps = sctp->sctp_sctps; 153*11042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 1540Sstevel@tonic-gate 155*11042SErik.Nordmark@Sun.COM if (connp->conn_family == AF_INET) { 1560Sstevel@tonic-gate supp_af = PARM_SUPP_V4; 1570Sstevel@tonic-gate } else { 1580Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 1590Sstevel@tonic-gate supp_af = PARM_SUPP_V6; 1600Sstevel@tonic-gate else 1610Sstevel@tonic-gate supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 1620Sstevel@tonic-gate } 1630Sstevel@tonic-gate initlen = sizeof (*chp) + sizeof (*icp); 1645586Skcpoon if (sctp->sctp_send_adaptation) { 1650Sstevel@tonic-gate initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate initlen += sctp_supaddr_param_len(sctp); 1683795Skcpoon initlen += sctp_addr_params(sctp, supp_af, NULL, B_TRUE); 1693448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 1700Sstevel@tonic-gate initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 1710Sstevel@tonic-gate 1720Sstevel@tonic-gate /* 1730Sstevel@tonic-gate * This could be a INIT retransmission in which case sh_verf may 1740Sstevel@tonic-gate * be non-zero, zero it out just to be sure. 1750Sstevel@tonic-gate */ 1760Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = 0; 1770Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = 0; 1780Sstevel@tonic-gate 179*11042SErik.Nordmark@Sun.COM mp = sctp_make_mp(sctp, fp, initlen); 1801735Skcpoon if (mp == NULL) { 1813448Sdh155122 SCTP_KSTAT(sctps, sctp_send_init_failed); 1820Sstevel@tonic-gate return (NULL); 1831735Skcpoon } 184*11042SErik.Nordmark@Sun.COM /* sctp_make_mp could have discovered we have no usable sources */ 185*11042SErik.Nordmark@Sun.COM if (sctp->sctp_nsaddrs == 0) { 186*11042SErik.Nordmark@Sun.COM freemsg(mp); 187*11042SErik.Nordmark@Sun.COM SCTP_KSTAT(sctps, sctp_send_init_failed); 188*11042SErik.Nordmark@Sun.COM return (NULL); 189*11042SErik.Nordmark@Sun.COM } 1900Sstevel@tonic-gate 1910Sstevel@tonic-gate /* Lay in a new INIT chunk, starting with the chunk header */ 1920Sstevel@tonic-gate chp = (sctp_chunk_hdr_t *)mp->b_wptr; 1930Sstevel@tonic-gate chp->sch_id = CHUNK_INIT; 1940Sstevel@tonic-gate chp->sch_flags = 0; 1950Sstevel@tonic-gate schlen = (uint16_t)initlen; 1960Sstevel@tonic-gate U16_TO_ABE16(schlen, &(chp->sch_len)); 1970Sstevel@tonic-gate 1980Sstevel@tonic-gate mp->b_wptr += initlen; 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate icp = (sctp_init_chunk_t *)(chp + 1); 2010Sstevel@tonic-gate icp->sic_inittag = sctp->sctp_lvtag; 2020Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 2030Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 2040Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 2050Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 2060Sstevel@tonic-gate 2070Sstevel@tonic-gate p = (uchar_t *)(icp + 1); 2080Sstevel@tonic-gate 2095586Skcpoon /* Adaptation layer param */ 2105586Skcpoon p += sctp_adaptation_code_param(sctp, p); 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* Add supported address types parameter */ 2130Sstevel@tonic-gate p += sctp_supaddr_param(sctp, p); 2140Sstevel@tonic-gate 2150Sstevel@tonic-gate /* Add address parameters */ 2163795Skcpoon p += sctp_addr_params(sctp, supp_af, p, B_FALSE); 2170Sstevel@tonic-gate 2180Sstevel@tonic-gate /* Add Forward-TSN-Supported param */ 2193448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 2200Sstevel@tonic-gate p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 2210Sstevel@tonic-gate 2220Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 2230Sstevel@tonic-gate 224*11042SErik.Nordmark@Sun.COM sctp_set_iplen(sctp, mp, fp->ixa); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate return (mp); 2270Sstevel@tonic-gate } 2280Sstevel@tonic-gate 2290Sstevel@tonic-gate /* 2300Sstevel@tonic-gate * Extracts the verification tag from an INIT chunk. If the INIT 2310Sstevel@tonic-gate * chunk is truncated or malformed, returns 0. 2320Sstevel@tonic-gate */ 2330Sstevel@tonic-gate uint32_t 2340Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch) 2350Sstevel@tonic-gate { 2360Sstevel@tonic-gate sctp_init_chunk_t *init; 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate init = (sctp_init_chunk_t *)(initch + 1); 2390Sstevel@tonic-gate return (init->sic_inittag); 2400Sstevel@tonic-gate } 2410Sstevel@tonic-gate 2420Sstevel@tonic-gate size_t 2433795Skcpoon sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify) 2440Sstevel@tonic-gate { 2453795Skcpoon size_t param_len; 2463795Skcpoon 2470Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate /* 250432Svi117747 * If we have only one local address or it is a loopback or linklocal 251432Svi117747 * association, we let the peer pull the address from the IP header. 2520Sstevel@tonic-gate */ 2533795Skcpoon if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback || 254432Svi117747 sctp->sctp_linklocal) { 2550Sstevel@tonic-gate return (0); 256432Svi117747 } 257432Svi117747 2583795Skcpoon param_len = sctp_saddr_info(sctp, af, p, modify); 2593795Skcpoon return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len); 2600Sstevel@tonic-gate } 261