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