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