sctp: import internal copy of usrsctp library
[platform/upstream/gstreamer.git] / ext / sctp / usrsctp / usrsctplib / netinet / sctp_usrreq.c
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__)
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
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
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
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
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