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
sctp_supaddr_param_len(sctp_t * sctp)47 sctp_supaddr_param_len(sctp_t *sctp)
48 {
49 return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t));
50 }
51
52 size_t
sctp_supaddr_param(sctp_t * sctp,uchar_t * p)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
sctp_options_param_len(const sctp_t * sctp,int option)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
sctp_options_param(const sctp_t * sctp,void * p,int option)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
sctp_adaptation_code_param(sctp_t * sctp,uchar_t * p)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 *
sctp_init_mp(sctp_t * sctp,sctp_faddr_t * fp)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
sctp_init2vtag(sctp_chunk_hdr_t * initch)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
sctp_addr_params(sctp_t * sctp,int af,uchar_t * p,boolean_t modify)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