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*13009SChandrasekar.Marimuthu@Sun.COM * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 240Sstevel@tonic-gate */ 250Sstevel@tonic-gate 260Sstevel@tonic-gate #include <sys/types.h> 270Sstevel@tonic-gate #include <sys/stream.h> 280Sstevel@tonic-gate #include <sys/ddi.h> 290Sstevel@tonic-gate #include <sys/sunddi.h> 300Sstevel@tonic-gate 310Sstevel@tonic-gate #include <netinet/in.h> 320Sstevel@tonic-gate #include <netinet/ip6.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <inet/common.h> 350Sstevel@tonic-gate #include <inet/ipclassifier.h> 360Sstevel@tonic-gate #include <inet/ip.h> 370Sstevel@tonic-gate #include <inet/ip6.h> 380Sstevel@tonic-gate #include <inet/mib2.h> 390Sstevel@tonic-gate #include <inet/nd.h> 400Sstevel@tonic-gate #include <inet/optcom.h> 413448Sdh155122 #include <inet/ipclassifier.h> 420Sstevel@tonic-gate #include "sctp_impl.h" 430Sstevel@tonic-gate #include "sctp_addr.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate /*ARGSUSED*/ 460Sstevel@tonic-gate size_t 470Sstevel@tonic-gate sctp_supaddr_param_len(sctp_t *sctp) 480Sstevel@tonic-gate { 490Sstevel@tonic-gate return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 500Sstevel@tonic-gate } 510Sstevel@tonic-gate 520Sstevel@tonic-gate size_t 530Sstevel@tonic-gate sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 540Sstevel@tonic-gate { 550Sstevel@tonic-gate sctp_parm_hdr_t *sph; 560Sstevel@tonic-gate uint16_t *addrtype; 5711042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 580Sstevel@tonic-gate 590Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 600Sstevel@tonic-gate sph->sph_type = htons(PARM_SUPP_ADDRS); 610Sstevel@tonic-gate addrtype = (uint16_t *)(sph + 1); 6211042SErik.Nordmark@Sun.COM switch (connp->conn_family) { 6311042SErik.Nordmark@Sun.COM case AF_INET: 640Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR4); 650Sstevel@tonic-gate *addrtype = 0; 660Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 670Sstevel@tonic-gate break; 6811042SErik.Nordmark@Sun.COM case AF_INET6: 690Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR6); 700Sstevel@tonic-gate if (!sctp->sctp_connp->conn_ipv6_v6only) { 710Sstevel@tonic-gate *addrtype = htons(PARM_ADDR4); 720Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 730Sstevel@tonic-gate sizeof (*addrtype) * 2); 740Sstevel@tonic-gate } else { 750Sstevel@tonic-gate *addrtype = 0; 760Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 770Sstevel@tonic-gate sizeof (*addrtype)); 780Sstevel@tonic-gate } 790Sstevel@tonic-gate break; 800Sstevel@tonic-gate default: 810Sstevel@tonic-gate break; 820Sstevel@tonic-gate } 830Sstevel@tonic-gate return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 840Sstevel@tonic-gate } 850Sstevel@tonic-gate 860Sstevel@tonic-gate /* 870Sstevel@tonic-gate * Currently, we support on PRSCTP option, there is more to come. 880Sstevel@tonic-gate */ 890Sstevel@tonic-gate /*ARGSUSED*/ 900Sstevel@tonic-gate size_t 910Sstevel@tonic-gate sctp_options_param_len(const sctp_t *sctp, int option) 920Sstevel@tonic-gate { 930Sstevel@tonic-gate size_t optlen; 940Sstevel@tonic-gate 950Sstevel@tonic-gate switch (option) { 960Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 970Sstevel@tonic-gate optlen = sizeof (sctp_parm_hdr_t); 980Sstevel@tonic-gate break; 990Sstevel@tonic-gate default: 1000Sstevel@tonic-gate ASSERT(0); 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate return (optlen); 1040Sstevel@tonic-gate } 1050Sstevel@tonic-gate 1060Sstevel@tonic-gate /*ARGSUSED*/ 1070Sstevel@tonic-gate size_t 1080Sstevel@tonic-gate sctp_options_param(const sctp_t *sctp, void *p, int option) 1090Sstevel@tonic-gate { 1100Sstevel@tonic-gate sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate switch (option) { 1130Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1140Sstevel@tonic-gate sph->sph_type = htons(PARM_FORWARD_TSN); 1150Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph)); 1160Sstevel@tonic-gate break; 1170Sstevel@tonic-gate default: 1180Sstevel@tonic-gate ASSERT(0); 1190Sstevel@tonic-gate } 1200Sstevel@tonic-gate 1210Sstevel@tonic-gate return (sizeof (*sph)); 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate size_t 1265586Skcpoon sctp_adaptation_code_param(sctp_t *sctp, uchar_t *p) 1270Sstevel@tonic-gate { 1280Sstevel@tonic-gate sctp_parm_hdr_t *sph; 1290Sstevel@tonic-gate 1305586Skcpoon if (!sctp->sctp_send_adaptation) { 1310Sstevel@tonic-gate return (0); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 1340Sstevel@tonic-gate sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 1350Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 1365586Skcpoon *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaptation_code); 1370Sstevel@tonic-gate 1380Sstevel@tonic-gate return (sizeof (*sph) + sizeof (uint32_t)); 1390Sstevel@tonic-gate } 1400Sstevel@tonic-gate 1410Sstevel@tonic-gate mblk_t * 14211042SErik.Nordmark@Sun.COM sctp_init_mp(sctp_t *sctp, sctp_faddr_t *fp) 1430Sstevel@tonic-gate { 1440Sstevel@tonic-gate mblk_t *mp; 1450Sstevel@tonic-gate uchar_t *p; 1460Sstevel@tonic-gate size_t initlen; 1470Sstevel@tonic-gate sctp_init_chunk_t *icp; 1480Sstevel@tonic-gate sctp_chunk_hdr_t *chp; 1490Sstevel@tonic-gate uint16_t schlen; 1500Sstevel@tonic-gate int supp_af; 15111042SErik.Nordmark@Sun.COM sctp_stack_t *sctps = sctp->sctp_sctps; 15211042SErik.Nordmark@Sun.COM conn_t *connp = sctp->sctp_connp; 1530Sstevel@tonic-gate 15411042SErik.Nordmark@Sun.COM if (connp->conn_family == AF_INET) { 1550Sstevel@tonic-gate supp_af = PARM_SUPP_V4; 1560Sstevel@tonic-gate } else { 1570Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 1580Sstevel@tonic-gate supp_af = PARM_SUPP_V6; 1590Sstevel@tonic-gate else 1600Sstevel@tonic-gate supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 1610Sstevel@tonic-gate } 1620Sstevel@tonic-gate initlen = sizeof (*chp) + sizeof (*icp); 1635586Skcpoon if (sctp->sctp_send_adaptation) { 1640Sstevel@tonic-gate initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 1650Sstevel@tonic-gate } 1660Sstevel@tonic-gate initlen += sctp_supaddr_param_len(sctp); 1673795Skcpoon initlen += sctp_addr_params(sctp, supp_af, NULL, B_TRUE); 1683448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 1690Sstevel@tonic-gate initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 1700Sstevel@tonic-gate 1710Sstevel@tonic-gate /* 1720Sstevel@tonic-gate * This could be a INIT retransmission in which case sh_verf may 1730Sstevel@tonic-gate * be non-zero, zero it out just to be sure. 1740Sstevel@tonic-gate */ 1750Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = 0; 1760Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = 0; 1770Sstevel@tonic-gate 17811042SErik.Nordmark@Sun.COM mp = sctp_make_mp(sctp, fp, initlen); 1791735Skcpoon if (mp == NULL) { 1803448Sdh155122 SCTP_KSTAT(sctps, sctp_send_init_failed); 1810Sstevel@tonic-gate return (NULL); 1821735Skcpoon } 18311042SErik.Nordmark@Sun.COM /* sctp_make_mp could have discovered we have no usable sources */ 18411042SErik.Nordmark@Sun.COM if (sctp->sctp_nsaddrs == 0) { 18511042SErik.Nordmark@Sun.COM freemsg(mp); 18611042SErik.Nordmark@Sun.COM SCTP_KSTAT(sctps, sctp_send_init_failed); 18711042SErik.Nordmark@Sun.COM return (NULL); 18811042SErik.Nordmark@Sun.COM } 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate /* Lay in a new INIT chunk, starting with the chunk header */ 1910Sstevel@tonic-gate chp = (sctp_chunk_hdr_t *)mp->b_wptr; 1920Sstevel@tonic-gate chp->sch_id = CHUNK_INIT; 1930Sstevel@tonic-gate chp->sch_flags = 0; 1940Sstevel@tonic-gate schlen = (uint16_t)initlen; 1950Sstevel@tonic-gate U16_TO_ABE16(schlen, &(chp->sch_len)); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate mp->b_wptr += initlen; 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate icp = (sctp_init_chunk_t *)(chp + 1); 2000Sstevel@tonic-gate icp->sic_inittag = sctp->sctp_lvtag; 2010Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 2020Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 2030Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 2040Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate p = (uchar_t *)(icp + 1); 2070Sstevel@tonic-gate 2085586Skcpoon /* Adaptation layer param */ 2095586Skcpoon p += sctp_adaptation_code_param(sctp, p); 2100Sstevel@tonic-gate 2110Sstevel@tonic-gate /* Add supported address types parameter */ 2120Sstevel@tonic-gate p += sctp_supaddr_param(sctp, p); 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* Add address parameters */ 2153795Skcpoon p += sctp_addr_params(sctp, supp_af, p, B_FALSE); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* Add Forward-TSN-Supported param */ 2183448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 2190Sstevel@tonic-gate p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 2220Sstevel@tonic-gate 223*13009SChandrasekar.Marimuthu@Sun.COM sctp_set_iplen(sctp, mp, fp->sf_ixa); 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate return (mp); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate /* 2290Sstevel@tonic-gate * Extracts the verification tag from an INIT chunk. If the INIT 2300Sstevel@tonic-gate * chunk is truncated or malformed, returns 0. 2310Sstevel@tonic-gate */ 2320Sstevel@tonic-gate uint32_t 2330Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch) 2340Sstevel@tonic-gate { 2350Sstevel@tonic-gate sctp_init_chunk_t *init; 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate init = (sctp_init_chunk_t *)(initch + 1); 2380Sstevel@tonic-gate return (init->sic_inittag); 2390Sstevel@tonic-gate } 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate size_t 2423795Skcpoon sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify) 2430Sstevel@tonic-gate { 2443795Skcpoon size_t param_len; 2453795Skcpoon 2460Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* 249432Svi117747 * If we have only one local address or it is a loopback or linklocal 250432Svi117747 * association, we let the peer pull the address from the IP header. 2510Sstevel@tonic-gate */ 2523795Skcpoon if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback || 253432Svi117747 sctp->sctp_linklocal) { 2540Sstevel@tonic-gate return (0); 255432Svi117747 } 256432Svi117747 2573795Skcpoon param_len = sctp_saddr_info(sctp, af, p, modify); 2583795Skcpoon return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len); 2590Sstevel@tonic-gate } 260