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