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