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