docs/how-to-build.md: use proper markup for directory names
[unleashed/tickless.git] / kernel / net / sctp / sctp_init.c
blob802776914555033eac1cdb8c4862c4c4378663da
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #include <sys/ddi.h>
29 #include <sys/sunddi.h>
31 #include <netinet/in.h>
32 #include <netinet/ip6.h>
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 <inet/sctp/sctp_impl.h>
43 #include <inet/sctp/sctp_addr.h>
45 /*ARGSUSED*/
46 size_t
47 sctp_supaddr_param_len(sctp_t *sctp)
49 return (sizeof (sctp_parm_hdr_t) + sizeof (int32_t));
52 size_t
53 sctp_supaddr_param(sctp_t *sctp, uchar_t *p)
55 sctp_parm_hdr_t *sph;
56 uint16_t *addrtype;
57 conn_t *connp = sctp->sctp_connp;
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));
79 break;
80 default:
81 break;
83 return (sizeof (*sph) + (sizeof (*addrtype) * 2));
87 * Currently, we support on PRSCTP option, there is more to come.
89 /*ARGSUSED*/
90 size_t
91 sctp_options_param_len(const sctp_t *sctp, int option)
93 size_t optlen;
95 switch (option) {
96 case SCTP_PRSCTP_OPTION:
97 optlen = sizeof (sctp_parm_hdr_t);
98 break;
99 default:
100 ASSERT(0);
103 return (optlen);
106 /*ARGSUSED*/
107 size_t
108 sctp_options_param(const sctp_t *sctp, void *p, int option)
110 sctp_parm_hdr_t *sph = (sctp_parm_hdr_t *)p;
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);
121 return (sizeof (*sph));
125 size_t
126 sctp_adaptation_code_param(sctp_t *sctp, uchar_t *p)
128 sctp_parm_hdr_t *sph;
130 if (!sctp->sctp_send_adaptation) {
131 return (0);
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);
138 return (sizeof (*sph) + sizeof (uint32_t));
141 mblk_t *
142 sctp_init_mp(sctp_t *sctp, sctp_faddr_t *fp)
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;
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;
162 initlen = sizeof (*chp) + sizeof (*icp);
163 if (sctp->sctp_send_adaptation) {
164 initlen += (sizeof (sctp_parm_hdr_t) + sizeof (uint32_t));
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);
172 * This could be a INIT retransmission in which case sh_verf may
173 * be non-zero, zero it out just to be sure.
175 sctp->sctp_sctph->sh_verf = 0;
176 sctp->sctp_sctph6->sh_verf = 0;
178 mp = sctp_make_mp(sctp, fp, initlen);
179 if (mp == NULL) {
180 SCTP_KSTAT(sctps, sctp_send_init_failed);
181 return (NULL);
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);
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));
197 mp->b_wptr += initlen;
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));
206 p = (uchar_t *)(icp + 1);
208 /* Adaptation layer param */
209 p += sctp_adaptation_code_param(sctp, p);
211 /* Add supported address types parameter */
212 p += sctp_supaddr_param(sctp, p);
214 /* Add address parameters */
215 p += sctp_addr_params(sctp, supp_af, p, B_FALSE);
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);
221 BUMP_LOCAL(sctp->sctp_obchunks);
223 sctp_set_iplen(sctp, mp, fp->sf_ixa);
225 return (mp);
229 * Extracts the verification tag from an INIT chunk. If the INIT
230 * chunk is truncated or malformed, returns 0.
232 uint32_t
233 sctp_init2vtag(sctp_chunk_hdr_t *initch)
235 sctp_init_chunk_t *init;
237 init = (sctp_init_chunk_t *)(initch + 1);
238 return (init->sic_inittag);
241 size_t
242 sctp_addr_params(sctp_t *sctp, int af, uchar_t *p, boolean_t modify)
244 size_t param_len;
246 ASSERT(sctp->sctp_nsaddrs > 0);
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.
252 if ((!modify && sctp->sctp_nsaddrs == 1) || sctp->sctp_loopback ||
253 sctp->sctp_linklocal) {
254 return (0);
257 param_len = sctp_saddr_info(sctp, af, p, modify);
258 return ((sctp->sctp_nsaddrs == 1) ? 0 : param_len);