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