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