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
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 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);
193*432Svi117747 	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);
2050Sstevel@tonic-gate 	if (mp == NULL)
2060Sstevel@tonic-gate 		return (NULL);
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 	/* Lay in a new INIT chunk, starting with the chunk header */
2090Sstevel@tonic-gate 	chp = (sctp_chunk_hdr_t *)mp->b_wptr;
2100Sstevel@tonic-gate 	chp->sch_id = CHUNK_INIT;
2110Sstevel@tonic-gate 	chp->sch_flags = 0;
2120Sstevel@tonic-gate 	schlen = (uint16_t)initlen;
2130Sstevel@tonic-gate 	U16_TO_ABE16(schlen, &(chp->sch_len));
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 	mp->b_wptr += initlen;
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	icp = (sctp_init_chunk_t *)(chp + 1);
2180Sstevel@tonic-gate 	icp->sic_inittag = sctp->sctp_lvtag;
2190Sstevel@tonic-gate 	U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd));
2200Sstevel@tonic-gate 	U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr));
2210Sstevel@tonic-gate 	U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr));
2220Sstevel@tonic-gate 	U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn));
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	p = (uchar_t *)(icp + 1);
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate 	/* Adaption layer param */
2270Sstevel@tonic-gate 	p += sctp_adaption_code_param(sctp, p);
2280Sstevel@tonic-gate 
2290Sstevel@tonic-gate 	/* Add supported address types parameter */
2300Sstevel@tonic-gate 	p += sctp_supaddr_param(sctp, p);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	/* Add address parameters */
2330Sstevel@tonic-gate 	p += sctp_addr_params(sctp, supp_af, p);
2340Sstevel@tonic-gate 
2350Sstevel@tonic-gate 	/* Add Forward-TSN-Supported param */
2360Sstevel@tonic-gate 	if (sctp->sctp_prsctp_aware && sctp_prsctp_enabled)
2370Sstevel@tonic-gate 		p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION);
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_obchunks);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 	sctp_set_iplen(sctp, mp);
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 	return (mp);
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate /*
2470Sstevel@tonic-gate  * Extracts the verification tag from an INIT chunk. If the INIT
2480Sstevel@tonic-gate  * chunk is truncated or malformed, returns 0.
2490Sstevel@tonic-gate  */
2500Sstevel@tonic-gate uint32_t
2510Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch)
2520Sstevel@tonic-gate {
2530Sstevel@tonic-gate 	sctp_init_chunk_t *init;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	init = (sctp_init_chunk_t *)(initch + 1);
2560Sstevel@tonic-gate 	return (init->sic_inittag);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate size_t
260*432Svi117747 sctp_addr_params_len(sctp_t *sctp, int af, boolean_t modify)
2610Sstevel@tonic-gate {
2620Sstevel@tonic-gate 	ASSERT(sctp->sctp_nsaddrs > 0);
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	/*
265*432Svi117747 	 * If we have only one local address or it is a loopback or linklocal
266*432Svi117747 	 * association, we let the peer pull the address from the IP header.
2670Sstevel@tonic-gate 	 */
268*432Svi117747 	if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback ||
269*432Svi117747 	    sctp->sctp_linklocal) {
2700Sstevel@tonic-gate 		return (0);
271*432Svi117747 	}
272*432Svi117747 
273*432Svi117747 	return (sctp_saddr_info(sctp, af, NULL, modify));
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate size_t
2770Sstevel@tonic-gate sctp_addr_params(sctp_t *sctp, int af, uchar_t *p)
2780Sstevel@tonic-gate {
279*432Svi117747 	/*
280*432Svi117747 	 * If we have only one local address or it is a loopback or linklocal
281*432Svi117747 	 * association, we let the peer pull the address from the IP header.
282*432Svi117747 	 */
283*432Svi117747 	if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback ||
284*432Svi117747 	    sctp->sctp_linklocal) {
2850Sstevel@tonic-gate 		return (0);
286*432Svi117747 	}
287*432Svi117747 	return (sctp_saddr_info(sctp, af, p, B_FALSE));
2880Sstevel@tonic-gate }
289