xref: /titanic_44/usr/src/uts/common/inet/sctp/sctp_init.c (revision 5ee6ac27d4fd4c9412183aa8cc1143f36ae04a8c)
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 (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
30 
31 #include <netinet/in.h>
32 #include <netinet/ip6.h>
33 
34 #include <inet/common.h>
35 #include <inet/ipclassifier.h>
36 #include <inet/ip.h>
37 #include <inet/ip6.h>
38 #include <inet/mib2.h>
39 #include <inet/nd.h>
40 #include <inet/optcom.h>
41 #include <inet/ipclassifier.h>
42 #include "sctp_impl.h"
43 #include "sctp_addr.h"
44 
45 /*ARGSUSED*/
46 size_t
47 sctp_supaddr_param_len(sctp_t *sctp)
48 {
49 	return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t));
50 }
51 
52 size_t
53 sctp_supaddr_param(sctp_t *sctp, uchar_t *p)
54 {
55 	sctp_parm_hdr_t *sph;
56 	uint16_t *addrtype;
57 	conn_t		*connp = sctp->sctp_connp;
58 
59 	sph = (sctp_parm_hdr_t *)p;
60 	sph->sph_type = htons(PARM_SUPP_ADDRS);
61 	addrtype = (uint16_t *)(sph + 1);
62 	switch (connp->conn_family) {
63 	case AF_INET:
64 		*addrtype++ = htons(PARM_ADDR4);
65 		*addrtype = 0;
66 		sph->sph_len = htons(sizeof (*sph) + sizeof (*addrtype));
67 		break;
68 	case AF_INET6:
69 		*addrtype++ = htons(PARM_ADDR6);
70 		if (!sctp->sctp_connp->conn_ipv6_v6only) {
71 			*addrtype = htons(PARM_ADDR4);
72 			sph->sph_len = htons(sizeof (*sph) +
73 			    sizeof (*addrtype) * 2);
74 		} else {
75 			*addrtype = 0;
76 			sph->sph_len = htons(sizeof (*sph) +
77 			    sizeof (*addrtype));
78 		}
79 		break;
80 	default:
81 		break;
82 	}
83 	return (sizeof (*sph) + (sizeof (*addrtype) * 2));
84 }
85 
86 /*
87  * Currently, we support on PRSCTP option, there is more to come.
88  */
89 /*ARGSUSED*/
90 size_t
91 sctp_options_param_len(const sctp_t *sctp, int option)
92 {
93 	size_t	optlen;
94 
95 	switch (option) {
96 	case SCTP_PRSCTP_OPTION:
97 		optlen = sizeof (sctp_parm_hdr_t);
98 		break;
99 	default:
100 		ASSERT(0);
101 	}
102 
103 	return (optlen);
104 }
105 
106 /*ARGSUSED*/
107 size_t
108 sctp_options_param(const sctp_t *sctp, void *p, int option)
109 {
110 	sctp_parm_hdr_t	*sph = (sctp_parm_hdr_t *)p;
111 
112 	switch (option) {
113 	case SCTP_PRSCTP_OPTION:
114 		sph->sph_type = htons(PARM_FORWARD_TSN);
115 		sph->sph_len = htons(sizeof (*sph));
116 		break;
117 	default:
118 		ASSERT(0);
119 	}
120 
121 	return (sizeof (*sph));
122 
123 }
124 
125 size_t
126 sctp_adaptation_code_param(sctp_t *sctp, uchar_t *p)
127 {
128 	sctp_parm_hdr_t *sph;
129 
130 	if (!sctp->sctp_send_adaptation) {
131 		return (0);
132 	}
133 	sph = (sctp_parm_hdr_t *)p;
134 	sph->sph_type = htons(PARM_ADAPT_LAYER_IND);
135 	sph->sph_len = htons(sizeof (*sph) + sizeof (uint32_t));
136 	*(uint32_t *)(sph + 1) = htonl(sctp->sctp_tx_adaptation_code);
137 
138 	return (sizeof (*sph) + sizeof (uint32_t));
139 }
140 
141 mblk_t *
142 sctp_init_mp(sctp_t *sctp, sctp_faddr_t *fp)
143 {
144 	mblk_t			*mp;
145 	uchar_t			*p;
146 	size_t			initlen;
147 	sctp_init_chunk_t	*icp;
148 	sctp_chunk_hdr_t	*chp;
149 	uint16_t		schlen;
150 	int			supp_af;
151 	sctp_stack_t		*sctps = sctp->sctp_sctps;
152 	conn_t			*connp = sctp->sctp_connp;
153 
154 	if (connp->conn_family == AF_INET) {
155 		supp_af = PARM_SUPP_V4;
156 	} else {
157 		if (sctp->sctp_connp->conn_ipv6_v6only)
158 			supp_af = PARM_SUPP_V6;
159 		else
160 			supp_af = PARM_SUPP_V6 | PARM_SUPP_V4;
161 	}
162 	initlen = sizeof (*chp) + sizeof (*icp);
163 	if (sctp->sctp_send_adaptation) {
164 		initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t));
165 	}
166 	initlen += sctp_supaddr_param_len(sctp);
167 	initlen += sctp_addr_params(sctp, supp_af, NULL, B_TRUE);
168 	if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled)
169 		initlen += sctp_options_param_len(sctp, SCTP_PRSCTP_OPTION);
170 
171 	/*
172 	 * This could be a INIT retransmission in which case sh_verf may
173 	 * be non-zero, zero it out just to be sure.
174 	 */
175 	sctp->sctp_sctph->sh_verf = 0;
176 	sctp->sctp_sctph6->sh_verf = 0;
177 
178 	mp = sctp_make_mp(sctp, fp, initlen);
179 	if (mp == NULL) {
180 		SCTP_KSTAT(sctps, sctp_send_init_failed);
181 		return (NULL);
182 	}
183 	/* sctp_make_mp could have discovered we have no usable sources */
184 	if (sctp->sctp_nsaddrs == 0) {
185 		freemsg(mp);
186 		SCTP_KSTAT(sctps, sctp_send_init_failed);
187 		return (NULL);
188 	}
189 
190 	/* Lay in a new INIT chunk, starting with the chunk header */
191 	chp = (sctp_chunk_hdr_t *)mp->b_wptr;
192 	chp->sch_id = CHUNK_INIT;
193 	chp->sch_flags = 0;
194 	schlen = (uint16_t)initlen;
195 	U16_TO_ABE16(schlen, &(chp->sch_len));
196 
197 	mp->b_wptr += initlen;
198 
199 	icp = (sctp_init_chunk_t *)(chp + 1);
200 	icp->sic_inittag = sctp->sctp_lvtag;
201 	U32_TO_ABE32(sctp->sctp_rwnd, &(icp->sic_a_rwnd));
202 	U16_TO_ABE16(sctp->sctp_num_ostr, &(icp->sic_outstr));
203 	U16_TO_ABE16(sctp->sctp_num_istr, &(icp->sic_instr));
204 	U32_TO_ABE32(sctp->sctp_ltsn, &(icp->sic_inittsn));
205 
206 	p = (uchar_t *)(icp + 1);
207 
208 	/* Adaptation layer param */
209 	p += sctp_adaptation_code_param(sctp, p);
210 
211 	/* Add supported address types parameter */
212 	p += sctp_supaddr_param(sctp, p);
213 
214 	/* Add address parameters */
215 	p += sctp_addr_params(sctp, supp_af, p, B_FALSE);
216 
217 	/* Add Forward-TSN-Supported param */
218 	if (sctp->sctp_prsctp_aware && sctps->sctps_prsctp_enabled)
219 		p += sctp_options_param(sctp, p, SCTP_PRSCTP_OPTION);
220 
221 	BUMP_LOCAL(sctp->sctp_obchunks);
222 
223 	sctp_set_iplen(sctp, mp, fp->sf_ixa);
224 
225 	return (mp);
226 }
227 
228 /*
229  * Extracts the verification tag from an INIT chunk. If the INIT
230  * chunk is truncated or malformed, returns 0.
231  */
232 uint32_t
233 sctp_init2vtag(sctp_chunk_hdr_t *initch)
234 {
235 	sctp_init_chunk_t *init;
236 
237 	init = (sctp_init_chunk_t *)(initch + 1);
238 	return (init->sic_inittag);
239 }
240 
241 size_t
242 sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify)
243 {
244 	size_t	param_len;
245 
246 	ASSERT(sctp->sctp_nsaddrs > 0);
247 
248 	/*
249 	 * If we have only one local address or it is a loopback or linklocal
250 	 * association, we let the peer pull the address from the IP header.
251 	 */
252 	if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback ||
253 	    sctp->sctp_linklocal) {
254 		return (0);
255 	}
256 
257 	param_len = sctp_saddr_info(sctp, af, p, modify);
258 	return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len);
259 }
260