1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * CDDL HEADER START
3*0Sstevel@tonic-gate  *
4*0Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*0Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*0Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*0Sstevel@tonic-gate  * with the License.
8*0Sstevel@tonic-gate  *
9*0Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*0Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*0Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*0Sstevel@tonic-gate  * and limitations under the License.
13*0Sstevel@tonic-gate  *
14*0Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*0Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*0Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*0Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*0Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*0Sstevel@tonic-gate  *
20*0Sstevel@tonic-gate  * CDDL HEADER END
21*0Sstevel@tonic-gate  */
22*0Sstevel@tonic-gate /*
23*0Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*0Sstevel@tonic-gate  * Use is subject to license terms.
25*0Sstevel@tonic-gate  */
26*0Sstevel@tonic-gate 
27*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*0Sstevel@tonic-gate 
29*0Sstevel@tonic-gate #include <sys/types.h>
30*0Sstevel@tonic-gate #include <sys/stream.h>
31*0Sstevel@tonic-gate #include <sys/ddi.h>
32*0Sstevel@tonic-gate #include <sys/sunddi.h>
33*0Sstevel@tonic-gate 
34*0Sstevel@tonic-gate #include <netinet/in.h>
35*0Sstevel@tonic-gate #include <netinet/ip6.h>
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate #include <inet/common.h>
38*0Sstevel@tonic-gate #include <inet/ipclassifier.h>
39*0Sstevel@tonic-gate #include <inet/ip.h>
40*0Sstevel@tonic-gate #include <inet/ip6.h>
41*0Sstevel@tonic-gate #include <inet/mib2.h>
42*0Sstevel@tonic-gate #include <inet/nd.h>
43*0Sstevel@tonic-gate #include <inet/optcom.h>
44*0Sstevel@tonic-gate #include "sctp_impl.h"
45*0Sstevel@tonic-gate #include "sctp_addr.h"
46*0Sstevel@tonic-gate 
47*0Sstevel@tonic-gate /*
48*0Sstevel@tonic-gate  * This will compute the checksum over the SCTP packet, so this
49*0Sstevel@tonic-gate  * function should only be called after the whole packet has been
50*0Sstevel@tonic-gate  * built.
51*0Sstevel@tonic-gate  *
52*0Sstevel@tonic-gate  * rptr should point to the IP / SCTP composite header.
53*0Sstevel@tonic-gate  * len should be the length of the entire packet, including the IP
54*0Sstevel@tonic-gate  *     header.
55*0Sstevel@tonic-gate  */
56*0Sstevel@tonic-gate void
57*0Sstevel@tonic-gate sctp_add_hdr(sctp_t *sctp, uchar_t *rptr, size_t len)
58*0Sstevel@tonic-gate {
59*0Sstevel@tonic-gate 	ipha_t *iphdr;
60*0Sstevel@tonic-gate 	short iplen;
61*0Sstevel@tonic-gate 
62*0Sstevel@tonic-gate 	ASSERT(len >= sctp->sctp_hdr_len);
63*0Sstevel@tonic-gate 
64*0Sstevel@tonic-gate 	/* Copy the common header from the template */
65*0Sstevel@tonic-gate 	bcopy(sctp->sctp_iphc, rptr, sctp->sctp_hdr_len);
66*0Sstevel@tonic-gate 
67*0Sstevel@tonic-gate 	/* Set the total length in the IP hdr */
68*0Sstevel@tonic-gate 	iplen = (short)len;
69*0Sstevel@tonic-gate 	iphdr = (ipha_t *)rptr;
70*0Sstevel@tonic-gate 	U16_TO_ABE16(iplen, &iphdr->ipha_length);
71*0Sstevel@tonic-gate }
72*0Sstevel@tonic-gate 
73*0Sstevel@tonic-gate /*ARGSUSED*/
74*0Sstevel@tonic-gate size_t
75*0Sstevel@tonic-gate sctp_supaddr_param_len(sctp_t *sctp)
76*0Sstevel@tonic-gate {
77*0Sstevel@tonic-gate 	return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t));
78*0Sstevel@tonic-gate }
79*0Sstevel@tonic-gate 
80*0Sstevel@tonic-gate size_t
81*0Sstevel@tonic-gate sctp_supaddr_param(sctp_t *sctp, uchar_t *p)
82*0Sstevel@tonic-gate {
83*0Sstevel@tonic-gate 	sctp_parm_hdr_t *sph;
84*0Sstevel@tonic-gate 	uint16_t *addrtype;
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate 	sph = (sctp_parm_hdr_t *)p;
87*0Sstevel@tonic-gate 	sph->sph_type = htons(PARM_SUPP_ADDRS);
88*0Sstevel@tonic-gate 	addrtype = (uint16_t *)(sph + 1);
89*0Sstevel@tonic-gate 	switch (sctp->sctp_ipversion) {
90*0Sstevel@tonic-gate 	case IPV4_VERSION:
91*0Sstevel@tonic-gate 		*addrtype++ = htons(PARM_ADDR4);
92*0Sstevel@tonic-gate 		*addrtype = 0;
93*0Sstevel@tonic-gate 		sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype));
94*0Sstevel@tonic-gate 		break;
95*0Sstevel@tonic-gate 	case IPV6_VERSION:
96*0Sstevel@tonic-gate 		*addrtype++ = htons(PARM_ADDR6);
97*0Sstevel@tonic-gate 		if (!sctp->sctp_connp->conn_ipv6_v6only) {
98*0Sstevel@tonic-gate 			*addrtype = htons(PARM_ADDR4);
99*0Sstevel@tonic-gate 			sph->sph_len = htons(sizeof (*sph) +
100*0Sstevel@tonic-gate 			    sizeof (*addrtype) * 2);
101*0Sstevel@tonic-gate 		} else {
102*0Sstevel@tonic-gate 			*addrtype = 0;
103*0Sstevel@tonic-gate 			sph->sph_len = htons(sizeof (*sph) +
104*0Sstevel@tonic-gate 			    sizeof (*addrtype));
105*0Sstevel@tonic-gate 		}
106*0Sstevel@tonic-gate 		break;
107*0Sstevel@tonic-gate 	default:
108*0Sstevel@tonic-gate 		break;
109*0Sstevel@tonic-gate 	}
110*0Sstevel@tonic-gate 	return (sizeof (*sph) + (sizeof (*addrtype) * 2));
111*0Sstevel@tonic-gate }
112*0Sstevel@tonic-gate 
113*0Sstevel@tonic-gate /*
114*0Sstevel@tonic-gate  * Currently, we support on PRSCTP option, there is more to come.
115*0Sstevel@tonic-gate  */
116*0Sstevel@tonic-gate /*ARGSUSED*/
117*0Sstevel@tonic-gate size_t
118*0Sstevel@tonic-gate sctp_options_param_len(const sctp_t *sctp, int option)
119*0Sstevel@tonic-gate {
120*0Sstevel@tonic-gate 	size_t	optlen;
121*0Sstevel@tonic-gate 
122*0Sstevel@tonic-gate 	switch (option) {
123*0Sstevel@tonic-gate 	case SCTP_PRSCTP_OPTION:
124*0Sstevel@tonic-gate 		optlen = sizeof (sctp_parm_hdr_t);
125*0Sstevel@tonic-gate 		break;
126*0Sstevel@tonic-gate 	default:
127*0Sstevel@tonic-gate 		ASSERT(0);
128*0Sstevel@tonic-gate 	}
129*0Sstevel@tonic-gate 
130*0Sstevel@tonic-gate 	return (optlen);
131*0Sstevel@tonic-gate }
132*0Sstevel@tonic-gate 
133*0Sstevel@tonic-gate /*ARGSUSED*/
134*0Sstevel@tonic-gate size_t
135*0Sstevel@tonic-gate sctp_options_param(const sctp_t *sctp, void *p, int option)
136*0Sstevel@tonic-gate {
137*0Sstevel@tonic-gate 	sctp_parm_hdr_t	*sph = (sctp_parm_hdr_t *)p;
138*0Sstevel@tonic-gate 
139*0Sstevel@tonic-gate 	switch (option) {
140*0Sstevel@tonic-gate 	case SCTP_PRSCTP_OPTION:
141*0Sstevel@tonic-gate 		sph->sph_type = htons(PARM_FORWARD_TSN);
142*0Sstevel@tonic-gate 		sph->sph_len = htons(sizeof (*sph));
143*0Sstevel@tonic-gate 		break;
144*0Sstevel@tonic-gate 	default:
145*0Sstevel@tonic-gate 		ASSERT(0);
146*0Sstevel@tonic-gate 	}
147*0Sstevel@tonic-gate 
148*0Sstevel@tonic-gate 	return (sizeof (*sph));
149*0Sstevel@tonic-gate 
150*0Sstevel@tonic-gate }
151*0Sstevel@tonic-gate 
152*0Sstevel@tonic-gate size_t
153*0Sstevel@tonic-gate sctp_adaption_code_param(sctp_t *sctp, uchar_t *p)
154*0Sstevel@tonic-gate {
155*0Sstevel@tonic-gate 	sctp_parm_hdr_t *sph;
156*0Sstevel@tonic-gate 
157*0Sstevel@tonic-gate 	if (!sctp->sctp_send_adaption) {
158*0Sstevel@tonic-gate 		return (0);
159*0Sstevel@tonic-gate 	}
160*0Sstevel@tonic-gate 	sph = (sctp_parm_hdr_t *)p;
161*0Sstevel@tonic-gate 	sph->sph_type = htons(PARM_ADAPT_LAYER_IND);
162*0Sstevel@tonic-gate 	sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t));
163*0Sstevel@tonic-gate 	*(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaption_code);
164*0Sstevel@tonic-gate 
165*0Sstevel@tonic-gate 	return (sizeof (*sph) + sizeof (uint32_t));
166*0Sstevel@tonic-gate }
167*0Sstevel@tonic-gate 
168*0Sstevel@tonic-gate mblk_t *
169*0Sstevel@tonic-gate sctp_init_mp(sctp_t *sctp)
170*0Sstevel@tonic-gate {
171*0Sstevel@tonic-gate 	mblk_t			*mp;
172*0Sstevel@tonic-gate 	uchar_t			*p;
173*0Sstevel@tonic-gate 	size_t			initlen;
174*0Sstevel@tonic-gate 	sctp_init_chunk_t	*icp;
175*0Sstevel@tonic-gate 	sctp_chunk_hdr_t	*chp;
176*0Sstevel@tonic-gate 	uint16_t		schlen;
177*0Sstevel@tonic-gate 	int			supp_af;
178*0Sstevel@tonic-gate 
179*0Sstevel@tonic-gate 	if (sctp->sctp_family == AF_INET) {
180*0Sstevel@tonic-gate 		supp_af = PARM_SUPP_V4;
181*0Sstevel@tonic-gate 	} else {
182*0Sstevel@tonic-gate 		/* Assume here that a v6 endpoint supports v4 address. */
183*0Sstevel@tonic-gate 		if (sctp->sctp_connp->conn_ipv6_v6only)
184*0Sstevel@tonic-gate 			supp_af = PARM_SUPP_V6;
185*0Sstevel@tonic-gate 		else
186*0Sstevel@tonic-gate 			supp_af = PARM_SUPP_V6 | PARM_SUPP_V4;
187*0Sstevel@tonic-gate 	}
188*0Sstevel@tonic-gate 	initlen = sizeof (*chp) + sizeof (*icp);
189*0Sstevel@tonic-gate 	if (sctp->sctp_send_adaption) {
190*0Sstevel@tonic-gate 		initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t));
191*0Sstevel@tonic-gate 	}
192*0Sstevel@tonic-gate 	initlen += sctp_supaddr_param_len(sctp);
193*0Sstevel@tonic-gate 	initlen += sctp_addr_params_len(sctp, supp_af);
194*0Sstevel@tonic-gate 	if (sctp->sctp_prsctp_aware && sctp_prsctp_enabled)
195*0Sstevel@tonic-gate 		initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION);
196*0Sstevel@tonic-gate 
197*0Sstevel@tonic-gate 	/*
198*0Sstevel@tonic-gate 	 * This could be a INIT retransmission in which case sh_verf may
199*0Sstevel@tonic-gate 	 * be non-zero, zero it out just to be sure.
200*0Sstevel@tonic-gate 	 */
201*0Sstevel@tonic-gate 	sctp->sctp_sctph->sh_verf = 0;
202*0Sstevel@tonic-gate 	sctp->sctp_sctph6->sh_verf = 0;
203*0Sstevel@tonic-gate 
204*0Sstevel@tonic-gate 	mp = sctp_make_mp(sctp, NULL, initlen);
205*0Sstevel@tonic-gate 	if (mp == NULL)
206*0Sstevel@tonic-gate 		return (NULL);
207*0Sstevel@tonic-gate 
208*0Sstevel@tonic-gate 	/* Lay in a new INIT chunk, starting with the chunk header */
209*0Sstevel@tonic-gate 	chp = (sctp_chunk_hdr_t *)mp->b_wptr;
210*0Sstevel@tonic-gate 	chp->sch_id = CHUNK_INIT;
211*0Sstevel@tonic-gate 	chp->sch_flags = 0;
212*0Sstevel@tonic-gate 	schlen = (uint16_t)initlen;
213*0Sstevel@tonic-gate 	U16_TO_ABE16(schlen, &(chp->sch_len));
214*0Sstevel@tonic-gate 
215*0Sstevel@tonic-gate 	mp->b_wptr += initlen;
216*0Sstevel@tonic-gate 
217*0Sstevel@tonic-gate 	icp = (sctp_init_chunk_t *)(chp + 1);
218*0Sstevel@tonic-gate 	icp->sic_inittag = sctp->sctp_lvtag;
219*0Sstevel@tonic-gate 	U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd));
220*0Sstevel@tonic-gate 	U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr));
221*0Sstevel@tonic-gate 	U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr));
222*0Sstevel@tonic-gate 	U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn));
223*0Sstevel@tonic-gate 
224*0Sstevel@tonic-gate 	p = (uchar_t *)(icp + 1);
225*0Sstevel@tonic-gate 
226*0Sstevel@tonic-gate 	/* Adaption layer param */
227*0Sstevel@tonic-gate 	p += sctp_adaption_code_param(sctp, p);
228*0Sstevel@tonic-gate 
229*0Sstevel@tonic-gate 	/* Add supported address types parameter */
230*0Sstevel@tonic-gate 	p += sctp_supaddr_param(sctp, p);
231*0Sstevel@tonic-gate 
232*0Sstevel@tonic-gate 	/* Add address parameters */
233*0Sstevel@tonic-gate 	p += sctp_addr_params(sctp, supp_af, p);
234*0Sstevel@tonic-gate 
235*0Sstevel@tonic-gate 	/* Add Forward-TSN-Supported param */
236*0Sstevel@tonic-gate 	if (sctp->sctp_prsctp_aware && sctp_prsctp_enabled)
237*0Sstevel@tonic-gate 		p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION);
238*0Sstevel@tonic-gate 
239*0Sstevel@tonic-gate 	BUMP_LOCAL(sctp->sctp_obchunks);
240*0Sstevel@tonic-gate 
241*0Sstevel@tonic-gate 	sctp_set_iplen(sctp, mp);
242*0Sstevel@tonic-gate 
243*0Sstevel@tonic-gate 	return (mp);
244*0Sstevel@tonic-gate }
245*0Sstevel@tonic-gate 
246*0Sstevel@tonic-gate /*
247*0Sstevel@tonic-gate  * Extracts the verification tag from an INIT chunk. If the INIT
248*0Sstevel@tonic-gate  * chunk is truncated or malformed, returns 0.
249*0Sstevel@tonic-gate  */
250*0Sstevel@tonic-gate uint32_t
251*0Sstevel@tonic-gate sctp_init2vtag(sctp_chunk_hdr_t *initch)
252*0Sstevel@tonic-gate {
253*0Sstevel@tonic-gate 	sctp_init_chunk_t *init;
254*0Sstevel@tonic-gate 
255*0Sstevel@tonic-gate 	init = (sctp_init_chunk_t *)(initch + 1);
256*0Sstevel@tonic-gate 	return (init->sic_inittag);
257*0Sstevel@tonic-gate }
258*0Sstevel@tonic-gate 
259*0Sstevel@tonic-gate size_t
260*0Sstevel@tonic-gate sctp_addr_params_len(sctp_t *sctp, int af)
261*0Sstevel@tonic-gate {
262*0Sstevel@tonic-gate 	ASSERT(sctp->sctp_nsaddrs > 0);
263*0Sstevel@tonic-gate 
264*0Sstevel@tonic-gate 	/*
265*0Sstevel@tonic-gate 	 * If we have only one local address, we can send less on the
266*0Sstevel@tonic-gate 	 * wire by not including the address parameter and letting the peer
267*0Sstevel@tonic-gate 	 * pull it from the IP header.
268*0Sstevel@tonic-gate 	 */
269*0Sstevel@tonic-gate 	if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback)
270*0Sstevel@tonic-gate 		return (0);
271*0Sstevel@tonic-gate 	return (sctp_addr_len(sctp, af));
272*0Sstevel@tonic-gate }
273*0Sstevel@tonic-gate 
274*0Sstevel@tonic-gate size_t
275*0Sstevel@tonic-gate sctp_addr_params(sctp_t *sctp, int af, uchar_t *p)
276*0Sstevel@tonic-gate {
277*0Sstevel@tonic-gate 	if (sctp->sctp_nsaddrs == 1 || sctp->sctp_loopback)
278*0Sstevel@tonic-gate 		return (0);
279*0Sstevel@tonic-gate 
280*0Sstevel@tonic-gate 	return (sctp_addr_val(sctp, af, p));
281*0Sstevel@tonic-gate }
282