1 /*-
2 * SPDX-License-Identifier: BSD-3-Clause
3 *
4 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
5 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
6 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * a) Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
13 *
14 * b) Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the distribution.
17 *
18 * c) Neither the name of Cisco Systems, Inc. nor the names of its
19 * contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
24 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
26 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
32 * THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <netinet/sctp_os.h>
36 #include <sys/proc.h>
37 #include <netinet/sctp_pcb.h>
38 #include <netinet/sctp_header.h>
39 #include <netinet/sctp_var.h>
40 #ifdef INET6
41 #include <netinet6/sctp6_var.h>
42 #endif
43 #include <netinet/sctp_sysctl.h>
44 #include <netinet/sctp_output.h>
45 #include <netinet/sctp_uio.h>
46 #include <netinet/sctp_asconf.h>
47 #include <netinet/sctputil.h>
48 #include <netinet/sctp_indata.h>
49 #include <netinet/sctp_timer.h>
50 #include <netinet/sctp_auth.h>
51 #include <netinet/sctp_bsd_addr.h>
52 #include <netinet/udp.h>
53 #include <sys/eventhandler.h>
54
55 extern const struct sctp_cc_functions sctp_cc_functions[];
56 extern const struct sctp_ss_functions sctp_ss_functions[];
57
58 void
sctp_init(void)59 sctp_init(void)
60 {
61 u_long sb_max_adj;
62
63 /* Initialize and modify the sysctled variables */
64 sctp_init_sysctls();
65 if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
66 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
67 /*
68 * Allow a user to take no more than 1/2 the number of clusters or
69 * the SB_MAX, whichever is smaller, for the send window.
70 */
71 sb_max_adj = (u_long)((u_quad_t)(SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
72 SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
73 (((uint32_t)nmbclusters / 2) * MCLBYTES));
74 /*
75 * Now for the recv window, should we take the same amount? or
76 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
77 * now I will just copy.
78 */
79 SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
80 SCTP_BASE_VAR(first_time) = 0;
81 SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
82 sctp_pcb_init();
83 #if defined(SCTP_PACKET_LOGGING)
84 SCTP_BASE_VAR(packet_log_writers) = 0;
85 SCTP_BASE_VAR(packet_log_end) = 0;
86 memset(&SCTP_BASE_VAR(packet_log_buffer), 0, SCTP_PACKET_LOG_SIZE);
87 #endif
88 SCTP_BASE_VAR(eh_tag) = EVENTHANDLER_REGISTER(rt_addrmsg,
89 sctp_addr_change_event_handler, NULL, EVENTHANDLER_PRI_FIRST);
90 }
91
92 #ifdef VIMAGE
93 static void
sctp_finish(void * unused __unused)94 sctp_finish(void *unused __unused)
95 {
96 EVENTHANDLER_DEREGISTER(rt_addrmsg, SCTP_BASE_VAR(eh_tag));
97 sctp_pcb_finish();
98 }
99
100 VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL);
101 #endif
102
103 void
sctp_pathmtu_adjustment(struct sctp_tcb * stcb,uint32_t mtu,bool resend)104 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint32_t mtu, bool resend)
105 {
106 struct sctp_association *asoc;
107 struct sctp_tmit_chunk *chk;
108 uint32_t overhead;
109
110 asoc = &stcb->asoc;
111 KASSERT(mtu < asoc->smallest_mtu,
112 ("Currently only reducing association MTU %u supported (MTU %u)",
113 asoc->smallest_mtu, mtu));
114 asoc->smallest_mtu = mtu;
115 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
116 overhead = SCTP_MIN_OVERHEAD;
117 } else {
118 overhead = SCTP_MIN_V4_OVERHEAD;
119 }
120 if (asoc->idata_supported) {
121 if (sctp_auth_is_required_chunk(SCTP_IDATA, asoc->peer_auth_chunks)) {
122 overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
123 }
124 } else {
125 if (sctp_auth_is_required_chunk(SCTP_DATA, asoc->peer_auth_chunks)) {
126 overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
127 }
128 }
129 KASSERT(overhead % 4 == 0,
130 ("overhead (%u) not a multiple of 4", overhead));
131 TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
132 if (((uint32_t)chk->send_size + overhead) > mtu) {
133 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
134 }
135 }
136 TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
137 if (((uint32_t)chk->send_size + overhead) > mtu) {
138 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
139 if (resend && chk->sent < SCTP_DATAGRAM_RESEND) {
140 /*
141 * If requested, mark the chunk for
142 * immediate resend, since we sent it being
143 * too big.
144 */
145 sctp_flight_size_decrease(chk);
146 sctp_total_flight_decrease(stcb, chk);
147 chk->sent = SCTP_DATAGRAM_RESEND;
148 sctp_ucount_incr(asoc->sent_queue_retran_cnt);
149 chk->rec.data.doing_fast_retransmit = 0;
150 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
151 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
152 chk->whoTo->flight_size,
153 chk->book_size,
154 (uint32_t)(uintptr_t)chk->whoTo,
155 chk->rec.data.tsn);
156 }
157 /* Clear any time, so NO RTT is being done. */
158 if (chk->do_rtt == 1) {
159 chk->do_rtt = 0;
160 chk->whoTo->rto_needed = 1;
161 }
162 }
163 }
164 }
165 }
166
167 #ifdef INET
168 void
sctp_notify(struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,uint8_t icmp_type,uint8_t icmp_code,uint16_t ip_len,uint32_t next_mtu)169 sctp_notify(struct sctp_inpcb *inp,
170 struct sctp_tcb *stcb,
171 struct sctp_nets *net,
172 uint8_t icmp_type,
173 uint8_t icmp_code,
174 uint16_t ip_len,
175 uint32_t next_mtu)
176 {
177 int timer_stopped;
178
179 if (icmp_type != ICMP_UNREACH) {
180 /* We only care about unreachable */
181 SCTP_TCB_UNLOCK(stcb);
182 return;
183 }
184 if ((icmp_code == ICMP_UNREACH_NET) ||
185 (icmp_code == ICMP_UNREACH_HOST) ||
186 (icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
187 (icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
188 (icmp_code == ICMP_UNREACH_ISOLATED) ||
189 (icmp_code == ICMP_UNREACH_NET_PROHIB) ||
190 (icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
191 (icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
192 /* Mark the net unreachable. */
193 if (net->dest_state & SCTP_ADDR_REACHABLE) {
194 /* OK, that destination is NOT reachable. */
195 net->dest_state &= ~SCTP_ADDR_REACHABLE;
196 net->dest_state &= ~SCTP_ADDR_PF;
197 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
198 stcb, 0,
199 (void *)net, SCTP_SO_NOT_LOCKED);
200 }
201 SCTP_TCB_UNLOCK(stcb);
202 } else if ((icmp_code == ICMP_UNREACH_PROTOCOL) ||
203 (icmp_code == ICMP_UNREACH_PORT)) {
204 /* Treat it like an ABORT. */
205 sctp_abort_notification(stcb, true, false, 0, NULL, SCTP_SO_NOT_LOCKED);
206 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
207 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
208 /* no need to unlock here, since the TCB is gone */
209 } else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
210 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
211 SCTP_TCB_UNLOCK(stcb);
212 return;
213 }
214 /* Find the next (smaller) MTU */
215 if (next_mtu == 0) {
216 /*
217 * Old type router that does not tell us what the
218 * next MTU is. Rats we will have to guess (in a
219 * educated fashion of course).
220 */
221 next_mtu = sctp_get_prev_mtu(ip_len);
222 }
223 /* Stop the PMTU timer. */
224 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
225 timer_stopped = 1;
226 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
227 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
228 } else {
229 timer_stopped = 0;
230 }
231 /* Update the path MTU. */
232 if (net->port) {
233 next_mtu -= sizeof(struct udphdr);
234 }
235 if (net->mtu > next_mtu) {
236 net->mtu = next_mtu;
237 if (net->port) {
238 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
239 } else {
240 sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
241 }
242 }
243 /* Update the association MTU */
244 if (stcb->asoc.smallest_mtu > next_mtu) {
245 sctp_pathmtu_adjustment(stcb, next_mtu, true);
246 }
247 /* Finally, start the PMTU timer if it was running before. */
248 if (timer_stopped) {
249 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
250 }
251 SCTP_TCB_UNLOCK(stcb);
252 } else {
253 SCTP_TCB_UNLOCK(stcb);
254 }
255 }
256
257 void
sctp_ctlinput(int cmd,struct sockaddr * sa,void * vip)258 sctp_ctlinput(int cmd, struct sockaddr *sa, void *vip)
259 {
260 struct ip *outer_ip;
261 struct ip *inner_ip;
262 struct sctphdr *sh;
263 struct icmp *icmp;
264 struct sctp_inpcb *inp;
265 struct sctp_tcb *stcb;
266 struct sctp_nets *net;
267 struct sctp_init_chunk *ch;
268 struct sockaddr_in src, dst;
269
270 if (sa->sa_family != AF_INET ||
271 ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
272 return;
273 }
274 if (PRC_IS_REDIRECT(cmd)) {
275 vip = NULL;
276 } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
277 return;
278 }
279 if (vip != NULL) {
280 inner_ip = (struct ip *)vip;
281 icmp = (struct icmp *)((caddr_t)inner_ip -
282 (sizeof(struct icmp) - sizeof(struct ip)));
283 outer_ip = (struct ip *)((caddr_t)icmp - sizeof(struct ip));
284 sh = (struct sctphdr *)((caddr_t)inner_ip + (inner_ip->ip_hl << 2));
285 memset(&src, 0, sizeof(struct sockaddr_in));
286 src.sin_family = AF_INET;
287 src.sin_len = sizeof(struct sockaddr_in);
288 src.sin_port = sh->src_port;
289 src.sin_addr = inner_ip->ip_src;
290 memset(&dst, 0, sizeof(struct sockaddr_in));
291 dst.sin_family = AF_INET;
292 dst.sin_len = sizeof(struct sockaddr_in);
293 dst.sin_port = sh->dest_port;
294 dst.sin_addr = inner_ip->ip_dst;
295 /*
296 * 'dst' holds the dest of the packet that failed to be
297 * sent. 'src' holds our local endpoint address. Thus we
298 * reverse the dst and the src in the lookup.
299 */
300 inp = NULL;
301 net = NULL;
302 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&dst,
303 (struct sockaddr *)&src,
304 &inp, &net, 1,
305 SCTP_DEFAULT_VRFID);
306 if ((stcb != NULL) &&
307 (net != NULL) &&
308 (inp != NULL)) {
309 /* Check the verification tag */
310 if (ntohl(sh->v_tag) != 0) {
311 /*
312 * This must be the verification tag used
313 * for sending out packets. We don't
314 * consider packets reflecting the
315 * verification tag.
316 */
317 if (ntohl(sh->v_tag) != stcb->asoc.peer_vtag) {
318 SCTP_TCB_UNLOCK(stcb);
319 return;
320 }
321 } else {
322 if (ntohs(outer_ip->ip_len) >=
323 sizeof(struct ip) +
324 8 + (inner_ip->ip_hl << 2) + 20) {
325 /*
326 * In this case we can check if we
327 * got an INIT chunk and if the
328 * initiate tag matches.
329 */
330 ch = (struct sctp_init_chunk *)(sh + 1);
331 if ((ch->ch.chunk_type != SCTP_INITIATION) ||
332 (ntohl(ch->init.initiate_tag) != stcb->asoc.my_vtag)) {
333 SCTP_TCB_UNLOCK(stcb);
334 return;
335 }
336 } else {
337 SCTP_TCB_UNLOCK(stcb);
338 return;
339 }
340 }
341 sctp_notify(inp, stcb, net,
342 icmp->icmp_type,
343 icmp->icmp_code,
344 ntohs(inner_ip->ip_len),
345 (uint32_t)ntohs(icmp->icmp_nextmtu));
346 } else {
347 if ((stcb == NULL) && (inp != NULL)) {
348 /* reduce ref-count */
349 SCTP_INP_WLOCK(inp);
350 SCTP_INP_DECR_REF(inp);
351 SCTP_INP_WUNLOCK(inp);
352 }
353 if (stcb) {
354 SCTP_TCB_UNLOCK(stcb);
355 }
356 }
357 }
358 return;
359 }
360 #endif
361
362 static int
sctp_getcred(SYSCTL_HANDLER_ARGS)363 sctp_getcred(SYSCTL_HANDLER_ARGS)
364 {
365 struct xucred xuc;
366 struct sockaddr_in addrs[2];
367 struct sctp_inpcb *inp;
368 struct sctp_nets *net;
369 struct sctp_tcb *stcb;
370 int error;
371 uint32_t vrf_id;
372
373 /* FIX, for non-bsd is this right? */
374 vrf_id = SCTP_DEFAULT_VRFID;
375
376 error = priv_check(req->td, PRIV_NETINET_GETCRED);
377
378 if (error)
379 return (error);
380
381 error = SYSCTL_IN(req, addrs, sizeof(addrs));
382 if (error)
383 return (error);
384
385 stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
386 sintosa(&addrs[0]),
387 &inp, &net, 1, vrf_id);
388 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
389 if ((inp != NULL) && (stcb == NULL)) {
390 /* reduce ref-count */
391 SCTP_INP_WLOCK(inp);
392 SCTP_INP_DECR_REF(inp);
393 goto cred_can_cont;
394 }
395
396 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
397 error = ENOENT;
398 goto out;
399 }
400 SCTP_TCB_UNLOCK(stcb);
401 /*
402 * We use the write lock here, only since in the error leg we need
403 * it. If we used RLOCK, then we would have to
404 * wlock/decr/unlock/rlock. Which in theory could create a hole.
405 * Better to use higher wlock.
406 */
407 SCTP_INP_WLOCK(inp);
408 cred_can_cont:
409 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
410 if (error) {
411 SCTP_INP_WUNLOCK(inp);
412 goto out;
413 }
414 cru2x(inp->sctp_socket->so_cred, &xuc);
415 SCTP_INP_WUNLOCK(inp);
416 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
417 out:
418 return (error);
419 }
420
421 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred,
422 CTLTYPE_OPAQUE | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
423 0, 0, sctp_getcred, "S,ucred",
424 "Get the ucred of a SCTP connection");
425
426 void
sctp_abort(struct socket * so)427 sctp_abort(struct socket *so)
428 {
429 struct epoch_tracker et;
430 struct sctp_inpcb *inp;
431
432 inp = (struct sctp_inpcb *)so->so_pcb;
433 if (inp == NULL) {
434 return;
435 }
436
437 SCTP_INP_WLOCK(inp);
438 NET_EPOCH_ENTER(et);
439 #ifdef SCTP_LOG_CLOSING
440 sctp_log_closing(inp, NULL, 17);
441 #endif
442 if (((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0)) {
443 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP;
444 #ifdef SCTP_LOG_CLOSING
445 sctp_log_closing(inp, NULL, 16);
446 #endif
447 SCTP_INP_WUNLOCK(inp);
448 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
449 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
450 SOCK_LOCK(so);
451 KASSERT(!SOLISTENING(so),
452 ("sctp_abort: called on listening socket %p", so));
453 SCTP_SB_CLEAR(so->so_snd);
454 SCTP_SB_CLEAR(so->so_rcv);
455 /* Now null out the reference, we are completely detached. */
456 so->so_pcb = NULL;
457 SOCK_UNLOCK(so);
458 } else {
459 SCTP_INP_WUNLOCK(inp);
460 }
461 NET_EPOCH_EXIT(et);
462 }
463
464 #ifdef INET
465 static int
sctp_attach(struct socket * so,int proto SCTP_UNUSED,struct thread * p SCTP_UNUSED)466 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
467 {
468 struct sctp_inpcb *inp;
469 struct inpcb *ip_inp;
470 int error;
471 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
472
473 inp = (struct sctp_inpcb *)so->so_pcb;
474 if (inp != NULL) {
475 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
476 return (EINVAL);
477 }
478 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
479 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
480 if (error) {
481 return (error);
482 }
483 }
484 error = sctp_inpcb_alloc(so, vrf_id);
485 if (error) {
486 return (error);
487 }
488 inp = (struct sctp_inpcb *)so->so_pcb;
489 SCTP_INP_WLOCK(inp);
490 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
491 ip_inp = &inp->ip_inp.inp;
492 ip_inp->inp_vflag |= INP_IPV4;
493 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
494 SCTP_INP_WUNLOCK(inp);
495 return (0);
496 }
497
498 static int
sctp_bind(struct socket * so,struct sockaddr * addr,struct thread * p)499 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
500 {
501 struct sctp_inpcb *inp;
502
503 inp = (struct sctp_inpcb *)so->so_pcb;
504 if (inp == NULL) {
505 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
506 return (EINVAL);
507 }
508 if (addr != NULL) {
509 if ((addr->sa_family != AF_INET) ||
510 (addr->sa_len != sizeof(struct sockaddr_in))) {
511 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
512 return (EINVAL);
513 }
514 }
515 return (sctp_inpcb_bind(so, addr, NULL, p));
516 }
517
518 #endif
519 void
sctp_close(struct socket * so)520 sctp_close(struct socket *so)
521 {
522 struct epoch_tracker et;
523 struct sctp_inpcb *inp;
524
525 inp = (struct sctp_inpcb *)so->so_pcb;
526 if (inp == NULL)
527 return;
528
529 /*
530 * Inform all the lower layer assoc that we are done.
531 */
532 SCTP_INP_WLOCK(inp);
533 NET_EPOCH_ENTER(et);
534 #ifdef SCTP_LOG_CLOSING
535 sctp_log_closing(inp, NULL, 17);
536 #endif
537 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
538 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP;
539 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
540 (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
541 #ifdef SCTP_LOG_CLOSING
542 sctp_log_closing(inp, NULL, 13);
543 #endif
544 SCTP_INP_WUNLOCK(inp);
545 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
546 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
547 } else {
548 #ifdef SCTP_LOG_CLOSING
549 sctp_log_closing(inp, NULL, 14);
550 #endif
551 SCTP_INP_WUNLOCK(inp);
552 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
553 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
554 }
555 /*
556 * The socket is now detached, no matter what the state of
557 * the SCTP association.
558 */
559 SOCK_LOCK(so);
560 if (!SOLISTENING(so)) {
561 SCTP_SB_CLEAR(so->so_snd);
562 SCTP_SB_CLEAR(so->so_rcv);
563 }
564 /* Now null out the reference, we are completely detached. */
565 so->so_pcb = NULL;
566 SOCK_UNLOCK(so);
567 } else {
568 SCTP_INP_WUNLOCK(inp);
569 }
570 NET_EPOCH_EXIT(et);
571 }
572
573 int
574 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
575 struct mbuf *control, struct thread *p);
576
577 int
sctp_sendm(struct socket * so,int flags,struct mbuf * m,struct sockaddr * addr,struct mbuf * control,struct thread * p)578 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
579 struct mbuf *control, struct thread *p)
580 {
581 struct sctp_inpcb *inp;
582 int error;
583
584 inp = (struct sctp_inpcb *)so->so_pcb;
585 if (inp == NULL) {
586 if (control) {
587 sctp_m_freem(control);
588 control = NULL;
589 }
590 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
591 sctp_m_freem(m);
592 return (EINVAL);
593 }
594 /* Got to have an to address if we are NOT a connected socket */
595 if ((addr == NULL) &&
596 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
597 (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
598 goto connected_type;
599 }
600
601 error = 0;
602 if (addr == NULL) {
603 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
604 error = EDESTADDRREQ;
605 } else if (addr->sa_family != AF_INET) {
606 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
607 error = EAFNOSUPPORT;
608 } else if (addr->sa_len != sizeof(struct sockaddr_in)) {
609 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
610 error = EINVAL;
611 }
612 if (error != 0) {
613 sctp_m_freem(m);
614 if (control) {
615 sctp_m_freem(control);
616 control = NULL;
617 }
618 return (error);
619 }
620 connected_type:
621 /* now what about control */
622 if (control) {
623 if (inp->control) {
624 sctp_m_freem(inp->control);
625 inp->control = NULL;
626 }
627 inp->control = control;
628 }
629 /* Place the data */
630 if (inp->pkt) {
631 SCTP_BUF_NEXT(inp->pkt_last) = m;
632 inp->pkt_last = m;
633 } else {
634 inp->pkt_last = inp->pkt = m;
635 }
636 if (
637 /* FreeBSD uses a flag passed */
638 ((flags & PRUS_MORETOCOME) == 0)
639 ) {
640 /*
641 * note with the current version this code will only be used
642 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
643 * re-defining sosend to use the sctp_sosend. One can
644 * optionally switch back to this code (by changing back the
645 * definitions) but this is not advisable. This code is used
646 * by FreeBSD when sending a file with sendfile() though.
647 */
648 struct epoch_tracker et;
649 int ret;
650
651 NET_EPOCH_ENTER(et);
652 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
653 NET_EPOCH_EXIT(et);
654 inp->pkt = NULL;
655 inp->control = NULL;
656 return (ret);
657 } else {
658 return (0);
659 }
660 }
661
662 int
sctp_disconnect(struct socket * so)663 sctp_disconnect(struct socket *so)
664 {
665 struct epoch_tracker et;
666 struct sctp_inpcb *inp;
667 struct sctp_association *asoc;
668 struct sctp_tcb *stcb;
669
670 inp = (struct sctp_inpcb *)so->so_pcb;
671 if (inp == NULL) {
672 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
673 return (ENOTCONN);
674 }
675 SCTP_INP_RLOCK(inp);
676 KASSERT(inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE ||
677 inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL,
678 ("Not a one-to-one style socket"));
679 stcb = LIST_FIRST(&inp->sctp_asoc_list);
680 if (stcb == NULL) {
681 SCTP_INP_RUNLOCK(inp);
682 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
683 return (ENOTCONN);
684 }
685 SCTP_TCB_LOCK(stcb);
686 asoc = &stcb->asoc;
687 if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
688 /* We are about to be freed, out of here */
689 SCTP_TCB_UNLOCK(stcb);
690 SCTP_INP_RUNLOCK(inp);
691 return (0);
692 }
693 NET_EPOCH_ENTER(et);
694 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
695 (SCTP_SBAVAIL(&so->so_rcv) > 0)) {
696 if (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) {
697 /* Left with Data unread */
698 struct mbuf *op_err;
699
700 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
701 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
702 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
703 }
704 SCTP_INP_RUNLOCK(inp);
705 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
706 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
707 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
708 }
709 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
710 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
711 /* No unlock tcb assoc is gone */
712 NET_EPOCH_EXIT(et);
713 return (0);
714 }
715 if (TAILQ_EMPTY(&asoc->send_queue) &&
716 TAILQ_EMPTY(&asoc->sent_queue) &&
717 (asoc->stream_queue_cnt == 0)) {
718 /* there is nothing queued to send, so done */
719 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
720 goto abort_anyway;
721 }
722 if ((SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_SENT) &&
723 (SCTP_GET_STATE(stcb) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
724 /* only send SHUTDOWN 1st time thru */
725 struct sctp_nets *netp;
726
727 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
728 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
729 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
730 }
731 SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
732 sctp_stop_timers_for_shutdown(stcb);
733 if (stcb->asoc.alternate) {
734 netp = stcb->asoc.alternate;
735 } else {
736 netp = stcb->asoc.primary_destination;
737 }
738 sctp_send_shutdown(stcb, netp);
739 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
740 stcb->sctp_ep, stcb, netp);
741 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
742 stcb->sctp_ep, stcb, NULL);
743 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
744 }
745 } else {
746 /*
747 * we still got (or just got) data to send, so set
748 * SHUTDOWN_PENDING
749 */
750 /*
751 * XXX sockets draft says that SCTP_EOF should be sent with
752 * no data. currently, we will allow user data to be sent
753 * first and move to SHUTDOWN-PENDING
754 */
755 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
756 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
757 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
758 }
759 if (TAILQ_EMPTY(&asoc->send_queue) &&
760 TAILQ_EMPTY(&asoc->sent_queue) &&
761 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
762 struct mbuf *op_err;
763
764 abort_anyway:
765 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
766 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
767 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
768 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
769 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) ||
770 (SCTP_GET_STATE(stcb) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
771 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
772 }
773 SCTP_INP_RUNLOCK(inp);
774 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
775 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
776 NET_EPOCH_EXIT(et);
777 return (0);
778 } else {
779 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
780 }
781 }
782 soisdisconnecting(so);
783 NET_EPOCH_EXIT(et);
784 SCTP_TCB_UNLOCK(stcb);
785 SCTP_INP_RUNLOCK(inp);
786 return (0);
787 }
788
789 int
sctp_flush(struct socket * so,int how)790 sctp_flush(struct socket *so, int how)
791 {
792 struct epoch_tracker et;
793 struct sctp_tcb *stcb;
794 struct sctp_queued_to_read *control, *ncontrol;
795 struct sctp_inpcb *inp;
796 struct mbuf *m, *op_err;
797 bool need_to_abort = false;
798
799 /*
800 * For 1-to-1 style sockets, flush the read queue and trigger an
801 * ungraceful shutdown of the association, if and only if user
802 * messages are lost. Loosing notifications does not need to be
803 * signalled to the peer.
804 */
805 if (how == PRU_FLUSH_WR) {
806 /* This function is only relevant for the read directions. */
807 return (0);
808 }
809 inp = (struct sctp_inpcb *)so->so_pcb;
810 if (inp == NULL) {
811 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
812 return (EINVAL);
813 }
814 SCTP_INP_WLOCK(inp);
815 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
816 /* For 1-to-many style sockets this function does nothing. */
817 SCTP_INP_WUNLOCK(inp);
818 return (0);
819 }
820 stcb = LIST_FIRST(&inp->sctp_asoc_list);
821 if (stcb != NULL) {
822 SCTP_TCB_LOCK(stcb);
823 }
824 SCTP_INP_READ_LOCK(inp);
825 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
826 SOCK_LOCK(so);
827 TAILQ_FOREACH_SAFE(control, &inp->read_queue, next, ncontrol) {
828 if ((control->spec_flags & M_NOTIFICATION) == 0) {
829 need_to_abort = true;
830 }
831 TAILQ_REMOVE(&inp->read_queue, control, next);
832 control->on_read_q = 0;
833 for (m = control->data; m; m = SCTP_BUF_NEXT(m)) {
834 sctp_sbfree(control, control->stcb, &so->so_rcv, m);
835 }
836 if (control->on_strm_q == 0) {
837 sctp_free_remote_addr(control->whoFrom);
838 if (control->data) {
839 sctp_m_freem(control->data);
840 control->data = NULL;
841 }
842 sctp_free_a_readq(stcb, control);
843 } else {
844 stcb->asoc.size_on_all_streams += control->length;
845 }
846 }
847 SOCK_UNLOCK(so);
848 SCTP_INP_READ_UNLOCK(inp);
849 if (need_to_abort && (stcb != NULL)) {
850 inp->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
851 SCTP_INP_WUNLOCK(inp);
852 op_err = sctp_generate_cause(SCTP_CAUSE_OUT_OF_RESC, "");
853 NET_EPOCH_ENTER(et);
854 sctp_abort_an_association(inp, stcb, op_err, false, SCTP_SO_LOCKED);
855 NET_EPOCH_EXIT(et);
856 return (ECONNABORTED);
857 }
858 if (stcb != NULL) {
859 SCTP_TCB_UNLOCK(stcb);
860 }
861 SCTP_INP_WUNLOCK(inp);
862 return (0);
863 }
864
865 int
sctp_shutdown(struct socket * so)866 sctp_shutdown(struct socket *so)
867 {
868 struct sctp_inpcb *inp;
869
870 inp = (struct sctp_inpcb *)so->so_pcb;
871 if (inp == NULL) {
872 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
873 return (EINVAL);
874 }
875 SCTP_INP_RLOCK(inp);
876 /* For UDP model this is a invalid call */
877 if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
878 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
879 /* Restore the flags that the soshutdown took away. */
880 SOCKBUF_LOCK(&so->so_rcv);
881 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
882 SOCKBUF_UNLOCK(&so->so_rcv);
883 /* This proc will wakeup for read and do nothing (I hope) */
884 SCTP_INP_RUNLOCK(inp);
885 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
886 return (EOPNOTSUPP);
887 } else {
888 /*
889 * Ok, if we reach here its the TCP model and it is either a
890 * SHUT_WR or SHUT_RDWR. This means we put the shutdown flag
891 * against it.
892 */
893 struct epoch_tracker et;
894 struct sctp_tcb *stcb;
895 struct sctp_association *asoc;
896 struct sctp_nets *netp;
897
898 if ((so->so_state &
899 (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
900 SCTP_INP_RUNLOCK(inp);
901 return (ENOTCONN);
902 }
903 socantsendmore(so);
904
905 stcb = LIST_FIRST(&inp->sctp_asoc_list);
906 if (stcb == NULL) {
907 /*
908 * Ok, we hit the case that the shutdown call was
909 * made after an abort or something. Nothing to do
910 * now.
911 */
912 SCTP_INP_RUNLOCK(inp);
913 return (0);
914 }
915 SCTP_TCB_LOCK(stcb);
916 asoc = &stcb->asoc;
917 if (asoc->state & SCTP_STATE_ABOUT_TO_BE_FREED) {
918 SCTP_TCB_UNLOCK(stcb);
919 SCTP_INP_RUNLOCK(inp);
920 return (0);
921 }
922 if ((SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_WAIT) &&
923 (SCTP_GET_STATE(stcb) != SCTP_STATE_COOKIE_ECHOED) &&
924 (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN)) {
925 /*
926 * If we are not in or before ESTABLISHED, there is
927 * no protocol action required.
928 */
929 SCTP_TCB_UNLOCK(stcb);
930 SCTP_INP_RUNLOCK(inp);
931 return (0);
932 }
933 NET_EPOCH_ENTER(et);
934 if (stcb->asoc.alternate) {
935 netp = stcb->asoc.alternate;
936 } else {
937 netp = stcb->asoc.primary_destination;
938 }
939 if ((SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) &&
940 TAILQ_EMPTY(&asoc->send_queue) &&
941 TAILQ_EMPTY(&asoc->sent_queue) &&
942 (asoc->stream_queue_cnt == 0)) {
943 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
944 goto abort_anyway;
945 }
946 /* there is nothing queued to send, so I'm done... */
947 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
948 SCTP_SET_STATE(stcb, SCTP_STATE_SHUTDOWN_SENT);
949 sctp_stop_timers_for_shutdown(stcb);
950 sctp_send_shutdown(stcb, netp);
951 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
952 stcb->sctp_ep, stcb, netp);
953 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
954 stcb->sctp_ep, stcb, NULL);
955 } else {
956 /*
957 * We still got (or just got) data to send, so set
958 * SHUTDOWN_PENDING.
959 */
960 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_SHUTDOWN_PENDING);
961 if ((*asoc->ss_functions.sctp_ss_is_user_msgs_incomplete) (stcb, asoc)) {
962 SCTP_ADD_SUBSTATE(stcb, SCTP_STATE_PARTIAL_MSG_LEFT);
963 }
964 if (TAILQ_EMPTY(&asoc->send_queue) &&
965 TAILQ_EMPTY(&asoc->sent_queue) &&
966 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
967 struct mbuf *op_err;
968
969 abort_anyway:
970 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
971 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
972 SCTP_INP_RUNLOCK(inp);
973 sctp_abort_an_association(stcb->sctp_ep, stcb,
974 op_err, false, SCTP_SO_LOCKED);
975 NET_EPOCH_EXIT(et);
976 return (0);
977 }
978 }
979 /*
980 * XXX: Why do this in the case where we have still data
981 * queued?
982 */
983 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
984 SCTP_TCB_UNLOCK(stcb);
985 SCTP_INP_RUNLOCK(inp);
986 NET_EPOCH_EXIT(et);
987 return (0);
988 }
989 }
990
991 /*
992 * copies a "user" presentable address and removes embedded scope, etc.
993 * returns 0 on success, 1 on error
994 */
995 static uint32_t
sctp_fill_user_address(struct sockaddr * dst,struct sockaddr * src)996 sctp_fill_user_address(struct sockaddr *dst, struct sockaddr *src)
997 {
998 #ifdef INET6
999 struct sockaddr_in6 lsa6;
1000
1001 src = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)src,
1002 &lsa6);
1003 #endif
1004 memcpy(dst, src, src->sa_len);
1005 return (0);
1006 }
1007
1008 static size_t
sctp_fill_up_addresses_vrf(struct sctp_inpcb * inp,struct sctp_tcb * stcb,size_t limit,struct sockaddr * addr,uint32_t vrf_id)1009 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1010 struct sctp_tcb *stcb,
1011 size_t limit,
1012 struct sockaddr *addr,
1013 uint32_t vrf_id)
1014 {
1015 struct sctp_ifn *sctp_ifn;
1016 struct sctp_ifa *sctp_ifa;
1017 size_t actual;
1018 int loopback_scope;
1019 #if defined(INET)
1020 int ipv4_local_scope, ipv4_addr_legal;
1021 #endif
1022 #if defined(INET6)
1023 int local_scope, site_scope, ipv6_addr_legal;
1024 #endif
1025 struct sctp_vrf *vrf;
1026
1027 SCTP_IPI_ADDR_LOCK_ASSERT();
1028 actual = 0;
1029 if (limit == 0)
1030 return (actual);
1031
1032 if (stcb) {
1033 /* Turn on all the appropriate scope */
1034 loopback_scope = stcb->asoc.scope.loopback_scope;
1035 #if defined(INET)
1036 ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1037 ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1038 #endif
1039 #if defined(INET6)
1040 local_scope = stcb->asoc.scope.local_scope;
1041 site_scope = stcb->asoc.scope.site_scope;
1042 ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1043 #endif
1044 } else {
1045 /* Use generic values for endpoints. */
1046 loopback_scope = 1;
1047 #if defined(INET)
1048 ipv4_local_scope = 1;
1049 #endif
1050 #if defined(INET6)
1051 local_scope = 1;
1052 site_scope = 1;
1053 #endif
1054 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1055 #if defined(INET6)
1056 ipv6_addr_legal = 1;
1057 #endif
1058 #if defined(INET)
1059 if (SCTP_IPV6_V6ONLY(inp)) {
1060 ipv4_addr_legal = 0;
1061 } else {
1062 ipv4_addr_legal = 1;
1063 }
1064 #endif
1065 } else {
1066 #if defined(INET6)
1067 ipv6_addr_legal = 0;
1068 #endif
1069 #if defined(INET)
1070 ipv4_addr_legal = 1;
1071 #endif
1072 }
1073 }
1074 vrf = sctp_find_vrf(vrf_id);
1075 if (vrf == NULL) {
1076 return (0);
1077 }
1078 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1079 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1080 if ((loopback_scope == 0) &&
1081 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1082 /* Skip loopback if loopback_scope not set */
1083 continue;
1084 }
1085 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1086 if (stcb) {
1087 /*
1088 * For the BOUND-ALL case, the list
1089 * associated with a TCB is Always
1090 * considered a reverse list.. i.e.
1091 * it lists addresses that are NOT
1092 * part of the association. If this
1093 * is one of those we must skip it.
1094 */
1095 if (sctp_is_addr_restricted(stcb,
1096 sctp_ifa)) {
1097 continue;
1098 }
1099 }
1100 switch (sctp_ifa->address.sa.sa_family) {
1101 #ifdef INET
1102 case AF_INET:
1103 if (ipv4_addr_legal) {
1104 struct sockaddr_in *sin;
1105
1106 sin = &sctp_ifa->address.sin;
1107 if (sin->sin_addr.s_addr == 0) {
1108 /*
1109 * we skip
1110 * unspecified
1111 * addresses
1112 */
1113 continue;
1114 }
1115 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1116 &sin->sin_addr) != 0) {
1117 continue;
1118 }
1119 if ((ipv4_local_scope == 0) &&
1120 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1121 continue;
1122 }
1123 #ifdef INET6
1124 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1125 if (actual + sizeof(struct sockaddr_in6) > limit) {
1126 return (actual);
1127 }
1128 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)addr);
1129 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1130 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1131 actual += sizeof(struct sockaddr_in6);
1132 } else {
1133 #endif
1134 if (actual + sizeof(struct sockaddr_in) > limit) {
1135 return (actual);
1136 }
1137 memcpy(addr, sin, sizeof(struct sockaddr_in));
1138 ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1139 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in));
1140 actual += sizeof(struct sockaddr_in);
1141 #ifdef INET6
1142 }
1143 #endif
1144 } else {
1145 continue;
1146 }
1147 break;
1148 #endif
1149 #ifdef INET6
1150 case AF_INET6:
1151 if (ipv6_addr_legal) {
1152 struct sockaddr_in6 *sin6;
1153
1154 sin6 = &sctp_ifa->address.sin6;
1155 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1156 /*
1157 * we skip
1158 * unspecified
1159 * addresses
1160 */
1161 continue;
1162 }
1163 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1164 &sin6->sin6_addr) != 0) {
1165 continue;
1166 }
1167 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1168 if (local_scope == 0)
1169 continue;
1170 if (sin6->sin6_scope_id == 0) {
1171 if (sa6_recoverscope(sin6) != 0)
1172 /*
1173 *
1174 * bad
1175 * link
1176 *
1177 * local
1178 *
1179 * address
1180 */
1181 continue;
1182 }
1183 }
1184 if ((site_scope == 0) &&
1185 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1186 continue;
1187 }
1188 if (actual + sizeof(struct sockaddr_in6) > limit) {
1189 return (actual);
1190 }
1191 memcpy(addr, sin6, sizeof(struct sockaddr_in6));
1192 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1193 addr = (struct sockaddr *)((caddr_t)addr + sizeof(struct sockaddr_in6));
1194 actual += sizeof(struct sockaddr_in6);
1195 } else {
1196 continue;
1197 }
1198 break;
1199 #endif
1200 default:
1201 /* TSNH */
1202 break;
1203 }
1204 }
1205 }
1206 } else {
1207 struct sctp_laddr *laddr;
1208 size_t sa_len;
1209
1210 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1211 if (stcb) {
1212 if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1213 continue;
1214 }
1215 }
1216 sa_len = laddr->ifa->address.sa.sa_len;
1217 if (actual + sa_len > limit) {
1218 return (actual);
1219 }
1220 if (sctp_fill_user_address(addr, &laddr->ifa->address.sa))
1221 continue;
1222 switch (laddr->ifa->address.sa.sa_family) {
1223 #ifdef INET
1224 case AF_INET:
1225 ((struct sockaddr_in *)addr)->sin_port = inp->sctp_lport;
1226 break;
1227 #endif
1228 #ifdef INET6
1229 case AF_INET6:
1230 ((struct sockaddr_in6 *)addr)->sin6_port = inp->sctp_lport;
1231 break;
1232 #endif
1233 default:
1234 /* TSNH */
1235 break;
1236 }
1237 addr = (struct sockaddr *)((caddr_t)addr + sa_len);
1238 actual += sa_len;
1239 }
1240 }
1241 return (actual);
1242 }
1243
1244 static size_t
sctp_fill_up_addresses(struct sctp_inpcb * inp,struct sctp_tcb * stcb,size_t limit,struct sockaddr * addr)1245 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1246 struct sctp_tcb *stcb,
1247 size_t limit,
1248 struct sockaddr *addr)
1249 {
1250 size_t size;
1251
1252 SCTP_IPI_ADDR_RLOCK();
1253 /* fill up addresses for the endpoint's default vrf */
1254 size = sctp_fill_up_addresses_vrf(inp, stcb, limit, addr,
1255 inp->def_vrf_id);
1256 SCTP_IPI_ADDR_RUNLOCK();
1257 return (size);
1258 }
1259
1260 static size_t
sctp_max_size_addresses_vrf(struct sctp_inpcb * inp,uint32_t vrf_id)1261 sctp_max_size_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1262 {
1263 struct sctp_vrf *vrf;
1264 size_t size;
1265
1266 /*
1267 * In both sub-set bound an bound_all cases we return the size of
1268 * the maximum number of addresses that you could get. In reality
1269 * the sub-set bound may have an exclusion list for a given TCB or
1270 * in the bound-all case a TCB may NOT include the loopback or other
1271 * addresses as well.
1272 */
1273 SCTP_IPI_ADDR_LOCK_ASSERT();
1274 vrf = sctp_find_vrf(vrf_id);
1275 if (vrf == NULL) {
1276 return (0);
1277 }
1278 size = 0;
1279 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1280 struct sctp_ifn *sctp_ifn;
1281 struct sctp_ifa *sctp_ifa;
1282
1283 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1284 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1285 /* Count them if they are the right type */
1286 switch (sctp_ifa->address.sa.sa_family) {
1287 #ifdef INET
1288 case AF_INET:
1289 #ifdef INET6
1290 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1291 size += sizeof(struct sockaddr_in6);
1292 else
1293 size += sizeof(struct sockaddr_in);
1294 #else
1295 size += sizeof(struct sockaddr_in);
1296 #endif
1297 break;
1298 #endif
1299 #ifdef INET6
1300 case AF_INET6:
1301 size += sizeof(struct sockaddr_in6);
1302 break;
1303 #endif
1304 default:
1305 break;
1306 }
1307 }
1308 }
1309 } else {
1310 struct sctp_laddr *laddr;
1311
1312 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1313 switch (laddr->ifa->address.sa.sa_family) {
1314 #ifdef INET
1315 case AF_INET:
1316 #ifdef INET6
1317 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1318 size += sizeof(struct sockaddr_in6);
1319 else
1320 size += sizeof(struct sockaddr_in);
1321 #else
1322 size += sizeof(struct sockaddr_in);
1323 #endif
1324 break;
1325 #endif
1326 #ifdef INET6
1327 case AF_INET6:
1328 size += sizeof(struct sockaddr_in6);
1329 break;
1330 #endif
1331 default:
1332 break;
1333 }
1334 }
1335 }
1336 return (size);
1337 }
1338
1339 static size_t
sctp_max_size_addresses(struct sctp_inpcb * inp)1340 sctp_max_size_addresses(struct sctp_inpcb *inp)
1341 {
1342 size_t size;
1343
1344 SCTP_IPI_ADDR_RLOCK();
1345 /* Maximum size of all addresses for the endpoint's default VRF */
1346 size = sctp_max_size_addresses_vrf(inp, inp->def_vrf_id);
1347 SCTP_IPI_ADDR_RUNLOCK();
1348 return (size);
1349 }
1350
1351 static int
sctp_do_connect_x(struct socket * so,struct sctp_inpcb * inp,void * optval,size_t optsize,void * p,int delay)1352 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1353 size_t optsize, void *p, int delay)
1354 {
1355 int error;
1356 int creat_lock_on = 0;
1357 struct sctp_tcb *stcb = NULL;
1358 struct sockaddr *sa;
1359 unsigned int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1360 uint32_t vrf_id;
1361 sctp_assoc_t *a_id;
1362
1363 SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1364
1365 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1366 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1367 /* We are already connected AND the TCP model */
1368 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1369 return (EADDRINUSE);
1370 }
1371
1372 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1373 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1374 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1375 return (EINVAL);
1376 }
1377
1378 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1379 SCTP_INP_RLOCK(inp);
1380 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1381 SCTP_INP_RUNLOCK(inp);
1382 }
1383 if (stcb) {
1384 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1385 return (EALREADY);
1386 }
1387 SCTP_INP_INCR_REF(inp);
1388 SCTP_ASOC_CREATE_LOCK(inp);
1389 creat_lock_on = 1;
1390 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1391 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1392 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1393 error = EFAULT;
1394 goto out_now;
1395 }
1396 totaddrp = (unsigned int *)optval;
1397 totaddr = *totaddrp;
1398 sa = (struct sockaddr *)(totaddrp + 1);
1399 error = sctp_connectx_helper_find(inp, sa, totaddr, &num_v4, &num_v6, (unsigned int)(optsize - sizeof(int)));
1400 if (error != 0) {
1401 /* Already have or am bring up an association */
1402 SCTP_ASOC_CREATE_UNLOCK(inp);
1403 creat_lock_on = 0;
1404 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1405 goto out_now;
1406 }
1407 #ifdef INET6
1408 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1409 (num_v6 > 0)) {
1410 error = EINVAL;
1411 goto out_now;
1412 }
1413 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1414 (num_v4 > 0)) {
1415 if (SCTP_IPV6_V6ONLY(inp)) {
1416 /*
1417 * if IPV6_V6ONLY flag, ignore connections destined
1418 * to a v4 addr or v4-mapped addr
1419 */
1420 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1421 error = EINVAL;
1422 goto out_now;
1423 }
1424 }
1425 #endif /* INET6 */
1426 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
1427 /* Bind a ephemeral port */
1428 error = sctp_inpcb_bind(so, NULL, NULL, p);
1429 if (error) {
1430 goto out_now;
1431 }
1432 }
1433
1434 /* FIX ME: do we want to pass in a vrf on the connect call? */
1435 vrf_id = inp->def_vrf_id;
1436
1437 /* We are GOOD to go */
1438 stcb = sctp_aloc_assoc_connected(inp, sa, &error, 0, 0, vrf_id,
1439 inp->sctp_ep.pre_open_stream_count,
1440 inp->sctp_ep.port,
1441 (struct thread *)p,
1442 SCTP_INITIALIZE_AUTH_PARAMS);
1443 if (stcb == NULL) {
1444 /* Gak! no memory */
1445 goto out_now;
1446 }
1447 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
1448 /* move to second address */
1449 switch (sa->sa_family) {
1450 #ifdef INET
1451 case AF_INET:
1452 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1453 break;
1454 #endif
1455 #ifdef INET6
1456 case AF_INET6:
1457 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1458 break;
1459 #endif
1460 default:
1461 break;
1462 }
1463
1464 error = 0;
1465 sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
1466 /* Fill in the return id */
1467 if (error) {
1468 goto out_now;
1469 }
1470 a_id = (sctp_assoc_t *)optval;
1471 *a_id = sctp_get_associd(stcb);
1472
1473 if (delay) {
1474 /* doing delayed connection */
1475 stcb->asoc.delayed_connection = 1;
1476 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1477 } else {
1478 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1479 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1480 }
1481 SCTP_TCB_UNLOCK(stcb);
1482 out_now:
1483 if (creat_lock_on) {
1484 SCTP_ASOC_CREATE_UNLOCK(inp);
1485 }
1486 SCTP_INP_DECR_REF(inp);
1487 return (error);
1488 }
1489
1490 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1491 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1492 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1493 SCTP_INP_RLOCK(inp); \
1494 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1495 if (stcb) { \
1496 SCTP_TCB_LOCK(stcb); \
1497 } \
1498 SCTP_INP_RUNLOCK(inp); \
1499 } else if (assoc_id > SCTP_ALL_ASSOC) { \
1500 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1501 if (stcb == NULL) { \
1502 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1503 error = ENOENT; \
1504 break; \
1505 } \
1506 } else { \
1507 stcb = NULL; \
1508 } \
1509 }
1510
1511 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
1512 if (size < sizeof(type)) { \
1513 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1514 error = EINVAL; \
1515 break; \
1516 } else { \
1517 destp = (type *)srcp; \
1518 } \
1519 }
1520
1521 static int
sctp_getopt(struct socket * so,int optname,void * optval,size_t * optsize,void * p)1522 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
1523 void *p)
1524 {
1525 struct sctp_inpcb *inp = NULL;
1526 int error, val = 0;
1527 struct sctp_tcb *stcb = NULL;
1528
1529 if (optval == NULL) {
1530 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1531 return (EINVAL);
1532 }
1533
1534 inp = (struct sctp_inpcb *)so->so_pcb;
1535 if (inp == NULL) {
1536 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1537 return EINVAL;
1538 }
1539 error = 0;
1540
1541 switch (optname) {
1542 case SCTP_NODELAY:
1543 case SCTP_AUTOCLOSE:
1544 case SCTP_EXPLICIT_EOR:
1545 case SCTP_AUTO_ASCONF:
1546 case SCTP_DISABLE_FRAGMENTS:
1547 case SCTP_I_WANT_MAPPED_V4_ADDR:
1548 case SCTP_USE_EXT_RCVINFO:
1549 SCTP_INP_RLOCK(inp);
1550 switch (optname) {
1551 case SCTP_DISABLE_FRAGMENTS:
1552 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
1553 break;
1554 case SCTP_I_WANT_MAPPED_V4_ADDR:
1555 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
1556 break;
1557 case SCTP_AUTO_ASCONF:
1558 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1559 /* only valid for bound all sockets */
1560 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1561 } else {
1562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1563 error = EINVAL;
1564 goto flags_out;
1565 }
1566 break;
1567 case SCTP_EXPLICIT_EOR:
1568 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
1569 break;
1570 case SCTP_NODELAY:
1571 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
1572 break;
1573 case SCTP_USE_EXT_RCVINFO:
1574 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
1575 break;
1576 case SCTP_AUTOCLOSE:
1577 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
1578 val = sctp_ticks_to_secs(inp->sctp_ep.auto_close_time);
1579 else
1580 val = 0;
1581 break;
1582
1583 default:
1584 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
1585 error = ENOPROTOOPT;
1586 } /* end switch (sopt->sopt_name) */
1587 if (*optsize < sizeof(val)) {
1588 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1589 error = EINVAL;
1590 }
1591 flags_out:
1592 SCTP_INP_RUNLOCK(inp);
1593 if (error == 0) {
1594 /* return the option value */
1595 *(int *)optval = val;
1596 *optsize = sizeof(val);
1597 }
1598 break;
1599 case SCTP_GET_PACKET_LOG:
1600 {
1601 #ifdef SCTP_PACKET_LOGGING
1602 uint8_t *target;
1603 int ret;
1604
1605 SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
1606 ret = sctp_copy_out_packet_log(target, (int)*optsize);
1607 *optsize = ret;
1608 #else
1609 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1610 error = EOPNOTSUPP;
1611 #endif
1612 break;
1613 }
1614 case SCTP_REUSE_PORT:
1615 {
1616 uint32_t *value;
1617
1618 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
1619 /* Can't do this for a 1-m socket */
1620 error = EINVAL;
1621 break;
1622 }
1623 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1624 *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
1625 *optsize = sizeof(uint32_t);
1626 break;
1627 }
1628 case SCTP_PARTIAL_DELIVERY_POINT:
1629 {
1630 uint32_t *value;
1631
1632 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1633 *value = inp->partial_delivery_point;
1634 *optsize = sizeof(uint32_t);
1635 break;
1636 }
1637 case SCTP_FRAGMENT_INTERLEAVE:
1638 {
1639 uint32_t *value;
1640
1641 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1642 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
1643 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
1644 *value = SCTP_FRAG_LEVEL_2;
1645 } else {
1646 *value = SCTP_FRAG_LEVEL_1;
1647 }
1648 } else {
1649 *value = SCTP_FRAG_LEVEL_0;
1650 }
1651 *optsize = sizeof(uint32_t);
1652 break;
1653 }
1654 case SCTP_INTERLEAVING_SUPPORTED:
1655 {
1656 struct sctp_assoc_value *av;
1657
1658 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1659 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1660
1661 if (stcb) {
1662 av->assoc_value = stcb->asoc.idata_supported;
1663 SCTP_TCB_UNLOCK(stcb);
1664 } else {
1665 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1666 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1667 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1668 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
1669 SCTP_INP_RLOCK(inp);
1670 if (inp->idata_supported) {
1671 av->assoc_value = 1;
1672 } else {
1673 av->assoc_value = 0;
1674 }
1675 SCTP_INP_RUNLOCK(inp);
1676 } else {
1677 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1678 error = EINVAL;
1679 }
1680 }
1681 if (error == 0) {
1682 *optsize = sizeof(struct sctp_assoc_value);
1683 }
1684 break;
1685 }
1686 case SCTP_CMT_ON_OFF:
1687 {
1688 struct sctp_assoc_value *av;
1689
1690 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1691 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1692 if (stcb) {
1693 av->assoc_value = stcb->asoc.sctp_cmt_on_off;
1694 SCTP_TCB_UNLOCK(stcb);
1695 } else {
1696 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1697 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1698 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1699 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
1700 SCTP_INP_RLOCK(inp);
1701 av->assoc_value = inp->sctp_cmt_on_off;
1702 SCTP_INP_RUNLOCK(inp);
1703 } else {
1704 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1705 error = EINVAL;
1706 }
1707 }
1708 if (error == 0) {
1709 *optsize = sizeof(struct sctp_assoc_value);
1710 }
1711 break;
1712 }
1713 case SCTP_PLUGGABLE_CC:
1714 {
1715 struct sctp_assoc_value *av;
1716
1717 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1718 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1719 if (stcb) {
1720 av->assoc_value = stcb->asoc.congestion_control_module;
1721 SCTP_TCB_UNLOCK(stcb);
1722 } else {
1723 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1724 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1725 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1726 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
1727 SCTP_INP_RLOCK(inp);
1728 av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
1729 SCTP_INP_RUNLOCK(inp);
1730 } else {
1731 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1732 error = EINVAL;
1733 }
1734 }
1735 if (error == 0) {
1736 *optsize = sizeof(struct sctp_assoc_value);
1737 }
1738 break;
1739 }
1740 case SCTP_CC_OPTION:
1741 {
1742 struct sctp_cc_option *cc_opt;
1743
1744 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
1745 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
1746 if (stcb == NULL) {
1747 error = EINVAL;
1748 } else {
1749 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
1750 error = ENOTSUP;
1751 } else {
1752 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
1753 *optsize = sizeof(struct sctp_cc_option);
1754 }
1755 SCTP_TCB_UNLOCK(stcb);
1756 }
1757 break;
1758 }
1759 case SCTP_STREAM_SCHEDULER:
1760 {
1761 struct sctp_assoc_value *av;
1762
1763 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1764 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1765 if (stcb) {
1766 av->assoc_value = stcb->asoc.stream_scheduling_module;
1767 SCTP_TCB_UNLOCK(stcb);
1768 } else {
1769 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1770 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1771 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1772 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
1773 SCTP_INP_RLOCK(inp);
1774 av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
1775 SCTP_INP_RUNLOCK(inp);
1776 } else {
1777 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1778 error = EINVAL;
1779 }
1780 }
1781 if (error == 0) {
1782 *optsize = sizeof(struct sctp_assoc_value);
1783 }
1784 break;
1785 }
1786 case SCTP_STREAM_SCHEDULER_VALUE:
1787 {
1788 struct sctp_stream_value *av;
1789
1790 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
1791 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1792 if (stcb) {
1793 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
1794 (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
1795 &av->stream_value) < 0)) {
1796 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1797 error = EINVAL;
1798 } else {
1799 *optsize = sizeof(struct sctp_stream_value);
1800 }
1801 SCTP_TCB_UNLOCK(stcb);
1802 } else {
1803 /*
1804 * Can't get stream value without
1805 * association
1806 */
1807 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1808 error = EINVAL;
1809 }
1810 break;
1811 }
1812 case SCTP_GET_ADDR_LEN:
1813 {
1814 struct sctp_assoc_value *av;
1815
1816 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1817 error = EINVAL;
1818 #ifdef INET
1819 if (av->assoc_value == AF_INET) {
1820 av->assoc_value = sizeof(struct sockaddr_in);
1821 error = 0;
1822 }
1823 #endif
1824 #ifdef INET6
1825 if (av->assoc_value == AF_INET6) {
1826 av->assoc_value = sizeof(struct sockaddr_in6);
1827 error = 0;
1828 }
1829 #endif
1830 if (error) {
1831 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1832 } else {
1833 *optsize = sizeof(struct sctp_assoc_value);
1834 }
1835 break;
1836 }
1837 case SCTP_GET_ASSOC_NUMBER:
1838 {
1839 uint32_t *value, cnt;
1840
1841 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1842 SCTP_INP_RLOCK(inp);
1843 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1844 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1845 /* Can't do this for a 1-1 socket */
1846 error = EINVAL;
1847 SCTP_INP_RUNLOCK(inp);
1848 break;
1849 }
1850 cnt = 0;
1851 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1852 cnt++;
1853 }
1854 SCTP_INP_RUNLOCK(inp);
1855 *value = cnt;
1856 *optsize = sizeof(uint32_t);
1857 break;
1858 }
1859 case SCTP_GET_ASSOC_ID_LIST:
1860 {
1861 struct sctp_assoc_ids *ids;
1862 uint32_t at;
1863 size_t limit;
1864
1865 SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
1866 SCTP_INP_RLOCK(inp);
1867 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1868 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1869 /* Can't do this for a 1-1 socket */
1870 error = EINVAL;
1871 SCTP_INP_RUNLOCK(inp);
1872 break;
1873 }
1874 at = 0;
1875 limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
1876 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1877 if (at < limit) {
1878 ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
1879 if (at == 0) {
1880 error = EINVAL;
1881 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1882 break;
1883 }
1884 } else {
1885 error = EINVAL;
1886 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1887 break;
1888 }
1889 }
1890 SCTP_INP_RUNLOCK(inp);
1891 if (error == 0) {
1892 ids->gaids_number_of_ids = at;
1893 *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
1894 }
1895 break;
1896 }
1897 case SCTP_CONTEXT:
1898 {
1899 struct sctp_assoc_value *av;
1900
1901 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1902 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1903
1904 if (stcb) {
1905 av->assoc_value = stcb->asoc.context;
1906 SCTP_TCB_UNLOCK(stcb);
1907 } else {
1908 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1909 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1910 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1911 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
1912 SCTP_INP_RLOCK(inp);
1913 av->assoc_value = inp->sctp_context;
1914 SCTP_INP_RUNLOCK(inp);
1915 } else {
1916 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1917 error = EINVAL;
1918 }
1919 }
1920 if (error == 0) {
1921 *optsize = sizeof(struct sctp_assoc_value);
1922 }
1923 break;
1924 }
1925 case SCTP_VRF_ID:
1926 {
1927 uint32_t *default_vrfid;
1928
1929 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
1930 *default_vrfid = inp->def_vrf_id;
1931 *optsize = sizeof(uint32_t);
1932 break;
1933 }
1934 case SCTP_GET_ASOC_VRF:
1935 {
1936 struct sctp_assoc_value *id;
1937
1938 SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
1939 SCTP_FIND_STCB(inp, stcb, id->assoc_id);
1940 if (stcb == NULL) {
1941 error = EINVAL;
1942 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1943 } else {
1944 id->assoc_value = stcb->asoc.vrf_id;
1945 SCTP_TCB_UNLOCK(stcb);
1946 *optsize = sizeof(struct sctp_assoc_value);
1947 }
1948 break;
1949 }
1950 case SCTP_GET_VRF_IDS:
1951 {
1952 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1953 error = EOPNOTSUPP;
1954 break;
1955 }
1956 case SCTP_GET_NONCE_VALUES:
1957 {
1958 struct sctp_get_nonce_values *gnv;
1959
1960 SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
1961 SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
1962
1963 if (stcb) {
1964 gnv->gn_peers_tag = stcb->asoc.peer_vtag;
1965 gnv->gn_local_tag = stcb->asoc.my_vtag;
1966 SCTP_TCB_UNLOCK(stcb);
1967 *optsize = sizeof(struct sctp_get_nonce_values);
1968 } else {
1969 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
1970 error = ENOTCONN;
1971 }
1972 break;
1973 }
1974 case SCTP_DELAYED_SACK:
1975 {
1976 struct sctp_sack_info *sack;
1977
1978 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
1979 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
1980 if (stcb) {
1981 sack->sack_delay = stcb->asoc.delayed_ack;
1982 sack->sack_freq = stcb->asoc.sack_freq;
1983 SCTP_TCB_UNLOCK(stcb);
1984 } else {
1985 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1986 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1987 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
1988 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC))) {
1989 SCTP_INP_RLOCK(inp);
1990 sack->sack_delay = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
1991 sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
1992 SCTP_INP_RUNLOCK(inp);
1993 } else {
1994 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1995 error = EINVAL;
1996 }
1997 }
1998 if (error == 0) {
1999 *optsize = sizeof(struct sctp_sack_info);
2000 }
2001 break;
2002 }
2003 case SCTP_GET_SNDBUF_USE:
2004 {
2005 struct sctp_sockstat *ss;
2006
2007 SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2008 SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2009
2010 if (stcb) {
2011 ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2012 ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2013 stcb->asoc.size_on_all_streams);
2014 SCTP_TCB_UNLOCK(stcb);
2015 *optsize = sizeof(struct sctp_sockstat);
2016 } else {
2017 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2018 error = ENOTCONN;
2019 }
2020 break;
2021 }
2022 case SCTP_MAX_BURST:
2023 {
2024 struct sctp_assoc_value *av;
2025
2026 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2027 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2028
2029 if (stcb) {
2030 av->assoc_value = stcb->asoc.max_burst;
2031 SCTP_TCB_UNLOCK(stcb);
2032 } else {
2033 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2034 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2035 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2036 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2037 SCTP_INP_RLOCK(inp);
2038 av->assoc_value = inp->sctp_ep.max_burst;
2039 SCTP_INP_RUNLOCK(inp);
2040 } else {
2041 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2042 error = EINVAL;
2043 }
2044 }
2045 if (error == 0) {
2046 *optsize = sizeof(struct sctp_assoc_value);
2047 }
2048 break;
2049 }
2050 case SCTP_MAXSEG:
2051 {
2052 struct sctp_assoc_value *av;
2053
2054 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2055 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2056
2057 if (stcb) {
2058 av->assoc_value = stcb->asoc.sctp_frag_point;
2059 SCTP_TCB_UNLOCK(stcb);
2060 } else {
2061 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2062 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2063 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2064 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
2065 SCTP_INP_RLOCK(inp);
2066 av->assoc_value = inp->sctp_frag_point;
2067 SCTP_INP_RUNLOCK(inp);
2068 } else {
2069 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2070 error = EINVAL;
2071 }
2072 }
2073 if (error == 0) {
2074 *optsize = sizeof(struct sctp_assoc_value);
2075 }
2076 break;
2077 }
2078 case SCTP_GET_STAT_LOG:
2079 error = sctp_fill_stat_log(optval, optsize);
2080 break;
2081 case SCTP_EVENTS:
2082 {
2083 struct sctp_event_subscribe *events;
2084
2085 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2086 memset(events, 0, sizeof(struct sctp_event_subscribe));
2087 SCTP_INP_RLOCK(inp);
2088 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2089 events->sctp_data_io_event = 1;
2090
2091 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2092 events->sctp_association_event = 1;
2093
2094 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2095 events->sctp_address_event = 1;
2096
2097 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2098 events->sctp_send_failure_event = 1;
2099
2100 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2101 events->sctp_peer_error_event = 1;
2102
2103 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2104 events->sctp_shutdown_event = 1;
2105
2106 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2107 events->sctp_partial_delivery_event = 1;
2108
2109 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2110 events->sctp_adaptation_layer_event = 1;
2111
2112 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2113 events->sctp_authentication_event = 1;
2114
2115 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2116 events->sctp_sender_dry_event = 1;
2117
2118 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2119 events->sctp_stream_reset_event = 1;
2120 SCTP_INP_RUNLOCK(inp);
2121 *optsize = sizeof(struct sctp_event_subscribe);
2122 break;
2123 }
2124 case SCTP_ADAPTATION_LAYER:
2125 {
2126 uint32_t *value;
2127
2128 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2129
2130 SCTP_INP_RLOCK(inp);
2131 *value = inp->sctp_ep.adaptation_layer_indicator;
2132 SCTP_INP_RUNLOCK(inp);
2133 *optsize = sizeof(uint32_t);
2134 break;
2135 }
2136 case SCTP_SET_INITIAL_DBG_SEQ:
2137 {
2138 uint32_t *value;
2139
2140 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2141 SCTP_INP_RLOCK(inp);
2142 *value = inp->sctp_ep.initial_sequence_debug;
2143 SCTP_INP_RUNLOCK(inp);
2144 *optsize = sizeof(uint32_t);
2145 break;
2146 }
2147 case SCTP_GET_LOCAL_ADDR_SIZE:
2148 {
2149 uint32_t *value;
2150
2151 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2152 SCTP_INP_RLOCK(inp);
2153 *value = (uint32_t)sctp_max_size_addresses(inp);
2154 SCTP_INP_RUNLOCK(inp);
2155 *optsize = sizeof(uint32_t);
2156 break;
2157 }
2158 case SCTP_GET_REMOTE_ADDR_SIZE:
2159 {
2160 uint32_t *value;
2161 struct sctp_nets *net;
2162 size_t size;
2163
2164 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2165 /* FIXME MT: change to sctp_assoc_value? */
2166 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t)*value);
2167
2168 if (stcb != NULL) {
2169 size = 0;
2170 /* Count the sizes */
2171 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2172 switch (net->ro._l_addr.sa.sa_family) {
2173 #ifdef INET
2174 case AF_INET:
2175 #ifdef INET6
2176 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2177 size += sizeof(struct sockaddr_in6);
2178 } else {
2179 size += sizeof(struct sockaddr_in);
2180 }
2181 #else
2182 size += sizeof(struct sockaddr_in);
2183 #endif
2184 break;
2185 #endif
2186 #ifdef INET6
2187 case AF_INET6:
2188 size += sizeof(struct sockaddr_in6);
2189 break;
2190 #endif
2191 default:
2192 break;
2193 }
2194 }
2195 SCTP_TCB_UNLOCK(stcb);
2196 *value = (uint32_t)size;
2197 *optsize = sizeof(uint32_t);
2198 } else {
2199 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2200 ((sctp_assoc_t)*value <= SCTP_ALL_ASSOC)) {
2201 error = EINVAL;
2202 } else {
2203 error = ENOENT;
2204 }
2205 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2206 }
2207 break;
2208 }
2209 case SCTP_GET_PEER_ADDRESSES:
2210 /*
2211 * Get the address information, an array is passed in to
2212 * fill up we pack it.
2213 */
2214 {
2215 size_t cpsz, left;
2216 struct sockaddr *addr;
2217 struct sctp_nets *net;
2218 struct sctp_getaddresses *saddr;
2219
2220 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2221 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2222
2223 if (stcb != NULL) {
2224 left = *optsize - offsetof(struct sctp_getaddresses, addr);
2225 *optsize = offsetof(struct sctp_getaddresses, addr);
2226 addr = &saddr->addr[0].sa;
2227
2228 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2229 switch (net->ro._l_addr.sa.sa_family) {
2230 #ifdef INET
2231 case AF_INET:
2232 #ifdef INET6
2233 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2234 cpsz = sizeof(struct sockaddr_in6);
2235 } else {
2236 cpsz = sizeof(struct sockaddr_in);
2237 }
2238 #else
2239 cpsz = sizeof(struct sockaddr_in);
2240 #endif
2241 break;
2242 #endif
2243 #ifdef INET6
2244 case AF_INET6:
2245 cpsz = sizeof(struct sockaddr_in6);
2246 break;
2247 #endif
2248 default:
2249 cpsz = 0;
2250 break;
2251 }
2252 if (cpsz == 0) {
2253 break;
2254 }
2255 if (left < cpsz) {
2256 /* not enough room. */
2257 break;
2258 }
2259 #if defined(INET) && defined(INET6)
2260 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2261 (net->ro._l_addr.sa.sa_family == AF_INET)) {
2262 /* Must map the address */
2263 in6_sin_2_v4mapsin6(&net->ro._l_addr.sin,
2264 (struct sockaddr_in6 *)addr);
2265 } else {
2266 memcpy(addr, &net->ro._l_addr, cpsz);
2267 }
2268 #else
2269 memcpy(addr, &net->ro._l_addr, cpsz);
2270 #endif
2271 ((struct sockaddr_in *)addr)->sin_port = stcb->rport;
2272
2273 addr = (struct sockaddr *)((caddr_t)addr + cpsz);
2274 left -= cpsz;
2275 *optsize += cpsz;
2276 }
2277 SCTP_TCB_UNLOCK(stcb);
2278 } else {
2279 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2280 (saddr->sget_assoc_id <= SCTP_ALL_ASSOC)) {
2281 error = EINVAL;
2282 } else {
2283 error = ENOENT;
2284 }
2285 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2286 }
2287 break;
2288 }
2289 case SCTP_GET_LOCAL_ADDRESSES:
2290 {
2291 size_t limit, actual;
2292 struct sctp_getaddresses *saddr;
2293
2294 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2295 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2296
2297 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2298 ((saddr->sget_assoc_id == SCTP_CURRENT_ASSOC) ||
2299 (saddr->sget_assoc_id == SCTP_ALL_ASSOC))) {
2300 error = EINVAL;
2301 } else {
2302 limit = *optsize - offsetof(struct sctp_getaddresses, addr);
2303 actual = sctp_fill_up_addresses(inp, stcb, limit, &saddr->addr[0].sa);
2304 *optsize = offsetof(struct sctp_getaddresses, addr) + actual;
2305 }
2306 if (stcb != NULL) {
2307 SCTP_TCB_UNLOCK(stcb);
2308 }
2309 break;
2310 }
2311 case SCTP_PEER_ADDR_PARAMS:
2312 {
2313 struct sctp_paddrparams *paddrp;
2314 struct sctp_nets *net;
2315 struct sockaddr *addr;
2316 #if defined(INET) && defined(INET6)
2317 struct sockaddr_in sin_store;
2318 #endif
2319
2320 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2321 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2322
2323 #if defined(INET) && defined(INET6)
2324 if (paddrp->spp_address.ss_family == AF_INET6) {
2325 struct sockaddr_in6 *sin6;
2326
2327 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
2328 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2329 in6_sin6_2_sin(&sin_store, sin6);
2330 addr = (struct sockaddr *)&sin_store;
2331 } else {
2332 addr = (struct sockaddr *)&paddrp->spp_address;
2333 }
2334 } else {
2335 addr = (struct sockaddr *)&paddrp->spp_address;
2336 }
2337 #else
2338 addr = (struct sockaddr *)&paddrp->spp_address;
2339 #endif
2340 if (stcb != NULL) {
2341 net = sctp_findnet(stcb, addr);
2342 } else {
2343 /*
2344 * We increment here since
2345 * sctp_findassociation_ep_addr() wil do a
2346 * decrement if it finds the stcb as long as
2347 * the locked tcb (last argument) is NOT a
2348 * TCB.. aka NULL.
2349 */
2350 net = NULL;
2351 SCTP_INP_INCR_REF(inp);
2352 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
2353 if (stcb == NULL) {
2354 SCTP_INP_DECR_REF(inp);
2355 }
2356 }
2357 if ((stcb != NULL) && (net == NULL)) {
2358 #ifdef INET
2359 if (addr->sa_family == AF_INET) {
2360 struct sockaddr_in *sin;
2361
2362 sin = (struct sockaddr_in *)addr;
2363 if (sin->sin_addr.s_addr != INADDR_ANY) {
2364 error = EINVAL;
2365 SCTP_TCB_UNLOCK(stcb);
2366 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2367 break;
2368 }
2369 } else
2370 #endif
2371 #ifdef INET6
2372 if (addr->sa_family == AF_INET6) {
2373 struct sockaddr_in6 *sin6;
2374
2375 sin6 = (struct sockaddr_in6 *)addr;
2376 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2377 error = EINVAL;
2378 SCTP_TCB_UNLOCK(stcb);
2379 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2380 break;
2381 }
2382 } else
2383 #endif
2384 {
2385 error = EAFNOSUPPORT;
2386 SCTP_TCB_UNLOCK(stcb);
2387 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2388 break;
2389 }
2390 }
2391
2392 if (stcb != NULL) {
2393 /* Applies to the specific association */
2394 paddrp->spp_flags = 0;
2395 if (net != NULL) {
2396 paddrp->spp_hbinterval = net->heart_beat_delay;
2397 paddrp->spp_pathmaxrxt = net->failure_threshold;
2398 paddrp->spp_pathmtu = net->mtu;
2399 switch (net->ro._l_addr.sa.sa_family) {
2400 #ifdef INET
2401 case AF_INET:
2402 paddrp->spp_pathmtu -= SCTP_MIN_V4_OVERHEAD;
2403 break;
2404 #endif
2405 #ifdef INET6
2406 case AF_INET6:
2407 paddrp->spp_pathmtu -= SCTP_MIN_OVERHEAD;
2408 break;
2409 #endif
2410 default:
2411 break;
2412 }
2413 /* get flags for HB */
2414 if (net->dest_state & SCTP_ADDR_NOHB) {
2415 paddrp->spp_flags |= SPP_HB_DISABLE;
2416 } else {
2417 paddrp->spp_flags |= SPP_HB_ENABLE;
2418 }
2419 /* get flags for PMTU */
2420 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
2421 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2422 } else {
2423 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2424 }
2425 if (net->dscp & 0x01) {
2426 paddrp->spp_dscp = net->dscp & 0xfc;
2427 paddrp->spp_flags |= SPP_DSCP;
2428 }
2429 #ifdef INET6
2430 if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
2431 (net->flowlabel & 0x80000000)) {
2432 paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
2433 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2434 }
2435 #endif
2436 } else {
2437 /*
2438 * No destination so return default
2439 * value
2440 */
2441 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2442 paddrp->spp_pathmtu = stcb->asoc.default_mtu;
2443 if (stcb->asoc.default_dscp & 0x01) {
2444 paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
2445 paddrp->spp_flags |= SPP_DSCP;
2446 }
2447 #ifdef INET6
2448 if (stcb->asoc.default_flowlabel & 0x80000000) {
2449 paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
2450 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2451 }
2452 #endif
2453 /* default settings should be these */
2454 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2455 paddrp->spp_flags |= SPP_HB_DISABLE;
2456 } else {
2457 paddrp->spp_flags |= SPP_HB_ENABLE;
2458 }
2459 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2460 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2461 } else {
2462 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2463 }
2464 paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2465 }
2466 paddrp->spp_assoc_id = sctp_get_associd(stcb);
2467 SCTP_TCB_UNLOCK(stcb);
2468 } else {
2469 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2470 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2471 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2472 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
2473 /* Use endpoint defaults */
2474 SCTP_INP_RLOCK(inp);
2475 paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2476 paddrp->spp_hbinterval = sctp_ticks_to_msecs(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
2477 paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
2478 /* get inp's default */
2479 if (inp->sctp_ep.default_dscp & 0x01) {
2480 paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
2481 paddrp->spp_flags |= SPP_DSCP;
2482 }
2483 #ifdef INET6
2484 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2485 (inp->sctp_ep.default_flowlabel & 0x80000000)) {
2486 paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
2487 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2488 }
2489 #endif
2490 paddrp->spp_pathmtu = inp->sctp_ep.default_mtu;
2491
2492 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2493 paddrp->spp_flags |= SPP_HB_ENABLE;
2494 } else {
2495 paddrp->spp_flags |= SPP_HB_DISABLE;
2496 }
2497 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2498 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2499 } else {
2500 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2501 }
2502 SCTP_INP_RUNLOCK(inp);
2503 } else {
2504 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2505 error = EINVAL;
2506 }
2507 }
2508 if (error == 0) {
2509 *optsize = sizeof(struct sctp_paddrparams);
2510 }
2511 break;
2512 }
2513 case SCTP_GET_PEER_ADDR_INFO:
2514 {
2515 struct sctp_paddrinfo *paddri;
2516 struct sctp_nets *net;
2517 struct sockaddr *addr;
2518 #if defined(INET) && defined(INET6)
2519 struct sockaddr_in sin_store;
2520 #endif
2521
2522 SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
2523 SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
2524
2525 #if defined(INET) && defined(INET6)
2526 if (paddri->spinfo_address.ss_family == AF_INET6) {
2527 struct sockaddr_in6 *sin6;
2528
2529 sin6 = (struct sockaddr_in6 *)&paddri->spinfo_address;
2530 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
2531 in6_sin6_2_sin(&sin_store, sin6);
2532 addr = (struct sockaddr *)&sin_store;
2533 } else {
2534 addr = (struct sockaddr *)&paddri->spinfo_address;
2535 }
2536 } else {
2537 addr = (struct sockaddr *)&paddri->spinfo_address;
2538 }
2539 #else
2540 addr = (struct sockaddr *)&paddri->spinfo_address;
2541 #endif
2542 if (stcb != NULL) {
2543 net = sctp_findnet(stcb, addr);
2544 } else {
2545 /*
2546 * We increment here since
2547 * sctp_findassociation_ep_addr() wil do a
2548 * decrement if it finds the stcb as long as
2549 * the locked tcb (last argument) is NOT a
2550 * TCB.. aka NULL.
2551 */
2552 net = NULL;
2553 SCTP_INP_INCR_REF(inp);
2554 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
2555 if (stcb == NULL) {
2556 SCTP_INP_DECR_REF(inp);
2557 }
2558 }
2559
2560 if ((stcb != NULL) && (net != NULL)) {
2561 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2562 /* It's unconfirmed */
2563 paddri->spinfo_state = SCTP_UNCONFIRMED;
2564 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2565 /* It's active */
2566 paddri->spinfo_state = SCTP_ACTIVE;
2567 } else {
2568 /* It's inactive */
2569 paddri->spinfo_state = SCTP_INACTIVE;
2570 }
2571 paddri->spinfo_cwnd = net->cwnd;
2572 paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2573 paddri->spinfo_rto = net->RTO;
2574 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2575 paddri->spinfo_mtu = net->mtu;
2576 switch (addr->sa_family) {
2577 #if defined(INET)
2578 case AF_INET:
2579 paddri->spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
2580 break;
2581 #endif
2582 #if defined(INET6)
2583 case AF_INET6:
2584 paddri->spinfo_mtu -= SCTP_MIN_OVERHEAD;
2585 break;
2586 #endif
2587 default:
2588 break;
2589 }
2590 SCTP_TCB_UNLOCK(stcb);
2591 *optsize = sizeof(struct sctp_paddrinfo);
2592 } else {
2593 if (stcb != NULL) {
2594 SCTP_TCB_UNLOCK(stcb);
2595 }
2596 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2597 error = ENOENT;
2598 }
2599 break;
2600 }
2601 case SCTP_PCB_STATUS:
2602 {
2603 struct sctp_pcbinfo *spcb;
2604
2605 SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
2606 sctp_fill_pcbinfo(spcb);
2607 *optsize = sizeof(struct sctp_pcbinfo);
2608 break;
2609 }
2610 case SCTP_STATUS:
2611 {
2612 struct sctp_nets *net;
2613 struct sctp_status *sstat;
2614
2615 SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
2616 SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
2617
2618 if (stcb == NULL) {
2619 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2620 error = EINVAL;
2621 break;
2622 }
2623 sstat->sstat_state = sctp_map_assoc_state(stcb->asoc.state);
2624 sstat->sstat_assoc_id = sctp_get_associd(stcb);
2625 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2626 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2627 /*
2628 * We can't include chunks that have been passed to
2629 * the socket layer. Only things in queue.
2630 */
2631 sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
2632 stcb->asoc.cnt_on_all_streams);
2633 sstat->sstat_instrms = stcb->asoc.streamincnt;
2634 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2635 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb);
2636 net = stcb->asoc.primary_destination;
2637 if (net != NULL) {
2638 memcpy(&sstat->sstat_primary.spinfo_address,
2639 &net->ro._l_addr,
2640 ((struct sockaddr *)(&net->ro._l_addr))->sa_len);
2641 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2642 /*
2643 * Again the user can get info from
2644 * sctp_constants.h for what the state of
2645 * the network is.
2646 */
2647 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2648 /* It's unconfirmed */
2649 sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
2650 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2651 /* It's active */
2652 sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
2653 } else {
2654 /* It's inactive */
2655 sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
2656 }
2657 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2658 sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2659 sstat->sstat_primary.spinfo_rto = net->RTO;
2660 sstat->sstat_primary.spinfo_mtu = net->mtu;
2661 switch (stcb->asoc.primary_destination->ro._l_addr.sa.sa_family) {
2662 #if defined(INET)
2663 case AF_INET:
2664 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_V4_OVERHEAD;
2665 break;
2666 #endif
2667 #if defined(INET6)
2668 case AF_INET6:
2669 sstat->sstat_primary.spinfo_mtu -= SCTP_MIN_OVERHEAD;
2670 break;
2671 #endif
2672 default:
2673 break;
2674 }
2675 } else {
2676 memset(&sstat->sstat_primary, 0, sizeof(struct sctp_paddrinfo));
2677 }
2678 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2679 SCTP_TCB_UNLOCK(stcb);
2680 *optsize = sizeof(struct sctp_status);
2681 break;
2682 }
2683 case SCTP_RTOINFO:
2684 {
2685 struct sctp_rtoinfo *srto;
2686
2687 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
2688 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
2689
2690 if (stcb) {
2691 srto->srto_initial = stcb->asoc.initial_rto;
2692 srto->srto_max = stcb->asoc.maxrto;
2693 srto->srto_min = stcb->asoc.minrto;
2694 SCTP_TCB_UNLOCK(stcb);
2695 } else {
2696 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2697 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2698 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2699 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
2700 SCTP_INP_RLOCK(inp);
2701 srto->srto_initial = inp->sctp_ep.initial_rto;
2702 srto->srto_max = inp->sctp_ep.sctp_maxrto;
2703 srto->srto_min = inp->sctp_ep.sctp_minrto;
2704 SCTP_INP_RUNLOCK(inp);
2705 } else {
2706 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2707 error = EINVAL;
2708 }
2709 }
2710 if (error == 0) {
2711 *optsize = sizeof(struct sctp_rtoinfo);
2712 }
2713 break;
2714 }
2715 case SCTP_TIMEOUTS:
2716 {
2717 struct sctp_timeouts *stimo;
2718
2719 SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
2720 SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
2721
2722 if (stcb) {
2723 stimo->stimo_init = stcb->asoc.timoinit;
2724 stimo->stimo_data = stcb->asoc.timodata;
2725 stimo->stimo_sack = stcb->asoc.timosack;
2726 stimo->stimo_shutdown = stcb->asoc.timoshutdown;
2727 stimo->stimo_heartbeat = stcb->asoc.timoheartbeat;
2728 stimo->stimo_cookie = stcb->asoc.timocookie;
2729 stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
2730 SCTP_TCB_UNLOCK(stcb);
2731 *optsize = sizeof(struct sctp_timeouts);
2732 } else {
2733 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2734 error = EINVAL;
2735 }
2736 break;
2737 }
2738 case SCTP_ASSOCINFO:
2739 {
2740 struct sctp_assocparams *sasoc;
2741
2742 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
2743 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
2744
2745 if (stcb) {
2746 sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(stcb->asoc.cookie_life);
2747 sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2748 sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2749 sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2750 sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2751 SCTP_TCB_UNLOCK(stcb);
2752 } else {
2753 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2754 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2755 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2756 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
2757 SCTP_INP_RLOCK(inp);
2758 sasoc->sasoc_cookie_life = sctp_ticks_to_msecs(inp->sctp_ep.def_cookie_life);
2759 sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2760 sasoc->sasoc_number_peer_destinations = 0;
2761 sasoc->sasoc_peer_rwnd = 0;
2762 sasoc->sasoc_local_rwnd = (uint32_t)sbspace(&inp->sctp_socket->so_rcv);
2763 SCTP_INP_RUNLOCK(inp);
2764 } else {
2765 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2766 error = EINVAL;
2767 }
2768 }
2769 if (error == 0) {
2770 *optsize = sizeof(struct sctp_assocparams);
2771 }
2772 break;
2773 }
2774 case SCTP_DEFAULT_SEND_PARAM:
2775 {
2776 struct sctp_sndrcvinfo *s_info;
2777
2778 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
2779 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
2780
2781 if (stcb) {
2782 memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
2783 SCTP_TCB_UNLOCK(stcb);
2784 } else {
2785 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2786 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2787 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2788 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC))) {
2789 SCTP_INP_RLOCK(inp);
2790 memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
2791 SCTP_INP_RUNLOCK(inp);
2792 } else {
2793 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2794 error = EINVAL;
2795 }
2796 }
2797 if (error == 0) {
2798 *optsize = sizeof(struct sctp_sndrcvinfo);
2799 }
2800 break;
2801 }
2802 case SCTP_INITMSG:
2803 {
2804 struct sctp_initmsg *sinit;
2805
2806 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
2807 SCTP_INP_RLOCK(inp);
2808 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2809 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2810 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2811 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2812 SCTP_INP_RUNLOCK(inp);
2813 *optsize = sizeof(struct sctp_initmsg);
2814 break;
2815 }
2816 case SCTP_PRIMARY_ADDR:
2817 /* we allow a "get" operation on this */
2818 {
2819 struct sctp_setprim *ssp;
2820
2821 SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
2822 SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
2823
2824 if (stcb) {
2825 union sctp_sockstore *addr;
2826
2827 addr = &stcb->asoc.primary_destination->ro._l_addr;
2828 switch (addr->sa.sa_family) {
2829 #ifdef INET
2830 case AF_INET:
2831 #ifdef INET6
2832 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2833 in6_sin_2_v4mapsin6(&addr->sin,
2834 (struct sockaddr_in6 *)&ssp->ssp_addr);
2835 } else {
2836 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
2837 }
2838 #else
2839 memcpy(&ssp->ssp_addr, &addr->sin, sizeof(struct sockaddr_in));
2840 #endif
2841 break;
2842 #endif
2843 #ifdef INET6
2844 case AF_INET6:
2845 memcpy(&ssp->ssp_addr, &addr->sin6, sizeof(struct sockaddr_in6));
2846 break;
2847 #endif
2848 default:
2849 break;
2850 }
2851 SCTP_TCB_UNLOCK(stcb);
2852 *optsize = sizeof(struct sctp_setprim);
2853 } else {
2854 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2855 error = EINVAL;
2856 }
2857 break;
2858 }
2859 case SCTP_HMAC_IDENT:
2860 {
2861 struct sctp_hmacalgo *shmac;
2862 sctp_hmaclist_t *hmaclist;
2863 size_t size;
2864 int i;
2865
2866 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
2867
2868 SCTP_INP_RLOCK(inp);
2869 hmaclist = inp->sctp_ep.local_hmacs;
2870 if (hmaclist == NULL) {
2871 /* no HMACs to return */
2872 *optsize = sizeof(*shmac);
2873 SCTP_INP_RUNLOCK(inp);
2874 break;
2875 }
2876 /* is there room for all of the hmac ids? */
2877 size = sizeof(*shmac) + (hmaclist->num_algo *
2878 sizeof(shmac->shmac_idents[0]));
2879 if (*optsize < size) {
2880 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2881 error = EINVAL;
2882 SCTP_INP_RUNLOCK(inp);
2883 break;
2884 }
2885 /* copy in the list */
2886 shmac->shmac_number_of_idents = hmaclist->num_algo;
2887 for (i = 0; i < hmaclist->num_algo; i++) {
2888 shmac->shmac_idents[i] = hmaclist->hmac[i];
2889 }
2890 SCTP_INP_RUNLOCK(inp);
2891 *optsize = size;
2892 break;
2893 }
2894 case SCTP_AUTH_ACTIVE_KEY:
2895 {
2896 struct sctp_authkeyid *scact;
2897
2898 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
2899 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
2900
2901 if (stcb) {
2902 /* get the active key on the assoc */
2903 scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
2904 SCTP_TCB_UNLOCK(stcb);
2905 } else {
2906 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2907 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2908 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2909 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC))) {
2910 /* get the endpoint active key */
2911 SCTP_INP_RLOCK(inp);
2912 scact->scact_keynumber = inp->sctp_ep.default_keyid;
2913 SCTP_INP_RUNLOCK(inp);
2914 } else {
2915 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2916 error = EINVAL;
2917 }
2918 }
2919 if (error == 0) {
2920 *optsize = sizeof(struct sctp_authkeyid);
2921 }
2922 break;
2923 }
2924 case SCTP_LOCAL_AUTH_CHUNKS:
2925 {
2926 struct sctp_authchunks *sac;
2927 sctp_auth_chklist_t *chklist = NULL;
2928 size_t size = 0;
2929
2930 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2931 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2932
2933 if (stcb) {
2934 /* get off the assoc */
2935 chklist = stcb->asoc.local_auth_chunks;
2936 /* is there enough space? */
2937 size = sctp_auth_get_chklist_size(chklist);
2938 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2939 error = EINVAL;
2940 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2941 } else {
2942 /* copy in the chunks */
2943 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2944 sac->gauth_number_of_chunks = (uint32_t)size;
2945 *optsize = sizeof(struct sctp_authchunks) + size;
2946 }
2947 SCTP_TCB_UNLOCK(stcb);
2948 } else {
2949 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2950 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2951 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
2952 (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC))) {
2953 /* get off the endpoint */
2954 SCTP_INP_RLOCK(inp);
2955 chklist = inp->sctp_ep.local_auth_chunks;
2956 /* is there enough space? */
2957 size = sctp_auth_get_chklist_size(chklist);
2958 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2959 error = EINVAL;
2960 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2961 } else {
2962 /* copy in the chunks */
2963 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2964 sac->gauth_number_of_chunks = (uint32_t)size;
2965 *optsize = sizeof(struct sctp_authchunks) + size;
2966 }
2967 SCTP_INP_RUNLOCK(inp);
2968 } else {
2969 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2970 error = EINVAL;
2971 }
2972 }
2973 break;
2974 }
2975 case SCTP_PEER_AUTH_CHUNKS:
2976 {
2977 struct sctp_authchunks *sac;
2978 sctp_auth_chklist_t *chklist = NULL;
2979 size_t size = 0;
2980
2981 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2982 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2983
2984 if (stcb) {
2985 /* get off the assoc */
2986 chklist = stcb->asoc.peer_auth_chunks;
2987 /* is there enough space? */
2988 size = sctp_auth_get_chklist_size(chklist);
2989 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2990 error = EINVAL;
2991 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2992 } else {
2993 /* copy in the chunks */
2994 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2995 sac->gauth_number_of_chunks = (uint32_t)size;
2996 *optsize = sizeof(struct sctp_authchunks) + size;
2997 }
2998 SCTP_TCB_UNLOCK(stcb);
2999 } else {
3000 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
3001 error = ENOENT;
3002 }
3003 break;
3004 }
3005 case SCTP_EVENT:
3006 {
3007 struct sctp_event *event;
3008 uint32_t event_type;
3009
3010 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
3011 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
3012
3013 switch (event->se_type) {
3014 case SCTP_ASSOC_CHANGE:
3015 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
3016 break;
3017 case SCTP_PEER_ADDR_CHANGE:
3018 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
3019 break;
3020 case SCTP_REMOTE_ERROR:
3021 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
3022 break;
3023 case SCTP_SEND_FAILED:
3024 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3025 break;
3026 case SCTP_SHUTDOWN_EVENT:
3027 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3028 break;
3029 case SCTP_ADAPTATION_INDICATION:
3030 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
3031 break;
3032 case SCTP_PARTIAL_DELIVERY_EVENT:
3033 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
3034 break;
3035 case SCTP_AUTHENTICATION_EVENT:
3036 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
3037 break;
3038 case SCTP_STREAM_RESET_EVENT:
3039 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3040 break;
3041 case SCTP_SENDER_DRY_EVENT:
3042 event_type = SCTP_PCB_FLAGS_DRYEVNT;
3043 break;
3044 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
3045 event_type = 0;
3046 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
3047 error = ENOTSUP;
3048 break;
3049 case SCTP_ASSOC_RESET_EVENT:
3050 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
3051 break;
3052 case SCTP_STREAM_CHANGE_EVENT:
3053 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
3054 break;
3055 case SCTP_SEND_FAILED_EVENT:
3056 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
3057 break;
3058 default:
3059 event_type = 0;
3060 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3061 error = EINVAL;
3062 break;
3063 }
3064 if (event_type > 0) {
3065 if (stcb) {
3066 event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3067 } else {
3068 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3069 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3070 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3071 (event->se_assoc_id == SCTP_FUTURE_ASSOC))) {
3072 SCTP_INP_RLOCK(inp);
3073 event->se_on = sctp_is_feature_on(inp, event_type);
3074 SCTP_INP_RUNLOCK(inp);
3075 } else {
3076 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3077 error = EINVAL;
3078 }
3079 }
3080 }
3081 if (stcb != NULL) {
3082 SCTP_TCB_UNLOCK(stcb);
3083 }
3084 if (error == 0) {
3085 *optsize = sizeof(struct sctp_event);
3086 }
3087 break;
3088 }
3089 case SCTP_RECVRCVINFO:
3090 if (*optsize < sizeof(int)) {
3091 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3092 error = EINVAL;
3093 } else {
3094 SCTP_INP_RLOCK(inp);
3095 *(int *)optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3096 SCTP_INP_RUNLOCK(inp);
3097 *optsize = sizeof(int);
3098 }
3099 break;
3100 case SCTP_RECVNXTINFO:
3101 if (*optsize < sizeof(int)) {
3102 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3103 error = EINVAL;
3104 } else {
3105 SCTP_INP_RLOCK(inp);
3106 *(int *)optval = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3107 SCTP_INP_RUNLOCK(inp);
3108 *optsize = sizeof(int);
3109 }
3110 break;
3111 case SCTP_DEFAULT_SNDINFO:
3112 {
3113 struct sctp_sndinfo *info;
3114
3115 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3116 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3117
3118 if (stcb) {
3119 info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3120 info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3121 info->snd_flags &= 0xfff0;
3122 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3123 info->snd_context = stcb->asoc.def_send.sinfo_context;
3124 SCTP_TCB_UNLOCK(stcb);
3125 } else {
3126 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3127 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3128 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3129 (info->snd_assoc_id == SCTP_FUTURE_ASSOC))) {
3130 SCTP_INP_RLOCK(inp);
3131 info->snd_sid = inp->def_send.sinfo_stream;
3132 info->snd_flags = inp->def_send.sinfo_flags;
3133 info->snd_flags &= 0xfff0;
3134 info->snd_ppid = inp->def_send.sinfo_ppid;
3135 info->snd_context = inp->def_send.sinfo_context;
3136 SCTP_INP_RUNLOCK(inp);
3137 } else {
3138 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3139 error = EINVAL;
3140 }
3141 }
3142 if (error == 0) {
3143 *optsize = sizeof(struct sctp_sndinfo);
3144 }
3145 break;
3146 }
3147 case SCTP_DEFAULT_PRINFO:
3148 {
3149 struct sctp_default_prinfo *info;
3150
3151 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3152 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3153
3154 if (stcb) {
3155 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3156 info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3157 SCTP_TCB_UNLOCK(stcb);
3158 } else {
3159 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3160 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3161 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3162 (info->pr_assoc_id == SCTP_FUTURE_ASSOC))) {
3163 SCTP_INP_RLOCK(inp);
3164 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3165 info->pr_value = inp->def_send.sinfo_timetolive;
3166 SCTP_INP_RUNLOCK(inp);
3167 } else {
3168 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3169 error = EINVAL;
3170 }
3171 }
3172 if (error == 0) {
3173 *optsize = sizeof(struct sctp_default_prinfo);
3174 }
3175 break;
3176 }
3177 case SCTP_PEER_ADDR_THLDS:
3178 {
3179 struct sctp_paddrthlds *thlds;
3180 struct sctp_nets *net;
3181 struct sockaddr *addr;
3182 #if defined(INET) && defined(INET6)
3183 struct sockaddr_in sin_store;
3184 #endif
3185
3186 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3187 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3188
3189 #if defined(INET) && defined(INET6)
3190 if (thlds->spt_address.ss_family == AF_INET6) {
3191 struct sockaddr_in6 *sin6;
3192
3193 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
3194 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3195 in6_sin6_2_sin(&sin_store, sin6);
3196 addr = (struct sockaddr *)&sin_store;
3197 } else {
3198 addr = (struct sockaddr *)&thlds->spt_address;
3199 }
3200 } else {
3201 addr = (struct sockaddr *)&thlds->spt_address;
3202 }
3203 #else
3204 addr = (struct sockaddr *)&thlds->spt_address;
3205 #endif
3206 if (stcb != NULL) {
3207 net = sctp_findnet(stcb, addr);
3208 } else {
3209 /*
3210 * We increment here since
3211 * sctp_findassociation_ep_addr() wil do a
3212 * decrement if it finds the stcb as long as
3213 * the locked tcb (last argument) is NOT a
3214 * TCB.. aka NULL.
3215 */
3216 net = NULL;
3217 SCTP_INP_INCR_REF(inp);
3218 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3219 if (stcb == NULL) {
3220 SCTP_INP_DECR_REF(inp);
3221 }
3222 }
3223 if ((stcb != NULL) && (net == NULL)) {
3224 #ifdef INET
3225 if (addr->sa_family == AF_INET) {
3226 struct sockaddr_in *sin;
3227
3228 sin = (struct sockaddr_in *)addr;
3229 if (sin->sin_addr.s_addr != INADDR_ANY) {
3230 error = EINVAL;
3231 SCTP_TCB_UNLOCK(stcb);
3232 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3233 break;
3234 }
3235 } else
3236 #endif
3237 #ifdef INET6
3238 if (addr->sa_family == AF_INET6) {
3239 struct sockaddr_in6 *sin6;
3240
3241 sin6 = (struct sockaddr_in6 *)addr;
3242 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3243 error = EINVAL;
3244 SCTP_TCB_UNLOCK(stcb);
3245 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3246 break;
3247 }
3248 } else
3249 #endif
3250 {
3251 error = EAFNOSUPPORT;
3252 SCTP_TCB_UNLOCK(stcb);
3253 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3254 break;
3255 }
3256 }
3257
3258 if (stcb != NULL) {
3259 if (net != NULL) {
3260 thlds->spt_pathmaxrxt = net->failure_threshold;
3261 thlds->spt_pathpfthld = net->pf_threshold;
3262 thlds->spt_pathcpthld = 0xffff;
3263 } else {
3264 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3265 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3266 thlds->spt_pathcpthld = 0xffff;
3267 }
3268 thlds->spt_assoc_id = sctp_get_associd(stcb);
3269 SCTP_TCB_UNLOCK(stcb);
3270 } else {
3271 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3272 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3273 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3274 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
3275 /* Use endpoint defaults */
3276 SCTP_INP_RLOCK(inp);
3277 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3278 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3279 thlds->spt_pathcpthld = 0xffff;
3280 SCTP_INP_RUNLOCK(inp);
3281 } else {
3282 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3283 error = EINVAL;
3284 }
3285 }
3286 if (error == 0) {
3287 *optsize = sizeof(struct sctp_paddrthlds);
3288 }
3289 break;
3290 }
3291 case SCTP_REMOTE_UDP_ENCAPS_PORT:
3292 {
3293 struct sctp_udpencaps *encaps;
3294 struct sctp_nets *net;
3295 struct sockaddr *addr;
3296 #if defined(INET) && defined(INET6)
3297 struct sockaddr_in sin_store;
3298 #endif
3299
3300 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3301 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3302
3303 #if defined(INET) && defined(INET6)
3304 if (encaps->sue_address.ss_family == AF_INET6) {
3305 struct sockaddr_in6 *sin6;
3306
3307 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
3308 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3309 in6_sin6_2_sin(&sin_store, sin6);
3310 addr = (struct sockaddr *)&sin_store;
3311 } else {
3312 addr = (struct sockaddr *)&encaps->sue_address;
3313 }
3314 } else {
3315 addr = (struct sockaddr *)&encaps->sue_address;
3316 }
3317 #else
3318 addr = (struct sockaddr *)&encaps->sue_address;
3319 #endif
3320 if (stcb) {
3321 net = sctp_findnet(stcb, addr);
3322 } else {
3323 /*
3324 * We increment here since
3325 * sctp_findassociation_ep_addr() wil do a
3326 * decrement if it finds the stcb as long as
3327 * the locked tcb (last argument) is NOT a
3328 * TCB.. aka NULL.
3329 */
3330 net = NULL;
3331 SCTP_INP_INCR_REF(inp);
3332 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
3333 if (stcb == NULL) {
3334 SCTP_INP_DECR_REF(inp);
3335 }
3336 }
3337 if ((stcb != NULL) && (net == NULL)) {
3338 #ifdef INET
3339 if (addr->sa_family == AF_INET) {
3340 struct sockaddr_in *sin;
3341
3342 sin = (struct sockaddr_in *)addr;
3343 if (sin->sin_addr.s_addr != INADDR_ANY) {
3344 error = EINVAL;
3345 SCTP_TCB_UNLOCK(stcb);
3346 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3347 break;
3348 }
3349 } else
3350 #endif
3351 #ifdef INET6
3352 if (addr->sa_family == AF_INET6) {
3353 struct sockaddr_in6 *sin6;
3354
3355 sin6 = (struct sockaddr_in6 *)addr;
3356 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3357 error = EINVAL;
3358 SCTP_TCB_UNLOCK(stcb);
3359 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3360 break;
3361 }
3362 } else
3363 #endif
3364 {
3365 error = EAFNOSUPPORT;
3366 SCTP_TCB_UNLOCK(stcb);
3367 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3368 break;
3369 }
3370 }
3371
3372 if (stcb != NULL) {
3373 if (net) {
3374 encaps->sue_port = net->port;
3375 } else {
3376 encaps->sue_port = stcb->asoc.port;
3377 }
3378 SCTP_TCB_UNLOCK(stcb);
3379 } else {
3380 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3381 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3382 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3383 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
3384 SCTP_INP_RLOCK(inp);
3385 encaps->sue_port = inp->sctp_ep.port;
3386 SCTP_INP_RUNLOCK(inp);
3387 } else {
3388 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3389 error = EINVAL;
3390 }
3391 }
3392 if (error == 0) {
3393 *optsize = sizeof(struct sctp_udpencaps);
3394 }
3395 break;
3396 }
3397 case SCTP_ECN_SUPPORTED:
3398 {
3399 struct sctp_assoc_value *av;
3400
3401 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3402 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3403
3404 if (stcb) {
3405 av->assoc_value = stcb->asoc.ecn_supported;
3406 SCTP_TCB_UNLOCK(stcb);
3407 } else {
3408 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3409 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3410 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3411 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3412 SCTP_INP_RLOCK(inp);
3413 av->assoc_value = inp->ecn_supported;
3414 SCTP_INP_RUNLOCK(inp);
3415 } else {
3416 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3417 error = EINVAL;
3418 }
3419 }
3420 if (error == 0) {
3421 *optsize = sizeof(struct sctp_assoc_value);
3422 }
3423 break;
3424 }
3425 case SCTP_PR_SUPPORTED:
3426 {
3427 struct sctp_assoc_value *av;
3428
3429 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3430 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3431
3432 if (stcb) {
3433 av->assoc_value = stcb->asoc.prsctp_supported;
3434 SCTP_TCB_UNLOCK(stcb);
3435 } else {
3436 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3437 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3438 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3439 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3440 SCTP_INP_RLOCK(inp);
3441 av->assoc_value = inp->prsctp_supported;
3442 SCTP_INP_RUNLOCK(inp);
3443 } else {
3444 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3445 error = EINVAL;
3446 }
3447 }
3448 if (error == 0) {
3449 *optsize = sizeof(struct sctp_assoc_value);
3450 }
3451 break;
3452 }
3453 case SCTP_AUTH_SUPPORTED:
3454 {
3455 struct sctp_assoc_value *av;
3456
3457 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3458 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3459
3460 if (stcb) {
3461 av->assoc_value = stcb->asoc.auth_supported;
3462 SCTP_TCB_UNLOCK(stcb);
3463 } else {
3464 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3465 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3466 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3467 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3468 SCTP_INP_RLOCK(inp);
3469 av->assoc_value = inp->auth_supported;
3470 SCTP_INP_RUNLOCK(inp);
3471 } else {
3472 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3473 error = EINVAL;
3474 }
3475 }
3476 if (error == 0) {
3477 *optsize = sizeof(struct sctp_assoc_value);
3478 }
3479 break;
3480 }
3481 case SCTP_ASCONF_SUPPORTED:
3482 {
3483 struct sctp_assoc_value *av;
3484
3485 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3486 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3487
3488 if (stcb) {
3489 av->assoc_value = stcb->asoc.asconf_supported;
3490 SCTP_TCB_UNLOCK(stcb);
3491 } else {
3492 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3493 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3494 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3495 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3496 SCTP_INP_RLOCK(inp);
3497 av->assoc_value = inp->asconf_supported;
3498 SCTP_INP_RUNLOCK(inp);
3499 } else {
3500 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3501 error = EINVAL;
3502 }
3503 }
3504 if (error == 0) {
3505 *optsize = sizeof(struct sctp_assoc_value);
3506 }
3507 break;
3508 }
3509 case SCTP_RECONFIG_SUPPORTED:
3510 {
3511 struct sctp_assoc_value *av;
3512
3513 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3514 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3515
3516 if (stcb) {
3517 av->assoc_value = stcb->asoc.reconfig_supported;
3518 SCTP_TCB_UNLOCK(stcb);
3519 } else {
3520 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3521 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3522 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3523 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3524 SCTP_INP_RLOCK(inp);
3525 av->assoc_value = inp->reconfig_supported;
3526 SCTP_INP_RUNLOCK(inp);
3527 } else {
3528 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3529 error = EINVAL;
3530 }
3531 }
3532 if (error == 0) {
3533 *optsize = sizeof(struct sctp_assoc_value);
3534 }
3535 break;
3536 }
3537 case SCTP_NRSACK_SUPPORTED:
3538 {
3539 struct sctp_assoc_value *av;
3540
3541 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3542 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3543
3544 if (stcb) {
3545 av->assoc_value = stcb->asoc.nrsack_supported;
3546 SCTP_TCB_UNLOCK(stcb);
3547 } else {
3548 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3549 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3550 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3551 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3552 SCTP_INP_RLOCK(inp);
3553 av->assoc_value = inp->nrsack_supported;
3554 SCTP_INP_RUNLOCK(inp);
3555 } else {
3556 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3557 error = EINVAL;
3558 }
3559 }
3560 if (error == 0) {
3561 *optsize = sizeof(struct sctp_assoc_value);
3562 }
3563 break;
3564 }
3565 case SCTP_PKTDROP_SUPPORTED:
3566 {
3567 struct sctp_assoc_value *av;
3568
3569 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3570 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3571
3572 if (stcb) {
3573 av->assoc_value = stcb->asoc.pktdrop_supported;
3574 SCTP_TCB_UNLOCK(stcb);
3575 } else {
3576 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3577 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3578 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3579 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3580 SCTP_INP_RLOCK(inp);
3581 av->assoc_value = inp->pktdrop_supported;
3582 SCTP_INP_RUNLOCK(inp);
3583 } else {
3584 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3585 error = EINVAL;
3586 }
3587 }
3588 if (error == 0) {
3589 *optsize = sizeof(struct sctp_assoc_value);
3590 }
3591 break;
3592 }
3593 case SCTP_ENABLE_STREAM_RESET:
3594 {
3595 struct sctp_assoc_value *av;
3596
3597 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3598 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3599
3600 if (stcb) {
3601 av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support;
3602 SCTP_TCB_UNLOCK(stcb);
3603 } else {
3604 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3605 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3606 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3607 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3608 SCTP_INP_RLOCK(inp);
3609 av->assoc_value = (uint32_t)inp->local_strreset_support;
3610 SCTP_INP_RUNLOCK(inp);
3611 } else {
3612 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3613 error = EINVAL;
3614 }
3615 }
3616 if (error == 0) {
3617 *optsize = sizeof(struct sctp_assoc_value);
3618 }
3619 break;
3620 }
3621 case SCTP_PR_STREAM_STATUS:
3622 {
3623 struct sctp_prstatus *sprstat;
3624 uint16_t sid;
3625 uint16_t policy;
3626
3627 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3628 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3629
3630 sid = sprstat->sprstat_sid;
3631 policy = sprstat->sprstat_policy;
3632 #if defined(SCTP_DETAILED_STR_STATS)
3633 if ((stcb != NULL) &&
3634 (sid < stcb->asoc.streamoutcnt) &&
3635 (policy != SCTP_PR_SCTP_NONE) &&
3636 ((policy <= SCTP_PR_SCTP_MAX) ||
3637 (policy == SCTP_PR_SCTP_ALL))) {
3638 if (policy == SCTP_PR_SCTP_ALL) {
3639 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
3640 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
3641 } else {
3642 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
3643 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
3644 }
3645 #else
3646 if ((stcb != NULL) &&
3647 (sid < stcb->asoc.streamoutcnt) &&
3648 (policy == SCTP_PR_SCTP_ALL)) {
3649 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
3650 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
3651 #endif
3652 } else {
3653 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3654 error = EINVAL;
3655 }
3656 if (stcb != NULL) {
3657 SCTP_TCB_UNLOCK(stcb);
3658 }
3659 if (error == 0) {
3660 *optsize = sizeof(struct sctp_prstatus);
3661 }
3662 break;
3663 }
3664 case SCTP_PR_ASSOC_STATUS:
3665 {
3666 struct sctp_prstatus *sprstat;
3667 uint16_t policy;
3668
3669 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3670 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3671
3672 policy = sprstat->sprstat_policy;
3673 if ((stcb != NULL) &&
3674 (policy != SCTP_PR_SCTP_NONE) &&
3675 ((policy <= SCTP_PR_SCTP_MAX) ||
3676 (policy == SCTP_PR_SCTP_ALL))) {
3677 if (policy == SCTP_PR_SCTP_ALL) {
3678 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
3679 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
3680 } else {
3681 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
3682 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
3683 }
3684 } else {
3685 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3686 error = EINVAL;
3687 }
3688 if (stcb != NULL) {
3689 SCTP_TCB_UNLOCK(stcb);
3690 }
3691 if (error == 0) {
3692 *optsize = sizeof(struct sctp_prstatus);
3693 }
3694 break;
3695 }
3696 case SCTP_MAX_CWND:
3697 {
3698 struct sctp_assoc_value *av;
3699
3700 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3701 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3702
3703 if (stcb) {
3704 av->assoc_value = stcb->asoc.max_cwnd;
3705 SCTP_TCB_UNLOCK(stcb);
3706 } else {
3707 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3708 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3709 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3710 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3711 SCTP_INP_RLOCK(inp);
3712 av->assoc_value = inp->max_cwnd;
3713 SCTP_INP_RUNLOCK(inp);
3714 } else {
3715 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3716 error = EINVAL;
3717 }
3718 }
3719 if (error == 0) {
3720 *optsize = sizeof(struct sctp_assoc_value);
3721 }
3722 break;
3723 }
3724 default:
3725 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3726 error = ENOPROTOOPT;
3727 break;
3728 } /* end switch (sopt->sopt_name) */
3729 if (error) {
3730 *optsize = 0;
3731 }
3732 return (error);
3733 }
3734
3735 static int
3736 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3737 void *p)
3738 {
3739 int error, set_opt;
3740 uint32_t *mopt;
3741 struct sctp_tcb *stcb = NULL;
3742 struct sctp_inpcb *inp = NULL;
3743 uint32_t vrf_id;
3744
3745 if (optval == NULL) {
3746 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3747 return (EINVAL);
3748 }
3749 inp = (struct sctp_inpcb *)so->so_pcb;
3750 if (inp == NULL) {
3751 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3752 return (EINVAL);
3753 }
3754 vrf_id = inp->def_vrf_id;
3755
3756 error = 0;
3757 switch (optname) {
3758 case SCTP_NODELAY:
3759 case SCTP_AUTOCLOSE:
3760 case SCTP_AUTO_ASCONF:
3761 case SCTP_EXPLICIT_EOR:
3762 case SCTP_DISABLE_FRAGMENTS:
3763 case SCTP_USE_EXT_RCVINFO:
3764 case SCTP_I_WANT_MAPPED_V4_ADDR:
3765 /* copy in the option value */
3766 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3767 set_opt = 0;
3768 if (error)
3769 break;
3770 switch (optname) {
3771 case SCTP_DISABLE_FRAGMENTS:
3772 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3773 break;
3774 case SCTP_AUTO_ASCONF:
3775 /*
3776 * NOTE: we don't really support this flag
3777 */
3778 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3779 /* only valid for bound all sockets */
3780 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3781 (*mopt != 0)) {
3782 /* forbidden by admin */
3783 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3784 return (EPERM);
3785 }
3786 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3787 } else {
3788 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3789 return (EINVAL);
3790 }
3791 break;
3792 case SCTP_EXPLICIT_EOR:
3793 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3794 break;
3795 case SCTP_USE_EXT_RCVINFO:
3796 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3797 break;
3798 case SCTP_I_WANT_MAPPED_V4_ADDR:
3799 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3800 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3801 } else {
3802 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3803 return (EINVAL);
3804 }
3805 break;
3806 case SCTP_NODELAY:
3807 set_opt = SCTP_PCB_FLAGS_NODELAY;
3808 break;
3809 case SCTP_AUTOCLOSE:
3810 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3811 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3812 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3813 return (EINVAL);
3814 }
3815 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3816 /*
3817 * The value is in ticks. Note this does not effect
3818 * old associations, only new ones.
3819 */
3820 inp->sctp_ep.auto_close_time = sctp_secs_to_ticks(*mopt);
3821 break;
3822 }
3823 SCTP_INP_WLOCK(inp);
3824 if (*mopt != 0) {
3825 sctp_feature_on(inp, set_opt);
3826 } else {
3827 sctp_feature_off(inp, set_opt);
3828 }
3829 SCTP_INP_WUNLOCK(inp);
3830 break;
3831 case SCTP_REUSE_PORT:
3832 {
3833 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3834 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3835 /* Can't set it after we are bound */
3836 error = EINVAL;
3837 break;
3838 }
3839 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3840 /* Can't do this for a 1-m socket */
3841 error = EINVAL;
3842 break;
3843 }
3844 if (optval)
3845 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3846 else
3847 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3848 break;
3849 }
3850 case SCTP_PARTIAL_DELIVERY_POINT:
3851 {
3852 uint32_t *value;
3853
3854 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3855 if (*value > SCTP_SB_LIMIT_RCV(so)) {
3856 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3857 error = EINVAL;
3858 break;
3859 }
3860 inp->partial_delivery_point = *value;
3861 break;
3862 }
3863 case SCTP_FRAGMENT_INTERLEAVE:
3864 /* not yet until we re-write sctp_recvmsg() */
3865 {
3866 uint32_t *level;
3867
3868 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3869 if (*level == SCTP_FRAG_LEVEL_2) {
3870 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3871 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3872 } else if (*level == SCTP_FRAG_LEVEL_1) {
3873 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3874 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3875 } else if (*level == SCTP_FRAG_LEVEL_0) {
3876 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3877 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3878
3879 } else {
3880 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3881 error = EINVAL;
3882 }
3883 break;
3884 }
3885 case SCTP_INTERLEAVING_SUPPORTED:
3886 {
3887 struct sctp_assoc_value *av;
3888
3889 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3890 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3891
3892 if (stcb) {
3893 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3894 error = EINVAL;
3895 SCTP_TCB_UNLOCK(stcb);
3896 } else {
3897 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3898 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3899 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3900 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
3901 SCTP_INP_WLOCK(inp);
3902 if (av->assoc_value == 0) {
3903 inp->idata_supported = 0;
3904 } else {
3905 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) &&
3906 (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) {
3907 inp->idata_supported = 1;
3908 } else {
3909 /*
3910 * Must have Frag
3911 * interleave and
3912 * stream interleave
3913 * on
3914 */
3915 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3916 error = EINVAL;
3917 }
3918 }
3919 SCTP_INP_WUNLOCK(inp);
3920 } else {
3921 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3922 error = EINVAL;
3923 }
3924 }
3925 break;
3926 }
3927 case SCTP_CMT_ON_OFF:
3928 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3929 struct sctp_assoc_value *av;
3930
3931 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3932 if (av->assoc_value > SCTP_CMT_MAX) {
3933 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3934 error = EINVAL;
3935 break;
3936 }
3937 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3938 if (stcb) {
3939 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3940 SCTP_TCB_UNLOCK(stcb);
3941 } else {
3942 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3943 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3944 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3945 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3946 (av->assoc_id == SCTP_ALL_ASSOC)))) {
3947 SCTP_INP_WLOCK(inp);
3948 inp->sctp_cmt_on_off = av->assoc_value;
3949 SCTP_INP_WUNLOCK(inp);
3950 }
3951 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3952 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3953 (av->assoc_id == SCTP_ALL_ASSOC))) {
3954 SCTP_INP_RLOCK(inp);
3955 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3956 SCTP_TCB_LOCK(stcb);
3957 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3958 SCTP_TCB_UNLOCK(stcb);
3959 }
3960 SCTP_INP_RUNLOCK(inp);
3961 }
3962 }
3963 } else {
3964 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3965 error = ENOPROTOOPT;
3966 }
3967 break;
3968 case SCTP_PLUGGABLE_CC:
3969 {
3970 struct sctp_assoc_value *av;
3971 struct sctp_nets *net;
3972
3973 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3974 if ((av->assoc_value != SCTP_CC_RFC2581) &&
3975 (av->assoc_value != SCTP_CC_HSTCP) &&
3976 (av->assoc_value != SCTP_CC_HTCP) &&
3977 (av->assoc_value != SCTP_CC_RTCC)) {
3978 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3979 error = EINVAL;
3980 break;
3981 }
3982 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3983 if (stcb) {
3984 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3985 stcb->asoc.congestion_control_module = av->assoc_value;
3986 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3987 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3988 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3989 }
3990 }
3991 SCTP_TCB_UNLOCK(stcb);
3992 } else {
3993 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3994 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3995 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
3996 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
3997 (av->assoc_id == SCTP_ALL_ASSOC)))) {
3998 SCTP_INP_WLOCK(inp);
3999 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
4000 SCTP_INP_WUNLOCK(inp);
4001 }
4002 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4003 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4004 (av->assoc_id == SCTP_ALL_ASSOC))) {
4005 SCTP_INP_RLOCK(inp);
4006 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4007 SCTP_TCB_LOCK(stcb);
4008 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
4009 stcb->asoc.congestion_control_module = av->assoc_value;
4010 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
4011 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4012 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
4013 }
4014 }
4015 SCTP_TCB_UNLOCK(stcb);
4016 }
4017 SCTP_INP_RUNLOCK(inp);
4018 }
4019 }
4020 break;
4021 }
4022 case SCTP_CC_OPTION:
4023 {
4024 struct sctp_cc_option *cc_opt;
4025
4026 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
4027 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
4028 if (stcb == NULL) {
4029 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4030 (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC)) {
4031 SCTP_INP_RLOCK(inp);
4032 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4033 SCTP_TCB_LOCK(stcb);
4034 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
4035 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
4036 }
4037 SCTP_TCB_UNLOCK(stcb);
4038 }
4039 SCTP_INP_RUNLOCK(inp);
4040 } else {
4041 error = EINVAL;
4042 }
4043 } else {
4044 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
4045 error = ENOTSUP;
4046 } else {
4047 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
4048 cc_opt);
4049 }
4050 SCTP_TCB_UNLOCK(stcb);
4051 }
4052 break;
4053 }
4054 case SCTP_STREAM_SCHEDULER:
4055 {
4056 struct sctp_assoc_value *av;
4057
4058 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4059 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
4060 (av->assoc_value != SCTP_SS_RR) &&
4061 (av->assoc_value != SCTP_SS_RR_PKT) &&
4062 (av->assoc_value != SCTP_SS_PRIO) &&
4063 (av->assoc_value != SCTP_SS_FB) &&
4064 (av->assoc_value != SCTP_SS_FCFS)) {
4065 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4066 error = EINVAL;
4067 break;
4068 }
4069 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4070 if (stcb) {
4071 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
4072 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4073 stcb->asoc.stream_scheduling_module = av->assoc_value;
4074 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
4075 SCTP_TCB_UNLOCK(stcb);
4076 } else {
4077 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4078 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4079 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4080 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4081 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4082 SCTP_INP_WLOCK(inp);
4083 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
4084 SCTP_INP_WUNLOCK(inp);
4085 }
4086 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4087 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4088 (av->assoc_id == SCTP_ALL_ASSOC))) {
4089 SCTP_INP_RLOCK(inp);
4090 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4091 SCTP_TCB_LOCK(stcb);
4092 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, true);
4093 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
4094 stcb->asoc.stream_scheduling_module = av->assoc_value;
4095 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc);
4096 SCTP_TCB_UNLOCK(stcb);
4097 }
4098 SCTP_INP_RUNLOCK(inp);
4099 }
4100 }
4101 break;
4102 }
4103 case SCTP_STREAM_SCHEDULER_VALUE:
4104 {
4105 struct sctp_stream_value *av;
4106
4107 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
4108 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4109 if (stcb) {
4110 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
4111 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
4112 av->stream_value) < 0)) {
4113 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4114 error = EINVAL;
4115 }
4116 SCTP_TCB_UNLOCK(stcb);
4117 } else {
4118 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4119 (av->assoc_id == SCTP_CURRENT_ASSOC)) {
4120 SCTP_INP_RLOCK(inp);
4121 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4122 SCTP_TCB_LOCK(stcb);
4123 if (av->stream_id < stcb->asoc.streamoutcnt) {
4124 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
4125 &stcb->asoc,
4126 &stcb->asoc.strmout[av->stream_id],
4127 av->stream_value);
4128 }
4129 SCTP_TCB_UNLOCK(stcb);
4130 }
4131 SCTP_INP_RUNLOCK(inp);
4132 } else {
4133 /*
4134 * Can't set stream value without
4135 * association
4136 */
4137 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4138 error = EINVAL;
4139 }
4140 }
4141 break;
4142 }
4143 case SCTP_CLR_STAT_LOG:
4144 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4145 error = EOPNOTSUPP;
4146 break;
4147 case SCTP_CONTEXT:
4148 {
4149 struct sctp_assoc_value *av;
4150
4151 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4152 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4153
4154 if (stcb) {
4155 stcb->asoc.context = av->assoc_value;
4156 SCTP_TCB_UNLOCK(stcb);
4157 } else {
4158 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4159 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4160 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4161 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4162 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4163 SCTP_INP_WLOCK(inp);
4164 inp->sctp_context = av->assoc_value;
4165 SCTP_INP_WUNLOCK(inp);
4166 }
4167 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4168 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4169 (av->assoc_id == SCTP_ALL_ASSOC))) {
4170 SCTP_INP_RLOCK(inp);
4171 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4172 SCTP_TCB_LOCK(stcb);
4173 stcb->asoc.context = av->assoc_value;
4174 SCTP_TCB_UNLOCK(stcb);
4175 }
4176 SCTP_INP_RUNLOCK(inp);
4177 }
4178 }
4179 break;
4180 }
4181 case SCTP_VRF_ID:
4182 {
4183 uint32_t *default_vrfid;
4184
4185 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
4186 if (*default_vrfid > SCTP_MAX_VRF_ID) {
4187 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4188 error = EINVAL;
4189 break;
4190 }
4191 inp->def_vrf_id = *default_vrfid;
4192 break;
4193 }
4194 case SCTP_DEL_VRF_ID:
4195 {
4196 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4197 error = EOPNOTSUPP;
4198 break;
4199 }
4200 case SCTP_ADD_VRF_ID:
4201 {
4202 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4203 error = EOPNOTSUPP;
4204 break;
4205 }
4206 case SCTP_DELAYED_SACK:
4207 {
4208 struct sctp_sack_info *sack;
4209
4210 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
4211 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
4212 if (sack->sack_delay) {
4213 if (sack->sack_delay > SCTP_MAX_SACK_DELAY) {
4214 error = EINVAL;
4215 if (stcb != NULL) {
4216 SCTP_TCB_UNLOCK(stcb);
4217 }
4218 break;
4219 }
4220 }
4221 if (stcb) {
4222 if (sack->sack_delay) {
4223 stcb->asoc.delayed_ack = sack->sack_delay;
4224 }
4225 if (sack->sack_freq) {
4226 stcb->asoc.sack_freq = sack->sack_freq;
4227 }
4228 SCTP_TCB_UNLOCK(stcb);
4229 } else {
4230 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4231 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4232 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4233 ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
4234 (sack->sack_assoc_id == SCTP_ALL_ASSOC)))) {
4235 SCTP_INP_WLOCK(inp);
4236 if (sack->sack_delay) {
4237 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = sctp_msecs_to_ticks(sack->sack_delay);
4238 }
4239 if (sack->sack_freq) {
4240 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
4241 }
4242 SCTP_INP_WUNLOCK(inp);
4243 }
4244 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4245 ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
4246 (sack->sack_assoc_id == SCTP_ALL_ASSOC))) {
4247 SCTP_INP_RLOCK(inp);
4248 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4249 SCTP_TCB_LOCK(stcb);
4250 if (sack->sack_delay) {
4251 stcb->asoc.delayed_ack = sack->sack_delay;
4252 }
4253 if (sack->sack_freq) {
4254 stcb->asoc.sack_freq = sack->sack_freq;
4255 }
4256 SCTP_TCB_UNLOCK(stcb);
4257 }
4258 SCTP_INP_RUNLOCK(inp);
4259 }
4260 }
4261 break;
4262 }
4263 case SCTP_AUTH_CHUNK:
4264 {
4265 struct sctp_authchunk *sauth;
4266
4267 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4268
4269 SCTP_INP_WLOCK(inp);
4270 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4271 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4272 error = EINVAL;
4273 } else {
4274 inp->auth_supported = 1;
4275 }
4276 SCTP_INP_WUNLOCK(inp);
4277 break;
4278 }
4279 case SCTP_AUTH_KEY:
4280 {
4281 struct sctp_authkey *sca;
4282 struct sctp_keyhead *shared_keys;
4283 sctp_sharedkey_t *shared_key;
4284 sctp_key_t *key = NULL;
4285 size_t size;
4286
4287 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4288 if (sca->sca_keylength == 0) {
4289 size = optsize - sizeof(struct sctp_authkey);
4290 } else {
4291 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4292 size = sca->sca_keylength;
4293 } else {
4294 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4295 error = EINVAL;
4296 break;
4297 }
4298 }
4299 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4300
4301 if (stcb) {
4302 shared_keys = &stcb->asoc.shared_keys;
4303 /* clear the cached keys for this key id */
4304 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4305 /*
4306 * create the new shared key and
4307 * insert/replace it
4308 */
4309 if (size > 0) {
4310 key = sctp_set_key(sca->sca_key, (uint32_t)size);
4311 if (key == NULL) {
4312 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4313 error = ENOMEM;
4314 SCTP_TCB_UNLOCK(stcb);
4315 break;
4316 }
4317 }
4318 shared_key = sctp_alloc_sharedkey();
4319 if (shared_key == NULL) {
4320 sctp_free_key(key);
4321 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4322 error = ENOMEM;
4323 SCTP_TCB_UNLOCK(stcb);
4324 break;
4325 }
4326 shared_key->key = key;
4327 shared_key->keyid = sca->sca_keynumber;
4328 error = sctp_insert_sharedkey(shared_keys, shared_key);
4329 SCTP_TCB_UNLOCK(stcb);
4330 } else {
4331 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4332 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4333 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4334 ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4335 (sca->sca_assoc_id == SCTP_ALL_ASSOC)))) {
4336 SCTP_INP_WLOCK(inp);
4337 shared_keys = &inp->sctp_ep.shared_keys;
4338 /*
4339 * clear the cached keys on all
4340 * assocs for this key id
4341 */
4342 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4343 /*
4344 * create the new shared key and
4345 * insert/replace it
4346 */
4347 if (size > 0) {
4348 key = sctp_set_key(sca->sca_key, (uint32_t)size);
4349 if (key == NULL) {
4350 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4351 error = ENOMEM;
4352 SCTP_INP_WUNLOCK(inp);
4353 break;
4354 }
4355 }
4356 shared_key = sctp_alloc_sharedkey();
4357 if (shared_key == NULL) {
4358 sctp_free_key(key);
4359 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4360 error = ENOMEM;
4361 SCTP_INP_WUNLOCK(inp);
4362 break;
4363 }
4364 shared_key->key = key;
4365 shared_key->keyid = sca->sca_keynumber;
4366 error = sctp_insert_sharedkey(shared_keys, shared_key);
4367 SCTP_INP_WUNLOCK(inp);
4368 }
4369 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4370 ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4371 (sca->sca_assoc_id == SCTP_ALL_ASSOC))) {
4372 SCTP_INP_RLOCK(inp);
4373 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4374 SCTP_TCB_LOCK(stcb);
4375 shared_keys = &stcb->asoc.shared_keys;
4376 /*
4377 * clear the cached keys for
4378 * this key id
4379 */
4380 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4381 /*
4382 * create the new shared key
4383 * and insert/replace it
4384 */
4385 if (size > 0) {
4386 key = sctp_set_key(sca->sca_key, (uint32_t)size);
4387 if (key == NULL) {
4388 SCTP_TCB_UNLOCK(stcb);
4389 continue;
4390 }
4391 }
4392 shared_key = sctp_alloc_sharedkey();
4393 if (shared_key == NULL) {
4394 sctp_free_key(key);
4395 SCTP_TCB_UNLOCK(stcb);
4396 continue;
4397 }
4398 shared_key->key = key;
4399 shared_key->keyid = sca->sca_keynumber;
4400 error = sctp_insert_sharedkey(shared_keys, shared_key);
4401 SCTP_TCB_UNLOCK(stcb);
4402 }
4403 SCTP_INP_RUNLOCK(inp);
4404 }
4405 }
4406 break;
4407 }
4408 case SCTP_HMAC_IDENT:
4409 {
4410 struct sctp_hmacalgo *shmac;
4411 sctp_hmaclist_t *hmaclist;
4412 uint16_t hmacid;
4413 uint32_t i;
4414
4415 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4416 if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) ||
4417 (shmac->shmac_number_of_idents > 0xffff)) {
4418 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4419 error = EINVAL;
4420 break;
4421 }
4422
4423 hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents);
4424 if (hmaclist == NULL) {
4425 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4426 error = ENOMEM;
4427 break;
4428 }
4429 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4430 hmacid = shmac->shmac_idents[i];
4431 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4432 /* invalid HMACs were found */ ;
4433 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4434 error = EINVAL;
4435 sctp_free_hmaclist(hmaclist);
4436 goto sctp_set_hmac_done;
4437 }
4438 }
4439 for (i = 0; i < hmaclist->num_algo; i++) {
4440 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4441 /* already in list */
4442 break;
4443 }
4444 }
4445 if (i == hmaclist->num_algo) {
4446 /* not found in list */
4447 sctp_free_hmaclist(hmaclist);
4448 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4449 error = EINVAL;
4450 break;
4451 }
4452 /* set it on the endpoint */
4453 SCTP_INP_WLOCK(inp);
4454 if (inp->sctp_ep.local_hmacs)
4455 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4456 inp->sctp_ep.local_hmacs = hmaclist;
4457 SCTP_INP_WUNLOCK(inp);
4458 sctp_set_hmac_done:
4459 break;
4460 }
4461 case SCTP_AUTH_ACTIVE_KEY:
4462 {
4463 struct sctp_authkeyid *scact;
4464
4465 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4466 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4467
4468 /* set the active key on the right place */
4469 if (stcb) {
4470 /* set the active key on the assoc */
4471 if (sctp_auth_setactivekey(stcb,
4472 scact->scact_keynumber)) {
4473 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4474 SCTP_FROM_SCTP_USRREQ,
4475 EINVAL);
4476 error = EINVAL;
4477 }
4478 SCTP_TCB_UNLOCK(stcb);
4479 } else {
4480 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4481 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4482 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4483 ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4484 (scact->scact_assoc_id == SCTP_ALL_ASSOC)))) {
4485 SCTP_INP_WLOCK(inp);
4486 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4487 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4488 error = EINVAL;
4489 }
4490 SCTP_INP_WUNLOCK(inp);
4491 }
4492 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4493 ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4494 (scact->scact_assoc_id == SCTP_ALL_ASSOC))) {
4495 SCTP_INP_RLOCK(inp);
4496 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4497 SCTP_TCB_LOCK(stcb);
4498 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4499 SCTP_TCB_UNLOCK(stcb);
4500 }
4501 SCTP_INP_RUNLOCK(inp);
4502 }
4503 }
4504 break;
4505 }
4506 case SCTP_AUTH_DELETE_KEY:
4507 {
4508 struct sctp_authkeyid *scdel;
4509
4510 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4511 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4512
4513 /* delete the key from the right place */
4514 if (stcb) {
4515 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4516 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4517 error = EINVAL;
4518 }
4519 SCTP_TCB_UNLOCK(stcb);
4520 } else {
4521 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4522 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4523 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4524 ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4525 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)))) {
4526 SCTP_INP_WLOCK(inp);
4527 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4528 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4529 error = EINVAL;
4530 }
4531 SCTP_INP_WUNLOCK(inp);
4532 }
4533 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4534 ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4535 (scdel->scact_assoc_id == SCTP_ALL_ASSOC))) {
4536 SCTP_INP_RLOCK(inp);
4537 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4538 SCTP_TCB_LOCK(stcb);
4539 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4540 SCTP_TCB_UNLOCK(stcb);
4541 }
4542 SCTP_INP_RUNLOCK(inp);
4543 }
4544 }
4545 break;
4546 }
4547 case SCTP_AUTH_DEACTIVATE_KEY:
4548 {
4549 struct sctp_authkeyid *keyid;
4550
4551 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4552 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4553
4554 /* deactivate the key from the right place */
4555 if (stcb) {
4556 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4557 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4558 error = EINVAL;
4559 }
4560 SCTP_TCB_UNLOCK(stcb);
4561 } else {
4562 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4563 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4564 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4565 ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4566 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)))) {
4567 SCTP_INP_WLOCK(inp);
4568 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4569 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4570 error = EINVAL;
4571 }
4572 SCTP_INP_WUNLOCK(inp);
4573 }
4574 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4575 ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4576 (keyid->scact_assoc_id == SCTP_ALL_ASSOC))) {
4577 SCTP_INP_RLOCK(inp);
4578 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4579 SCTP_TCB_LOCK(stcb);
4580 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4581 SCTP_TCB_UNLOCK(stcb);
4582 }
4583 SCTP_INP_RUNLOCK(inp);
4584 }
4585 }
4586 break;
4587 }
4588 case SCTP_ENABLE_STREAM_RESET:
4589 {
4590 struct sctp_assoc_value *av;
4591
4592 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4593 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4594 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4595 error = EINVAL;
4596 break;
4597 }
4598 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4599 if (stcb) {
4600 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4601 SCTP_TCB_UNLOCK(stcb);
4602 } else {
4603 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4604 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4605 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4606 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4607 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4608 SCTP_INP_WLOCK(inp);
4609 inp->local_strreset_support = (uint8_t)av->assoc_value;
4610 SCTP_INP_WUNLOCK(inp);
4611 }
4612 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4613 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4614 (av->assoc_id == SCTP_ALL_ASSOC))) {
4615 SCTP_INP_RLOCK(inp);
4616 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4617 SCTP_TCB_LOCK(stcb);
4618 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value;
4619 SCTP_TCB_UNLOCK(stcb);
4620 }
4621 SCTP_INP_RUNLOCK(inp);
4622 }
4623 }
4624 break;
4625 }
4626 case SCTP_RESET_STREAMS:
4627 {
4628 struct sctp_reset_streams *strrst;
4629 int i, send_out = 0;
4630 int send_in = 0;
4631
4632 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4633 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4634 if (stcb == NULL) {
4635 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4636 error = ENOENT;
4637 break;
4638 }
4639 if (stcb->asoc.reconfig_supported == 0) {
4640 /*
4641 * Peer does not support the chunk type.
4642 */
4643 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4644 error = EOPNOTSUPP;
4645 SCTP_TCB_UNLOCK(stcb);
4646 break;
4647 }
4648 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
4649 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4650 error = EINVAL;
4651 SCTP_TCB_UNLOCK(stcb);
4652 break;
4653 }
4654 if (sizeof(struct sctp_reset_streams) +
4655 strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
4656 error = EINVAL;
4657 SCTP_TCB_UNLOCK(stcb);
4658 break;
4659 }
4660 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4661 send_in = 1;
4662 if (stcb->asoc.stream_reset_outstanding) {
4663 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4664 error = EALREADY;
4665 SCTP_TCB_UNLOCK(stcb);
4666 break;
4667 }
4668 }
4669 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4670 send_out = 1;
4671 }
4672 if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) {
4673 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4674 error = ENOMEM;
4675 SCTP_TCB_UNLOCK(stcb);
4676 break;
4677 }
4678 if ((send_in == 0) && (send_out == 0)) {
4679 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4680 error = EINVAL;
4681 SCTP_TCB_UNLOCK(stcb);
4682 break;
4683 }
4684 for (i = 0; i < strrst->srs_number_streams; i++) {
4685 if ((send_in) &&
4686 (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) {
4687 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4688 error = EINVAL;
4689 break;
4690 }
4691 if ((send_out) &&
4692 (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) {
4693 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4694 error = EINVAL;
4695 break;
4696 }
4697 }
4698 if (error) {
4699 SCTP_TCB_UNLOCK(stcb);
4700 break;
4701 }
4702 if (send_out) {
4703 int cnt;
4704 uint16_t strm;
4705
4706 if (strrst->srs_number_streams) {
4707 for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
4708 strm = strrst->srs_stream_list[i];
4709 if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
4710 stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
4711 cnt++;
4712 }
4713 }
4714 } else {
4715 /* Its all */
4716 for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
4717 if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
4718 stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
4719 cnt++;
4720 }
4721 }
4722 }
4723 }
4724 if (send_in) {
4725 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4726 strrst->srs_stream_list,
4727 send_in, 0, 0, 0, 0, 0);
4728 } else {
4729 error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
4730 }
4731 if (error == 0) {
4732 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4733 } else {
4734 /*
4735 * For outgoing streams don't report any
4736 * problems in sending the request to the
4737 * application. XXX: Double check resetting
4738 * incoming streams.
4739 */
4740 error = 0;
4741 }
4742 SCTP_TCB_UNLOCK(stcb);
4743 break;
4744 }
4745 case SCTP_ADD_STREAMS:
4746 {
4747 struct sctp_add_streams *stradd;
4748 uint8_t addstream = 0;
4749 uint16_t add_o_strmcnt = 0;
4750 uint16_t add_i_strmcnt = 0;
4751
4752 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4753 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4754 if (stcb == NULL) {
4755 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4756 error = ENOENT;
4757 break;
4758 }
4759 if (stcb->asoc.reconfig_supported == 0) {
4760 /*
4761 * Peer does not support the chunk type.
4762 */
4763 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4764 error = EOPNOTSUPP;
4765 SCTP_TCB_UNLOCK(stcb);
4766 break;
4767 }
4768 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
4769 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4770 error = EINVAL;
4771 SCTP_TCB_UNLOCK(stcb);
4772 break;
4773 }
4774 if (stcb->asoc.stream_reset_outstanding) {
4775 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4776 error = EALREADY;
4777 SCTP_TCB_UNLOCK(stcb);
4778 break;
4779 }
4780 if ((stradd->sas_outstrms == 0) &&
4781 (stradd->sas_instrms == 0)) {
4782 error = EINVAL;
4783 goto skip_stuff;
4784 }
4785 if (stradd->sas_outstrms) {
4786 addstream = 1;
4787 /* We allocate here */
4788 add_o_strmcnt = stradd->sas_outstrms;
4789 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4790 /* You can't have more than 64k */
4791 error = EINVAL;
4792 goto skip_stuff;
4793 }
4794 }
4795 if (stradd->sas_instrms) {
4796 int cnt;
4797
4798 addstream |= 2;
4799 /*
4800 * We allocate inside
4801 * sctp_send_str_reset_req()
4802 */
4803 add_i_strmcnt = stradd->sas_instrms;
4804 cnt = add_i_strmcnt;
4805 cnt += stcb->asoc.streamincnt;
4806 if (cnt > 0x0000ffff) {
4807 /* You can't have more than 64k */
4808 error = EINVAL;
4809 goto skip_stuff;
4810 }
4811 if (cnt > (int)stcb->asoc.max_inbound_streams) {
4812 /* More than you are allowed */
4813 error = EINVAL;
4814 goto skip_stuff;
4815 }
4816 }
4817 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4818 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4819 skip_stuff:
4820 SCTP_TCB_UNLOCK(stcb);
4821 break;
4822 }
4823 case SCTP_RESET_ASSOC:
4824 {
4825 int i;
4826 uint32_t *value;
4827
4828 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4829 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t)*value);
4830 if (stcb == NULL) {
4831 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4832 error = ENOENT;
4833 break;
4834 }
4835 if (stcb->asoc.reconfig_supported == 0) {
4836 /*
4837 * Peer does not support the chunk type.
4838 */
4839 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4840 error = EOPNOTSUPP;
4841 SCTP_TCB_UNLOCK(stcb);
4842 break;
4843 }
4844 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
4845 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4846 error = EINVAL;
4847 SCTP_TCB_UNLOCK(stcb);
4848 break;
4849 }
4850 if (stcb->asoc.stream_reset_outstanding) {
4851 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4852 error = EALREADY;
4853 SCTP_TCB_UNLOCK(stcb);
4854 break;
4855 }
4856 /*
4857 * Is there any data pending in the send or sent
4858 * queues?
4859 */
4860 if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
4861 !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
4862 busy_out:
4863 error = EBUSY;
4864 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4865 SCTP_TCB_UNLOCK(stcb);
4866 break;
4867 }
4868 /* Do any streams have data queued? */
4869 for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
4870 if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
4871 goto busy_out;
4872 }
4873 }
4874 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
4875 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4876 SCTP_TCB_UNLOCK(stcb);
4877 break;
4878 }
4879 case SCTP_CONNECT_X:
4880 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4881 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4882 error = EINVAL;
4883 break;
4884 }
4885 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4886 break;
4887 case SCTP_CONNECT_X_DELAYED:
4888 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4889 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4890 error = EINVAL;
4891 break;
4892 }
4893 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4894 break;
4895 case SCTP_CONNECT_X_COMPLETE:
4896 {
4897 struct sockaddr *sa;
4898
4899 /* FIXME MT: check correct? */
4900 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4901
4902 /* find tcb */
4903 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4904 SCTP_INP_RLOCK(inp);
4905 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4906 if (stcb) {
4907 SCTP_TCB_LOCK(stcb);
4908 }
4909 SCTP_INP_RUNLOCK(inp);
4910 } else {
4911 /*
4912 * We increment here since
4913 * sctp_findassociation_ep_addr() wil do a
4914 * decrement if it finds the stcb as long as
4915 * the locked tcb (last argument) is NOT a
4916 * TCB.. aka NULL.
4917 */
4918 SCTP_INP_INCR_REF(inp);
4919 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
4920 if (stcb == NULL) {
4921 SCTP_INP_DECR_REF(inp);
4922 }
4923 }
4924
4925 if (stcb == NULL) {
4926 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4927 error = ENOENT;
4928 break;
4929 }
4930 if (stcb->asoc.delayed_connection == 1) {
4931 stcb->asoc.delayed_connection = 0;
4932 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4933 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4934 stcb->asoc.primary_destination,
4935 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
4936 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4937 } else {
4938 /*
4939 * already expired or did not use delayed
4940 * connectx
4941 */
4942 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4943 error = EALREADY;
4944 }
4945 SCTP_TCB_UNLOCK(stcb);
4946 break;
4947 }
4948 case SCTP_MAX_BURST:
4949 {
4950 struct sctp_assoc_value *av;
4951
4952 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4953 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4954
4955 if (stcb) {
4956 stcb->asoc.max_burst = av->assoc_value;
4957 SCTP_TCB_UNLOCK(stcb);
4958 } else {
4959 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4960 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4961 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4962 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4963 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4964 SCTP_INP_WLOCK(inp);
4965 inp->sctp_ep.max_burst = av->assoc_value;
4966 SCTP_INP_WUNLOCK(inp);
4967 }
4968 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4969 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4970 (av->assoc_id == SCTP_ALL_ASSOC))) {
4971 SCTP_INP_RLOCK(inp);
4972 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4973 SCTP_TCB_LOCK(stcb);
4974 stcb->asoc.max_burst = av->assoc_value;
4975 SCTP_TCB_UNLOCK(stcb);
4976 }
4977 SCTP_INP_RUNLOCK(inp);
4978 }
4979 }
4980 break;
4981 }
4982 case SCTP_MAXSEG:
4983 {
4984 struct sctp_assoc_value *av;
4985
4986 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4987 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4988
4989 if (stcb) {
4990 stcb->asoc.sctp_frag_point = av->assoc_value;
4991 SCTP_TCB_UNLOCK(stcb);
4992 } else {
4993 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4994 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4995 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4996 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4997 SCTP_INP_WLOCK(inp);
4998 inp->sctp_frag_point = av->assoc_value;
4999 SCTP_INP_WUNLOCK(inp);
5000 } else {
5001 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5002 error = EINVAL;
5003 }
5004 }
5005 break;
5006 }
5007 case SCTP_EVENTS:
5008 {
5009 struct sctp_event_subscribe *events;
5010
5011 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
5012
5013 SCTP_INP_WLOCK(inp);
5014 if (events->sctp_data_io_event) {
5015 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5016 } else {
5017 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5018 }
5019
5020 if (events->sctp_association_event) {
5021 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5022 } else {
5023 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5024 }
5025
5026 if (events->sctp_address_event) {
5027 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5028 } else {
5029 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5030 }
5031
5032 if (events->sctp_send_failure_event) {
5033 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5034 } else {
5035 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5036 }
5037
5038 if (events->sctp_peer_error_event) {
5039 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5040 } else {
5041 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5042 }
5043
5044 if (events->sctp_shutdown_event) {
5045 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5046 } else {
5047 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5048 }
5049
5050 if (events->sctp_partial_delivery_event) {
5051 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5052 } else {
5053 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5054 }
5055
5056 if (events->sctp_adaptation_layer_event) {
5057 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5058 } else {
5059 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5060 }
5061
5062 if (events->sctp_authentication_event) {
5063 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5064 } else {
5065 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5066 }
5067
5068 if (events->sctp_sender_dry_event) {
5069 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5070 } else {
5071 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5072 }
5073
5074 if (events->sctp_stream_reset_event) {
5075 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5076 } else {
5077 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5078 }
5079
5080 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5081 SCTP_TCB_LOCK(stcb);
5082 if (events->sctp_association_event) {
5083 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5084 } else {
5085 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5086 }
5087 if (events->sctp_address_event) {
5088 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5089 } else {
5090 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5091 }
5092 if (events->sctp_send_failure_event) {
5093 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5094 } else {
5095 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5096 }
5097 if (events->sctp_peer_error_event) {
5098 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5099 } else {
5100 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5101 }
5102 if (events->sctp_shutdown_event) {
5103 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5104 } else {
5105 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5106 }
5107 if (events->sctp_partial_delivery_event) {
5108 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5109 } else {
5110 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5111 }
5112 if (events->sctp_adaptation_layer_event) {
5113 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5114 } else {
5115 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5116 }
5117 if (events->sctp_authentication_event) {
5118 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5119 } else {
5120 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5121 }
5122 if (events->sctp_sender_dry_event) {
5123 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5124 } else {
5125 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5126 }
5127 if (events->sctp_stream_reset_event) {
5128 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5129 } else {
5130 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5131 }
5132 SCTP_TCB_UNLOCK(stcb);
5133 }
5134 /*
5135 * Send up the sender dry event only for 1-to-1
5136 * style sockets.
5137 */
5138 if (events->sctp_sender_dry_event) {
5139 if (((inp->sctp_flags & (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_IN_TCPPOOL)) != 0) &&
5140 !SCTP_IS_LISTENING(inp)) {
5141 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5142 if (stcb != NULL) {
5143 SCTP_TCB_LOCK(stcb);
5144 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5145 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5146 (stcb->asoc.stream_queue_cnt == 0)) {
5147 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5148 }
5149 SCTP_TCB_UNLOCK(stcb);
5150 }
5151 }
5152 }
5153 SCTP_INP_WUNLOCK(inp);
5154 break;
5155 }
5156 case SCTP_ADAPTATION_LAYER:
5157 {
5158 struct sctp_setadaptation *adap_bits;
5159
5160 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5161 SCTP_INP_WLOCK(inp);
5162 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5163 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5164 SCTP_INP_WUNLOCK(inp);
5165 break;
5166 }
5167 #ifdef SCTP_DEBUG
5168 case SCTP_SET_INITIAL_DBG_SEQ:
5169 {
5170 uint32_t *vvv;
5171
5172 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5173 SCTP_INP_WLOCK(inp);
5174 inp->sctp_ep.initial_sequence_debug = *vvv;
5175 SCTP_INP_WUNLOCK(inp);
5176 break;
5177 }
5178 #endif
5179 case SCTP_DEFAULT_SEND_PARAM:
5180 {
5181 struct sctp_sndrcvinfo *s_info;
5182
5183 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
5184 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
5185
5186 if (stcb) {
5187 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5188 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5189 } else {
5190 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5191 error = EINVAL;
5192 }
5193 SCTP_TCB_UNLOCK(stcb);
5194 } else {
5195 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5196 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5197 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5198 ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
5199 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)))) {
5200 SCTP_INP_WLOCK(inp);
5201 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
5202 SCTP_INP_WUNLOCK(inp);
5203 }
5204 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5205 ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
5206 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC))) {
5207 SCTP_INP_RLOCK(inp);
5208 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5209 SCTP_TCB_LOCK(stcb);
5210 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5211 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5212 }
5213 SCTP_TCB_UNLOCK(stcb);
5214 }
5215 SCTP_INP_RUNLOCK(inp);
5216 }
5217 }
5218 break;
5219 }
5220 case SCTP_PEER_ADDR_PARAMS:
5221 {
5222 struct sctp_paddrparams *paddrp;
5223 struct sctp_nets *net;
5224 struct sockaddr *addr;
5225 #if defined(INET) && defined(INET6)
5226 struct sockaddr_in sin_store;
5227 #endif
5228
5229 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
5230 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
5231
5232 #if defined(INET) && defined(INET6)
5233 if (paddrp->spp_address.ss_family == AF_INET6) {
5234 struct sockaddr_in6 *sin6;
5235
5236 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
5237 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5238 in6_sin6_2_sin(&sin_store, sin6);
5239 addr = (struct sockaddr *)&sin_store;
5240 } else {
5241 addr = (struct sockaddr *)&paddrp->spp_address;
5242 }
5243 } else {
5244 addr = (struct sockaddr *)&paddrp->spp_address;
5245 }
5246 #else
5247 addr = (struct sockaddr *)&paddrp->spp_address;
5248 #endif
5249 if (stcb != NULL) {
5250 net = sctp_findnet(stcb, addr);
5251 } else {
5252 /*
5253 * We increment here since
5254 * sctp_findassociation_ep_addr() wil do a
5255 * decrement if it finds the stcb as long as
5256 * the locked tcb (last argument) is NOT a
5257 * TCB.. aka NULL.
5258 */
5259 net = NULL;
5260 SCTP_INP_INCR_REF(inp);
5261 stcb = sctp_findassociation_ep_addr(&inp, addr,
5262 &net, NULL, NULL);
5263 if (stcb == NULL) {
5264 SCTP_INP_DECR_REF(inp);
5265 }
5266 }
5267 if ((stcb != NULL) && (net == NULL)) {
5268 #ifdef INET
5269 if (addr->sa_family == AF_INET) {
5270 struct sockaddr_in *sin;
5271
5272 sin = (struct sockaddr_in *)addr;
5273 if (sin->sin_addr.s_addr != INADDR_ANY) {
5274 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5275 SCTP_TCB_UNLOCK(stcb);
5276 error = EINVAL;
5277 break;
5278 }
5279 } else
5280 #endif
5281 #ifdef INET6
5282 if (addr->sa_family == AF_INET6) {
5283 struct sockaddr_in6 *sin6;
5284
5285 sin6 = (struct sockaddr_in6 *)addr;
5286 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5287 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5288 SCTP_TCB_UNLOCK(stcb);
5289 error = EINVAL;
5290 break;
5291 }
5292 } else
5293 #endif
5294 {
5295 error = EAFNOSUPPORT;
5296 SCTP_TCB_UNLOCK(stcb);
5297 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5298 break;
5299 }
5300 }
5301 /* sanity checks */
5302 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5303 if (stcb)
5304 SCTP_TCB_UNLOCK(stcb);
5305 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5306 return (EINVAL);
5307 }
5308
5309 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5310 if (stcb)
5311 SCTP_TCB_UNLOCK(stcb);
5312 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5313 return (EINVAL);
5314 }
5315 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) &&
5316 (paddrp->spp_pathmtu > 0) &&
5317 ((paddrp->spp_pathmtu < SCTP_SMALLEST_PMTU) ||
5318 (paddrp->spp_pathmtu > SCTP_LARGEST_PMTU))) {
5319 if (stcb)
5320 SCTP_TCB_UNLOCK(stcb);
5321 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5322 return (EINVAL);
5323 }
5324
5325 if (stcb != NULL) {
5326 /************************TCB SPECIFIC SET ******************/
5327 if (net != NULL) {
5328 /************************NET SPECIFIC SET ******************/
5329 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5330 if (((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) &&
5331 ((net->dest_state & SCTP_ADDR_NOHB) == 0)) {
5332 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5333 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
5334 }
5335 net->dest_state |= SCTP_ADDR_NOHB;
5336 }
5337 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5338 if (paddrp->spp_hbinterval) {
5339 net->heart_beat_delay = paddrp->spp_hbinterval;
5340 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5341 net->heart_beat_delay = 0;
5342 }
5343 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5344 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5345 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5346 net->dest_state &= ~SCTP_ADDR_NOHB;
5347 }
5348 if (paddrp->spp_flags & SPP_HB_DEMAND) {
5349 if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
5350 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5351 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5352 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5353 }
5354 }
5355 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5356 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5357 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5358 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
5359 }
5360 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5361 if (paddrp->spp_pathmtu > 0) {
5362 net->mtu = paddrp->spp_pathmtu;
5363 switch (net->ro._l_addr.sa.sa_family) {
5364 #ifdef INET
5365 case AF_INET:
5366 net->mtu += SCTP_MIN_V4_OVERHEAD;
5367 break;
5368 #endif
5369 #ifdef INET6
5370 case AF_INET6:
5371 net->mtu += SCTP_MIN_OVERHEAD;
5372 break;
5373 #endif
5374 default:
5375 break;
5376 }
5377 if (net->mtu < stcb->asoc.smallest_mtu) {
5378 sctp_pathmtu_adjustment(stcb, net->mtu, true);
5379 }
5380 }
5381 }
5382 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5383 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5384 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5385 }
5386 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5387 }
5388 if (paddrp->spp_pathmaxrxt > 0) {
5389 if (net->dest_state & SCTP_ADDR_PF) {
5390 if (net->error_count > paddrp->spp_pathmaxrxt) {
5391 net->dest_state &= ~SCTP_ADDR_PF;
5392 }
5393 } else {
5394 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5395 (net->error_count > net->pf_threshold)) {
5396 net->dest_state |= SCTP_ADDR_PF;
5397 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5398 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5399 stcb->sctp_ep, stcb, net,
5400 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
5401 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5402 }
5403 }
5404 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5405 if (net->error_count > paddrp->spp_pathmaxrxt) {
5406 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5407 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5408 }
5409 } else {
5410 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5411 net->dest_state |= SCTP_ADDR_REACHABLE;
5412 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5413 }
5414 }
5415 net->failure_threshold = paddrp->spp_pathmaxrxt;
5416 }
5417 if (paddrp->spp_flags & SPP_DSCP) {
5418 net->dscp = paddrp->spp_dscp & 0xfc;
5419 net->dscp |= 0x01;
5420 }
5421 #ifdef INET6
5422 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5423 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5424 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5425 net->flowlabel |= 0x80000000;
5426 }
5427 }
5428 #endif
5429 } else {
5430 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5431 if (paddrp->spp_pathmaxrxt > 0) {
5432 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5433 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5434 if (net->dest_state & SCTP_ADDR_PF) {
5435 if (net->error_count > paddrp->spp_pathmaxrxt) {
5436 net->dest_state &= ~SCTP_ADDR_PF;
5437 }
5438 } else {
5439 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5440 (net->error_count > net->pf_threshold)) {
5441 net->dest_state |= SCTP_ADDR_PF;
5442 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5443 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5444 stcb->sctp_ep, stcb, net,
5445 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13);
5446 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5447 }
5448 }
5449 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5450 if (net->error_count > paddrp->spp_pathmaxrxt) {
5451 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5452 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5453 }
5454 } else {
5455 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5456 net->dest_state |= SCTP_ADDR_REACHABLE;
5457 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5458 }
5459 }
5460 net->failure_threshold = paddrp->spp_pathmaxrxt;
5461 }
5462 }
5463 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5464 if (paddrp->spp_hbinterval != 0) {
5465 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5466 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5467 stcb->asoc.heart_beat_delay = 0;
5468 }
5469 /* Turn back on the timer */
5470 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5471 if (paddrp->spp_hbinterval != 0) {
5472 net->heart_beat_delay = paddrp->spp_hbinterval;
5473 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5474 net->heart_beat_delay = 0;
5475 }
5476 if (net->dest_state & SCTP_ADDR_NOHB) {
5477 net->dest_state &= ~SCTP_ADDR_NOHB;
5478 }
5479 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5480 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14);
5481 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5482 }
5483 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5484 }
5485 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5486 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5487 if ((net->dest_state & SCTP_ADDR_NOHB) == 0) {
5488 net->dest_state |= SCTP_ADDR_NOHB;
5489 if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
5490 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5491 inp, stcb, net,
5492 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15);
5493 }
5494 }
5495 }
5496 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5497 }
5498 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5499 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5500 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5501 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5502 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16);
5503 }
5504 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5505 if (paddrp->spp_pathmtu > 0) {
5506 net->mtu = paddrp->spp_pathmtu;
5507 switch (net->ro._l_addr.sa.sa_family) {
5508 #ifdef INET
5509 case AF_INET:
5510 net->mtu += SCTP_MIN_V4_OVERHEAD;
5511 break;
5512 #endif
5513 #ifdef INET6
5514 case AF_INET6:
5515 net->mtu += SCTP_MIN_OVERHEAD;
5516 break;
5517 #endif
5518 default:
5519 break;
5520 }
5521 if (net->mtu < stcb->asoc.smallest_mtu) {
5522 sctp_pathmtu_adjustment(stcb, net->mtu, true);
5523 }
5524 }
5525 }
5526 if (paddrp->spp_pathmtu > 0) {
5527 stcb->asoc.default_mtu = paddrp->spp_pathmtu;
5528 }
5529 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5530 }
5531 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5532 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5533 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5534 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5535 }
5536 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5537 }
5538 stcb->asoc.default_mtu = 0;
5539 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5540 }
5541 if (paddrp->spp_flags & SPP_DSCP) {
5542 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5543 net->dscp = paddrp->spp_dscp & 0xfc;
5544 net->dscp |= 0x01;
5545 }
5546 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5547 stcb->asoc.default_dscp |= 0x01;
5548 }
5549 #ifdef INET6
5550 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5551 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5552 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5553 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5554 net->flowlabel |= 0x80000000;
5555 }
5556 }
5557 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5558 stcb->asoc.default_flowlabel |= 0x80000000;
5559 }
5560 #endif
5561 }
5562 SCTP_TCB_UNLOCK(stcb);
5563 } else {
5564 /************************NO TCB, SET TO default stuff ******************/
5565 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5566 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5567 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5568 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
5569 SCTP_INP_WLOCK(inp);
5570 /*
5571 * For the TOS/FLOWLABEL stuff you
5572 * set it with the options on the
5573 * socket
5574 */
5575 if (paddrp->spp_pathmaxrxt > 0) {
5576 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5577 }
5578
5579 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5580 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5581 else if (paddrp->spp_hbinterval != 0) {
5582 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5583 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5584 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
5585 }
5586
5587 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5588 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5589 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5590 } else if (paddrp->spp_hbinterval) {
5591 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
5592 }
5593 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5594 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5595 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5596 }
5597 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5598 inp->sctp_ep.default_mtu = 0;
5599 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5600 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5601 if (paddrp->spp_pathmtu > 0) {
5602 inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
5603 }
5604 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5605 }
5606 if (paddrp->spp_flags & SPP_DSCP) {
5607 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5608 inp->sctp_ep.default_dscp |= 0x01;
5609 }
5610 #ifdef INET6
5611 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5612 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5613 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5614 inp->sctp_ep.default_flowlabel |= 0x80000000;
5615 }
5616 }
5617 #endif
5618 SCTP_INP_WUNLOCK(inp);
5619 } else {
5620 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5621 error = EINVAL;
5622 }
5623 }
5624 break;
5625 }
5626 case SCTP_RTOINFO:
5627 {
5628 struct sctp_rtoinfo *srto;
5629 uint32_t new_init, new_min, new_max;
5630
5631 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5632 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5633
5634 if (stcb) {
5635 if (srto->srto_initial)
5636 new_init = srto->srto_initial;
5637 else
5638 new_init = stcb->asoc.initial_rto;
5639 if (srto->srto_max)
5640 new_max = srto->srto_max;
5641 else
5642 new_max = stcb->asoc.maxrto;
5643 if (srto->srto_min)
5644 new_min = srto->srto_min;
5645 else
5646 new_min = stcb->asoc.minrto;
5647 if ((new_min <= new_init) && (new_init <= new_max)) {
5648 stcb->asoc.initial_rto = new_init;
5649 stcb->asoc.maxrto = new_max;
5650 stcb->asoc.minrto = new_min;
5651 } else {
5652 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5653 error = EINVAL;
5654 }
5655 SCTP_TCB_UNLOCK(stcb);
5656 } else {
5657 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5658 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5659 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5660 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
5661 SCTP_INP_WLOCK(inp);
5662 if (srto->srto_initial)
5663 new_init = srto->srto_initial;
5664 else
5665 new_init = inp->sctp_ep.initial_rto;
5666 if (srto->srto_max)
5667 new_max = srto->srto_max;
5668 else
5669 new_max = inp->sctp_ep.sctp_maxrto;
5670 if (srto->srto_min)
5671 new_min = srto->srto_min;
5672 else
5673 new_min = inp->sctp_ep.sctp_minrto;
5674 if ((new_min <= new_init) && (new_init <= new_max)) {
5675 inp->sctp_ep.initial_rto = new_init;
5676 inp->sctp_ep.sctp_maxrto = new_max;
5677 inp->sctp_ep.sctp_minrto = new_min;
5678 } else {
5679 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5680 error = EINVAL;
5681 }
5682 SCTP_INP_WUNLOCK(inp);
5683 } else {
5684 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5685 error = EINVAL;
5686 }
5687 }
5688 break;
5689 }
5690 case SCTP_ASSOCINFO:
5691 {
5692 struct sctp_assocparams *sasoc;
5693
5694 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5695 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5696 if (sasoc->sasoc_cookie_life > 0) {
5697 /* boundary check the cookie life */
5698 if (sasoc->sasoc_cookie_life < SCTP_MIN_COOKIE_LIFE) {
5699 sasoc->sasoc_cookie_life = SCTP_MIN_COOKIE_LIFE;
5700 }
5701 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5702 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5703 }
5704 }
5705 if (stcb) {
5706 if (sasoc->sasoc_asocmaxrxt > 0) {
5707 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5708 }
5709 if (sasoc->sasoc_cookie_life > 0) {
5710 stcb->asoc.cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
5711 }
5712 SCTP_TCB_UNLOCK(stcb);
5713 } else {
5714 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5715 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5716 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5717 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
5718 SCTP_INP_WLOCK(inp);
5719 if (sasoc->sasoc_asocmaxrxt > 0) {
5720 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5721 }
5722 if (sasoc->sasoc_cookie_life > 0) {
5723 inp->sctp_ep.def_cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
5724 }
5725 SCTP_INP_WUNLOCK(inp);
5726 } else {
5727 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5728 error = EINVAL;
5729 }
5730 }
5731 break;
5732 }
5733 case SCTP_INITMSG:
5734 {
5735 struct sctp_initmsg *sinit;
5736
5737 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5738 SCTP_INP_WLOCK(inp);
5739 if (sinit->sinit_num_ostreams)
5740 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5741
5742 if (sinit->sinit_max_instreams)
5743 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5744
5745 if (sinit->sinit_max_attempts)
5746 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5747
5748 if (sinit->sinit_max_init_timeo)
5749 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5750 SCTP_INP_WUNLOCK(inp);
5751 break;
5752 }
5753 case SCTP_PRIMARY_ADDR:
5754 {
5755 struct sctp_setprim *spa;
5756 struct sctp_nets *net;
5757 struct sockaddr *addr;
5758 #if defined(INET) && defined(INET6)
5759 struct sockaddr_in sin_store;
5760 #endif
5761
5762 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5763 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5764
5765 #if defined(INET) && defined(INET6)
5766 if (spa->ssp_addr.ss_family == AF_INET6) {
5767 struct sockaddr_in6 *sin6;
5768
5769 sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
5770 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5771 in6_sin6_2_sin(&sin_store, sin6);
5772 addr = (struct sockaddr *)&sin_store;
5773 } else {
5774 addr = (struct sockaddr *)&spa->ssp_addr;
5775 }
5776 } else {
5777 addr = (struct sockaddr *)&spa->ssp_addr;
5778 }
5779 #else
5780 addr = (struct sockaddr *)&spa->ssp_addr;
5781 #endif
5782 if (stcb != NULL) {
5783 net = sctp_findnet(stcb, addr);
5784 } else {
5785 /*
5786 * We increment here since
5787 * sctp_findassociation_ep_addr() wil do a
5788 * decrement if it finds the stcb as long as
5789 * the locked tcb (last argument) is NOT a
5790 * TCB.. aka NULL.
5791 */
5792 net = NULL;
5793 SCTP_INP_INCR_REF(inp);
5794 stcb = sctp_findassociation_ep_addr(&inp, addr,
5795 &net, NULL, NULL);
5796 if (stcb == NULL) {
5797 SCTP_INP_DECR_REF(inp);
5798 }
5799 }
5800
5801 if ((stcb != NULL) && (net != NULL)) {
5802 if (net != stcb->asoc.primary_destination) {
5803 if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
5804 /* Ok we need to set it */
5805 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5806 if ((stcb->asoc.alternate) &&
5807 ((net->dest_state & SCTP_ADDR_PF) == 0) &&
5808 (net->dest_state & SCTP_ADDR_REACHABLE)) {
5809 sctp_free_remote_addr(stcb->asoc.alternate);
5810 stcb->asoc.alternate = NULL;
5811 }
5812 } else {
5813 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5814 error = EINVAL;
5815 }
5816 } else {
5817 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5818 error = EINVAL;
5819 }
5820 }
5821 } else {
5822 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5823 error = EINVAL;
5824 }
5825 if (stcb != NULL) {
5826 SCTP_TCB_UNLOCK(stcb);
5827 }
5828 break;
5829 }
5830 case SCTP_SET_DYNAMIC_PRIMARY:
5831 {
5832 union sctp_sockstore *ss;
5833
5834 error = priv_check(curthread,
5835 PRIV_NETINET_RESERVEDPORT);
5836 if (error)
5837 break;
5838
5839 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5840 /* SUPER USER CHECK? */
5841 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5842 break;
5843 }
5844 case SCTP_SET_PEER_PRIMARY_ADDR:
5845 {
5846 struct sctp_setpeerprim *sspp;
5847 struct sockaddr *addr;
5848 #if defined(INET) && defined(INET6)
5849 struct sockaddr_in sin_store;
5850 #endif
5851
5852 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5853 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5854 if (stcb != NULL) {
5855 struct sctp_ifa *ifa;
5856
5857 #if defined(INET) && defined(INET6)
5858 if (sspp->sspp_addr.ss_family == AF_INET6) {
5859 struct sockaddr_in6 *sin6;
5860
5861 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5862 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5863 in6_sin6_2_sin(&sin_store, sin6);
5864 addr = (struct sockaddr *)&sin_store;
5865 } else {
5866 addr = (struct sockaddr *)&sspp->sspp_addr;
5867 }
5868 } else {
5869 addr = (struct sockaddr *)&sspp->sspp_addr;
5870 }
5871 #else
5872 addr = (struct sockaddr *)&sspp->sspp_addr;
5873 #endif
5874 ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5875 if (ifa == NULL) {
5876 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5877 error = EINVAL;
5878 goto out_of_it;
5879 }
5880 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5881 /*
5882 * Must validate the ifa found is in
5883 * our ep
5884 */
5885 struct sctp_laddr *laddr;
5886 int found = 0;
5887
5888 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5889 if (laddr->ifa == NULL) {
5890 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5891 __func__);
5892 continue;
5893 }
5894 if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
5895 (!sctp_is_addr_pending(stcb, laddr->ifa))) {
5896 continue;
5897 }
5898 if (laddr->ifa == ifa) {
5899 found = 1;
5900 break;
5901 }
5902 }
5903 if (!found) {
5904 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5905 error = EINVAL;
5906 goto out_of_it;
5907 }
5908 } else {
5909 switch (addr->sa_family) {
5910 #ifdef INET
5911 case AF_INET:
5912 {
5913 struct sockaddr_in *sin;
5914
5915 sin = (struct sockaddr_in *)addr;
5916 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5917 &sin->sin_addr) != 0) {
5918 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5919 error = EINVAL;
5920 goto out_of_it;
5921 }
5922 break;
5923 }
5924 #endif
5925 #ifdef INET6
5926 case AF_INET6:
5927 {
5928 struct sockaddr_in6 *sin6;
5929
5930 sin6 = (struct sockaddr_in6 *)addr;
5931 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5932 &sin6->sin6_addr) != 0) {
5933 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5934 error = EINVAL;
5935 goto out_of_it;
5936 }
5937 break;
5938 }
5939 #endif
5940 default:
5941 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5942 error = EINVAL;
5943 goto out_of_it;
5944 }
5945 }
5946 if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
5947 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5948 error = EINVAL;
5949 }
5950 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5951 out_of_it:
5952 SCTP_TCB_UNLOCK(stcb);
5953 } else {
5954 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5955 error = EINVAL;
5956 }
5957 break;
5958 }
5959 case SCTP_BINDX_ADD_ADDR:
5960 {
5961 struct sockaddr *sa;
5962 struct thread *td;
5963
5964 td = (struct thread *)p;
5965 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5966 #ifdef INET
5967 if (sa->sa_family == AF_INET) {
5968 if (optsize < sizeof(struct sockaddr_in)) {
5969 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5970 error = EINVAL;
5971 break;
5972 }
5973 if (td != NULL &&
5974 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
5975 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5976 break;
5977 }
5978 } else
5979 #endif
5980 #ifdef INET6
5981 if (sa->sa_family == AF_INET6) {
5982 if (optsize < sizeof(struct sockaddr_in6)) {
5983 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5984 error = EINVAL;
5985 break;
5986 }
5987 if (td != NULL &&
5988 (error = prison_local_ip6(td->td_ucred,
5989 &(((struct sockaddr_in6 *)sa)->sin6_addr),
5990 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5991 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5992 break;
5993 }
5994 } else
5995 #endif
5996 {
5997 error = EAFNOSUPPORT;
5998 break;
5999 }
6000 sctp_bindx_add_address(so, inp, sa, vrf_id, &error, p);
6001 break;
6002 }
6003 case SCTP_BINDX_REM_ADDR:
6004 {
6005 struct sockaddr *sa;
6006 struct thread *td;
6007
6008 td = (struct thread *)p;
6009
6010 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
6011 #ifdef INET
6012 if (sa->sa_family == AF_INET) {
6013 if (optsize < sizeof(struct sockaddr_in)) {
6014 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6015 error = EINVAL;
6016 break;
6017 }
6018 if (td != NULL &&
6019 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6020 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6021 break;
6022 }
6023 } else
6024 #endif
6025 #ifdef INET6
6026 if (sa->sa_family == AF_INET6) {
6027 if (optsize < sizeof(struct sockaddr_in6)) {
6028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6029 error = EINVAL;
6030 break;
6031 }
6032 if (td != NULL &&
6033 (error = prison_local_ip6(td->td_ucred,
6034 &(((struct sockaddr_in6 *)sa)->sin6_addr),
6035 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6036 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6037 break;
6038 }
6039 } else
6040 #endif
6041 {
6042 error = EAFNOSUPPORT;
6043 break;
6044 }
6045 sctp_bindx_delete_address(inp, sa, vrf_id, &error);
6046 break;
6047 }
6048 case SCTP_EVENT:
6049 {
6050 struct sctp_event *event;
6051 uint32_t event_type;
6052
6053 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6054 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6055 switch (event->se_type) {
6056 case SCTP_ASSOC_CHANGE:
6057 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6058 break;
6059 case SCTP_PEER_ADDR_CHANGE:
6060 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6061 break;
6062 case SCTP_REMOTE_ERROR:
6063 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6064 break;
6065 case SCTP_SEND_FAILED:
6066 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6067 break;
6068 case SCTP_SHUTDOWN_EVENT:
6069 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6070 break;
6071 case SCTP_ADAPTATION_INDICATION:
6072 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6073 break;
6074 case SCTP_PARTIAL_DELIVERY_EVENT:
6075 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6076 break;
6077 case SCTP_AUTHENTICATION_EVENT:
6078 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6079 break;
6080 case SCTP_STREAM_RESET_EVENT:
6081 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6082 break;
6083 case SCTP_SENDER_DRY_EVENT:
6084 event_type = SCTP_PCB_FLAGS_DRYEVNT;
6085 break;
6086 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6087 event_type = 0;
6088 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6089 error = ENOTSUP;
6090 break;
6091 case SCTP_ASSOC_RESET_EVENT:
6092 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6093 break;
6094 case SCTP_STREAM_CHANGE_EVENT:
6095 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6096 break;
6097 case SCTP_SEND_FAILED_EVENT:
6098 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6099 break;
6100 default:
6101 event_type = 0;
6102 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6103 error = EINVAL;
6104 break;
6105 }
6106 if (event_type > 0) {
6107 if (stcb) {
6108 if (event->se_on) {
6109 sctp_stcb_feature_on(inp, stcb, event_type);
6110 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6111 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6112 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6113 (stcb->asoc.stream_queue_cnt == 0)) {
6114 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6115 }
6116 }
6117 } else {
6118 sctp_stcb_feature_off(inp, stcb, event_type);
6119 }
6120 SCTP_TCB_UNLOCK(stcb);
6121 } else {
6122 /*
6123 * We don't want to send up a storm
6124 * of events, so return an error for
6125 * sender dry events
6126 */
6127 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
6128 (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6129 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
6130 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
6131 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6132 error = ENOTSUP;
6133 break;
6134 }
6135 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6136 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6137 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6138 ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
6139 (event->se_assoc_id == SCTP_ALL_ASSOC)))) {
6140 SCTP_INP_WLOCK(inp);
6141 if (event->se_on) {
6142 sctp_feature_on(inp, event_type);
6143 } else {
6144 sctp_feature_off(inp, event_type);
6145 }
6146 SCTP_INP_WUNLOCK(inp);
6147 }
6148 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6149 ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
6150 (event->se_assoc_id == SCTP_ALL_ASSOC))) {
6151 SCTP_INP_RLOCK(inp);
6152 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6153 SCTP_TCB_LOCK(stcb);
6154 if (event->se_on) {
6155 sctp_stcb_feature_on(inp, stcb, event_type);
6156 } else {
6157 sctp_stcb_feature_off(inp, stcb, event_type);
6158 }
6159 SCTP_TCB_UNLOCK(stcb);
6160 }
6161 SCTP_INP_RUNLOCK(inp);
6162 }
6163 }
6164 } else {
6165 if (stcb) {
6166 SCTP_TCB_UNLOCK(stcb);
6167 }
6168 }
6169 break;
6170 }
6171 case SCTP_RECVRCVINFO:
6172 {
6173 int *onoff;
6174
6175 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6176 SCTP_INP_WLOCK(inp);
6177 if (*onoff != 0) {
6178 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6179 } else {
6180 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6181 }
6182 SCTP_INP_WUNLOCK(inp);
6183 break;
6184 }
6185 case SCTP_RECVNXTINFO:
6186 {
6187 int *onoff;
6188
6189 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6190 SCTP_INP_WLOCK(inp);
6191 if (*onoff != 0) {
6192 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6193 } else {
6194 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6195 }
6196 SCTP_INP_WUNLOCK(inp);
6197 break;
6198 }
6199 case SCTP_DEFAULT_SNDINFO:
6200 {
6201 struct sctp_sndinfo *info;
6202 uint16_t policy;
6203
6204 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
6205 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
6206
6207 if (stcb) {
6208 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6209 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6210 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6211 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6212 stcb->asoc.def_send.sinfo_flags |= policy;
6213 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6214 stcb->asoc.def_send.sinfo_context = info->snd_context;
6215 } else {
6216 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6217 error = EINVAL;
6218 }
6219 SCTP_TCB_UNLOCK(stcb);
6220 } else {
6221 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6222 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6223 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6224 ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
6225 (info->snd_assoc_id == SCTP_ALL_ASSOC)))) {
6226 SCTP_INP_WLOCK(inp);
6227 inp->def_send.sinfo_stream = info->snd_sid;
6228 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
6229 inp->def_send.sinfo_flags = info->snd_flags;
6230 inp->def_send.sinfo_flags |= policy;
6231 inp->def_send.sinfo_ppid = info->snd_ppid;
6232 inp->def_send.sinfo_context = info->snd_context;
6233 SCTP_INP_WUNLOCK(inp);
6234 }
6235 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6236 ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
6237 (info->snd_assoc_id == SCTP_ALL_ASSOC))) {
6238 SCTP_INP_RLOCK(inp);
6239 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6240 SCTP_TCB_LOCK(stcb);
6241 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6242 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6243 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6244 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6245 stcb->asoc.def_send.sinfo_flags |= policy;
6246 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6247 stcb->asoc.def_send.sinfo_context = info->snd_context;
6248 }
6249 SCTP_TCB_UNLOCK(stcb);
6250 }
6251 SCTP_INP_RUNLOCK(inp);
6252 }
6253 }
6254 break;
6255 }
6256 case SCTP_DEFAULT_PRINFO:
6257 {
6258 struct sctp_default_prinfo *info;
6259
6260 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
6261 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
6262
6263 if (info->pr_policy > SCTP_PR_SCTP_MAX) {
6264 if (stcb) {
6265 SCTP_TCB_UNLOCK(stcb);
6266 }
6267 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6268 error = EINVAL;
6269 break;
6270 }
6271 if (stcb) {
6272 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6273 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6274 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6275 SCTP_TCB_UNLOCK(stcb);
6276 } else {
6277 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6278 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6279 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6280 ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
6281 (info->pr_assoc_id == SCTP_ALL_ASSOC)))) {
6282 SCTP_INP_WLOCK(inp);
6283 inp->def_send.sinfo_flags &= 0xfff0;
6284 inp->def_send.sinfo_flags |= info->pr_policy;
6285 inp->def_send.sinfo_timetolive = info->pr_value;
6286 SCTP_INP_WUNLOCK(inp);
6287 }
6288 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6289 ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
6290 (info->pr_assoc_id == SCTP_ALL_ASSOC))) {
6291 SCTP_INP_RLOCK(inp);
6292 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6293 SCTP_TCB_LOCK(stcb);
6294 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6295 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6296 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6297 SCTP_TCB_UNLOCK(stcb);
6298 }
6299 SCTP_INP_RUNLOCK(inp);
6300 }
6301 }
6302 break;
6303 }
6304 case SCTP_PEER_ADDR_THLDS:
6305 /* Applies to the specific association */
6306 {
6307 struct sctp_paddrthlds *thlds;
6308 struct sctp_nets *net;
6309 struct sockaddr *addr;
6310 #if defined(INET) && defined(INET6)
6311 struct sockaddr_in sin_store;
6312 #endif
6313
6314 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
6315 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
6316
6317 #if defined(INET) && defined(INET6)
6318 if (thlds->spt_address.ss_family == AF_INET6) {
6319 struct sockaddr_in6 *sin6;
6320
6321 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
6322 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6323 in6_sin6_2_sin(&sin_store, sin6);
6324 addr = (struct sockaddr *)&sin_store;
6325 } else {
6326 addr = (struct sockaddr *)&thlds->spt_address;
6327 }
6328 } else {
6329 addr = (struct sockaddr *)&thlds->spt_address;
6330 }
6331 #else
6332 addr = (struct sockaddr *)&thlds->spt_address;
6333 #endif
6334 if (stcb != NULL) {
6335 net = sctp_findnet(stcb, addr);
6336 } else {
6337 /*
6338 * We increment here since
6339 * sctp_findassociation_ep_addr() wil do a
6340 * decrement if it finds the stcb as long as
6341 * the locked tcb (last argument) is NOT a
6342 * TCB.. aka NULL.
6343 */
6344 net = NULL;
6345 SCTP_INP_INCR_REF(inp);
6346 stcb = sctp_findassociation_ep_addr(&inp, addr,
6347 &net, NULL, NULL);
6348 if (stcb == NULL) {
6349 SCTP_INP_DECR_REF(inp);
6350 }
6351 }
6352 if ((stcb != NULL) && (net == NULL)) {
6353 #ifdef INET
6354 if (addr->sa_family == AF_INET) {
6355 struct sockaddr_in *sin;
6356
6357 sin = (struct sockaddr_in *)addr;
6358 if (sin->sin_addr.s_addr != INADDR_ANY) {
6359 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6360 SCTP_TCB_UNLOCK(stcb);
6361 error = EINVAL;
6362 break;
6363 }
6364 } else
6365 #endif
6366 #ifdef INET6
6367 if (addr->sa_family == AF_INET6) {
6368 struct sockaddr_in6 *sin6;
6369
6370 sin6 = (struct sockaddr_in6 *)addr;
6371 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6372 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6373 SCTP_TCB_UNLOCK(stcb);
6374 error = EINVAL;
6375 break;
6376 }
6377 } else
6378 #endif
6379 {
6380 error = EAFNOSUPPORT;
6381 SCTP_TCB_UNLOCK(stcb);
6382 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6383 break;
6384 }
6385 }
6386 if (thlds->spt_pathcpthld != 0xffff) {
6387 if (stcb != NULL) {
6388 SCTP_TCB_UNLOCK(stcb);
6389 }
6390 error = EINVAL;
6391 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6392 break;
6393 }
6394 if (stcb != NULL) {
6395 if (net != NULL) {
6396 net->failure_threshold = thlds->spt_pathmaxrxt;
6397 net->pf_threshold = thlds->spt_pathpfthld;
6398 if (net->dest_state & SCTP_ADDR_PF) {
6399 if ((net->error_count > net->failure_threshold) ||
6400 (net->error_count <= net->pf_threshold)) {
6401 net->dest_state &= ~SCTP_ADDR_PF;
6402 }
6403 } else {
6404 if ((net->error_count > net->pf_threshold) &&
6405 (net->error_count <= net->failure_threshold)) {
6406 net->dest_state |= SCTP_ADDR_PF;
6407 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6408 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6409 stcb->sctp_ep, stcb, net,
6410 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17);
6411 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6412 }
6413 }
6414 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6415 if (net->error_count > net->failure_threshold) {
6416 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6417 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6418 }
6419 } else {
6420 if (net->error_count <= net->failure_threshold) {
6421 net->dest_state |= SCTP_ADDR_REACHABLE;
6422 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6423 }
6424 }
6425 } else {
6426 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6427 net->failure_threshold = thlds->spt_pathmaxrxt;
6428 net->pf_threshold = thlds->spt_pathpfthld;
6429 if (net->dest_state & SCTP_ADDR_PF) {
6430 if ((net->error_count > net->failure_threshold) ||
6431 (net->error_count <= net->pf_threshold)) {
6432 net->dest_state &= ~SCTP_ADDR_PF;
6433 }
6434 } else {
6435 if ((net->error_count > net->pf_threshold) &&
6436 (net->error_count <= net->failure_threshold)) {
6437 net->dest_state |= SCTP_ADDR_PF;
6438 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6439 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6440 stcb->sctp_ep, stcb, net,
6441 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18);
6442 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6443 }
6444 }
6445 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6446 if (net->error_count > net->failure_threshold) {
6447 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6448 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6449 }
6450 } else {
6451 if (net->error_count <= net->failure_threshold) {
6452 net->dest_state |= SCTP_ADDR_REACHABLE;
6453 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6454 }
6455 }
6456 }
6457 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6458 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6459 }
6460 SCTP_TCB_UNLOCK(stcb);
6461 } else {
6462 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6463 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6464 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6465 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
6466 SCTP_INP_WLOCK(inp);
6467 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6468 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6469 SCTP_INP_WUNLOCK(inp);
6470 } else {
6471 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6472 error = EINVAL;
6473 }
6474 }
6475 break;
6476 }
6477 case SCTP_REMOTE_UDP_ENCAPS_PORT:
6478 {
6479 struct sctp_udpencaps *encaps;
6480 struct sctp_nets *net;
6481 struct sockaddr *addr;
6482 #if defined(INET) && defined(INET6)
6483 struct sockaddr_in sin_store;
6484 #endif
6485
6486 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6487 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6488
6489 #if defined(INET) && defined(INET6)
6490 if (encaps->sue_address.ss_family == AF_INET6) {
6491 struct sockaddr_in6 *sin6;
6492
6493 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
6494 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6495 in6_sin6_2_sin(&sin_store, sin6);
6496 addr = (struct sockaddr *)&sin_store;
6497 } else {
6498 addr = (struct sockaddr *)&encaps->sue_address;
6499 }
6500 } else {
6501 addr = (struct sockaddr *)&encaps->sue_address;
6502 }
6503 #else
6504 addr = (struct sockaddr *)&encaps->sue_address;
6505 #endif
6506 if (stcb != NULL) {
6507 net = sctp_findnet(stcb, addr);
6508 } else {
6509 /*
6510 * We increment here since
6511 * sctp_findassociation_ep_addr() wil do a
6512 * decrement if it finds the stcb as long as
6513 * the locked tcb (last argument) is NOT a
6514 * TCB.. aka NULL.
6515 */
6516 net = NULL;
6517 SCTP_INP_INCR_REF(inp);
6518 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
6519 if (stcb == NULL) {
6520 SCTP_INP_DECR_REF(inp);
6521 }
6522 }
6523 if ((stcb != NULL) && (net == NULL)) {
6524 #ifdef INET
6525 if (addr->sa_family == AF_INET) {
6526 struct sockaddr_in *sin;
6527
6528 sin = (struct sockaddr_in *)addr;
6529 if (sin->sin_addr.s_addr != INADDR_ANY) {
6530 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6531 SCTP_TCB_UNLOCK(stcb);
6532 error = EINVAL;
6533 break;
6534 }
6535 } else
6536 #endif
6537 #ifdef INET6
6538 if (addr->sa_family == AF_INET6) {
6539 struct sockaddr_in6 *sin6;
6540
6541 sin6 = (struct sockaddr_in6 *)addr;
6542 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6543 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6544 SCTP_TCB_UNLOCK(stcb);
6545 error = EINVAL;
6546 break;
6547 }
6548 } else
6549 #endif
6550 {
6551 error = EAFNOSUPPORT;
6552 SCTP_TCB_UNLOCK(stcb);
6553 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6554 break;
6555 }
6556 }
6557
6558 if (stcb != NULL) {
6559 if (net != NULL) {
6560 net->port = encaps->sue_port;
6561 } else {
6562 stcb->asoc.port = encaps->sue_port;
6563 }
6564 SCTP_TCB_UNLOCK(stcb);
6565 } else {
6566 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6567 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6568 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6569 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
6570 SCTP_INP_WLOCK(inp);
6571 inp->sctp_ep.port = encaps->sue_port;
6572 SCTP_INP_WUNLOCK(inp);
6573 } else {
6574 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6575 error = EINVAL;
6576 }
6577 }
6578 break;
6579 }
6580 case SCTP_ECN_SUPPORTED:
6581 {
6582 struct sctp_assoc_value *av;
6583
6584 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6585 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6586
6587 if (stcb) {
6588 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6589 error = EINVAL;
6590 SCTP_TCB_UNLOCK(stcb);
6591 } else {
6592 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6593 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6594 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6595 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6596 SCTP_INP_WLOCK(inp);
6597 if (av->assoc_value == 0) {
6598 inp->ecn_supported = 0;
6599 } else {
6600 inp->ecn_supported = 1;
6601 }
6602 SCTP_INP_WUNLOCK(inp);
6603 } else {
6604 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6605 error = EINVAL;
6606 }
6607 }
6608 break;
6609 }
6610 case SCTP_PR_SUPPORTED:
6611 {
6612 struct sctp_assoc_value *av;
6613
6614 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6615 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6616
6617 if (stcb) {
6618 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6619 error = EINVAL;
6620 SCTP_TCB_UNLOCK(stcb);
6621 } else {
6622 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6623 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6624 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6625 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6626 SCTP_INP_WLOCK(inp);
6627 if (av->assoc_value == 0) {
6628 inp->prsctp_supported = 0;
6629 } else {
6630 inp->prsctp_supported = 1;
6631 }
6632 SCTP_INP_WUNLOCK(inp);
6633 } else {
6634 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6635 error = EINVAL;
6636 }
6637 }
6638 break;
6639 }
6640 case SCTP_AUTH_SUPPORTED:
6641 {
6642 struct sctp_assoc_value *av;
6643
6644 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6645 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6646
6647 if (stcb) {
6648 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6649 error = EINVAL;
6650 SCTP_TCB_UNLOCK(stcb);
6651 } else {
6652 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6653 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6654 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6655 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6656 if ((av->assoc_value == 0) &&
6657 (inp->asconf_supported == 1)) {
6658 /*
6659 * AUTH is required for
6660 * ASCONF
6661 */
6662 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6663 error = EINVAL;
6664 } else {
6665 SCTP_INP_WLOCK(inp);
6666 if (av->assoc_value == 0) {
6667 inp->auth_supported = 0;
6668 } else {
6669 inp->auth_supported = 1;
6670 }
6671 SCTP_INP_WUNLOCK(inp);
6672 }
6673 } else {
6674 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6675 error = EINVAL;
6676 }
6677 }
6678 break;
6679 }
6680 case SCTP_ASCONF_SUPPORTED:
6681 {
6682 struct sctp_assoc_value *av;
6683
6684 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6685 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6686
6687 if (stcb) {
6688 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6689 error = EINVAL;
6690 SCTP_TCB_UNLOCK(stcb);
6691 } else {
6692 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6693 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6694 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6695 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6696 if ((av->assoc_value != 0) &&
6697 (inp->auth_supported == 0)) {
6698 /*
6699 * AUTH is required for
6700 * ASCONF
6701 */
6702 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6703 error = EINVAL;
6704 } else {
6705 SCTP_INP_WLOCK(inp);
6706 if (av->assoc_value == 0) {
6707 inp->asconf_supported = 0;
6708 sctp_auth_delete_chunk(SCTP_ASCONF,
6709 inp->sctp_ep.local_auth_chunks);
6710 sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6711 inp->sctp_ep.local_auth_chunks);
6712 } else {
6713 inp->asconf_supported = 1;
6714 sctp_auth_add_chunk(SCTP_ASCONF,
6715 inp->sctp_ep.local_auth_chunks);
6716 sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6717 inp->sctp_ep.local_auth_chunks);
6718 }
6719 SCTP_INP_WUNLOCK(inp);
6720 }
6721 } else {
6722 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6723 error = EINVAL;
6724 }
6725 }
6726 break;
6727 }
6728 case SCTP_RECONFIG_SUPPORTED:
6729 {
6730 struct sctp_assoc_value *av;
6731
6732 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6733 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6734
6735 if (stcb) {
6736 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6737 error = EINVAL;
6738 SCTP_TCB_UNLOCK(stcb);
6739 } else {
6740 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6741 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6742 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6743 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6744 SCTP_INP_WLOCK(inp);
6745 if (av->assoc_value == 0) {
6746 inp->reconfig_supported = 0;
6747 } else {
6748 inp->reconfig_supported = 1;
6749 }
6750 SCTP_INP_WUNLOCK(inp);
6751 } else {
6752 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6753 error = EINVAL;
6754 }
6755 }
6756 break;
6757 }
6758 case SCTP_NRSACK_SUPPORTED:
6759 {
6760 struct sctp_assoc_value *av;
6761
6762 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6763 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6764
6765 if (stcb) {
6766 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6767 error = EINVAL;
6768 SCTP_TCB_UNLOCK(stcb);
6769 } else {
6770 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6771 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6772 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6773 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6774 SCTP_INP_WLOCK(inp);
6775 if (av->assoc_value == 0) {
6776 inp->nrsack_supported = 0;
6777 } else {
6778 inp->nrsack_supported = 1;
6779 }
6780 SCTP_INP_WUNLOCK(inp);
6781 } else {
6782 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6783 error = EINVAL;
6784 }
6785 }
6786 break;
6787 }
6788 case SCTP_PKTDROP_SUPPORTED:
6789 {
6790 struct sctp_assoc_value *av;
6791
6792 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6793 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6794
6795 if (stcb) {
6796 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6797 error = EINVAL;
6798 SCTP_TCB_UNLOCK(stcb);
6799 } else {
6800 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6801 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6802 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6803 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6804 SCTP_INP_WLOCK(inp);
6805 if (av->assoc_value == 0) {
6806 inp->pktdrop_supported = 0;
6807 } else {
6808 inp->pktdrop_supported = 1;
6809 }
6810 SCTP_INP_WUNLOCK(inp);
6811 } else {
6812 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6813 error = EINVAL;
6814 }
6815 }
6816 break;
6817 }
6818 case SCTP_MAX_CWND:
6819 {
6820 struct sctp_assoc_value *av;
6821 struct sctp_nets *net;
6822
6823 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6824 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6825
6826 if (stcb) {
6827 stcb->asoc.max_cwnd = av->assoc_value;
6828 if (stcb->asoc.max_cwnd > 0) {
6829 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6830 if ((net->cwnd > stcb->asoc.max_cwnd) &&
6831 (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
6832 net->cwnd = stcb->asoc.max_cwnd;
6833 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
6834 net->cwnd = net->mtu - sizeof(struct sctphdr);
6835 }
6836 }
6837 }
6838 }
6839 SCTP_TCB_UNLOCK(stcb);
6840 } else {
6841 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6842 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6843 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6844 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6845 SCTP_INP_WLOCK(inp);
6846 inp->max_cwnd = av->assoc_value;
6847 SCTP_INP_WUNLOCK(inp);
6848 } else {
6849 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6850 error = EINVAL;
6851 }
6852 }
6853 break;
6854 }
6855 default:
6856 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6857 error = ENOPROTOOPT;
6858 break;
6859 } /* end switch (opt) */
6860 return (error);
6861 }
6862
6863 int
6864 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6865 {
6866 struct epoch_tracker et;
6867 struct sctp_inpcb *inp;
6868 void *optval = NULL;
6869 void *p;
6870 size_t optsize = 0;
6871 int error = 0;
6872
6873 if ((sopt->sopt_level == SOL_SOCKET) &&
6874 (sopt->sopt_name == SO_SETFIB)) {
6875 inp = (struct sctp_inpcb *)so->so_pcb;
6876 if (inp == NULL) {
6877 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6878 return (EINVAL);
6879 }
6880 SCTP_INP_WLOCK(inp);
6881 inp->fibnum = so->so_fibnum;
6882 SCTP_INP_WUNLOCK(inp);
6883 return (0);
6884 }
6885 if (sopt->sopt_level != IPPROTO_SCTP) {
6886 /* wrong proto level... send back up to IP */
6887 #ifdef INET6
6888 if (INP_CHECK_SOCKAF(so, AF_INET6))
6889 error = ip6_ctloutput(so, sopt);
6890 #endif /* INET6 */
6891 #if defined(INET) && defined(INET6)
6892 else
6893 #endif
6894 #ifdef INET
6895 error = ip_ctloutput(so, sopt);
6896 #endif
6897 return (error);
6898 }
6899 optsize = sopt->sopt_valsize;
6900 if (optsize > SCTP_SOCKET_OPTION_LIMIT) {
6901 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6902 return (ENOBUFS);
6903 }
6904 if (optsize) {
6905 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6906 if (optval == NULL) {
6907 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6908 return (ENOBUFS);
6909 }
6910 error = sooptcopyin(sopt, optval, optsize, optsize);
6911 if (error) {
6912 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6913 goto out;
6914 }
6915 }
6916 p = (void *)sopt->sopt_td;
6917 if (sopt->sopt_dir == SOPT_SET) {
6918 NET_EPOCH_ENTER(et);
6919 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6920 NET_EPOCH_EXIT(et);
6921 } else if (sopt->sopt_dir == SOPT_GET) {
6922 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6923 } else {
6924 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6925 error = EINVAL;
6926 }
6927 if ((error == 0) && (optval != NULL)) {
6928 error = sooptcopyout(sopt, optval, optsize);
6929 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6930 } else if (optval != NULL) {
6931 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6932 }
6933 out:
6934 return (error);
6935 }
6936
6937 #ifdef INET
6938 static int
6939 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6940 {
6941 struct epoch_tracker et;
6942 int error = 0;
6943 int create_lock_on = 0;
6944 uint32_t vrf_id;
6945 struct sctp_inpcb *inp;
6946 struct sctp_tcb *stcb = NULL;
6947
6948 inp = (struct sctp_inpcb *)so->so_pcb;
6949 if (inp == NULL) {
6950 /* I made the same as TCP since we are not setup? */
6951 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6952 return (ECONNRESET);
6953 }
6954 if (addr == NULL) {
6955 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6956 return EINVAL;
6957 }
6958
6959 switch (addr->sa_family) {
6960 #ifdef INET6
6961 case AF_INET6:
6962 {
6963 struct sockaddr_in6 *sin6;
6964
6965 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6966 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6967 return (EINVAL);
6968 }
6969 sin6 = (struct sockaddr_in6 *)addr;
6970 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6->sin6_addr)) != 0) {
6971 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6972 return (error);
6973 }
6974 break;
6975 }
6976 #endif
6977 #ifdef INET
6978 case AF_INET:
6979 {
6980 struct sockaddr_in *sin;
6981
6982 if (addr->sa_len != sizeof(struct sockaddr_in)) {
6983 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6984 return (EINVAL);
6985 }
6986 sin = (struct sockaddr_in *)addr;
6987 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
6988 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6989 return (error);
6990 }
6991 break;
6992 }
6993 #endif
6994 default:
6995 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6996 return (EAFNOSUPPORT);
6997 }
6998 SCTP_INP_INCR_REF(inp);
6999 SCTP_ASOC_CREATE_LOCK(inp);
7000 create_lock_on = 1;
7001 NET_EPOCH_ENTER(et);
7002
7003 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
7004 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
7005 /* Should I really unlock ? */
7006 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
7007 error = EFAULT;
7008 goto out_now;
7009 }
7010 #ifdef INET6
7011 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7012 (addr->sa_family == AF_INET6)) {
7013 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7014 error = EINVAL;
7015 goto out_now;
7016 }
7017 #endif
7018 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7019 /* Bind a ephemeral port */
7020 error = sctp_inpcb_bind(so, NULL, NULL, p);
7021 if (error) {
7022 goto out_now;
7023 }
7024 }
7025 /* Now do we connect? */
7026 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
7027 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
7028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7029 error = EINVAL;
7030 goto out_now;
7031 }
7032 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7033 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7034 /* We are already connected AND the TCP model */
7035 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7036 error = EADDRINUSE;
7037 goto out_now;
7038 }
7039 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7040 SCTP_INP_RLOCK(inp);
7041 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7042 SCTP_INP_RUNLOCK(inp);
7043 } else {
7044 /*
7045 * We increment here since sctp_findassociation_ep_addr()
7046 * will do a decrement if it finds the stcb as long as the
7047 * locked tcb (last argument) is NOT a TCB.. aka NULL.
7048 */
7049 SCTP_INP_INCR_REF(inp);
7050 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
7051 if (stcb == NULL) {
7052 SCTP_INP_DECR_REF(inp);
7053 } else {
7054 SCTP_TCB_UNLOCK(stcb);
7055 }
7056 }
7057 if (stcb != NULL) {
7058 /* Already have or am bring up an association */
7059 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
7060 error = EALREADY;
7061 goto out_now;
7062 }
7063
7064 vrf_id = inp->def_vrf_id;
7065 /* We are GOOD to go */
7066 stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
7067 inp->sctp_ep.pre_open_stream_count,
7068 inp->sctp_ep.port, p,
7069 SCTP_INITIALIZE_AUTH_PARAMS);
7070 if (stcb == NULL) {
7071 /* Gak! no memory */
7072 goto out_now;
7073 }
7074 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
7075 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
7076
7077 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7078 SCTP_TCB_UNLOCK(stcb);
7079 out_now:
7080 NET_EPOCH_EXIT(et);
7081 if (create_lock_on) {
7082 SCTP_ASOC_CREATE_UNLOCK(inp);
7083 }
7084 SCTP_INP_DECR_REF(inp);
7085 return (error);
7086 }
7087 #endif
7088
7089 int
7090 sctp_listen(struct socket *so, int backlog, struct thread *p)
7091 {
7092 /*
7093 * Note this module depends on the protocol processing being called
7094 * AFTER any socket level flags and backlog are applied to the
7095 * socket. The traditional way that the socket flags are applied is
7096 * AFTER protocol processing. We have made a change to the
7097 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
7098 * place if the socket API for SCTP is to work properly.
7099 */
7100
7101 int error = 0;
7102 struct sctp_inpcb *inp;
7103
7104 inp = (struct sctp_inpcb *)so->so_pcb;
7105 if (inp == NULL) {
7106 /* I made the same as TCP since we are not setup? */
7107 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7108 return (ECONNRESET);
7109 }
7110 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
7111 /* See if we have a listener */
7112 struct sctp_inpcb *tinp;
7113 union sctp_sockstore store;
7114
7115 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
7116 /* not bound all */
7117 struct sctp_laddr *laddr;
7118
7119 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7120 memcpy(&store, &laddr->ifa->address, sizeof(store));
7121 switch (store.sa.sa_family) {
7122 #ifdef INET
7123 case AF_INET:
7124 store.sin.sin_port = inp->sctp_lport;
7125 break;
7126 #endif
7127 #ifdef INET6
7128 case AF_INET6:
7129 store.sin6.sin6_port = inp->sctp_lport;
7130 break;
7131 #endif
7132 default:
7133 break;
7134 }
7135 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7136 if (tinp && (tinp != inp) &&
7137 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7138 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7139 (SCTP_IS_LISTENING(tinp))) {
7140 /*
7141 * we have a listener already and
7142 * its not this inp.
7143 */
7144 SCTP_INP_DECR_REF(tinp);
7145 return (EADDRINUSE);
7146 } else if (tinp) {
7147 SCTP_INP_DECR_REF(tinp);
7148 }
7149 }
7150 } else {
7151 /* Setup a local addr bound all */
7152 memset(&store, 0, sizeof(store));
7153 #ifdef INET6
7154 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
7155 store.sa.sa_family = AF_INET6;
7156 store.sa.sa_len = sizeof(struct sockaddr_in6);
7157 }
7158 #endif
7159 #ifdef INET
7160 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7161 store.sa.sa_family = AF_INET;
7162 store.sa.sa_len = sizeof(struct sockaddr_in);
7163 }
7164 #endif
7165 switch (store.sa.sa_family) {
7166 #ifdef INET
7167 case AF_INET:
7168 store.sin.sin_port = inp->sctp_lport;
7169 break;
7170 #endif
7171 #ifdef INET6
7172 case AF_INET6:
7173 store.sin6.sin6_port = inp->sctp_lport;
7174 break;
7175 #endif
7176 default:
7177 break;
7178 }
7179 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7180 if (tinp && (tinp != inp) &&
7181 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7182 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7183 (SCTP_IS_LISTENING(tinp))) {
7184 /*
7185 * we have a listener already and its not
7186 * this inp.
7187 */
7188 SCTP_INP_DECR_REF(tinp);
7189 return (EADDRINUSE);
7190 } else if (tinp) {
7191 SCTP_INP_DECR_REF(tinp);
7192 }
7193 }
7194 }
7195 SCTP_INP_RLOCK(inp);
7196 #ifdef SCTP_LOCK_LOGGING
7197 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
7198 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
7199 }
7200 #endif
7201 SOCK_LOCK(so);
7202 error = solisten_proto_check(so);
7203 SOCK_UNLOCK(so);
7204 if (error) {
7205 SCTP_INP_RUNLOCK(inp);
7206 return (error);
7207 }
7208 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
7209 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
7210 /*
7211 * The unlucky case - We are in the tcp pool with this guy.
7212 * - Someone else is in the main inp slot. - We must move
7213 * this guy (the listener) to the main slot - We must then
7214 * move the guy that was listener to the TCP Pool.
7215 */
7216 if (sctp_swap_inpcb_for_listen(inp)) {
7217 SCTP_INP_RUNLOCK(inp);
7218 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7219 return (EADDRINUSE);
7220 }
7221 }
7222
7223 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7224 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7225 /* We are already connected AND the TCP model */
7226 SCTP_INP_RUNLOCK(inp);
7227 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7228 return (EADDRINUSE);
7229 }
7230 SCTP_INP_RUNLOCK(inp);
7231 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7232 /* We must do a bind. */
7233 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
7234 /* bind error, probably perm */
7235 return (error);
7236 }
7237 }
7238 SCTP_INP_WLOCK(inp);
7239 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
7240 SOCK_LOCK(so);
7241 solisten_proto(so, backlog);
7242 SOCK_UNLOCK(so);
7243 }
7244 if (backlog > 0) {
7245 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
7246 } else {
7247 inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
7248 }
7249 SCTP_INP_WUNLOCK(inp);
7250 return (error);
7251 }
7252
7253 static int sctp_defered_wakeup_cnt = 0;
7254
7255 int
7256 sctp_accept(struct socket *so, struct sockaddr **addr)
7257 {
7258 struct sctp_tcb *stcb;
7259 struct sctp_inpcb *inp;
7260 union sctp_sockstore store;
7261 #ifdef INET6
7262 int error;
7263 #endif
7264 inp = (struct sctp_inpcb *)so->so_pcb;
7265
7266 if (inp == NULL) {
7267 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7268 return (ECONNRESET);
7269 }
7270 SCTP_INP_WLOCK(inp);
7271 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7272 SCTP_INP_WUNLOCK(inp);
7273 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
7274 return (EOPNOTSUPP);
7275 }
7276 if (so->so_state & SS_ISDISCONNECTED) {
7277 SCTP_INP_WUNLOCK(inp);
7278 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
7279 return (ECONNABORTED);
7280 }
7281 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7282 if (stcb == NULL) {
7283 SCTP_INP_WUNLOCK(inp);
7284 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7285 return (ECONNRESET);
7286 }
7287 SCTP_TCB_LOCK(stcb);
7288 store = stcb->asoc.primary_destination->ro._l_addr;
7289 SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
7290 /* Wake any delayed sleep action */
7291 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
7292 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
7293 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
7294 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
7295 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
7296 if (sowriteable(inp->sctp_socket)) {
7297 sowwakeup_locked(inp->sctp_socket);
7298 } else {
7299 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
7300 }
7301 }
7302 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
7303 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
7304 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
7305 if (soreadable(inp->sctp_socket)) {
7306 sctp_defered_wakeup_cnt++;
7307 sorwakeup_locked(inp->sctp_socket);
7308 } else {
7309 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
7310 }
7311 }
7312 }
7313 SCTP_INP_WUNLOCK(inp);
7314 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
7315 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
7316 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
7317 } else {
7318 SCTP_TCB_UNLOCK(stcb);
7319 }
7320 switch (store.sa.sa_family) {
7321 #ifdef INET
7322 case AF_INET:
7323 {
7324 struct sockaddr_in *sin;
7325
7326 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7327 if (sin == NULL)
7328 return (ENOMEM);
7329 sin->sin_family = AF_INET;
7330 sin->sin_len = sizeof(*sin);
7331 sin->sin_port = store.sin.sin_port;
7332 sin->sin_addr = store.sin.sin_addr;
7333 *addr = (struct sockaddr *)sin;
7334 break;
7335 }
7336 #endif
7337 #ifdef INET6
7338 case AF_INET6:
7339 {
7340 struct sockaddr_in6 *sin6;
7341
7342 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
7343 if (sin6 == NULL)
7344 return (ENOMEM);
7345 sin6->sin6_family = AF_INET6;
7346 sin6->sin6_len = sizeof(*sin6);
7347 sin6->sin6_port = store.sin6.sin6_port;
7348 sin6->sin6_addr = store.sin6.sin6_addr;
7349 if ((error = sa6_recoverscope(sin6)) != 0) {
7350 SCTP_FREE_SONAME(sin6);
7351 return (error);
7352 }
7353 *addr = (struct sockaddr *)sin6;
7354 break;
7355 }
7356 #endif
7357 default:
7358 /* TSNH */
7359 break;
7360 }
7361 return (0);
7362 }
7363
7364 #ifdef INET
7365 int
7366 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
7367 {
7368 struct sockaddr_in *sin;
7369 uint32_t vrf_id;
7370 struct sctp_inpcb *inp;
7371 struct sctp_ifa *sctp_ifa;
7372
7373 /*
7374 * Do the malloc first in case it blocks.
7375 */
7376 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7377 if (sin == NULL)
7378 return (ENOMEM);
7379 sin->sin_family = AF_INET;
7380 sin->sin_len = sizeof(*sin);
7381 inp = (struct sctp_inpcb *)so->so_pcb;
7382 if (!inp) {
7383 SCTP_FREE_SONAME(sin);
7384 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7385 return (ECONNRESET);
7386 }
7387 SCTP_INP_RLOCK(inp);
7388 sin->sin_port = inp->sctp_lport;
7389 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
7390 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7391 struct sctp_tcb *stcb;
7392 struct sockaddr_in *sin_a;
7393 struct sctp_nets *net;
7394 int fnd;
7395
7396 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7397 if (stcb == NULL) {
7398 goto notConn;
7399 }
7400 fnd = 0;
7401 sin_a = NULL;
7402 SCTP_TCB_LOCK(stcb);
7403 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7404 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7405 if (sin_a == NULL)
7406 /* this will make coverity happy */
7407 continue;
7408
7409 if (sin_a->sin_family == AF_INET) {
7410 fnd = 1;
7411 break;
7412 }
7413 }
7414 if ((!fnd) || (sin_a == NULL)) {
7415 /* punt */
7416 SCTP_TCB_UNLOCK(stcb);
7417 goto notConn;
7418 }
7419
7420 vrf_id = inp->def_vrf_id;
7421 sctp_ifa = sctp_source_address_selection(inp,
7422 stcb,
7423 (sctp_route_t *)&net->ro,
7424 net, 0, vrf_id);
7425 if (sctp_ifa) {
7426 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
7427 sctp_free_ifa(sctp_ifa);
7428 }
7429 SCTP_TCB_UNLOCK(stcb);
7430 } else {
7431 /* For the bound all case you get back 0 */
7432 notConn:
7433 sin->sin_addr.s_addr = 0;
7434 }
7435
7436 } else {
7437 /* Take the first IPv4 address in the list */
7438 struct sctp_laddr *laddr;
7439 int fnd = 0;
7440
7441 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7442 if (laddr->ifa->address.sa.sa_family == AF_INET) {
7443 struct sockaddr_in *sin_a;
7444
7445 sin_a = &laddr->ifa->address.sin;
7446 sin->sin_addr = sin_a->sin_addr;
7447 fnd = 1;
7448 break;
7449 }
7450 }
7451 if (!fnd) {
7452 SCTP_FREE_SONAME(sin);
7453 SCTP_INP_RUNLOCK(inp);
7454 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7455 return (ENOENT);
7456 }
7457 }
7458 SCTP_INP_RUNLOCK(inp);
7459 (*addr) = (struct sockaddr *)sin;
7460 return (0);
7461 }
7462
7463 int
7464 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
7465 {
7466 struct sockaddr_in *sin;
7467 int fnd;
7468 struct sockaddr_in *sin_a;
7469 struct sctp_inpcb *inp;
7470 struct sctp_tcb *stcb;
7471 struct sctp_nets *net;
7472
7473 /* Do the malloc first in case it blocks. */
7474 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
7475 if (sin == NULL)
7476 return (ENOMEM);
7477 sin->sin_family = AF_INET;
7478 sin->sin_len = sizeof(*sin);
7479
7480 inp = (struct sctp_inpcb *)so->so_pcb;
7481 if ((inp == NULL) ||
7482 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7483 /* UDP type and listeners will drop out here */
7484 SCTP_FREE_SONAME(sin);
7485 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7486 return (ENOTCONN);
7487 }
7488 SCTP_INP_RLOCK(inp);
7489 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7490 if (stcb) {
7491 SCTP_TCB_LOCK(stcb);
7492 }
7493 SCTP_INP_RUNLOCK(inp);
7494 if (stcb == NULL) {
7495 SCTP_FREE_SONAME(sin);
7496 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7497 return (ECONNRESET);
7498 }
7499 fnd = 0;
7500 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7501 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7502 if (sin_a->sin_family == AF_INET) {
7503 fnd = 1;
7504 sin->sin_port = stcb->rport;
7505 sin->sin_addr = sin_a->sin_addr;
7506 break;
7507 }
7508 }
7509 SCTP_TCB_UNLOCK(stcb);
7510 if (!fnd) {
7511 /* No IPv4 address */
7512 SCTP_FREE_SONAME(sin);
7513 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7514 return (ENOENT);
7515 }
7516 (*addr) = (struct sockaddr *)sin;
7517 return (0);
7518 }
7519
7520 struct pr_usrreqs sctp_usrreqs = {
7521 .pru_abort = sctp_abort,
7522 .pru_accept = sctp_accept,
7523 .pru_attach = sctp_attach,
7524 .pru_bind = sctp_bind,
7525 .pru_connect = sctp_connect,
7526 .pru_control = in_control,
7527 .pru_close = sctp_close,
7528 .pru_detach = sctp_close,
7529 .pru_sopoll = sopoll_generic,
7530 .pru_flush = sctp_flush,
7531 .pru_disconnect = sctp_disconnect,
7532 .pru_listen = sctp_listen,
7533 .pru_peeraddr = sctp_peeraddr,
7534 .pru_send = sctp_sendm,
7535 .pru_shutdown = sctp_shutdown,
7536 .pru_sockaddr = sctp_ingetaddr,
7537 .pru_sosend = sctp_sosend,
7538 .pru_soreceive = sctp_soreceive
7539 };
7540 #endif
7541