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