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