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