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 /* 233448Sdh155122 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 280Sstevel@tonic-gate 290Sstevel@tonic-gate #include <sys/types.h> 300Sstevel@tonic-gate #include <sys/stream.h> 310Sstevel@tonic-gate #include <sys/ddi.h> 320Sstevel@tonic-gate #include <sys/sunddi.h> 330Sstevel@tonic-gate 340Sstevel@tonic-gate #include <netinet/in.h> 350Sstevel@tonic-gate #include <netinet/ip6.h> 360Sstevel@tonic-gate 370Sstevel@tonic-gate #include <inet/common.h> 380Sstevel@tonic-gate #include <inet/ipclassifier.h> 390Sstevel@tonic-gate #include <inet/ip.h> 400Sstevel@tonic-gate #include <inet/ip6.h> 410Sstevel@tonic-gate #include <inet/mib2.h> 420Sstevel@tonic-gate #include <inet/nd.h> 430Sstevel@tonic-gate #include <inet/optcom.h> 443448Sdh155122 #include <inet/ipclassifier.h> 450Sstevel@tonic-gate #include "sctp_impl.h" 460Sstevel@tonic-gate #include "sctp_addr.h" 470Sstevel@tonic-gate 480Sstevel@tonic-gate /* 490Sstevel@tonic-gate * This will compute the checksum over the SCTP packet, so this 500Sstevel@tonic-gate * function should only be called after the whole packet has been 510Sstevel@tonic-gate * built. 520Sstevel@tonic-gate * 530Sstevel@tonic-gate * rptr should point to the IP / SCTP composite header. 540Sstevel@tonic-gate * len should be the length of the entire packet, including the IP 550Sstevel@tonic-gate * header. 560Sstevel@tonic-gate */ 570Sstevel@tonic-gate void 580Sstevel@tonic-gate sctp_add_hdr(sctp_t *sctp, uchar_t *rptr, size_t len) 590Sstevel@tonic-gate { 600Sstevel@tonic-gate ipha_t *iphdr; 610Sstevel@tonic-gate short iplen; 620Sstevel@tonic-gate 630Sstevel@tonic-gate ASSERT(len >= sctp->sctp_hdr_len); 640Sstevel@tonic-gate 650Sstevel@tonic-gate /* Copy the common header from the template */ 660Sstevel@tonic-gate bcopy(sctp->sctp_iphc, rptr, sctp->sctp_hdr_len); 670Sstevel@tonic-gate 680Sstevel@tonic-gate /* Set the total length in the IP hdr */ 690Sstevel@tonic-gate iplen = (short)len; 700Sstevel@tonic-gate iphdr = (ipha_t *)rptr; 710Sstevel@tonic-gate U16_TO_ABE16(iplen, &iphdr->ipha_length); 720Sstevel@tonic-gate } 730Sstevel@tonic-gate 740Sstevel@tonic-gate /*ARGSUSED*/ 750Sstevel@tonic-gate size_t 760Sstevel@tonic-gate sctp_supaddr_param_len(sctp_t *sctp) 770Sstevel@tonic-gate { 780Sstevel@tonic-gate return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 790Sstevel@tonic-gate } 800Sstevel@tonic-gate 810Sstevel@tonic-gate size_t 820Sstevel@tonic-gate sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 830Sstevel@tonic-gate { 840Sstevel@tonic-gate sctp_parm_hdr_t *sph; 850Sstevel@tonic-gate uint16_t *addrtype; 860Sstevel@tonic-gate 870Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 880Sstevel@tonic-gate sph->sph_type = htons(PARM_SUPP_ADDRS); 890Sstevel@tonic-gate addrtype = (uint16_t *)(sph + 1); 900Sstevel@tonic-gate switch (sctp->sctp_ipversion) { 910Sstevel@tonic-gate case IPV4_VERSION: 920Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR4); 930Sstevel@tonic-gate *addrtype = 0; 940Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 950Sstevel@tonic-gate break; 960Sstevel@tonic-gate case IPV6_VERSION: 970Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR6); 980Sstevel@tonic-gate if (!sctp->sctp_connp->conn_ipv6_v6only) { 990Sstevel@tonic-gate *addrtype = htons(PARM_ADDR4); 1000Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 1010Sstevel@tonic-gate sizeof (*addrtype) * 2); 1020Sstevel@tonic-gate } else { 1030Sstevel@tonic-gate *addrtype = 0; 1040Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 1050Sstevel@tonic-gate sizeof (*addrtype)); 1060Sstevel@tonic-gate } 1070Sstevel@tonic-gate break; 1080Sstevel@tonic-gate default: 1090Sstevel@tonic-gate break; 1100Sstevel@tonic-gate } 1110Sstevel@tonic-gate return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 1120Sstevel@tonic-gate } 1130Sstevel@tonic-gate 1140Sstevel@tonic-gate /* 1150Sstevel@tonic-gate * Currently, we support on PRSCTP option, there is more to come. 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate /*ARGSUSED*/ 1180Sstevel@tonic-gate size_t 1190Sstevel@tonic-gate sctp_options_param_len(const sctp_t *sctp, int option) 1200Sstevel@tonic-gate { 1210Sstevel@tonic-gate size_t optlen; 1220Sstevel@tonic-gate 1230Sstevel@tonic-gate switch (option) { 1240Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1250Sstevel@tonic-gate optlen = sizeof (sctp_parm_hdr_t); 1260Sstevel@tonic-gate break; 1270Sstevel@tonic-gate default: 1280Sstevel@tonic-gate ASSERT(0); 1290Sstevel@tonic-gate } 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate return (optlen); 1320Sstevel@tonic-gate } 1330Sstevel@tonic-gate 1340Sstevel@tonic-gate /*ARGSUSED*/ 1350Sstevel@tonic-gate size_t 1360Sstevel@tonic-gate sctp_options_param(const sctp_t *sctp, void *p, int option) 1370Sstevel@tonic-gate { 1380Sstevel@tonic-gate sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate switch (option) { 1410Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1420Sstevel@tonic-gate sph->sph_type = htons(PARM_FORWARD_TSN); 1430Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph)); 1440Sstevel@tonic-gate break; 1450Sstevel@tonic-gate default: 1460Sstevel@tonic-gate ASSERT(0); 1470Sstevel@tonic-gate } 1480Sstevel@tonic-gate 1490Sstevel@tonic-gate return (sizeof (*sph)); 1500Sstevel@tonic-gate 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate size_t 1540Sstevel@tonic-gate sctp_adaption_code_param(sctp_t *sctp, uchar_t *p) 1550Sstevel@tonic-gate { 1560Sstevel@tonic-gate sctp_parm_hdr_t *sph; 1570Sstevel@tonic-gate 1580Sstevel@tonic-gate if (!sctp->sctp_send_adaption) { 1590Sstevel@tonic-gate return (0); 1600Sstevel@tonic-gate } 1610Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 1620Sstevel@tonic-gate sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 1630Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 1640Sstevel@tonic-gate *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaption_code); 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate return (sizeof (*sph) + sizeof (uint32_t)); 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate mblk_t * 1700Sstevel@tonic-gate sctp_init_mp(sctp_t *sctp) 1710Sstevel@tonic-gate { 1720Sstevel@tonic-gate mblk_t *mp; 1730Sstevel@tonic-gate uchar_t *p; 1740Sstevel@tonic-gate size_t initlen; 1750Sstevel@tonic-gate sctp_init_chunk_t *icp; 1760Sstevel@tonic-gate sctp_chunk_hdr_t *chp; 1770Sstevel@tonic-gate uint16_t schlen; 1780Sstevel@tonic-gate int supp_af; 1793448Sdh155122 sctp_stack_t *sctps = sctp->sctp_sctps; 1800Sstevel@tonic-gate 1810Sstevel@tonic-gate if (sctp->sctp_family == AF_INET) { 1820Sstevel@tonic-gate supp_af = PARM_SUPP_V4; 1830Sstevel@tonic-gate } else { 1840Sstevel@tonic-gate /* Assume here that a v6 endpoint supports v4 address. */ 1850Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 1860Sstevel@tonic-gate supp_af = PARM_SUPP_V6; 1870Sstevel@tonic-gate else 1880Sstevel@tonic-gate supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 1890Sstevel@tonic-gate } 1900Sstevel@tonic-gate initlen = sizeof (*chp) + sizeof (*icp); 1910Sstevel@tonic-gate if (sctp->sctp_send_adaption) { 1920Sstevel@tonic-gate initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 1930Sstevel@tonic-gate } 1940Sstevel@tonic-gate initlen += sctp_supaddr_param_len(sctp); 195*3795Skcpoon initlen += sctp_addr_params(sctp, supp_af, NULL, B_TRUE); 1963448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 1970Sstevel@tonic-gate initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 1980Sstevel@tonic-gate 1990Sstevel@tonic-gate /* 2000Sstevel@tonic-gate * This could be a INIT retransmission in which case sh_verf may 2010Sstevel@tonic-gate * be non-zero, zero it out just to be sure. 2020Sstevel@tonic-gate */ 2030Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = 0; 2040Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = 0; 2050Sstevel@tonic-gate 2060Sstevel@tonic-gate mp = sctp_make_mp(sctp, NULL, initlen); 2071735Skcpoon if (mp == NULL) { 2083448Sdh155122 SCTP_KSTAT(sctps, sctp_send_init_failed); 2090Sstevel@tonic-gate return (NULL); 2101735Skcpoon } 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* Lay in a new INIT chunk, starting with the chunk header */ 2130Sstevel@tonic-gate chp = (sctp_chunk_hdr_t *)mp->b_wptr; 2140Sstevel@tonic-gate chp->sch_id = CHUNK_INIT; 2150Sstevel@tonic-gate chp->sch_flags = 0; 2160Sstevel@tonic-gate schlen = (uint16_t)initlen; 2170Sstevel@tonic-gate U16_TO_ABE16(schlen, &(chp->sch_len)); 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate mp->b_wptr += initlen; 2200Sstevel@tonic-gate 2210Sstevel@tonic-gate icp = (sctp_init_chunk_t *)(chp + 1); 2220Sstevel@tonic-gate icp->sic_inittag = sctp->sctp_lvtag; 2230Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 2240Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 2250Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 2260Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate p = (uchar_t *)(icp + 1); 2290Sstevel@tonic-gate 2300Sstevel@tonic-gate /* Adaption layer param */ 2310Sstevel@tonic-gate p += sctp_adaption_code_param(sctp, p); 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate /* Add supported address types parameter */ 2340Sstevel@tonic-gate p += sctp_supaddr_param(sctp, p); 2350Sstevel@tonic-gate 2360Sstevel@tonic-gate /* Add address parameters */ 237*3795Skcpoon p += sctp_addr_params(sctp, supp_af, p, B_FALSE); 2380Sstevel@tonic-gate 2390Sstevel@tonic-gate /* Add Forward-TSN-Supported param */ 2403448Sdh155122 if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled) 2410Sstevel@tonic-gate p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate sctp_set_iplen(sctp, mp); 2460Sstevel@tonic-gate 2470Sstevel@tonic-gate return (mp); 2480Sstevel@tonic-gate } 2490Sstevel@tonic-gate 2500Sstevel@tonic-gate /* 2510Sstevel@tonic-gate * Extracts the verification tag from an INIT chunk. If the INIT 2520Sstevel@tonic-gate * chunk is truncated or malformed, returns 0. 2530Sstevel@tonic-gate */ 2540Sstevel@tonic-gate uint32_t 2550Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch) 2560Sstevel@tonic-gate { 2570Sstevel@tonic-gate sctp_init_chunk_t *init; 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate init = (sctp_init_chunk_t *)(initch + 1); 2600Sstevel@tonic-gate return (init->sic_inittag); 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate size_t 264*3795Skcpoon sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify) 2650Sstevel@tonic-gate { 266*3795Skcpoon size_t param_len; 267*3795Skcpoon 2680Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* 271432Svi117747 * If we have only one local address or it is a loopback or linklocal 272432Svi117747 * association, we let the peer pull the address from the IP header. 2730Sstevel@tonic-gate */ 274*3795Skcpoon if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback || 275432Svi117747 sctp->sctp_linklocal) { 2760Sstevel@tonic-gate return (0); 277432Svi117747 } 278432Svi117747 279*3795Skcpoon param_len = sctp_saddr_info(sctp, af, p, modify); 280*3795Skcpoon return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len); 2810Sstevel@tonic-gate } 282