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 5*1735Skcpoon * Common Development and Distribution License (the "License"). 6*1735Skcpoon * 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 */ 21*1735Skcpoon 220Sstevel@tonic-gate /* 23*1735Skcpoon * Copyright 2006 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> 440Sstevel@tonic-gate #include "sctp_impl.h" 450Sstevel@tonic-gate #include "sctp_addr.h" 460Sstevel@tonic-gate 470Sstevel@tonic-gate /* 480Sstevel@tonic-gate * This will compute the checksum over the SCTP packet, so this 490Sstevel@tonic-gate * function should only be called after the whole packet has been 500Sstevel@tonic-gate * built. 510Sstevel@tonic-gate * 520Sstevel@tonic-gate * rptr should point to the IP / SCTP composite header. 530Sstevel@tonic-gate * len should be the length of the entire packet, including the IP 540Sstevel@tonic-gate * header. 550Sstevel@tonic-gate */ 560Sstevel@tonic-gate void 570Sstevel@tonic-gate sctp_add_hdr(sctp_t *sctp, uchar_t *rptr, size_t len) 580Sstevel@tonic-gate { 590Sstevel@tonic-gate ipha_t *iphdr; 600Sstevel@tonic-gate short iplen; 610Sstevel@tonic-gate 620Sstevel@tonic-gate ASSERT(len >= sctp->sctp_hdr_len); 630Sstevel@tonic-gate 640Sstevel@tonic-gate /* Copy the common header from the template */ 650Sstevel@tonic-gate bcopy(sctp->sctp_iphc, rptr, sctp->sctp_hdr_len); 660Sstevel@tonic-gate 670Sstevel@tonic-gate /* Set the total length in the IP hdr */ 680Sstevel@tonic-gate iplen = (short)len; 690Sstevel@tonic-gate iphdr = (ipha_t *)rptr; 700Sstevel@tonic-gate U16_TO_ABE16(iplen, &iphdr->ipha_length); 710Sstevel@tonic-gate } 720Sstevel@tonic-gate 730Sstevel@tonic-gate /*ARGSUSED*/ 740Sstevel@tonic-gate size_t 750Sstevel@tonic-gate sctp_supaddr_param_len(sctp_t *sctp) 760Sstevel@tonic-gate { 770Sstevel@tonic-gate return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t)); 780Sstevel@tonic-gate } 790Sstevel@tonic-gate 800Sstevel@tonic-gate size_t 810Sstevel@tonic-gate sctp_supaddr_param(sctp_t *sctp, uchar_t *p) 820Sstevel@tonic-gate { 830Sstevel@tonic-gate sctp_parm_hdr_t *sph; 840Sstevel@tonic-gate uint16_t *addrtype; 850Sstevel@tonic-gate 860Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 870Sstevel@tonic-gate sph->sph_type = htons(PARM_SUPP_ADDRS); 880Sstevel@tonic-gate addrtype = (uint16_t *)(sph + 1); 890Sstevel@tonic-gate switch (sctp->sctp_ipversion) { 900Sstevel@tonic-gate case IPV4_VERSION: 910Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR4); 920Sstevel@tonic-gate *addrtype = 0; 930Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype)); 940Sstevel@tonic-gate break; 950Sstevel@tonic-gate case IPV6_VERSION: 960Sstevel@tonic-gate *addrtype++ = htons(PARM_ADDR6); 970Sstevel@tonic-gate if (!sctp->sctp_connp->conn_ipv6_v6only) { 980Sstevel@tonic-gate *addrtype = htons(PARM_ADDR4); 990Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 1000Sstevel@tonic-gate sizeof (*addrtype) * 2); 1010Sstevel@tonic-gate } else { 1020Sstevel@tonic-gate *addrtype = 0; 1030Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + 1040Sstevel@tonic-gate sizeof (*addrtype)); 1050Sstevel@tonic-gate } 1060Sstevel@tonic-gate break; 1070Sstevel@tonic-gate default: 1080Sstevel@tonic-gate break; 1090Sstevel@tonic-gate } 1100Sstevel@tonic-gate return (sizeof (*sph) + (sizeof (*addrtype) * 2)); 1110Sstevel@tonic-gate } 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* 1140Sstevel@tonic-gate * Currently, we support on PRSCTP option, there is more to come. 1150Sstevel@tonic-gate */ 1160Sstevel@tonic-gate /*ARGSUSED*/ 1170Sstevel@tonic-gate size_t 1180Sstevel@tonic-gate sctp_options_param_len(const sctp_t *sctp, int option) 1190Sstevel@tonic-gate { 1200Sstevel@tonic-gate size_t optlen; 1210Sstevel@tonic-gate 1220Sstevel@tonic-gate switch (option) { 1230Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1240Sstevel@tonic-gate optlen = sizeof (sctp_parm_hdr_t); 1250Sstevel@tonic-gate break; 1260Sstevel@tonic-gate default: 1270Sstevel@tonic-gate ASSERT(0); 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate return (optlen); 1310Sstevel@tonic-gate } 1320Sstevel@tonic-gate 1330Sstevel@tonic-gate /*ARGSUSED*/ 1340Sstevel@tonic-gate size_t 1350Sstevel@tonic-gate sctp_options_param(const sctp_t *sctp, void *p, int option) 1360Sstevel@tonic-gate { 1370Sstevel@tonic-gate sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p; 1380Sstevel@tonic-gate 1390Sstevel@tonic-gate switch (option) { 1400Sstevel@tonic-gate case SCTP_PRSCTP_OPTION: 1410Sstevel@tonic-gate sph->sph_type = htons(PARM_FORWARD_TSN); 1420Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph)); 1430Sstevel@tonic-gate break; 1440Sstevel@tonic-gate default: 1450Sstevel@tonic-gate ASSERT(0); 1460Sstevel@tonic-gate } 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate return (sizeof (*sph)); 1490Sstevel@tonic-gate 1500Sstevel@tonic-gate } 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate size_t 1530Sstevel@tonic-gate sctp_adaption_code_param(sctp_t *sctp, uchar_t *p) 1540Sstevel@tonic-gate { 1550Sstevel@tonic-gate sctp_parm_hdr_t *sph; 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (!sctp->sctp_send_adaption) { 1580Sstevel@tonic-gate return (0); 1590Sstevel@tonic-gate } 1600Sstevel@tonic-gate sph = (sctp_parm_hdr_t *)p; 1610Sstevel@tonic-gate sph->sph_type = htons(PARM_ADAPT_LAYER_IND); 1620Sstevel@tonic-gate sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t)); 1630Sstevel@tonic-gate *(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaption_code); 1640Sstevel@tonic-gate 1650Sstevel@tonic-gate return (sizeof (*sph) + sizeof (uint32_t)); 1660Sstevel@tonic-gate } 1670Sstevel@tonic-gate 1680Sstevel@tonic-gate mblk_t * 1690Sstevel@tonic-gate sctp_init_mp(sctp_t *sctp) 1700Sstevel@tonic-gate { 1710Sstevel@tonic-gate mblk_t *mp; 1720Sstevel@tonic-gate uchar_t *p; 1730Sstevel@tonic-gate size_t initlen; 1740Sstevel@tonic-gate sctp_init_chunk_t *icp; 1750Sstevel@tonic-gate sctp_chunk_hdr_t *chp; 1760Sstevel@tonic-gate uint16_t schlen; 1770Sstevel@tonic-gate int supp_af; 1780Sstevel@tonic-gate 1790Sstevel@tonic-gate if (sctp->sctp_family == AF_INET) { 1800Sstevel@tonic-gate supp_af = PARM_SUPP_V4; 1810Sstevel@tonic-gate } else { 1820Sstevel@tonic-gate /* Assume here that a v6 endpoint supports v4 address. */ 1830Sstevel@tonic-gate if (sctp->sctp_connp->conn_ipv6_v6only) 1840Sstevel@tonic-gate supp_af = PARM_SUPP_V6; 1850Sstevel@tonic-gate else 1860Sstevel@tonic-gate supp_af = PARM_SUPP_V6 | PARM_SUPP_V4; 1870Sstevel@tonic-gate } 1880Sstevel@tonic-gate initlen = sizeof (*chp) + sizeof (*icp); 1890Sstevel@tonic-gate if (sctp->sctp_send_adaption) { 1900Sstevel@tonic-gate initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t)); 1910Sstevel@tonic-gate } 1920Sstevel@tonic-gate initlen += sctp_supaddr_param_len(sctp); 193432Svi117747 initlen += sctp_addr_params_len(sctp, supp_af, B_TRUE); 1940Sstevel@tonic-gate if (sctp->sctp_prsctp_aware && sctp_prsctp_enabled) 1950Sstevel@tonic-gate initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION); 1960Sstevel@tonic-gate 1970Sstevel@tonic-gate /* 1980Sstevel@tonic-gate * This could be a INIT retransmission in which case sh_verf may 1990Sstevel@tonic-gate * be non-zero, zero it out just to be sure. 2000Sstevel@tonic-gate */ 2010Sstevel@tonic-gate sctp->sctp_sctph->sh_verf = 0; 2020Sstevel@tonic-gate sctp->sctp_sctph6->sh_verf = 0; 2030Sstevel@tonic-gate 2040Sstevel@tonic-gate mp = sctp_make_mp(sctp, NULL, initlen); 205*1735Skcpoon if (mp == NULL) { 206*1735Skcpoon SCTP_KSTAT(sctp_send_init_failed); 2070Sstevel@tonic-gate return (NULL); 208*1735Skcpoon } 2090Sstevel@tonic-gate 2100Sstevel@tonic-gate /* Lay in a new INIT chunk, starting with the chunk header */ 2110Sstevel@tonic-gate chp = (sctp_chunk_hdr_t *)mp->b_wptr; 2120Sstevel@tonic-gate chp->sch_id = CHUNK_INIT; 2130Sstevel@tonic-gate chp->sch_flags = 0; 2140Sstevel@tonic-gate schlen = (uint16_t)initlen; 2150Sstevel@tonic-gate U16_TO_ABE16(schlen, &(chp->sch_len)); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate mp->b_wptr += initlen; 2180Sstevel@tonic-gate 2190Sstevel@tonic-gate icp = (sctp_init_chunk_t *)(chp + 1); 2200Sstevel@tonic-gate icp->sic_inittag = sctp->sctp_lvtag; 2210Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd)); 2220Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr)); 2230Sstevel@tonic-gate U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr)); 2240Sstevel@tonic-gate U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn)); 2250Sstevel@tonic-gate 2260Sstevel@tonic-gate p = (uchar_t *)(icp + 1); 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate /* Adaption layer param */ 2290Sstevel@tonic-gate p += sctp_adaption_code_param(sctp, p); 2300Sstevel@tonic-gate 2310Sstevel@tonic-gate /* Add supported address types parameter */ 2320Sstevel@tonic-gate p += sctp_supaddr_param(sctp, p); 2330Sstevel@tonic-gate 2340Sstevel@tonic-gate /* Add address parameters */ 2350Sstevel@tonic-gate p += sctp_addr_params(sctp, supp_af, p); 2360Sstevel@tonic-gate 2370Sstevel@tonic-gate /* Add Forward-TSN-Supported param */ 2380Sstevel@tonic-gate if (sctp->sctp_prsctp_aware && sctp_prsctp_enabled) 2390Sstevel@tonic-gate p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION); 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate BUMP_LOCAL(sctp->sctp_obchunks); 2420Sstevel@tonic-gate 2430Sstevel@tonic-gate sctp_set_iplen(sctp, mp); 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate return (mp); 2460Sstevel@tonic-gate } 2470Sstevel@tonic-gate 2480Sstevel@tonic-gate /* 2490Sstevel@tonic-gate * Extracts the verification tag from an INIT chunk. If the INIT 2500Sstevel@tonic-gate * chunk is truncated or malformed, returns 0. 2510Sstevel@tonic-gate */ 2520Sstevel@tonic-gate uint32_t 2530Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch) 2540Sstevel@tonic-gate { 2550Sstevel@tonic-gate sctp_init_chunk_t *init; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate init = (sctp_init_chunk_t *)(initch + 1); 2580Sstevel@tonic-gate return (init->sic_inittag); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate size_t 262432Svi117747 sctp_addr_params_len(sctp_t *sctp, int af, boolean_t modify) 2630Sstevel@tonic-gate { 2640Sstevel@tonic-gate ASSERT(sctp->sctp_nsaddrs > 0); 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate /* 267432Svi117747 * If we have only one local address or it is a loopback or linklocal 268432Svi117747 * association, we let the peer pull the address from the IP header. 2690Sstevel@tonic-gate */ 270432Svi117747 if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback || 271432Svi117747 sctp->sctp_linklocal) { 2720Sstevel@tonic-gate return (0); 273432Svi117747 } 274432Svi117747 275432Svi117747 return (sctp_saddr_info(sctp, af, NULL, modify)); 2760Sstevel@tonic-gate } 2770Sstevel@tonic-gate 2780Sstevel@tonic-gate size_t 2790Sstevel@tonic-gate sctp_addr_params(sctp_t *sctp, int af, uchar_t *p) 2800Sstevel@tonic-gate { 281432Svi117747 /* 282432Svi117747 * If we have only one local address or it is a loopback or linklocal 283432Svi117747 * association, we let the peer pull the address from the IP header. 284432Svi117747 */ 285432Svi117747 if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback || 286432Svi117747 sctp->sctp_linklocal) { 2870Sstevel@tonic-gate return (0); 288432Svi117747 } 289432Svi117747 return (sctp_saddr_info(sctp, af, p, B_FALSE)); 2900Sstevel@tonic-gate } 291