Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/sctp/sctp_opt_data.c
+++ new/usr/src/uts/common/inet/sctp/sctp_opt_data.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/stream.h>
28 28 #define _SUN_TPI_VERSION 2
29 29 #include <sys/tihdr.h>
30 30 #include <sys/socket.h>
31 31 #include <sys/xti_inet.h>
32 32 #include <sys/systm.h>
33 33 #include <sys/ddi.h>
34 34 #include <sys/sunddi.h>
35 35 #include <sys/kmem.h>
36 36 #include <sys/strsubr.h>
37 37 #include <sys/strsun.h>
38 38 #include <sys/policy.h>
39 39
40 40 #include <inet/common.h>
41 41 #include <netinet/ip6.h>
42 42 #include <inet/ip.h>
43 43 #include <inet/ip_ire.h>
44 44 #include <inet/ip_if.h>
45 45 #include <inet/proto_set.h>
46 46 #include <inet/ipclassifier.h>
47 47 #include <inet/ipsec_impl.h>
48 48
49 49 #include <netinet/in.h>
50 50 #include <netinet/ip.h>
51 51 #include <netinet/tcp.h>
52 52
53 53 #include <inet/common.h>
54 54 #include <inet/ip.h>
55 55 #include <inet/ip6.h>
56 56 #include <inet/sctp_itf.h>
57 57 #include "sctp_impl.h"
58 58 #include "sctp_asconf.h"
59 59 #include "sctp_addr.h"
60 60
61 61 static int sctp_getpeeraddrs(sctp_t *, void *, int *);
62 62
63 63 static int
64 64 sctp_get_status(sctp_t *sctp, void *ptr)
65 65 {
66 66 struct sctp_status *sstat = ptr;
67 67 sctp_faddr_t *fp;
68 68 struct sockaddr_in *sin;
69 69 struct sockaddr_in6 *sin6;
70 70 struct sctp_paddrinfo *sp;
71 71 mblk_t *meta, *mp;
72 72 int i;
73 73 conn_t *connp = sctp->sctp_connp;
74 74
75 75 sstat->sstat_state = sctp->sctp_state;
76 76 sstat->sstat_rwnd = sctp->sctp_frwnd;
77 77
78 78 sp = &sstat->sstat_primary;
79 79 if (!sctp->sctp_primary) {
80 80 bzero(sp, sizeof (*sp));
81 81 goto noprim;
82 82 }
83 83 fp = sctp->sctp_primary;
84 84
85 85 if (fp->sf_isv4) {
86 86 sin = (struct sockaddr_in *)&sp->spinfo_address;
87 87 sin->sin_family = AF_INET;
88 88 sin->sin_port = connp->conn_fport;
89 89 IN6_V4MAPPED_TO_INADDR(&fp->sf_faddr, &sin->sin_addr);
90 90 sp->spinfo_mtu = sctp->sctp_hdr_len;
91 91 } else {
92 92 sin6 = (struct sockaddr_in6 *)&sp->spinfo_address;
93 93 sin6->sin6_family = AF_INET6;
94 94 sin6->sin6_port = connp->conn_fport;
95 95 sin6->sin6_addr = fp->sf_faddr;
96 96 sp->spinfo_mtu = sctp->sctp_hdr6_len;
97 97 }
98 98 sp->spinfo_state = fp->sf_state == SCTP_FADDRS_ALIVE ? SCTP_ACTIVE :
99 99 SCTP_INACTIVE;
100 100 sp->spinfo_cwnd = fp->sf_cwnd;
101 101 sp->spinfo_srtt = fp->sf_srtt;
102 102 sp->spinfo_rto = fp->sf_rto;
103 103 sp->spinfo_mtu += fp->sf_pmss;
104 104
105 105 noprim:
106 106 sstat->sstat_unackdata = 0;
107 107 sstat->sstat_penddata = 0;
108 108 sstat->sstat_instrms = sctp->sctp_num_istr;
109 109 sstat->sstat_outstrms = sctp->sctp_num_ostr;
110 110 sstat->sstat_fragmentation_point = sctp->sctp_mss -
111 111 sizeof (sctp_data_hdr_t);
112 112
113 113 /* count unack'd */
114 114 for (meta = sctp->sctp_xmit_head; meta; meta = meta->b_next) {
115 115 for (mp = meta->b_cont; mp; mp = mp->b_next) {
116 116 if (!SCTP_CHUNK_ISSENT(mp)) {
117 117 break;
118 118 }
119 119 if (!SCTP_CHUNK_ISACKED(mp)) {
120 120 sstat->sstat_unackdata++;
121 121 }
122 122 }
123 123 }
124 124
125 125 /*
126 126 * Count penddata chunks. We can only count chunks in SCTP (not
127 127 * data already delivered to socket layer).
128 128 */
129 129 if (sctp->sctp_instr != NULL) {
130 130 for (i = 0; i < sctp->sctp_num_istr; i++) {
131 131 for (meta = sctp->sctp_instr[i].istr_reass;
132 132 meta != NULL; meta = meta->b_next) {
133 133 for (mp = meta->b_cont; mp; mp = mp->b_cont) {
134 134 if (DB_TYPE(mp) != M_CTL) {
135 135 sstat->sstat_penddata++;
136 136 }
137 137 }
138 138 }
139 139 }
140 140 }
141 141 /* Un-Ordered Frag list */
142 142 for (meta = sctp->sctp_uo_frags; meta != NULL; meta = meta->b_next)
143 143 sstat->sstat_penddata++;
144 144
145 145 return (sizeof (*sstat));
146 146 }
147 147
148 148 /*
149 149 * SCTP_GET_PEER_ADDR_INFO
150 150 */
151 151 static int
152 152 sctp_get_paddrinfo(sctp_t *sctp, void *ptr, socklen_t *optlen)
153 153 {
154 154 struct sctp_paddrinfo *infop = ptr;
155 155 struct sockaddr_in *sin4;
156 156 struct sockaddr_in6 *sin6;
157 157 in6_addr_t faddr;
158 158 sctp_faddr_t *fp;
159 159
160 160 switch (infop->spinfo_address.ss_family) {
161 161 case AF_INET:
162 162 sin4 = (struct sockaddr_in *)&infop->spinfo_address;
163 163 IN6_INADDR_TO_V4MAPPED(&sin4->sin_addr, &faddr);
164 164 break;
165 165 case AF_INET6:
166 166 sin6 = (struct sockaddr_in6 *)&infop->spinfo_address;
167 167 faddr = sin6->sin6_addr;
168 168 break;
169 169 default:
170 170 return (EAFNOSUPPORT);
171 171 }
172 172
173 173 if ((fp = sctp_lookup_faddr(sctp, &faddr)) == NULL)
174 174 return (EINVAL);
175 175
176 176 infop->spinfo_state = (fp->sf_state == SCTP_FADDRS_ALIVE) ?
177 177 SCTP_ACTIVE : SCTP_INACTIVE;
178 178 infop->spinfo_cwnd = fp->sf_cwnd;
179 179 infop->spinfo_srtt = TICK_TO_MSEC(fp->sf_srtt);
180 180 infop->spinfo_rto = TICK_TO_MSEC(fp->sf_rto);
181 181 infop->spinfo_mtu = fp->sf_pmss;
182 182
183 183 *optlen = sizeof (struct sctp_paddrinfo);
184 184 return (0);
185 185 }
186 186
187 187 /*
188 188 * SCTP_RTOINFO
189 189 */
190 190 static int
191 191 sctp_get_rtoinfo(sctp_t *sctp, void *ptr)
192 192 {
193 193 struct sctp_rtoinfo *srto = ptr;
194 194
195 195 srto->srto_initial = TICK_TO_MSEC(sctp->sctp_rto_initial);
196 196 srto->srto_max = TICK_TO_MSEC(sctp->sctp_rto_max);
197 197 srto->srto_min = TICK_TO_MSEC(sctp->sctp_rto_min);
198 198
199 199 return (sizeof (*srto));
200 200 }
201 201
202 202 static int
203 203 sctp_set_rtoinfo(sctp_t *sctp, const void *invalp)
204 204 {
205 205 const struct sctp_rtoinfo *srto;
206 206 boolean_t ispriv;
207 207 sctp_stack_t *sctps = sctp->sctp_sctps;
208 208 conn_t *connp = sctp->sctp_connp;
209 209 uint32_t new_min, new_max;
210 210
211 211 srto = invalp;
212 212
213 213 ispriv = secpolicy_ip_config(connp->conn_cred, B_TRUE) == 0;
214 214
215 215 /*
216 216 * Bounds checking. Priviledged user can set the RTO initial
217 217 * outside the ndd boundary.
218 218 */
219 219 if (srto->srto_initial != 0 &&
220 220 (!ispriv && (srto->srto_initial < sctps->sctps_rto_initialg_low ||
221 221 srto->srto_initial > sctps->sctps_rto_initialg_high))) {
222 222 return (EINVAL);
223 223 }
224 224 if (srto->srto_max != 0 &&
225 225 (!ispriv && (srto->srto_max < sctps->sctps_rto_maxg_low ||
226 226 srto->srto_max > sctps->sctps_rto_maxg_high))) {
227 227 return (EINVAL);
228 228 }
229 229 if (srto->srto_min != 0 &&
230 230 (!ispriv && (srto->srto_min < sctps->sctps_rto_ming_low ||
231 231 srto->srto_min > sctps->sctps_rto_ming_high))) {
232 232 return (EINVAL);
233 233 }
234 234
235 235 new_min = (srto->srto_min != 0) ? srto->srto_min : sctp->sctp_rto_min;
236 236 new_max = (srto->srto_max != 0) ? srto->srto_max : sctp->sctp_rto_max;
237 237 if (new_max < new_min) {
238 238 return (EINVAL);
239 239 }
240 240
241 241 if (srto->srto_initial != 0) {
242 242 sctp->sctp_rto_initial = MSEC_TO_TICK(srto->srto_initial);
243 243 }
244 244
245 245 /* Ensure that sctp_rto_max will never be zero. */
246 246 if (srto->srto_max != 0) {
247 247 sctp->sctp_rto_max = MAX(MSEC_TO_TICK(srto->srto_max), 1);
248 248 }
249 249 if (srto->srto_min != 0) {
250 250 sctp->sctp_rto_min = MSEC_TO_TICK(srto->srto_min);
251 251 }
252 252
253 253 return (0);
254 254 }
255 255
256 256 /*
257 257 * SCTP_ASSOCINFO
258 258 */
259 259 static int
260 260 sctp_get_assocparams(sctp_t *sctp, void *ptr)
261 261 {
262 262 struct sctp_assocparams *sap = ptr;
263 263 sctp_faddr_t *fp;
264 264 uint16_t i;
265 265
266 266 sap->sasoc_asocmaxrxt = sctp->sctp_pa_max_rxt;
267 267
268 268 /*
269 269 * Count the number of peer addresses
270 270 */
271 271 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next) {
272 272 i++;
273 273 }
274 274 sap->sasoc_number_peer_destinations = i;
275 275 sap->sasoc_peer_rwnd = sctp->sctp_frwnd;
276 276 sap->sasoc_local_rwnd = sctp->sctp_rwnd;
277 277 sap->sasoc_cookie_life = TICK_TO_MSEC(sctp->sctp_cookie_lifetime);
278 278
279 279 return (sizeof (*sap));
280 280 }
281 281
282 282 static int
283 283 sctp_set_assocparams(sctp_t *sctp, const void *invalp)
284 284 {
285 285 const struct sctp_assocparams *sap = invalp;
286 286 uint32_t sum = 0;
287 287 sctp_faddr_t *fp;
288 288 sctp_stack_t *sctps = sctp->sctp_sctps;
289 289
290 290 if (sap->sasoc_asocmaxrxt) {
291 291 if (sctp->sctp_faddrs) {
292 292 /*
293 293 * Bounds check: as per rfc2960, assoc max retr cannot
294 294 * exceed the sum of all individual path max retr's.
295 295 */
296 296 for (fp = sctp->sctp_faddrs; fp; fp = fp->sf_next) {
297 297 sum += fp->sf_max_retr;
298 298 }
299 299 if (sap->sasoc_asocmaxrxt > sum) {
300 300 return (EINVAL);
301 301 }
302 302 }
303 303 if (sap->sasoc_asocmaxrxt < sctps->sctps_pa_max_retr_low ||
304 304 sap->sasoc_asocmaxrxt > sctps->sctps_pa_max_retr_high) {
305 305 /*
306 306 * Out of bounds.
307 307 */
308 308 return (EINVAL);
309 309 }
310 310 }
311 311 if (sap->sasoc_cookie_life != 0 &&
312 312 (sap->sasoc_cookie_life < sctps->sctps_cookie_life_low ||
313 313 sap->sasoc_cookie_life > sctps->sctps_cookie_life_high)) {
314 314 return (EINVAL);
315 315 }
316 316
317 317 if (sap->sasoc_asocmaxrxt > 0) {
318 318 sctp->sctp_pa_max_rxt = sap->sasoc_asocmaxrxt;
319 319 }
320 320 if (sap->sasoc_cookie_life > 0) {
321 321 sctp->sctp_cookie_lifetime = MSEC_TO_TICK(
322 322 sap->sasoc_cookie_life);
323 323 }
324 324 return (0);
325 325 }
326 326
327 327 /*
328 328 * SCTP_INITMSG
329 329 */
330 330 static int
331 331 sctp_get_initmsg(sctp_t *sctp, void *ptr)
332 332 {
333 333 struct sctp_initmsg *si = ptr;
334 334
335 335 si->sinit_num_ostreams = sctp->sctp_num_ostr;
336 336 si->sinit_max_instreams = sctp->sctp_num_istr;
337 337 si->sinit_max_attempts = sctp->sctp_max_init_rxt;
338 338 si->sinit_max_init_timeo = TICK_TO_MSEC(sctp->sctp_rto_max_init);
339 339
340 340 return (sizeof (*si));
341 341 }
342 342
343 343 static int
344 344 sctp_set_initmsg(sctp_t *sctp, const void *invalp, uint_t inlen)
345 345 {
346 346 const struct sctp_initmsg *si = invalp;
347 347 sctp_stack_t *sctps = sctp->sctp_sctps;
348 348 conn_t *connp = sctp->sctp_connp;
349 349
350 350 if (sctp->sctp_state > SCTPS_LISTEN) {
351 351 return (EINVAL);
352 352 }
353 353 if (inlen < sizeof (*si)) {
354 354 return (EINVAL);
355 355 }
356 356 if (si->sinit_num_ostreams != 0 &&
357 357 (si->sinit_num_ostreams < sctps->sctps_initial_out_streams_low ||
358 358 si->sinit_num_ostreams >
359 359 sctps->sctps_initial_out_streams_high)) {
360 360 /*
361 361 * Out of bounds.
362 362 */
363 363 return (EINVAL);
364 364 }
365 365 if (si->sinit_max_instreams != 0 &&
366 366 (si->sinit_max_instreams < sctps->sctps_max_in_streams_low ||
367 367 si->sinit_max_instreams > sctps->sctps_max_in_streams_high)) {
368 368 return (EINVAL);
369 369 }
370 370 if (si->sinit_max_attempts != 0 &&
371 371 (si->sinit_max_attempts < sctps->sctps_max_init_retr_low ||
372 372 si->sinit_max_attempts > sctps->sctps_max_init_retr_high)) {
373 373 return (EINVAL);
374 374 }
375 375 if (si->sinit_max_init_timeo != 0 &&
376 376 (secpolicy_ip_config(connp->conn_cred, B_TRUE) != 0 &&
377 377 (si->sinit_max_init_timeo < sctps->sctps_rto_maxg_low ||
378 378 si->sinit_max_init_timeo > sctps->sctps_rto_maxg_high))) {
379 379 return (EINVAL);
380 380 }
381 381 if (si->sinit_num_ostreams != 0)
382 382 sctp->sctp_num_ostr = si->sinit_num_ostreams;
383 383
384 384 if (si->sinit_max_instreams != 0)
385 385 sctp->sctp_num_istr = si->sinit_max_instreams;
386 386
387 387 if (si->sinit_max_attempts != 0)
388 388 sctp->sctp_max_init_rxt = si->sinit_max_attempts;
389 389
390 390 if (si->sinit_max_init_timeo != 0) {
391 391 sctp->sctp_rto_max_init =
392 392 MSEC_TO_TICK(si->sinit_max_init_timeo);
393 393 }
394 394 return (0);
395 395 }
396 396
397 397 /*
398 398 * SCTP_PEER_ADDR_PARAMS
399 399 */
400 400 static int
401 401 sctp_find_peer_fp(sctp_t *sctp, const struct sockaddr_storage *ss,
402 402 sctp_faddr_t **fpp)
403 403 {
404 404 struct sockaddr_in *sin;
405 405 struct sockaddr_in6 *sin6;
406 406 in6_addr_t addr;
407 407
408 408 if (ss->ss_family == AF_INET) {
409 409 sin = (struct sockaddr_in *)ss;
410 410 IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &addr);
411 411 } else if (ss->ss_family == AF_INET6) {
412 412 sin6 = (struct sockaddr_in6 *)ss;
413 413 addr = sin6->sin6_addr;
414 414 } else if (ss->ss_family) {
415 415 return (EAFNOSUPPORT);
416 416 }
417 417
418 418 if (!ss->ss_family ||
419 419 SCTP_IS_ADDR_UNSPEC(IN6_IS_ADDR_V4MAPPED(&addr), addr)) {
420 420 *fpp = NULL;
421 421 } else {
422 422 *fpp = sctp_lookup_faddr(sctp, &addr);
423 423 if (*fpp == NULL) {
424 424 return (EINVAL);
425 425 }
426 426 }
427 427 return (0);
428 428 }
429 429
430 430 static int
431 431 sctp_get_peer_addr_params(sctp_t *sctp, void *ptr)
432 432 {
433 433 struct sctp_paddrparams *spp = ptr;
434 434 sctp_faddr_t *fp;
435 435 int retval;
436 436
437 437 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
438 438 if (retval) {
439 439 return (retval);
440 440 }
441 441 if (fp) {
442 442 spp->spp_hbinterval = TICK_TO_MSEC(fp->sf_hb_interval);
443 443 spp->spp_pathmaxrxt = fp->sf_max_retr;
444 444 } else {
445 445 spp->spp_hbinterval = TICK_TO_MSEC(sctp->sctp_hb_interval);
446 446 spp->spp_pathmaxrxt = sctp->sctp_pp_max_rxt;
447 447 }
448 448 return (sizeof (*spp));
449 449 }
450 450
451 451 static int
452 452 sctp_set_peer_addr_params(sctp_t *sctp, const void *invalp)
453 453 {
454 454 const struct sctp_paddrparams *spp = invalp;
455 455 sctp_faddr_t *fp, *fp2;
456 456 int retval;
457 457 uint32_t sum = 0;
458 458 int64_t now;
459 459 sctp_stack_t *sctps = sctp->sctp_sctps;
460 460
461 461 retval = sctp_find_peer_fp(sctp, &spp->spp_address, &fp);
462 462 if (retval != 0) {
463 463 return (retval);
464 464 }
465 465
466 466 if (spp->spp_hbinterval && spp->spp_hbinterval != UINT32_MAX &&
467 467 (spp->spp_hbinterval < sctps->sctps_heartbeat_interval_low ||
468 468 spp->spp_hbinterval > sctps->sctps_heartbeat_interval_high)) {
469 469 return (EINVAL);
470 470 }
471 471 if (spp->spp_pathmaxrxt &&
472 472 (spp->spp_pathmaxrxt < sctps->sctps_pp_max_retr_low ||
473 473 spp->spp_pathmaxrxt > sctps->sctps_pp_max_retr_high)) {
474 474 return (EINVAL);
475 475 }
476 476 if (spp->spp_pathmaxrxt && sctp->sctp_faddrs) {
477 477 for (fp2 = sctp->sctp_faddrs; fp2; fp2 = fp2->sf_next) {
478 478 if (!fp || fp2 == fp) {
479 479 sum += spp->spp_pathmaxrxt;
480 480 } else {
481 481 sum += fp2->sf_max_retr;
482 482 }
483 483 }
484 484 if (sctp->sctp_pa_max_rxt > sum) {
485 485 return (EINVAL);
486 486 }
487 487 }
488 488
489 489 now = ddi_get_lbolt64();
490 490 if (fp != NULL) {
491 491 if (spp->spp_hbinterval == UINT32_MAX) {
492 492 /*
493 493 * Send heartbeat immediatelly, don't modify the
494 494 * current setting.
495 495 */
496 496 sctp_send_heartbeat(sctp, fp);
497 497 } else {
498 498 fp->sf_hb_interval = MSEC_TO_TICK(spp->spp_hbinterval);
499 499 fp->sf_hb_expiry = now + SET_HB_INTVL(fp);
500 500 /*
501 501 * Restart the heartbeat timer using the new intrvl.
502 502 * We need to call sctp_heartbeat_timer() to set
503 503 * the earliest heartbeat expiry time.
504 504 */
505 505 sctp_heartbeat_timer(sctp);
506 506 }
507 507 if (spp->spp_pathmaxrxt) {
508 508 fp->sf_max_retr = spp->spp_pathmaxrxt;
509 509 }
510 510 } else {
511 511 for (fp2 = sctp->sctp_faddrs; fp2 != NULL; fp2 = fp2->sf_next) {
512 512 if (spp->spp_hbinterval == UINT32_MAX) {
513 513 /*
514 514 * Send heartbeat immediatelly, don't modify
515 515 * the current setting.
516 516 */
517 517 sctp_send_heartbeat(sctp, fp2);
518 518 } else {
519 519 fp2->sf_hb_interval = MSEC_TO_TICK(
520 520 spp->spp_hbinterval);
521 521 fp2->sf_hb_expiry = now + SET_HB_INTVL(fp2);
522 522 }
523 523 if (spp->spp_pathmaxrxt) {
524 524 fp2->sf_max_retr = spp->spp_pathmaxrxt;
525 525 }
526 526 }
527 527 if (spp->spp_hbinterval != UINT32_MAX) {
528 528 sctp->sctp_hb_interval = MSEC_TO_TICK(
529 529 spp->spp_hbinterval);
530 530 /* Restart the heartbeat timer using the new intrvl. */
531 531 sctp_timer(sctp, sctp->sctp_heartbeat_mp,
532 532 sctp->sctp_hb_interval);
533 533 }
534 534 if (spp->spp_pathmaxrxt) {
535 535 sctp->sctp_pp_max_rxt = spp->spp_pathmaxrxt;
536 536 }
537 537 }
538 538 return (0);
539 539 }
540 540
541 541 /*
542 542 * SCTP_DEFAULT_SEND_PARAM
543 543 */
544 544 static int
545 545 sctp_get_def_send_params(sctp_t *sctp, void *ptr)
546 546 {
547 547 struct sctp_sndrcvinfo *sinfo = ptr;
548 548
549 549 sinfo->sinfo_stream = sctp->sctp_def_stream;
550 550 sinfo->sinfo_ssn = 0;
551 551 sinfo->sinfo_flags = sctp->sctp_def_flags;
552 552 sinfo->sinfo_ppid = sctp->sctp_def_ppid;
553 553 sinfo->sinfo_context = sctp->sctp_def_context;
554 554 sinfo->sinfo_timetolive = sctp->sctp_def_timetolive;
555 555 sinfo->sinfo_tsn = 0;
556 556 sinfo->sinfo_cumtsn = 0;
557 557
558 558 return (sizeof (*sinfo));
559 559 }
560 560
561 561 static int
562 562 sctp_set_def_send_params(sctp_t *sctp, const void *invalp)
563 563 {
564 564 const struct sctp_sndrcvinfo *sinfo = invalp;
565 565
566 566 if (sinfo->sinfo_stream >= sctp->sctp_num_ostr) {
567 567 return (EINVAL);
568 568 }
569 569
570 570 sctp->sctp_def_stream = sinfo->sinfo_stream;
571 571 sctp->sctp_def_flags = sinfo->sinfo_flags;
572 572 sctp->sctp_def_ppid = sinfo->sinfo_ppid;
573 573 sctp->sctp_def_context = sinfo->sinfo_context;
574 574 sctp->sctp_def_timetolive = sinfo->sinfo_timetolive;
575 575
576 576 return (0);
577 577 }
578 578
579 579 static int
580 580 sctp_set_prim(sctp_t *sctp, const void *invalp)
581 581 {
582 582 const struct sctp_setpeerprim *pp = invalp;
583 583 int retval;
584 584 sctp_faddr_t *fp;
585 585
586 586 retval = sctp_find_peer_fp(sctp, &pp->sspp_addr, &fp);
587 587 if (retval)
588 588 return (retval);
589 589
590 590 if (fp == NULL)
591 591 return (EINVAL);
592 592 if (fp == sctp->sctp_primary)
593 593 return (0);
594 594 sctp->sctp_primary = fp;
595 595
596 596 /* Only switch current if fp is alive */
597 597 if (fp->sf_state != SCTP_FADDRS_ALIVE || fp == sctp->sctp_current) {
598 598 return (0);
599 599 }
600 600 sctp_set_faddr_current(sctp, fp);
601 601
602 602 return (0);
603 603 }
604 604
↓ open down ↓ |
604 lines elided |
↑ open up ↑ |
605 605 /*
606 606 * Table of all known options handled on a SCTP protocol stack.
607 607 *
608 608 * Note: This table contains options processed by both SCTP and IP levels
609 609 * and is the superset of options that can be performed on a SCTP and IP
610 610 * stack.
611 611 */
612 612 opdes_t sctp_opt_arr[] = {
613 613
614 614 { SO_LINGER, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
615 - sizeof (struct linger), 0 },
615 + sizeof (struct linger), {0}},
616 616
617 -{ SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
618 -{ SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
619 -{ SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
620 -{ SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
617 +{ SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
618 +{ SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
619 +{ SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
620 +{ SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
621 621 },
622 -{ SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
623 -{ SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
624 -{ SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
625 -{ SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
626 -{ SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
627 -{ SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
628 -{ SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
622 +{ SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
623 +{ SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
624 +{ SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
625 +{ SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
626 +{ SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
627 +{ SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
628 +{ SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
629 629 },
630 -{ SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
630 +{ SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
631 631 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
632 - 0 },
632 + {0}},
633 633 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
634 - 0 },
634 + {0}},
635 635 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
636 - 0 },
637 -{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
636 + {0}},
637 +{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
638 638
639 -{ SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
639 +{ SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
640 640
641 -{ SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
641 +{ SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
642 642
643 643 { SCTP_ADAPTATION_LAYER, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
644 - sizeof (struct sctp_setadaptation), 0 },
644 + sizeof (struct sctp_setadaptation), {0}},
645 645 { SCTP_ADD_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
646 - sizeof (int), 0 },
646 + sizeof (int), {0}},
647 647 { SCTP_ASSOCINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
648 - sizeof (struct sctp_assocparams), 0 },
649 -{ SCTP_AUTOCLOSE, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
648 + sizeof (struct sctp_assocparams), {0}},
649 +{ SCTP_AUTOCLOSE, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
650 650 { SCTP_DEFAULT_SEND_PARAM, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
651 - sizeof (struct sctp_sndrcvinfo), 0 },
651 + sizeof (struct sctp_sndrcvinfo), {0}},
652 652 { SCTP_DISABLE_FRAGMENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
653 - sizeof (int), 0 },
653 + sizeof (int), {0}},
654 654 { SCTP_EVENTS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
655 - sizeof (struct sctp_event_subscribe), 0 },
655 + sizeof (struct sctp_event_subscribe), {0}},
656 656 { SCTP_GET_LADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
657 - sizeof (int), 0 },
658 -{ SCTP_GET_NLADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
659 -{ SCTP_GET_NPADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
657 + sizeof (int), {0}},
658 +{ SCTP_GET_NLADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
659 +{ SCTP_GET_NPADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
660 660 { SCTP_GET_PADDRS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, OP_VARLEN,
661 - sizeof (int), 0 },
661 + sizeof (int), {0}},
662 662 { SCTP_GET_PEER_ADDR_INFO, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
663 - sizeof (struct sctp_paddrinfo), 0 },
663 + sizeof (struct sctp_paddrinfo), {0}},
664 664 { SCTP_INITMSG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
665 - sizeof (struct sctp_initmsg), 0 },
665 + sizeof (struct sctp_initmsg), {0}},
666 666 { SCTP_I_WANT_MAPPED_V4_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
667 - sizeof (int), 0 },
668 -{ SCTP_MAXSEG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
669 -{ SCTP_NODELAY, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
667 + sizeof (int), {0}},
668 +{ SCTP_MAXSEG, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
669 +{ SCTP_NODELAY, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
670 670 { SCTP_PEER_ADDR_PARAMS, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
671 - sizeof (struct sctp_paddrparams), 0 },
671 + sizeof (struct sctp_paddrparams), {0}},
672 672 { SCTP_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
673 - sizeof (struct sctp_setpeerprim), 0 },
674 -{ SCTP_PRSCTP, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
673 + sizeof (struct sctp_setpeerprim), {0}},
674 +{ SCTP_PRSCTP, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
675 675 { SCTP_GET_ASSOC_STATS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
676 - sizeof (sctp_assoc_stats_t), 0 },
676 + sizeof (sctp_assoc_stats_t), {0}},
677 677 { SCTP_REM_ADDR, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, OP_VARLEN,
678 - sizeof (int), 0 },
678 + sizeof (int), {0}},
679 679 { SCTP_RTOINFO, IPPROTO_SCTP, OA_RW, OA_RW, OP_NP, 0,
680 - sizeof (struct sctp_rtoinfo), 0 },
680 + sizeof (struct sctp_rtoinfo), {0}},
681 681 { SCTP_SET_PEER_PRIMARY_ADDR, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
682 - sizeof (struct sctp_setprim), 0 },
682 + sizeof (struct sctp_setprim), {0}},
683 683 { SCTP_STATUS, IPPROTO_SCTP, OA_R, OA_R, OP_NP, 0,
684 - sizeof (struct sctp_status), 0 },
684 + sizeof (struct sctp_status), {0}},
685 685 { SCTP_UC_SWAP, IPPROTO_SCTP, OA_W, OA_W, OP_NP, 0,
686 - sizeof (struct sctp_uc_swap), 0 },
686 + sizeof (struct sctp_uc_swap), {0}},
687 687
688 688 { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
689 689 (OP_VARLEN|OP_NODEFAULT),
690 - 40, -1 /* not initialized */ },
690 + 40, {-1} /* not initialized */ },
691 691 { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
692 692 (OP_VARLEN|OP_NODEFAULT),
693 - 40, -1 /* not initialized */ },
693 + 40, {-1} /* not initialized */ },
694 694
695 -{ IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
696 -{ T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
695 +{ IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
696 +{ T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
697 697 { IP_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
698 - sizeof (int), -1 /* not initialized */ },
698 + sizeof (int), {-1}/* not initialized */ },
699 699
700 700 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
701 - sizeof (ipsec_req_t), -1 /* not initialized */ },
701 + sizeof (ipsec_req_t), {-1}/* not initialized */ },
702 702
703 703 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
704 - sizeof (int), 0 /* no ifindex */ },
704 + sizeof (int), {0}/* no ifindex */ },
705 705
706 706 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
707 - sizeof (int), 0 },
707 + sizeof (int), {0}},
708 708
709 709 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
710 - sizeof (int), -1 /* not initialized */ },
710 + sizeof (int), {-1}/* not initialized */ },
711 711
712 712 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
713 - sizeof (int), 0 /* no ifindex */ },
713 + sizeof (int), {0}/* no ifindex */ },
714 714
715 -{ IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
715 +{ IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
716 716
717 717 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
718 - sizeof (in_addr_t), -1 /* not initialized */ },
718 + sizeof (in_addr_t), {-1}/* not initialized */ },
719 719
720 720 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
721 - sizeof (int), 0 },
721 + sizeof (int), {0}},
722 722
723 723 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
724 724 (OP_NODEFAULT|OP_VARLEN),
725 - sizeof (struct in6_pktinfo), -1 /* not initialized */ },
725 + sizeof (struct in6_pktinfo), {-1}/* not initialized */ },
726 726 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
727 727 OP_NODEFAULT,
728 - sizeof (sin6_t), -1 /* not initialized */ },
728 + sizeof (sin6_t), {-1}/* not initialized */ },
729 729 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
730 730 (OP_VARLEN|OP_NODEFAULT), 255*8,
731 - -1 /* not initialized */ },
731 + {-1}/* not initialized */ },
732 732 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
733 733 (OP_VARLEN|OP_NODEFAULT), 255*8,
734 - -1 /* not initialized */ },
734 + {-1}/* not initialized */ },
735 735 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
736 736 (OP_VARLEN|OP_NODEFAULT), 255*8,
737 - -1 /* not initialized */ },
737 + {-1}/* not initialized */ },
738 738 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
739 739 (OP_VARLEN|OP_NODEFAULT), 255*8,
740 - -1 /* not initialized */ },
740 + {-1}/* not initialized */ },
741 741 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
742 742 OP_NODEFAULT,
743 - sizeof (int), -1 /* not initialized */ },
743 + sizeof (int), {-1}/* not initialized */ },
744 744 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
745 745 OP_NODEFAULT,
746 - sizeof (struct ip6_mtuinfo), -1 /* not initialized */ },
746 + sizeof (struct ip6_mtuinfo), {-1}/* not initialized */ },
747 747 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
748 - sizeof (int), 0 },
748 + sizeof (int), {0}},
749 749 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
750 - sizeof (int), 0 },
750 + sizeof (int), {0}},
751 751 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
752 - sizeof (int), 0 },
752 + sizeof (int), {0}},
753 753
754 754 /* Enable receipt of ancillary data */
755 755 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
756 - sizeof (int), 0 },
756 + sizeof (int), {0}},
757 757 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
758 - sizeof (int), 0 },
758 + sizeof (int), {0}},
759 759 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
760 - sizeof (int), 0 },
760 + sizeof (int), {0}},
761 761 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
762 - sizeof (int), 0 },
762 + sizeof (int), {0}},
763 763 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
764 - sizeof (int), 0 },
764 + sizeof (int), {0}},
765 765 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
766 - sizeof (int), 0 },
766 + sizeof (int), {0}},
767 767 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
768 - sizeof (int), 0 },
768 + sizeof (int), {0}},
769 769 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
770 - sizeof (int), 0 },
770 + sizeof (int), {0}},
771 771 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
772 - sizeof (int), 0 },
772 + sizeof (int), {0}},
773 773
774 774 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
775 - sizeof (ipsec_req_t), -1 /* not initialized */ },
775 + sizeof (ipsec_req_t), {-1}/* not initialized */ },
776 776 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
777 - sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
777 + sizeof (uint32_t), {IPV6_PREFER_SRC_DEFAULT} },
778 778 };
779 779
780 780 uint_t sctp_opt_arr_size = A_CNT(sctp_opt_arr);
781 781
782 782 /* Handy on off switch for socket option processing. */
783 783 #define ONOFF(x) ((x) == 0 ? 0 : 1)
784 784
785 785 /*
786 786 * SCTP routine to get the values of options.
787 787 */
788 788 int
789 789 sctp_get_opt(sctp_t *sctp, int level, int name, void *ptr, socklen_t *optlen)
790 790 {
791 791 int *i1 = (int *)ptr;
792 792 int retval = 0;
793 793 int buflen = *optlen;
794 794 conn_t *connp = sctp->sctp_connp;
795 795 conn_opt_arg_t coas;
796 796
797 797 coas.coa_connp = connp;
798 798 coas.coa_ixa = connp->conn_ixa;
799 799 coas.coa_ipp = &connp->conn_xmit_ipp;
800 800
801 801 /* In most cases, the return buffer is just an int */
802 802 *optlen = sizeof (int32_t);
803 803
804 804 RUN_SCTP(sctp);
805 805
806 806 if (connp->conn_state_flags & CONN_CLOSING) {
807 807 WAKE_SCTP(sctp);
808 808 return (EINVAL);
809 809 }
810 810
811 811 /*
812 812 * Check that the level and name are supported by SCTP, and that
813 813 * the length and credentials are ok.
814 814 */
815 815 retval = proto_opt_check(level, name, buflen, NULL, sctp_opt_arr,
816 816 sctp_opt_arr_size, B_FALSE, B_TRUE, connp->conn_cred);
817 817 if (retval != 0) {
818 818 WAKE_SCTP(sctp);
819 819 if (retval < 0) {
820 820 retval = proto_tlitosyserr(-retval);
821 821 }
822 822 return (retval);
823 823 }
824 824
825 825 switch (level) {
826 826 case IPPROTO_SCTP:
827 827 switch (name) {
828 828 case SCTP_RTOINFO:
829 829 *optlen = sctp_get_rtoinfo(sctp, ptr);
830 830 break;
831 831 case SCTP_ASSOCINFO:
832 832 *optlen = sctp_get_assocparams(sctp, ptr);
833 833 break;
834 834 case SCTP_INITMSG:
835 835 *optlen = sctp_get_initmsg(sctp, ptr);
836 836 break;
837 837 case SCTP_NODELAY:
838 838 *i1 = sctp->sctp_ndelay;
839 839 break;
840 840 case SCTP_AUTOCLOSE:
841 841 *i1 = TICK_TO_SEC(sctp->sctp_autoclose);
842 842 break;
843 843 case SCTP_ADAPTATION_LAYER:
844 844 ((struct sctp_setadaptation *)ptr)->ssb_adaptation_ind =
845 845 sctp->sctp_tx_adaptation_code;
846 846 break;
847 847 case SCTP_PEER_ADDR_PARAMS:
848 848 *optlen = sctp_get_peer_addr_params(sctp, ptr);
849 849 break;
850 850 case SCTP_DEFAULT_SEND_PARAM:
851 851 *optlen = sctp_get_def_send_params(sctp, ptr);
852 852 break;
853 853 case SCTP_EVENTS: {
854 854 struct sctp_event_subscribe *ev;
855 855
856 856 ev = (struct sctp_event_subscribe *)ptr;
857 857 ev->sctp_data_io_event =
858 858 ONOFF(sctp->sctp_recvsndrcvinfo);
859 859 ev->sctp_association_event =
860 860 ONOFF(sctp->sctp_recvassocevnt);
861 861 ev->sctp_address_event =
862 862 ONOFF(sctp->sctp_recvpathevnt);
863 863 ev->sctp_send_failure_event =
864 864 ONOFF(sctp->sctp_recvsendfailevnt);
865 865 ev->sctp_peer_error_event =
866 866 ONOFF(sctp->sctp_recvpeererr);
867 867 ev->sctp_shutdown_event =
868 868 ONOFF(sctp->sctp_recvshutdownevnt);
869 869 ev->sctp_partial_delivery_event =
870 870 ONOFF(sctp->sctp_recvpdevnt);
871 871 ev->sctp_adaptation_layer_event =
872 872 ONOFF(sctp->sctp_recvalevnt);
873 873 *optlen = sizeof (struct sctp_event_subscribe);
874 874 break;
875 875 }
876 876 case SCTP_STATUS:
877 877 *optlen = sctp_get_status(sctp, ptr);
878 878 break;
879 879 case SCTP_GET_PEER_ADDR_INFO:
880 880 retval = sctp_get_paddrinfo(sctp, ptr, optlen);
881 881 break;
882 882 case SCTP_GET_NLADDRS:
883 883 *(int32_t *)ptr = sctp->sctp_nsaddrs;
884 884 break;
885 885 case SCTP_GET_LADDRS: {
886 886 int addr_cnt;
887 887 int addr_size;
888 888
889 889 if (connp->conn_family == AF_INET)
890 890 addr_size = sizeof (struct sockaddr_in);
891 891 else
892 892 addr_size = sizeof (struct sockaddr_in6);
893 893 addr_cnt = buflen / addr_size;
894 894 retval = sctp_getmyaddrs(sctp, ptr, &addr_cnt);
895 895 if (retval == 0)
896 896 *optlen = addr_cnt * addr_size;
897 897 break;
898 898 }
899 899 case SCTP_GET_NPADDRS: {
900 900 int i;
901 901 sctp_faddr_t *fp;
902 902
903 903 for (i = 0, fp = sctp->sctp_faddrs; fp != NULL;
904 904 i++, fp = fp->sf_next)
905 905 ;
906 906 *(int32_t *)ptr = i;
907 907 break;
908 908 }
909 909 case SCTP_GET_PADDRS: {
910 910 int addr_cnt;
911 911 int addr_size;
912 912
913 913 if (connp->conn_family == AF_INET)
914 914 addr_size = sizeof (struct sockaddr_in);
915 915 else
916 916 addr_size = sizeof (struct sockaddr_in6);
917 917 addr_cnt = buflen / addr_size;
918 918 retval = sctp_getpeeraddrs(sctp, ptr, &addr_cnt);
919 919 if (retval == 0)
920 920 *optlen = addr_cnt * addr_size;
921 921 break;
922 922 }
923 923 case SCTP_PRSCTP:
924 924 *i1 = sctp->sctp_prsctp_aware ? 1 : 0;
925 925 break;
926 926
927 927 case SCTP_GET_ASSOC_STATS: {
928 928 sctp_assoc_stats_t *sas;
929 929
930 930 sas = (sctp_assoc_stats_t *)ptr;
931 931
932 932 /*
933 933 * Copy the current stats to the stats struct.
934 934 * For stats which can be reset by snmp users
935 935 * add the cumulative and current stats for
936 936 * the raw totals to output to the user.
937 937 */
938 938 sas->sas_gapcnt = sctp->sctp_gapcnt;
939 939 sas->sas_outseqtsns = sctp->sctp_outseqtsns;
940 940 sas->sas_osacks = sctp->sctp_osacks;
941 941 sas->sas_isacks = sctp->sctp_isacks;
942 942 sas->sas_idupchunks = sctp->sctp_idupchunks;
943 943 sas->sas_rtxchunks = sctp->sctp_rxtchunks +
944 944 sctp->sctp_cum_rxtchunks;
945 945 sas->sas_octrlchunks = sctp->sctp_obchunks +
946 946 sctp->sctp_cum_obchunks;
947 947 sas->sas_ictrlchunks = sctp->sctp_ibchunks +
948 948 sctp->sctp_cum_ibchunks;
949 949 sas->sas_oodchunks = sctp->sctp_odchunks +
950 950 sctp->sctp_cum_odchunks;
951 951 sas->sas_iodchunks = sctp->sctp_idchunks +
952 952 sctp->sctp_cum_idchunks;
953 953 sas->sas_ouodchunks = sctp->sctp_oudchunks +
954 954 sctp->sctp_cum_oudchunks;
955 955 sas->sas_iuodchunks = sctp->sctp_iudchunks +
956 956 sctp->sctp_cum_iudchunks;
957 957
958 958 /*
959 959 * Copy out the maximum observed RTO since the
960 960 * time this data was last requested
961 961 */
962 962 if (sctp->sctp_maxrto == 0) {
963 963 /* unchanged during obervation period */
964 964 sas->sas_maxrto = sctp->sctp_prev_maxrto;
965 965 } else {
966 966 /* record new period maximum */
967 967 sas->sas_maxrto = sctp->sctp_maxrto;
968 968 }
969 969 /* Record the value sent to the user this period */
970 970 sctp->sctp_prev_maxrto = sas->sas_maxrto;
971 971
972 972 /* Mark beginning of a new observation period */
973 973 sctp->sctp_maxrto = 0;
974 974
975 975 *optlen = sizeof (sctp_assoc_stats_t);
976 976 break;
977 977 }
978 978 case SCTP_I_WANT_MAPPED_V4_ADDR:
979 979 case SCTP_MAXSEG:
980 980 case SCTP_DISABLE_FRAGMENTS:
981 981 default:
982 982 /* Not yet supported. */
983 983 retval = ENOPROTOOPT;
984 984 break;
985 985 }
986 986 WAKE_SCTP(sctp);
987 987 return (retval);
988 988 case IPPROTO_IP:
989 989 if (connp->conn_family != AF_INET) {
990 990 retval = EINVAL;
991 991 break;
992 992 }
993 993 switch (name) {
994 994 case IP_OPTIONS:
995 995 case T_IP_OPTIONS: {
996 996 /*
997 997 * This is compatible with BSD in that in only return
998 998 * the reverse source route with the final destination
999 999 * as the last entry. The first 4 bytes of the option
1000 1000 * will contain the final destination. Allocate a
1001 1001 * buffer large enough to hold all the options, we
1002 1002 * add IP_ADDR_LEN to SCTP_MAX_IP_OPTIONS_LENGTH since
1003 1003 * ip_opt_get_user() adds the final destination
1004 1004 * at the start.
1005 1005 */
1006 1006 int opt_len;
1007 1007 uchar_t obuf[SCTP_MAX_IP_OPTIONS_LENGTH + IP_ADDR_LEN];
1008 1008
1009 1009 opt_len = ip_opt_get_user(connp, obuf);
1010 1010 ASSERT(opt_len <= sizeof (obuf));
1011 1011
1012 1012 if (buflen < opt_len) {
1013 1013 /* Silently truncate */
1014 1014 opt_len = buflen;
1015 1015 }
1016 1016 *optlen = opt_len;
1017 1017 bcopy(obuf, ptr, opt_len);
1018 1018 WAKE_SCTP(sctp);
1019 1019 return (0);
1020 1020 }
1021 1021 default:
1022 1022 break;
1023 1023 }
1024 1024 break;
1025 1025 }
1026 1026 mutex_enter(&connp->conn_lock);
1027 1027 retval = conn_opt_get(&coas, level, name, ptr);
1028 1028 mutex_exit(&connp->conn_lock);
1029 1029 WAKE_SCTP(sctp);
1030 1030 if (retval == -1)
1031 1031 return (EINVAL);
1032 1032 *optlen = retval;
1033 1033 return (0);
1034 1034 }
1035 1035
1036 1036 int
1037 1037 sctp_set_opt(sctp_t *sctp, int level, int name, const void *invalp,
1038 1038 socklen_t inlen)
1039 1039 {
1040 1040 int *i1 = (int *)invalp;
1041 1041 boolean_t onoff;
1042 1042 int retval = 0, addrcnt;
1043 1043 conn_t *connp = sctp->sctp_connp;
1044 1044 sctp_stack_t *sctps = sctp->sctp_sctps;
1045 1045 conn_opt_arg_t coas;
1046 1046
1047 1047 coas.coa_connp = connp;
1048 1048 coas.coa_ixa = connp->conn_ixa;
1049 1049 coas.coa_ipp = &connp->conn_xmit_ipp;
1050 1050 coas.coa_ancillary = B_FALSE;
1051 1051 coas.coa_changed = 0;
1052 1052
1053 1053 /* In all cases, the size of the option must be bigger than int */
1054 1054 if (inlen >= sizeof (int32_t)) {
1055 1055 onoff = ONOFF(*i1);
1056 1056 }
1057 1057 retval = 0;
1058 1058
1059 1059 RUN_SCTP(sctp);
1060 1060
1061 1061 if (connp->conn_state_flags & CONN_CLOSING) {
1062 1062 WAKE_SCTP(sctp);
1063 1063 return (EINVAL);
1064 1064 }
1065 1065
1066 1066 /*
1067 1067 * Check that the level and name are supported by SCTP, and that
1068 1068 * the length an credentials are ok.
1069 1069 */
1070 1070 retval = proto_opt_check(level, name, inlen, NULL, sctp_opt_arr,
1071 1071 sctp_opt_arr_size, B_TRUE, B_FALSE, connp->conn_cred);
1072 1072 if (retval != 0) {
1073 1073 if (retval < 0) {
1074 1074 retval = proto_tlitosyserr(-retval);
1075 1075 }
1076 1076 goto done;
1077 1077 }
1078 1078
1079 1079 /* Note: both SCTP and TCP interpret l_linger as being in seconds */
1080 1080 switch (level) {
1081 1081 case SOL_SOCKET:
1082 1082 switch (name) {
1083 1083 case SO_SNDBUF:
1084 1084 if (*i1 > sctps->sctps_max_buf) {
1085 1085 retval = ENOBUFS;
1086 1086 goto done;
1087 1087 }
1088 1088 if (*i1 < 0) {
1089 1089 retval = EINVAL;
1090 1090 goto done;
1091 1091 }
1092 1092 connp->conn_sndbuf = *i1;
1093 1093 if (sctps->sctps_snd_lowat_fraction != 0) {
1094 1094 connp->conn_sndlowat = connp->conn_sndbuf /
1095 1095 sctps->sctps_snd_lowat_fraction;
1096 1096 }
1097 1097 goto done;
1098 1098 case SO_RCVBUF:
1099 1099 if (*i1 > sctps->sctps_max_buf) {
1100 1100 retval = ENOBUFS;
1101 1101 goto done;
1102 1102 }
1103 1103 /* Silently ignore zero */
1104 1104 if (*i1 != 0) {
1105 1105 struct sock_proto_props sopp;
1106 1106
1107 1107 /*
1108 1108 * Insist on a receive window that is at least
1109 1109 * sctp_recv_hiwat_minmss * MSS (default 4*MSS)
1110 1110 * to avoid funny interactions of Nagle
1111 1111 * algorithm, SWS avoidance and delayed
1112 1112 * acknowledgement.
1113 1113 */
1114 1114 *i1 = MAX(*i1,
1115 1115 sctps->sctps_recv_hiwat_minmss *
1116 1116 sctp->sctp_mss);
1117 1117 /*
1118 1118 * Note that sctp_rwnd is modified by the
1119 1119 * protocol and here we just whack it.
1120 1120 */
1121 1121 connp->conn_rcvbuf = sctp->sctp_rwnd = *i1;
1122 1122 sctp->sctp_arwnd = sctp->sctp_rwnd;
1123 1123 sctp->sctp_pd_point = sctp->sctp_rwnd;
1124 1124
1125 1125 sopp.sopp_flags = SOCKOPT_RCVHIWAT;
1126 1126 sopp.sopp_rxhiwat = connp->conn_rcvbuf;
1127 1127 sctp->sctp_ulp_prop(sctp->sctp_ulpd, &sopp);
1128 1128
1129 1129 }
1130 1130 /*
1131 1131 * XXX should we return the rwnd here
1132 1132 * and sctp_opt_get ?
1133 1133 */
1134 1134 goto done;
1135 1135 case SO_ALLZONES:
1136 1136 if (sctp->sctp_state >= SCTPS_BOUND) {
1137 1137 retval = EINVAL;
1138 1138 goto done;
1139 1139 }
1140 1140 break;
1141 1141 case SO_MAC_EXEMPT:
1142 1142 if (sctp->sctp_state >= SCTPS_BOUND) {
1143 1143 retval = EINVAL;
1144 1144 goto done;
1145 1145 }
1146 1146 break;
1147 1147 }
1148 1148 break;
1149 1149
1150 1150 case IPPROTO_SCTP:
1151 1151 switch (name) {
1152 1152 case SCTP_RTOINFO:
1153 1153 retval = sctp_set_rtoinfo(sctp, invalp);
1154 1154 break;
1155 1155 case SCTP_ASSOCINFO:
1156 1156 retval = sctp_set_assocparams(sctp, invalp);
1157 1157 break;
1158 1158 case SCTP_INITMSG:
1159 1159 retval = sctp_set_initmsg(sctp, invalp, inlen);
1160 1160 break;
1161 1161 case SCTP_NODELAY:
1162 1162 sctp->sctp_ndelay = ONOFF(*i1);
1163 1163 break;
1164 1164 case SCTP_AUTOCLOSE:
1165 1165 if (SEC_TO_TICK(*i1) < 0) {
1166 1166 retval = EINVAL;
1167 1167 break;
1168 1168 }
1169 1169 /* Convert the number of seconds to ticks. */
1170 1170 sctp->sctp_autoclose = SEC_TO_TICK(*i1);
1171 1171 sctp_heartbeat_timer(sctp);
1172 1172 break;
1173 1173 case SCTP_SET_PEER_PRIMARY_ADDR:
1174 1174 retval = sctp_set_peerprim(sctp, invalp);
1175 1175 break;
1176 1176 case SCTP_PRIMARY_ADDR:
1177 1177 retval = sctp_set_prim(sctp, invalp);
1178 1178 break;
1179 1179 case SCTP_ADAPTATION_LAYER: {
1180 1180 struct sctp_setadaptation *ssb;
1181 1181
1182 1182 ssb = (struct sctp_setadaptation *)invalp;
1183 1183 sctp->sctp_send_adaptation = 1;
1184 1184 sctp->sctp_tx_adaptation_code = ssb->ssb_adaptation_ind;
1185 1185 break;
1186 1186 }
1187 1187 case SCTP_PEER_ADDR_PARAMS:
1188 1188 retval = sctp_set_peer_addr_params(sctp, invalp);
1189 1189 break;
1190 1190 case SCTP_DEFAULT_SEND_PARAM:
1191 1191 retval = sctp_set_def_send_params(sctp, invalp);
1192 1192 break;
1193 1193 case SCTP_EVENTS: {
1194 1194 struct sctp_event_subscribe *ev;
1195 1195
1196 1196 ev = (struct sctp_event_subscribe *)invalp;
1197 1197 sctp->sctp_recvsndrcvinfo =
1198 1198 ONOFF(ev->sctp_data_io_event);
1199 1199 sctp->sctp_recvassocevnt =
1200 1200 ONOFF(ev->sctp_association_event);
1201 1201 sctp->sctp_recvpathevnt =
1202 1202 ONOFF(ev->sctp_address_event);
1203 1203 sctp->sctp_recvsendfailevnt =
1204 1204 ONOFF(ev->sctp_send_failure_event);
1205 1205 sctp->sctp_recvpeererr =
1206 1206 ONOFF(ev->sctp_peer_error_event);
1207 1207 sctp->sctp_recvshutdownevnt =
1208 1208 ONOFF(ev->sctp_shutdown_event);
1209 1209 sctp->sctp_recvpdevnt =
1210 1210 ONOFF(ev->sctp_partial_delivery_event);
1211 1211 sctp->sctp_recvalevnt =
1212 1212 ONOFF(ev->sctp_adaptation_layer_event);
1213 1213 break;
1214 1214 }
1215 1215 case SCTP_ADD_ADDR:
1216 1216 case SCTP_REM_ADDR:
1217 1217 /*
1218 1218 * The sctp_t has to be bound first before
1219 1219 * the address list can be changed.
1220 1220 */
1221 1221 if (sctp->sctp_state < SCTPS_BOUND) {
1222 1222 retval = EINVAL;
1223 1223 break;
1224 1224 }
1225 1225 if (connp->conn_family == AF_INET) {
1226 1226 addrcnt = inlen / sizeof (struct sockaddr_in);
1227 1227 } else {
1228 1228 ASSERT(connp->conn_family == AF_INET6);
1229 1229 addrcnt = inlen / sizeof (struct sockaddr_in6);
1230 1230 }
1231 1231 if (name == SCTP_ADD_ADDR) {
1232 1232 retval = sctp_bind_add(sctp, invalp, addrcnt,
1233 1233 B_TRUE, connp->conn_lport);
1234 1234 } else {
1235 1235 retval = sctp_bind_del(sctp, invalp, addrcnt,
1236 1236 B_TRUE);
1237 1237 }
1238 1238 break;
1239 1239 case SCTP_UC_SWAP: {
1240 1240 struct sctp_uc_swap *us;
1241 1241
1242 1242 /*
1243 1243 * Change handle & upcalls.
1244 1244 */
1245 1245 us = (struct sctp_uc_swap *)invalp;
1246 1246 sctp->sctp_ulpd = us->sus_handle;
1247 1247 sctp->sctp_upcalls = us->sus_upcalls;
1248 1248 break;
1249 1249 }
1250 1250 case SCTP_PRSCTP:
1251 1251 sctp->sctp_prsctp_aware = onoff;
1252 1252 break;
1253 1253 case SCTP_I_WANT_MAPPED_V4_ADDR:
1254 1254 case SCTP_MAXSEG:
1255 1255 case SCTP_DISABLE_FRAGMENTS:
1256 1256 /* Not yet supported. */
1257 1257 retval = ENOPROTOOPT;
1258 1258 break;
1259 1259 }
1260 1260 goto done;
1261 1261
1262 1262 case IPPROTO_IP:
1263 1263 if (connp->conn_family != AF_INET) {
1264 1264 retval = ENOPROTOOPT;
1265 1265 goto done;
1266 1266 }
1267 1267 switch (name) {
1268 1268 case IP_SEC_OPT:
1269 1269 /*
1270 1270 * We should not allow policy setting after
1271 1271 * we start listening for connections.
1272 1272 */
1273 1273 if (sctp->sctp_state >= SCTPS_LISTEN) {
1274 1274 retval = EINVAL;
1275 1275 goto done;
1276 1276 }
1277 1277 break;
1278 1278 }
1279 1279 break;
1280 1280 case IPPROTO_IPV6:
1281 1281 if (connp->conn_family != AF_INET6) {
1282 1282 retval = EINVAL;
1283 1283 goto done;
1284 1284 }
1285 1285
1286 1286 switch (name) {
1287 1287 case IPV6_RECVPKTINFO:
1288 1288 /* Send it with the next msg */
1289 1289 sctp->sctp_recvifindex = 0;
1290 1290 break;
1291 1291 case IPV6_RECVTCLASS:
1292 1292 /* Force it to be sent up with the next msg */
1293 1293 sctp->sctp_recvtclass = 0xffffffffU;
1294 1294 break;
1295 1295 case IPV6_RECVHOPLIMIT:
1296 1296 /* Force it to be sent up with the next msg */
1297 1297 sctp->sctp_recvhops = 0xffffffffU;
1298 1298 break;
1299 1299 case IPV6_SEC_OPT:
1300 1300 /*
1301 1301 * We should not allow policy setting after
1302 1302 * we start listening for connections.
1303 1303 */
1304 1304 if (sctp->sctp_state >= SCTPS_LISTEN) {
1305 1305 retval = EINVAL;
1306 1306 goto done;
1307 1307 }
1308 1308 break;
1309 1309 case IPV6_V6ONLY:
1310 1310 /*
1311 1311 * After the bound state, setting the v6only option
1312 1312 * is too late.
1313 1313 */
1314 1314 if (sctp->sctp_state >= SCTPS_BOUND) {
1315 1315 retval = EINVAL;
1316 1316 goto done;
1317 1317 }
1318 1318 break;
1319 1319 }
1320 1320 break;
1321 1321 }
1322 1322
1323 1323 retval = conn_opt_set(&coas, level, name, inlen, (uchar_t *)invalp,
1324 1324 B_FALSE, connp->conn_cred);
1325 1325 if (retval != 0)
1326 1326 goto done;
1327 1327
1328 1328 if (coas.coa_changed & COA_ROUTE_CHANGED) {
1329 1329 sctp_faddr_t *fp;
1330 1330 /*
1331 1331 * We recache the information which might pick a different
1332 1332 * source and redo IPsec as a result.
1333 1333 */
1334 1334 for (fp = sctp->sctp_faddrs; fp != NULL; fp = fp->sf_next)
1335 1335 sctp_get_dest(sctp, fp);
1336 1336 }
1337 1337 if (coas.coa_changed & COA_HEADER_CHANGED) {
1338 1338 retval = sctp_build_hdrs(sctp, KM_NOSLEEP);
1339 1339 if (retval != 0)
1340 1340 goto done;
1341 1341 }
1342 1342 if (coas.coa_changed & COA_WROFF_CHANGED) {
1343 1343 connp->conn_wroff = connp->conn_ht_iphc_allocated +
1344 1344 sctps->sctps_wroff_xtra;
1345 1345 if (sctp->sctp_current != NULL) {
1346 1346 /*
1347 1347 * Could be setting options before setting up
1348 1348 * connection.
1349 1349 */
1350 1350 sctp_set_ulp_prop(sctp);
1351 1351 }
1352 1352 }
1353 1353 done:
1354 1354 WAKE_SCTP(sctp);
1355 1355 return (retval);
1356 1356 }
1357 1357
1358 1358 /*
1359 1359 * SCTP exported kernel interface for geting the first source address of
1360 1360 * a sctp_t. The parameter addr is assumed to have enough space to hold
1361 1361 * one socket address.
1362 1362 */
1363 1363 int
1364 1364 sctp_getsockname(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1365 1365 {
1366 1366 int err = 0;
1367 1367 int addrcnt = 1;
1368 1368 sin_t *sin4;
1369 1369 sin6_t *sin6;
1370 1370 conn_t *connp = sctp->sctp_connp;
1371 1371
1372 1372 ASSERT(sctp != NULL);
1373 1373
1374 1374 RUN_SCTP(sctp);
1375 1375 addr->sa_family = connp->conn_family;
1376 1376 switch (connp->conn_family) {
1377 1377 case AF_INET:
1378 1378 sin4 = (sin_t *)addr;
1379 1379 if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1380 1380 sctp->sctp_bound_to_all) {
1381 1381 sin4->sin_addr.s_addr = INADDR_ANY;
1382 1382 sin4->sin_port = connp->conn_lport;
1383 1383 } else {
1384 1384 err = sctp_getmyaddrs(sctp, sin4, &addrcnt);
1385 1385 if (err != 0) {
1386 1386 *addrlen = 0;
1387 1387 break;
1388 1388 }
1389 1389 }
1390 1390 *addrlen = sizeof (struct sockaddr_in);
1391 1391 break;
1392 1392 case AF_INET6:
1393 1393 sin6 = (sin6_t *)addr;
1394 1394 if ((sctp->sctp_state <= SCTPS_LISTEN) &&
1395 1395 sctp->sctp_bound_to_all) {
1396 1396 bzero(&sin6->sin6_addr, sizeof (sin6->sin6_addr));
1397 1397 sin6->sin6_port = connp->conn_lport;
1398 1398 } else {
1399 1399 err = sctp_getmyaddrs(sctp, sin6, &addrcnt);
1400 1400 if (err != 0) {
1401 1401 *addrlen = 0;
1402 1402 break;
1403 1403 }
1404 1404 }
1405 1405 *addrlen = sizeof (struct sockaddr_in6);
1406 1406 /* Note that flowinfo is only returned for getpeername */
1407 1407 break;
1408 1408 }
1409 1409 WAKE_SCTP(sctp);
1410 1410 return (err);
1411 1411 }
1412 1412
1413 1413 /*
1414 1414 * SCTP exported kernel interface for geting the primary peer address of
1415 1415 * a sctp_t. The parameter addr is assumed to have enough space to hold
1416 1416 * one socket address.
1417 1417 */
1418 1418 int
1419 1419 sctp_getpeername(sctp_t *sctp, struct sockaddr *addr, socklen_t *addrlen)
1420 1420 {
1421 1421 int err = 0;
1422 1422 int addrcnt = 1;
1423 1423 sin6_t *sin6;
1424 1424 conn_t *connp = sctp->sctp_connp;
1425 1425
1426 1426 ASSERT(sctp != NULL);
1427 1427
1428 1428 RUN_SCTP(sctp);
1429 1429 addr->sa_family = connp->conn_family;
1430 1430 switch (connp->conn_family) {
1431 1431 case AF_INET:
1432 1432 err = sctp_getpeeraddrs(sctp, addr, &addrcnt);
1433 1433 if (err != 0) {
1434 1434 *addrlen = 0;
1435 1435 break;
1436 1436 }
1437 1437 *addrlen = sizeof (struct sockaddr_in);
1438 1438 break;
1439 1439 case AF_INET6:
1440 1440 sin6 = (sin6_t *)addr;
1441 1441 err = sctp_getpeeraddrs(sctp, sin6, &addrcnt);
1442 1442 if (err != 0) {
1443 1443 *addrlen = 0;
1444 1444 break;
1445 1445 }
1446 1446 *addrlen = sizeof (struct sockaddr_in6);
1447 1447 break;
1448 1448 }
1449 1449 WAKE_SCTP(sctp);
1450 1450 return (err);
1451 1451 }
1452 1452
1453 1453 /*
1454 1454 * Return a list of IP addresses of the peer endpoint of this sctp_t.
1455 1455 * The parameter paddrs is supposed to be either (struct sockaddr_in *) or
1456 1456 * (struct sockaddr_in6 *) depending on the address family of the sctp_t.
1457 1457 */
1458 1458 int
1459 1459 sctp_getpeeraddrs(sctp_t *sctp, void *paddrs, int *addrcnt)
1460 1460 {
1461 1461 int family;
1462 1462 struct sockaddr_in *sin4;
1463 1463 struct sockaddr_in6 *sin6;
1464 1464 int max;
1465 1465 int cnt;
1466 1466 sctp_faddr_t *fp = sctp->sctp_faddrs;
1467 1467 in6_addr_t addr;
1468 1468 conn_t *connp = sctp->sctp_connp;
1469 1469
1470 1470 ASSERT(sctp != NULL);
1471 1471
1472 1472 if (sctp->sctp_faddrs == NULL)
1473 1473 return (ENOTCONN);
1474 1474
1475 1475 family = connp->conn_family;
1476 1476 max = *addrcnt;
1477 1477
1478 1478 /* If we want only one, give the primary */
1479 1479 if (max == 1) {
1480 1480 addr = sctp->sctp_primary->sf_faddr;
1481 1481 switch (family) {
1482 1482 case AF_INET:
1483 1483 sin4 = paddrs;
1484 1484 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1485 1485 sin4->sin_port = connp->conn_fport;
1486 1486 sin4->sin_family = AF_INET;
1487 1487 break;
1488 1488
1489 1489 case AF_INET6:
1490 1490 sin6 = paddrs;
1491 1491 sin6->sin6_addr = addr;
1492 1492 sin6->sin6_port = connp->conn_fport;
1493 1493 sin6->sin6_family = AF_INET6;
1494 1494 sin6->sin6_flowinfo = connp->conn_flowinfo;
1495 1495 if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1496 1496 sctp->sctp_primary != NULL &&
1497 1497 (sctp->sctp_primary->sf_ixa->ixa_flags &
1498 1498 IXAF_SCOPEID_SET)) {
1499 1499 sin6->sin6_scope_id =
1500 1500 sctp->sctp_primary->sf_ixa->ixa_scopeid;
1501 1501 } else {
1502 1502 sin6->sin6_scope_id = 0;
1503 1503 }
1504 1504 sin6->__sin6_src_id = 0;
1505 1505 break;
1506 1506 }
1507 1507 return (0);
1508 1508 }
1509 1509
1510 1510 for (cnt = 0; cnt < max && fp != NULL; cnt++, fp = fp->sf_next) {
1511 1511 addr = fp->sf_faddr;
1512 1512 switch (family) {
1513 1513 case AF_INET:
1514 1514 ASSERT(IN6_IS_ADDR_V4MAPPED(&addr));
1515 1515 sin4 = (struct sockaddr_in *)paddrs + cnt;
1516 1516 IN6_V4MAPPED_TO_INADDR(&addr, &sin4->sin_addr);
1517 1517 sin4->sin_port = connp->conn_fport;
1518 1518 sin4->sin_family = AF_INET;
1519 1519 break;
1520 1520 case AF_INET6:
1521 1521 sin6 = (struct sockaddr_in6 *)paddrs + cnt;
1522 1522 sin6->sin6_addr = addr;
1523 1523 sin6->sin6_port = connp->conn_fport;
1524 1524 sin6->sin6_family = AF_INET6;
1525 1525 sin6->sin6_flowinfo = connp->conn_flowinfo;
1526 1526 if (IN6_IS_ADDR_LINKSCOPE(&addr) &&
1527 1527 (fp->sf_ixa->ixa_flags & IXAF_SCOPEID_SET))
1528 1528 sin6->sin6_scope_id = fp->sf_ixa->ixa_scopeid;
1529 1529 else
1530 1530 sin6->sin6_scope_id = 0;
1531 1531 sin6->__sin6_src_id = 0;
1532 1532 break;
1533 1533 }
1534 1534 }
1535 1535 *addrcnt = cnt;
1536 1536 return (0);
1537 1537 }
↓ open down ↓ |
750 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX