Merge from vendor branch GCC:
[dragonfly.git] / sys / netinet / sctp_usrreq.c
1 /*      $KAME: sctp_usrreq.c,v 1.47 2005/03/06 16:04:18 itojun Exp $    */
2 /*      $DragonFly: src/sys/netinet/sctp_usrreq.c,v 1.6 2005/07/15 17:19:28 eirikn Exp $        */
3
4 /*
5  * Copyright (c) 2001, 2002, 2003, 2004 Cisco Systems, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by Cisco Systems, Inc.
19  * 4. Neither the name of the project nor the names of its contributors
20  *    may be used to endorse or promote products derived from this software
21  *    without specific prior written permission.
22  *
23  * THIS SOFTWARE IS PROVIDED BY CISCO SYSTEMS AND CONTRIBUTORS ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL CISCO SYSTEMS OR CONTRIBUTORS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  */
35 #if !(defined(__OpenBSD__) || defined(__APPLE__))
36 #include "opt_ipsec.h"
37 #endif
38 #if defined(__FreeBSD__) || defined(__DragonFly__)
39 #include "opt_inet6.h"
40 #include "opt_inet.h"
41 #endif
42 #if defined(__NetBSD__)
43 #include "opt_inet.h"
44 #endif
45
46 #ifdef __APPLE__
47 #include <sctp.h>
48 #elif !defined(__OpenBSD__)
49 #include "opt_sctp.h"
50 #endif
51
52 #include <sys/param.h>
53 #include <sys/systm.h>
54 #include <sys/kernel.h>
55 #include <sys/malloc.h>
56 #include <sys/mbuf.h>
57 #include <sys/domain.h>
58 #include <sys/proc.h>
59 #include <sys/protosw.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/sysctl.h>
63 #include <sys/syslog.h>
64 #include <sys/thread2.h>
65 #include <net/if.h>
66 #include <net/if_types.h>
67 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
68 #include <net/if_var.h>
69 #endif
70 #include <net/route.h>
71 #include <netinet/in.h>
72 #include <netinet/in_systm.h>
73 #include <netinet/ip.h>
74 #include <netinet/ip6.h>
75 #include <netinet/in_pcb.h>
76 #include <netinet/in_var.h>
77 #include <netinet/ip_var.h>
78 #include <netinet6/ip6_var.h>
79 #include <netinet6/in6_var.h>
80
81 #include <netinet/ip_icmp.h>
82 #include <netinet/icmp_var.h>
83 #include <netinet/sctp_pcb.h>
84 #include <netinet/sctp_header.h>
85 #include <netinet/sctp_var.h>
86 #include <netinet/sctp_output.h>
87 #include <netinet/sctp_uio.h>
88 #include <netinet/sctp_asconf.h>
89 #include <netinet/sctputil.h>
90 #include <netinet/sctp_indata.h>
91 #include <netinet/sctp_asconf.h>
92 #ifdef IPSEC
93 #ifndef __OpenBSD__
94 #include <netinet6/ipsec.h>
95 #include <netkey/key.h>
96 #else
97 #undef IPSEC
98 #endif
99 #endif /* IPSEC */
100
101 #include <net/net_osdep.h>
102
103 #if defined(HAVE_NRL_INPCB) || defined(__FreeBSD__) || defined(__DragonFly__)
104 #ifndef in6pcb
105 #define in6pcb          inpcb
106 #endif
107 #ifndef sotoin6pcb
108 #define sotoin6pcb      sotoinpcb
109 #endif
110 #endif
111
112 #ifdef SCTP_DEBUG
113 extern u_int32_t sctp_debug_on;
114 #endif /* SCTP_DEBUG */
115
116 /*
117  * sysctl tunable variables
118  */
119 int sctp_auto_asconf = SCTP_DEFAULT_AUTO_ASCONF;
120 int sctp_max_burst_default = SCTP_DEF_MAX_BURST;
121 int sctp_peer_chunk_oh = sizeof(struct mbuf);
122 int sctp_strict_init = 1;
123 int sctp_no_csum_on_loopback = 1;
124 unsigned int sctp_max_chunks_on_queue = SCTP_ASOC_MAX_CHUNKS_ON_QUEUE;
125 int sctp_sendspace = (128 * 1024);
126 int sctp_recvspace = 128 * (1024 +
127 #ifdef INET6
128                                 sizeof(struct sockaddr_in6)
129 #else
130                                 sizeof(struct sockaddr_in)
131 #endif
132         );
133 int sctp_strict_sacks = 0;
134 int sctp_ecn = 1;
135 int sctp_ecn_nonce = 0;
136
137 unsigned int sctp_delayed_sack_time_default = SCTP_RECV_MSEC;
138 unsigned int sctp_heartbeat_interval_default = SCTP_HB_DEFAULT_MSEC;
139 unsigned int sctp_pmtu_raise_time_default = SCTP_DEF_PMTU_RAISE_SEC;
140 unsigned int sctp_shutdown_guard_time_default = SCTP_DEF_MAX_SHUTDOWN_SEC;
141 unsigned int sctp_secret_lifetime_default = SCTP_DEFAULT_SECRET_LIFE_SEC;
142 unsigned int sctp_rto_max_default = SCTP_RTO_UPPER_BOUND;
143 unsigned int sctp_rto_min_default = SCTP_RTO_LOWER_BOUND;
144 unsigned int sctp_rto_initial_default = SCTP_RTO_INITIAL;
145 unsigned int sctp_init_rto_max_default = SCTP_RTO_UPPER_BOUND;
146 unsigned int sctp_valid_cookie_life_default = SCTP_DEFAULT_COOKIE_LIFE;
147 unsigned int sctp_init_rtx_max_default = SCTP_DEF_MAX_INIT;
148 unsigned int sctp_assoc_rtx_max_default = SCTP_DEF_MAX_SEND;
149 unsigned int sctp_path_rtx_max_default = SCTP_DEF_MAX_SEND/2;
150 unsigned int sctp_nr_outgoing_streams_default = SCTP_OSTREAM_INITIAL;
151
152 void
153 sctp_init(void)
154 {
155 #ifdef __OpenBSD__
156 #define nmbclusters     nmbclust
157 #endif
158         /* Init the SCTP pcb in sctp_pcb.c */
159         u_long sb_max_adj;
160
161         sctp_pcb_init();
162
163 #ifndef __OpenBSD__
164         if (nmbclusters > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
165                 sctp_max_chunks_on_queue = nmbclusters;
166 #else
167 /*      if (nmbclust > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
168         sctp_max_chunks_on_queue = nmbclust; FIX ME */
169         sctp_max_chunks_on_queue = nmbclust * 2;
170 #endif
171         /*
172          * Allow a user to take no more than 1/2 the number of clusters
173          * or the SB_MAX whichever is smaller for the send window.
174          */
175         sb_max_adj = (u_long)((u_quad_t)(SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
176         sctp_sendspace = min((min(SB_MAX, sb_max_adj)),
177 #ifndef __OpenBSD__
178                              ((nmbclusters/2) * SCTP_DEFAULT_MAXSEGMENT));
179 #else
180                              ((nmbclust/2) * SCTP_DEFAULT_MAXSEGMENT));
181 #endif
182         /*
183          * Now for the recv window, should we take the same amount?
184          * or should I do 1/2 the SB_MAX instead in the SB_MAX min above.
185          * For now I will just copy.
186          */
187         sctp_recvspace = sctp_sendspace;
188 #ifdef __OpenBSD__
189 #undef nmbclusters
190 #endif
191 }
192
193 #ifdef INET6
194 void
195 ip_2_ip6_hdr(struct ip6_hdr *ip6, struct ip *ip)
196 {
197         bzero(ip6, sizeof(*ip6));
198
199         ip6->ip6_vfc = IPV6_VERSION;
200         ip6->ip6_plen = ip->ip_len;
201         ip6->ip6_nxt = ip->ip_p;
202         ip6->ip6_hlim = ip->ip_ttl;
203         ip6->ip6_src.s6_addr32[2] = ip6->ip6_dst.s6_addr32[2] =
204                 IPV6_ADDR_INT32_SMP;
205         ip6->ip6_src.s6_addr32[3] = ip->ip_src.s_addr;
206         ip6->ip6_dst.s6_addr32[3] = ip->ip_dst.s_addr;
207 }
208 #endif /* INET6 */
209
210 static void
211 sctp_split_chunks(struct sctp_association *asoc,
212                   struct sctp_stream_out *strm,
213                   struct sctp_tmit_chunk *chk)
214 {
215         struct sctp_tmit_chunk *new_chk;
216
217         /* First we need a chunk */
218         new_chk = (struct sctp_tmit_chunk *)SCTP_ZONE_GET(sctppcbinfo.ipi_zone_chunk);
219         if (new_chk == NULL) {
220                 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
221                 return;
222         }
223         sctppcbinfo.ipi_count_chunk++;
224         sctppcbinfo.ipi_gencnt_chunk++;
225         /* Copy it all */
226         *new_chk = *chk;
227         /*  split the data */
228         new_chk->data = m_split(chk->data, (chk->send_size>>1), MB_DONTWAIT);
229         if (new_chk->data == NULL) {
230                 /* Can't split */
231                 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
232                 SCTP_ZONE_FREE(sctppcbinfo.ipi_zone_chunk, new_chk);
233                 sctppcbinfo.ipi_count_chunk--;
234                 if ((int)sctppcbinfo.ipi_count_chunk < 0) {
235                         panic("Chunk count is negative");
236                 }
237                 sctppcbinfo.ipi_gencnt_chunk++;
238                 return;
239
240         }
241         /* Data is now split adjust sizes */
242         chk->send_size >>= 1;
243         new_chk->send_size >>= 1;
244
245         chk->book_size >>= 1;
246         new_chk->book_size >>= 1;
247
248         /* now adjust the marks */
249         chk->rec.data.rcv_flags |= SCTP_DATA_FIRST_FRAG;
250         chk->rec.data.rcv_flags &= ~SCTP_DATA_LAST_FRAG;
251
252         new_chk->rec.data.rcv_flags &= ~SCTP_DATA_FIRST_FRAG;
253         new_chk->rec.data.rcv_flags |= SCTP_DATA_LAST_FRAG;
254
255         /* Increase ref count if dest is set */
256         if (chk->whoTo) {
257                 new_chk->whoTo->ref_count++;
258         }
259         /* now drop it on the end of the list*/
260         asoc->stream_queue_cnt++;
261         TAILQ_INSERT_AFTER(&strm->outqueue, chk, new_chk, sctp_next);
262 }
263
264 static void
265 sctp_notify_mbuf(struct sctp_inpcb *inp,
266                  struct sctp_tcb *stcb,
267                  struct sctp_nets *net,
268                  struct ip *ip,
269                  struct sctphdr *sh)
270
271 {
272         struct icmp *icmph;
273         int totsz;
274         uint16_t nxtsz;
275
276         /* protection */
277         if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
278             (ip == NULL) || (sh == NULL)) {
279                 if (stcb != NULL)
280                         SCTP_TCB_UNLOCK(stcb);
281                 return;
282         }
283         /* First job is to verify the vtag matches what I would send */
284         if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
285                 SCTP_TCB_UNLOCK(stcb);
286                 return;
287         }
288         icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
289                                                sizeof(struct ip)));
290         if (icmph->icmp_type != ICMP_UNREACH) {
291                 /* We only care about unreachable */
292                 SCTP_TCB_UNLOCK(stcb);
293                 return;
294         }
295         if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
296                 /* not a unreachable message due to frag. */
297                 SCTP_TCB_UNLOCK(stcb);
298                 return;
299         }
300         totsz = ip->ip_len;
301         nxtsz = ntohs(icmph->icmp_seq);
302         if (nxtsz == 0) {
303                 /*
304                  * old type router that does not tell us what the next size
305                  * mtu is. Rats we will have to guess (in a educated fashion
306                  * of course)
307                  */
308                 nxtsz = find_next_best_mtu(totsz);
309         }
310
311         /* Stop any PMTU timer */
312         sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
313
314         /* Adjust destination size limit */
315         if (net->mtu > nxtsz) {
316                 net->mtu = nxtsz;
317         }
318         /* now what about the ep? */
319         if (stcb->asoc.smallest_mtu > nxtsz) {
320                 struct sctp_tmit_chunk *chk, *nchk;
321                 struct sctp_stream_out *strm;
322                 /* Adjust that too */
323                 stcb->asoc.smallest_mtu = nxtsz;
324                 /* now off to subtract IP_DF flag if needed */
325
326                 TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
327                         if ((chk->send_size+IP_HDR_SIZE) > nxtsz) {
328                                 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
329                         }
330                 }
331                 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
332                         if ((chk->send_size+IP_HDR_SIZE) > nxtsz) {
333                                 /*
334                                  * For this guy we also mark for immediate
335                                  * resend since we sent to big of chunk
336                                  */
337                                 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
338                                 if (chk->sent != SCTP_DATAGRAM_RESEND) {
339                                         stcb->asoc.sent_queue_retran_cnt++;
340                                 }
341                                 chk->sent = SCTP_DATAGRAM_RESEND;
342                                 chk->rec.data.doing_fast_retransmit = 0;
343
344                                 /* Clear any time so NO RTT is being done */
345                                 chk->do_rtt = 0;
346                                 stcb->asoc.total_flight -= chk->book_size;
347                                 if (stcb->asoc.total_flight < 0) {
348                                         stcb->asoc.total_flight = 0;
349                                 }
350                                 stcb->asoc.total_flight_count--;
351                                 if (stcb->asoc.total_flight_count < 0) {
352                                         stcb->asoc.total_flight_count = 0;
353                                 }
354                                 net->flight_size -= chk->book_size;
355                                 if (net->flight_size < 0) {
356                                         net->flight_size = 0;
357                                 }
358                         }
359                 }
360                 TAILQ_FOREACH(strm, &stcb->asoc.out_wheel, next_spoke) {
361                         chk = TAILQ_FIRST(&strm->outqueue);
362                         while (chk) {
363                                 nchk = TAILQ_NEXT(chk, sctp_next);
364                                 if ((chk->send_size+SCTP_MED_OVERHEAD) > nxtsz) {
365                                         sctp_split_chunks(&stcb->asoc, strm, chk);
366                                 }
367                                 chk = nchk;
368                         }
369                 }
370         }
371         sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, NULL);
372         SCTP_TCB_UNLOCK(stcb);
373 }
374
375
376 void
377 sctp_notify(struct sctp_inpcb *inp,
378             int errno,
379             struct sctphdr *sh,
380             struct sockaddr *to,
381             struct sctp_tcb *stcb,
382             struct sctp_nets *net)
383 {
384         /* protection */
385         if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
386             (sh == NULL) || (to == NULL)) {
387 #ifdef SCTP_DEBUG
388                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
389                         printf("sctp-notify, bad call\n");
390                 }
391 #endif /* SCTP_DEBUG */
392                 return;
393         }
394         /* First job is to verify the vtag matches what I would send */
395         if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
396                 return;
397         }
398
399 /* FIX ME FIX ME PROTOPT i.e. no SCTP should ALWAYS be an ABORT */
400
401         if ((errno == EHOSTUNREACH) ||  /* Host is not reachable */
402             (errno == EHOSTDOWN) ||     /* Host is down */
403             (errno == ECONNREFUSED) ||  /* Host refused the connection, (not an abort?) */
404             (errno == ENOPROTOOPT)      /* SCTP is not present on host */
405                 ) {
406                 /*
407                  * Hmm reachablity problems we must examine closely.
408                  * If its not reachable, we may have lost a network.
409                  * Or if there is NO protocol at the other end named SCTP.
410                  * well we consider it a OOTB abort.
411                  */
412                 if ((errno == EHOSTUNREACH) || (errno == EHOSTDOWN)) {
413                         if (net->dest_state & SCTP_ADDR_REACHABLE) {
414                                 /* Ok that destination is NOT reachable */
415                                 net->dest_state &= ~SCTP_ADDR_REACHABLE;
416                                 net->dest_state |= SCTP_ADDR_NOT_REACHABLE;
417                                 net->error_count = net->failure_threshold + 1;
418                                 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
419                                                 stcb, SCTP_FAILED_THRESHOLD,
420                                                 (void *)net);
421                         }
422                         if (stcb)
423                                 SCTP_TCB_UNLOCK(stcb);
424                 } else {
425                         /*
426                          * Here the peer is either playing tricks on us,
427                          * including an address that belongs to someone who
428                          * does not support SCTP OR was a userland
429                          * implementation that shutdown and now is dead. In
430                          * either case treat it like a OOTB abort with no TCB
431                          */
432                         sctp_abort_notification(stcb, SCTP_PEER_FAULTY);
433                         sctp_free_assoc(inp, stcb);
434                         /* no need to unlock here, since the TCB is gone */
435                 }
436         } else {
437                 /* Send all others to the app */
438                 if (inp->sctp_socket) {
439                         SOCK_LOCK(inp->sctp_socket);
440                         inp->sctp_socket->so_error = errno;
441                         sctp_sowwakeup(inp, inp->sctp_socket);
442                         SOCK_UNLOCK(inp->sctp_socket);
443                 }
444                 if (stcb)
445                         SCTP_TCB_UNLOCK(stcb);
446         }
447 }
448
449 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
450 void
451 #else
452 void *
453 #endif
454 sctp_ctlinput(cmd, sa, vip)
455         int cmd;
456         struct sockaddr *sa;
457         void *vip;
458 {
459         struct ip *ip = vip;
460         struct sctphdr *sh;
461
462
463         if (sa->sa_family != AF_INET ||
464             ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
465 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
466                 return;
467 #else
468                 return (NULL);
469 #endif
470         }
471
472         if (PRC_IS_REDIRECT(cmd)) {
473                 ip = 0;
474         } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
475 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
476                 return;
477 #else
478                 return (NULL);
479 #endif
480         }
481         if (ip) {
482                 struct sctp_inpcb *inp;
483                 struct sctp_tcb *stcb;
484                 struct sctp_nets *net;
485                 struct sockaddr_in to, from;
486
487                 sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
488                 bzero(&to, sizeof(to));
489                 bzero(&from, sizeof(from));
490                 from.sin_family = to.sin_family = AF_INET;
491                 from.sin_len = to.sin_len = sizeof(to);
492                 from.sin_port = sh->src_port;
493                 from.sin_addr = ip->ip_src;
494                 to.sin_port = sh->dest_port;
495                 to.sin_addr = ip->ip_dst;
496
497                 /*
498                  * 'to' holds the dest of the packet that failed to be sent.
499                  * 'from' holds our local endpoint address.
500                  * Thus we reverse the to and the from in the lookup.
501                  */
502                 crit_enter();
503                 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&from,
504                                                     (struct sockaddr *)&to,
505                                                     &inp, &net, 1);
506                 if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
507                         if (cmd != PRC_MSGSIZE) {
508                                 int cm;
509                                 if (cmd == PRC_HOSTDEAD) {
510                                         cm = EHOSTUNREACH;
511                                 } else {
512                                         cm = inetctlerrmap[cmd];
513                                 }
514                                 sctp_notify(inp, cm, sh,
515                                             (struct sockaddr *)&to, stcb,
516                                             net);
517                         } else {
518                                 /* handle possible ICMP size messages */
519                                 sctp_notify_mbuf(inp, stcb, net, ip, sh);
520                         }
521                 } else {
522 #if (defined(__FreeBSD__) && __FreeBSD_version < 500000) || defined(__DragonFly__)
523                         /* XXX must be fixed for 5.x and higher, leave for 4.x */
524                         if (PRC_IS_REDIRECT(cmd) && inp) {
525                                 in_rtchange((struct inpcb *)inp,
526                                             inetctlerrmap[cmd]);
527                         }
528 #endif
529                         if ((stcb == NULL) && (inp != NULL)) {
530                                 /* reduce ref-count */
531                                 SCTP_INP_WLOCK(inp);
532                                 SCTP_INP_DECR_REF(inp);
533                                 SCTP_INP_WUNLOCK(inp);
534                         }
535
536                 }
537                 crit_exit();
538         }
539 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
540         return;
541 #else
542         return (NULL);
543 #endif
544 }
545
546 #if defined(__FreeBSD__) || defined(__DragonFly__)
547 static int
548 sctp_getcred(SYSCTL_HANDLER_ARGS)
549 {
550         struct sockaddr_in addrs[2];
551         struct sctp_inpcb *inp;
552         struct sctp_nets *net;
553         struct sctp_tcb *stcb;
554         int error;
555
556 #if __FreeBSD_version >= 500000 || defined(__DragonFly__)
557         error = suser(req->td);
558 #else
559         error = suser(req->p);
560 #endif
561         if (error)
562                 return (error);
563         error = SYSCTL_IN(req, addrs, sizeof(addrs));
564         if (error)
565                 return (error);
566
567         crit_enter();
568         stcb = sctp_findassociation_addr_sa(sintosa(&addrs[0]),
569                                            sintosa(&addrs[1]),
570                                            &inp, &net, 1);
571         if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
572                 if ((inp != NULL) && (stcb == NULL)) {
573                         /* reduce ref-count */
574                         SCTP_INP_WLOCK(inp);
575                         SCTP_INP_DECR_REF(inp);
576                         SCTP_INP_WUNLOCK(inp);
577                 }
578                 error = ENOENT;
579                 goto out;
580         }
581         error = SYSCTL_OUT(req, inp->sctp_socket->so_cred, sizeof(struct ucred));
582         SCTP_TCB_UNLOCK(stcb);
583 out:
584         crit_exit();
585         return (error);
586 }
587
588 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE|CTLFLAG_RW,
589             0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
590 #endif /* #if defined(__FreeBSD__) || defined(__DragonFly__) */
591
592 /*
593  * sysctl definitions
594  */
595 #if defined(__FreeBSD__) || defined (__APPLE__) || defined(__DragonFly__)
596
597 SYSCTL_DECL(_net_inet);
598
599 SYSCTL_NODE(_net_inet, OID_AUTO, sctp, CTLFLAG_RD, 0,
600         "sctp values");
601
602 SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxdgram, CTLFLAG_RW,
603            &sctp_sendspace, 0, "Maximum outgoing SCTP buffer size");
604
605 SYSCTL_INT(_net_inet_sctp, OID_AUTO, recvspace, CTLFLAG_RW,
606            &sctp_recvspace, 0, "Maximum incoming SCTP buffer size");
607
608 SYSCTL_INT(_net_inet_sctp, OID_AUTO, auto_asconf, CTLFLAG_RW,
609            &sctp_auto_asconf, 0, "Enable SCTP Auto-ASCONF");
610
611 SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_enable, CTLFLAG_RW,
612            &sctp_ecn, 0, "Enable SCTP ECN");
613
614 SYSCTL_INT(_net_inet_sctp, OID_AUTO, ecn_nonce, CTLFLAG_RW,
615            &sctp_ecn_nonce, 0, "Enable SCTP ECN Nonce");
616
617 SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_sacks, CTLFLAG_RW,
618            &sctp_strict_sacks, 0, "Enable SCTP Strict SACK checking");
619
620 SYSCTL_INT(_net_inet_sctp, OID_AUTO, loopback_nocsum, CTLFLAG_RW,
621            &sctp_no_csum_on_loopback, 0,
622            "Enable NO Csum on packets sent on loopback");
623
624 SYSCTL_INT(_net_inet_sctp, OID_AUTO, strict_init, CTLFLAG_RW,
625            &sctp_strict_init, 0,
626            "Enable strict INIT/INIT-ACK singleton enforcement");
627
628 SYSCTL_INT(_net_inet_sctp, OID_AUTO, peer_chkoh, CTLFLAG_RW,
629            &sctp_peer_chunk_oh, 0,
630            "Amount to debit peers rwnd per chunk sent");
631
632 SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxburst, CTLFLAG_RW,
633            &sctp_max_burst_default, 0,
634            "Default max burst for sctp endpoints");
635
636 SYSCTL_INT(_net_inet_sctp, OID_AUTO, maxchunks, CTLFLAG_RW,
637            &sctp_max_chunks_on_queue, 0,
638            "Default max chunks on queue per asoc");
639
640 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, delayed_sack_time, CTLFLAG_RW,
641             &sctp_delayed_sack_time_default, 0,
642             "Default delayed SACK timer in msec");
643
644 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, heartbeat_interval, CTLFLAG_RW,
645             &sctp_heartbeat_interval_default, 0,
646             "Default heartbeat interval in msec");
647
648 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, pmtu_raise_time, CTLFLAG_RW,
649             &sctp_pmtu_raise_time_default, 0,
650             "Default PMTU raise timer in sec");
651
652 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, shutdown_guard_time, CTLFLAG_RW,
653             &sctp_shutdown_guard_time_default, 0,
654             "Default shutdown guard timer in sec");
655
656 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, secret_lifetime, CTLFLAG_RW,
657             &sctp_secret_lifetime_default, 0,
658             "Default secret lifetime in sec");
659
660 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_max, CTLFLAG_RW,
661             &sctp_rto_max_default, 0,
662             "Default maximum retransmission timeout in msec");
663
664 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_min, CTLFLAG_RW,
665             &sctp_rto_min_default, 0,
666             "Default minimum retransmission timeout in msec");
667
668 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, rto_initial, CTLFLAG_RW,
669             &sctp_rto_initial_default, 0,
670             "Default initial retransmission timeout in msec");
671
672 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rto_max, CTLFLAG_RW,
673             &sctp_init_rto_max_default, 0,
674             "Default maximum retransmission timeout during association setup in msec");
675
676 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, valid_cookie_life, CTLFLAG_RW,
677             &sctp_valid_cookie_life_default, 0,
678             "Default cookie lifetime in sec");
679
680 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, init_rtx_max, CTLFLAG_RW,
681             &sctp_init_rtx_max_default, 0,
682             "Default maximum number of retransmission for INIT chunks");
683
684 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, assoc_rtx_max, CTLFLAG_RW,
685             &sctp_assoc_rtx_max_default, 0,
686             "Default maximum number of retransmissions per association");
687
688 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, path_rtx_max, CTLFLAG_RW,
689             &sctp_path_rtx_max_default, 0,
690             "Default maximum of retransmissions per path");
691
692 SYSCTL_UINT(_net_inet_sctp, OID_AUTO, nr_outgoing_streams, CTLFLAG_RW,
693             &sctp_nr_outgoing_streams_default, 0,
694             "Default number of outgoing streams");
695
696 #ifdef SCTP_DEBUG
697 SYSCTL_INT(_net_inet_sctp, OID_AUTO, debug, CTLFLAG_RW,
698            &sctp_debug_on, 0, "Configure debug output");
699 #endif /* SCTP_DEBUG */
700 #endif
701
702 static int
703 sctp_abort(struct socket *so)
704 {
705         struct sctp_inpcb *inp;
706
707         inp = (struct sctp_inpcb *)so->so_pcb;
708         if (inp == 0)
709                 return EINVAL;  /* ??? possible? panic instead? */
710
711         crit_enter();
712         sctp_inpcb_free(inp, 1);
713         crit_exit();
714         return 0;
715 }
716
717 static int
718 #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
719 sctp_attach(struct socket *so, int proto, struct thread *p)
720 #elif defined(__DragonFly__)
721 sctp_attach(struct socket *so, int proto, struct pru_attach_info *ai)
722 #else
723 sctp_attach(struct socket *so, int proto, struct proc *p)
724 #endif
725 {
726         struct sctp_inpcb *inp;
727         struct inpcb *ip_inp;
728         int error;
729
730         crit_enter();
731         inp = (struct sctp_inpcb *)so->so_pcb;
732         if (inp != 0) {
733                 crit_exit();
734                 return EINVAL;
735         }
736         error = soreserve(so, sctp_sendspace, sctp_recvspace, NULL);
737         if (error) {
738                 crit_exit();
739                 return error;
740         }
741         error = sctp_inpcb_alloc(so);
742         if (error) {
743                 crit_exit();
744                 return error;
745         }
746         inp = (struct sctp_inpcb *)so->so_pcb;
747         SCTP_INP_WLOCK(inp);
748
749         inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6;    /* I'm not v6! */
750         ip_inp = &inp->ip_inp.inp;
751 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
752         ip_inp->inp_vflag |= INP_IPV4;
753         ip_inp->inp_ip_ttl = ip_defttl;
754 #else
755         inp->inp_vflag |= INP_IPV4;
756         inp->inp_ip_ttl = ip_defttl;
757 #endif
758
759 #ifdef IPSEC
760 #if !(defined(__OpenBSD__) || defined(__APPLE__))
761         error = ipsec_init_pcbpolicy(so, &ip_inp->inp_sp);
762         if (error != 0) {
763                 sctp_inpcb_free(inp, 1);
764                 return error;
765         }
766 #endif
767 #endif /*IPSEC*/
768         SCTP_INP_WUNLOCK(inp);
769 #if defined(__NetBSD__)
770         so->so_send = sctp_sosend;
771 #endif
772         crit_exit();
773         return 0;
774 }
775
776 static int
777 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
778 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
779 {
780 #elif defined(__FreeBSD__) || defined(__APPLE__)
781 sctp_bind(struct socket *so, struct sockaddr *addr, struct proc *p)
782 {
783 #else
784 sctp_bind(struct socket *so, struct mbuf *nam, struct proc *p)
785 {
786         struct sockaddr *addr = nam ? mtod(nam, struct sockaddr *) : NULL;
787 #endif
788         struct sctp_inpcb *inp;
789         int error;
790
791 #ifdef INET6
792         if (addr && addr->sa_family != AF_INET)
793                 /* must be a v4 address! */
794                 return EINVAL;
795 #endif /* INET6 */
796
797         inp = (struct sctp_inpcb *)so->so_pcb;
798         if (inp == 0)
799                 return EINVAL;
800
801         crit_enter();
802         error = sctp_inpcb_bind(so, addr, p);
803         crit_exit();
804         return error;
805 }
806
807
808 static int
809 sctp_detach(struct socket *so)
810 {
811         struct sctp_inpcb *inp;
812
813         inp = (struct sctp_inpcb *)so->so_pcb;
814         if (inp == 0)
815                 return EINVAL;
816         crit_enter();
817         if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
818             (so->so_rcv.sb_cc > 0)) {
819                 sctp_inpcb_free(inp, 1);
820         } else {
821                 sctp_inpcb_free(inp, 0);
822         }
823         crit_exit();
824         return 0;
825 }
826
827 int
828 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
829 sctp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
830           struct mbuf *control, struct thread *p);
831 #else
832 sctp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
833           struct mbuf *control, struct proc *p);
834 #endif
835
836 int
837 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
838 sctp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
839           struct mbuf *control, struct thread *p)
840 {
841 #else
842 sctp_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
843           struct mbuf *control, struct proc *p)
844 {
845 #endif
846         struct sctp_inpcb *inp;
847         int error;
848         inp = (struct sctp_inpcb *)so->so_pcb;
849         if (inp == 0) {
850                 if (control) {
851                         sctp_m_freem(control);
852                         control = NULL;
853                 }
854                 sctp_m_freem(m);
855                 return EINVAL;
856         }
857         /* Got to have an to address if we are NOT a connected socket */
858         if ((addr == NULL) &&
859             ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
860              (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))
861                 ) {
862                 goto connected_type;
863         } else if (addr == NULL) {
864                 error = EDESTADDRREQ;
865                 sctp_m_freem(m);
866                 if (control) {
867                         sctp_m_freem(control);
868                         control = NULL;
869                 }
870                 return (error);
871         }
872 #ifdef INET6
873         if (addr->sa_family != AF_INET) {
874                 /* must be a v4 address! */
875                 sctp_m_freem(m);
876                 if (control) {
877                         sctp_m_freem(control);
878                         control = NULL;
879                 }
880                 error = EDESTADDRREQ;
881                 return EINVAL;
882         }
883 #endif /* INET6 */
884  connected_type:
885         /* now what about control */
886         if (control) {
887                 if (inp->control) {
888                         printf("huh? control set?\n");
889                         sctp_m_freem(inp->control);
890                         inp->control = NULL;
891                 }
892                 inp->control = control;
893         }
894         /* add it in possibly */
895         if ((inp->pkt) && (inp->pkt->m_flags & M_PKTHDR)) {
896                 struct mbuf *x;
897                 int c_len;
898
899                 c_len = 0;
900                 /* How big is it */
901                 for (x=m;x;x = x->m_next) {
902                         c_len += x->m_len;
903                 }
904                 inp->pkt->m_pkthdr.len += c_len;
905         }
906         /* Place the data */
907         if (inp->pkt) {
908                 inp->pkt_last->m_next = m;
909                 inp->pkt_last = m;
910         } else {
911                 inp->pkt_last = inp->pkt = m;
912         }
913         if (
914 #if defined (__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
915             /* FreeBSD uses a flag passed */
916             ((flags & PRUS_MORETOCOME) == 0)
917 #elif defined( __NetBSD__)
918             /* NetBSD uses the so_state field */
919             ((so->so_state & SS_MORETOCOME) == 0)
920 #else
921             1   /* Open BSD does not have any "more to come" indication */
922 #endif
923             ) {
924                 /*
925                  * note with the current version this code will only be used
926                  * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
927                  * re-defining sosend to use the sctp_sosend. One can
928                  * optionally switch back to this code (by changing back the
929                  * definitions) but this is not advisable.
930              */
931                 int ret;
932                 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
933                 inp->pkt = NULL;
934                 inp->control = NULL;
935                 return (ret);
936         } else {
937                 return (0);
938         }
939 }
940
941 static int
942 sctp_disconnect(struct socket *so)
943 {
944         struct sctp_inpcb *inp;
945
946         crit_enter();
947         inp = (struct sctp_inpcb *)so->so_pcb;
948         if (inp == NULL) {
949                 crit_exit();
950                 return (ENOTCONN);
951         }
952         SCTP_INP_RLOCK(inp);
953         if (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
954                 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
955                         /* No connection */
956                         crit_exit();
957                         SCTP_INP_RUNLOCK(inp);
958                         return (0);
959                 } else {
960                         int some_on_streamwheel = 0;
961                         struct sctp_association *asoc;
962                         struct sctp_tcb *stcb;
963
964                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
965                         if (stcb == NULL) {
966                                 crit_exit();
967                                 SCTP_INP_RUNLOCK(inp);
968                                 return (EINVAL);
969                         }
970                         asoc = &stcb->asoc;
971                         SCTP_TCB_LOCK(stcb);
972                         if (((so->so_options & SO_LINGER) &&
973                              (so->so_linger == 0)) ||
974                             (so->so_rcv.sb_cc > 0)) {
975                                 if (SCTP_GET_STATE(asoc) !=
976                                     SCTP_STATE_COOKIE_WAIT) {
977                                         /* Left with Data unread */
978                                         struct mbuf *err;
979                                         err = NULL;
980                                         MGET(err, MB_DONTWAIT, MT_DATA);
981                                         if (err) {
982                                                 /* Fill in the user initiated abort */
983                                                 struct sctp_paramhdr *ph;
984                                                 ph = mtod(err, struct sctp_paramhdr *);
985                                                 err->m_len = sizeof(struct sctp_paramhdr);
986                                                 ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
987                                                 ph->param_length = htons(err->m_len);
988                                         }
989                                         sctp_send_abort_tcb(stcb, err);
990                                 }
991                                 SCTP_INP_RUNLOCK(inp);
992                                 sctp_free_assoc(inp, stcb);
993                                 /* No unlock tcb assoc is gone */
994                                 crit_exit();
995                                 return (0);
996                         }
997                         if (!TAILQ_EMPTY(&asoc->out_wheel)) {
998                                 /* Check to see if some data queued */
999                                 struct sctp_stream_out *outs;
1000                                 TAILQ_FOREACH(outs, &asoc->out_wheel,
1001                                               next_spoke) {
1002                                         if (!TAILQ_EMPTY(&outs->outqueue)) {
1003                                                 some_on_streamwheel = 1;
1004                                                 break;
1005                                         }
1006                                 }
1007                         }
1008
1009                         if (TAILQ_EMPTY(&asoc->send_queue) &&
1010                             TAILQ_EMPTY(&asoc->sent_queue) &&
1011                             (some_on_streamwheel == 0)) {
1012                                 /* there is nothing queued to send, so done */
1013                                 if ((SCTP_GET_STATE(asoc) !=
1014                                      SCTP_STATE_SHUTDOWN_SENT) &&
1015                                     (SCTP_GET_STATE(asoc) !=
1016                                      SCTP_STATE_SHUTDOWN_ACK_SENT)) {
1017                                         /* only send SHUTDOWN 1st time thru */
1018 #ifdef SCTP_DEBUG
1019                                         if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
1020                                                 printf("%s:%d sends a shutdown\n",
1021                                                        __FILE__,
1022                                                        __LINE__
1023                                                         );
1024                                         }
1025 #endif
1026                                         sctp_send_shutdown(stcb,
1027                                                            stcb->asoc.primary_destination);
1028                                         sctp_chunk_output(stcb->sctp_ep, stcb, 1);
1029                                         asoc->state = SCTP_STATE_SHUTDOWN_SENT;
1030                                         sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1031                                                          stcb->sctp_ep, stcb,
1032                                                          asoc->primary_destination);
1033                                         sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1034                                                          stcb->sctp_ep, stcb,
1035                                                          asoc->primary_destination);
1036                                 }
1037                         } else {
1038                                 /*
1039                                  * we still got (or just got) data to send,
1040                                  * so set SHUTDOWN_PENDING
1041                                  */
1042                                 /*
1043                                  * XXX sockets draft says that MSG_EOF should
1044                                  * be sent with no data.
1045                                  * currently, we will allow user data to be
1046                                  * sent first and move to SHUTDOWN-PENDING
1047                                  */
1048                                 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1049                         }
1050                         SCTP_TCB_UNLOCK(stcb);
1051                         SCTP_INP_RUNLOCK(inp);
1052                         crit_exit();
1053                         return (0);
1054                 }
1055                 /* not reached */
1056         } else {
1057                 /* UDP model does not support this */
1058                 SCTP_INP_RUNLOCK(inp);
1059                 crit_exit();
1060                 return EOPNOTSUPP;
1061         }
1062 }
1063
1064 int
1065 sctp_shutdown(struct socket *so)
1066 {
1067         struct sctp_inpcb *inp;
1068
1069         crit_enter();
1070         inp = (struct sctp_inpcb *)so->so_pcb;
1071         if (inp == 0) {
1072                 crit_exit();
1073                 return EINVAL;
1074         }
1075         SCTP_INP_RLOCK(inp);
1076         /* For UDP model this is a invalid call */
1077         if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
1078                 /* Restore the flags that the soshutdown took away. */
1079 #if defined(__FreeBSD__) && __FreeBSD_version >= 502115
1080                 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
1081 #else
1082                 so->so_state &= ~SS_CANTRCVMORE;
1083 #endif
1084                 /* This proc will wakeup for read and do nothing (I hope) */
1085                 crit_exit();
1086                 SCTP_INP_RUNLOCK(inp);
1087                 return (EOPNOTSUPP);
1088         }
1089         /*
1090          * Ok if we reach here its the TCP model and it is either a SHUT_WR
1091          * or SHUT_RDWR. This means we put the shutdown flag against it.
1092          */
1093         {
1094                 int some_on_streamwheel = 0;
1095                 struct sctp_tcb *stcb;
1096                 struct sctp_association *asoc;
1097                 socantsendmore(so);
1098
1099                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1100                 if (stcb == NULL) {
1101                         /*
1102                          * Ok we hit the case that the shutdown call was made
1103                          * after an abort or something. Nothing to do now.
1104                          */
1105                         crit_exit();
1106                         return (0);
1107                 }
1108                 SCTP_TCB_LOCK(stcb);
1109                 asoc = &stcb->asoc;
1110
1111                 if (!TAILQ_EMPTY(&asoc->out_wheel)) {
1112                         /* Check to see if some data queued */
1113                         struct sctp_stream_out *outs;
1114                         TAILQ_FOREACH(outs, &asoc->out_wheel, next_spoke) {
1115                                 if (!TAILQ_EMPTY(&outs->outqueue)) {
1116                                         some_on_streamwheel = 1;
1117                                         break;
1118                                 }
1119                         }
1120                 }
1121                 if (TAILQ_EMPTY(&asoc->send_queue) &&
1122                     TAILQ_EMPTY(&asoc->sent_queue) &&
1123                     (some_on_streamwheel == 0)) {
1124                         /* there is nothing queued to send, so I'm done... */
1125                         if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
1126                                 /* only send SHUTDOWN the first time through */
1127 #ifdef SCTP_DEBUG
1128                                 if (sctp_debug_on & SCTP_DEBUG_OUTPUT4) {
1129                                         printf("%s:%d sends a shutdown\n",
1130                                                __FILE__,
1131                                                __LINE__
1132                                                 );
1133                                 }
1134 #endif
1135                                 sctp_send_shutdown(stcb,
1136                                                    stcb->asoc.primary_destination);
1137                                 sctp_chunk_output(stcb->sctp_ep, stcb, 1);
1138                                 asoc->state = SCTP_STATE_SHUTDOWN_SENT;
1139                                 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1140                                                  stcb->sctp_ep, stcb,
1141                                                  asoc->primary_destination);
1142                                 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1143                                                  stcb->sctp_ep, stcb,
1144                                                  asoc->primary_destination);
1145                         }
1146                 } else {
1147                         /*
1148                          * we still got (or just got) data to send, so
1149                          * set SHUTDOWN_PENDING
1150                          */
1151                         asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1152                 }
1153                 SCTP_TCB_UNLOCK(stcb);
1154         }
1155         SCTP_INP_RUNLOCK(inp);
1156         crit_exit();
1157         return 0;
1158 }
1159
1160 /*
1161  * copies a "user" presentable address and removes embedded scope, etc.
1162  * returns 0 on success, 1 on error
1163  */
1164 static uint32_t
1165 sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1166 {
1167         struct sockaddr_in6 lsa6;
1168         sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1169                                                    &lsa6);
1170         memcpy(ss, sa, sa->sa_len);
1171         return (0);
1172 }
1173
1174
1175 #if defined(__NetBSD__) || defined(__OpenBSD__)
1176 /*
1177  * On NetBSD and OpenBSD in6_sin_2_v4mapsin6() not used and not exported,
1178  * so we have to export it here.
1179  */
1180 void    in6_sin_2_v4mapsin6 __P((struct sockaddr_in *sin,
1181                                  struct sockaddr_in6 *sin6));
1182 #endif
1183
1184 static int
1185 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1186                        struct sctp_tcb *stcb,
1187                        int limit,
1188                        struct sockaddr_storage *sas)
1189 {
1190         struct ifnet *ifn;
1191         struct ifaddr *ifa;
1192         int loopback_scope, ipv4_local_scope, local_scope, site_scope, actual;
1193         int ipv4_addr_legal, ipv6_addr_legal;
1194         actual = 0;
1195         if (limit <= 0)
1196                 return (actual);
1197
1198         if (stcb) {
1199                 /* Turn on all the appropriate scope */
1200                 loopback_scope = stcb->asoc.loopback_scope;
1201                 ipv4_local_scope = stcb->asoc.ipv4_local_scope;
1202                 local_scope = stcb->asoc.local_scope;
1203                 site_scope = stcb->asoc.site_scope;
1204         } else {
1205                 /* Turn on ALL scope, since we look at the EP */
1206                 loopback_scope = ipv4_local_scope = local_scope =
1207                         site_scope = 1;
1208         }
1209         ipv4_addr_legal = ipv6_addr_legal = 0;
1210         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1211                 ipv6_addr_legal = 1;
1212                 if (
1213 #if defined(__OpenBSD__)
1214                 (0) /* we always do dual bind */
1215 #elif defined (__NetBSD__)
1216                 (((struct in6pcb *)inp)->in6p_flags & IN6P_IPV6_V6ONLY)
1217 #else
1218                 (((struct in6pcb *)inp)->inp_flags & IN6P_IPV6_V6ONLY)
1219 #endif
1220                 == 0) {
1221                         ipv4_addr_legal = 1;
1222                 }
1223         } else {
1224                 ipv4_addr_legal = 1;
1225         }
1226
1227         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1228                 TAILQ_FOREACH(ifn, &ifnet, if_list) {
1229                         if ((loopback_scope == 0) &&
1230                             (ifn->if_type == IFT_LOOP)) {
1231                                 /* Skip loopback if loopback_scope not set */
1232                                 continue;
1233                         }
1234                         TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
1235                                 if (stcb) {
1236                                 /*
1237                                  * For the BOUND-ALL case, the list
1238                                  * associated with a TCB is Always
1239                                  * considered a reverse list.. i.e.
1240                                  * it lists addresses that are NOT
1241                                  * part of the association. If this
1242                                  * is one of those we must skip it.
1243                                  */
1244                                         if (sctp_is_addr_restricted(stcb,
1245                                                                     ifa->ifa_addr)) {
1246                                                 continue;
1247                                         }
1248                                 }
1249                                 if ((ifa->ifa_addr->sa_family == AF_INET) &&
1250                                     (ipv4_addr_legal)) {
1251                                         struct sockaddr_in *sin;
1252                                         sin = (struct sockaddr_in *)ifa->ifa_addr;
1253                                         if (sin->sin_addr.s_addr == 0) {
1254                                                 /* we skip unspecifed addresses */
1255                                                 continue;
1256                                         }
1257                                         if ((ipv4_local_scope == 0) &&
1258                                             (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1259                                                 continue;
1260                                         }
1261                                         if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) {
1262                                                 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1263                                                 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1264                                                 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1265                                                 actual += sizeof(sizeof(struct sockaddr_in6));
1266                                         } else {
1267                                                 memcpy(sas, sin, sizeof(*sin));
1268                                                 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1269                                                 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1270                                                 actual += sizeof(*sin);
1271                                         }
1272                                         if (actual >= limit) {
1273                                                 return (actual);
1274                                         }
1275                                 } else if ((ifa->ifa_addr->sa_family == AF_INET6) &&
1276                                            (ipv6_addr_legal)) {
1277                                         struct sockaddr_in6 *sin6, lsa6;
1278                                         sin6 = (struct sockaddr_in6 *)ifa->ifa_addr;
1279                                         if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1280                                                 /* we skip unspecifed addresses */
1281                                                 continue;
1282                                         }
1283                                         if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1284                                                 if (local_scope == 0)
1285                                                         continue;
1286                                                 if (sin6->sin6_scope_id == 0) {
1287                                                         lsa6 = *sin6;
1288                                                         if (in6_recoverscope(&lsa6,
1289                                                                              &lsa6.sin6_addr,
1290                                                                              NULL))
1291                                                                 /* bad link local address */
1292                                                                 continue;
1293                                                         sin6 = &lsa6;
1294                                                 }
1295                                         }
1296                                         if ((site_scope == 0) &&
1297                                             (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1298                                                 continue;
1299                                         }
1300                                         memcpy(sas, sin6, sizeof(*sin6));
1301                                         ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1302                                         sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1303                                         actual += sizeof(*sin6);
1304                                         if (actual >= limit) {
1305                                                 return (actual);
1306                                         }
1307                                 }
1308                         }
1309                 }
1310         } else {
1311                 struct sctp_laddr *laddr;
1312                 /*
1313                  * If we have a TCB and we do NOT support ASCONF (it's
1314                  * turned off or otherwise) then the list is always the
1315                  * true list of addresses (the else case below).  Otherwise
1316                  * the list on the association is a list of addresses that
1317                  * are NOT part of the association.
1318                  */
1319                 if (inp->sctp_flags & SCTP_PCB_FLAGS_DO_ASCONF) {
1320                         /* The list is a NEGATIVE list */
1321                         LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1322                                 if (stcb) {
1323                                         if (sctp_is_addr_restricted(stcb, laddr->ifa->ifa_addr)) {
1324                                                 continue;
1325                                         }
1326                                 }
1327                                 if (sctp_fill_user_address(sas, laddr->ifa->ifa_addr))
1328                                         continue;
1329
1330                                 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1331                                 sas = (struct sockaddr_storage *)((caddr_t)sas +
1332                                                                   laddr->ifa->ifa_addr->sa_len);
1333                                 actual += laddr->ifa->ifa_addr->sa_len;
1334                                 if (actual >= limit) {
1335                                         return (actual);
1336                                 }
1337                         }
1338                 } else {
1339                         /* The list is a positive list if present */
1340                         if (stcb) {
1341                                 /* Must use the specific association list */
1342                                 LIST_FOREACH(laddr, &stcb->asoc.sctp_local_addr_list,
1343                                              sctp_nxt_addr) {
1344                                         if (sctp_fill_user_address(sas,
1345                                                                    laddr->ifa->ifa_addr))
1346                                                 continue;
1347                                         ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1348                                         sas = (struct sockaddr_storage *)((caddr_t)sas +
1349                                                                           laddr->ifa->ifa_addr->sa_len);
1350                                         actual += laddr->ifa->ifa_addr->sa_len;
1351                                         if (actual >= limit) {
1352                                                 return (actual);
1353                                         }
1354                                 }
1355                         } else {
1356                                 /* No endpoint so use the endpoints individual list */
1357                                 LIST_FOREACH(laddr, &inp->sctp_addr_list,
1358                                              sctp_nxt_addr) {
1359                                         if (sctp_fill_user_address(sas,
1360                                                                    laddr->ifa->ifa_addr))
1361                                                 continue;
1362                                         ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1363                                         sas = (struct sockaddr_storage *)((caddr_t)sas +
1364                                                                           laddr->ifa->ifa_addr->sa_len);
1365                                         actual += laddr->ifa->ifa_addr->sa_len;
1366                                         if (actual >= limit) {
1367                                                 return (actual);
1368                                         }
1369                                 }
1370                         }
1371                 }
1372         }
1373         return (actual);
1374 }
1375
1376 static int
1377 sctp_count_max_addresses(struct sctp_inpcb *inp)
1378 {
1379         int cnt = 0;
1380         /*
1381          * In both sub-set bound an bound_all cases we return the MAXIMUM
1382          * number of addresses that you COULD get. In reality the sub-set
1383          * bound may have an exclusion list for a given TCB OR in the
1384          * bound-all case a TCB may NOT include the loopback or other
1385          * addresses as well.
1386          */
1387         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1388                 struct ifnet *ifn;
1389                 struct ifaddr *ifa;
1390
1391                 TAILQ_FOREACH(ifn, &ifnet, if_list) {
1392                         TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
1393                                 /* Count them if they are the right type */
1394                                 if (ifa->ifa_addr->sa_family == AF_INET) {
1395                                         if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)
1396                                                 cnt += sizeof(struct sockaddr_in6);
1397                                         else
1398                                                 cnt += sizeof(struct sockaddr_in);
1399
1400                                 } else if (ifa->ifa_addr->sa_family == AF_INET6)
1401                                         cnt += sizeof(struct sockaddr_in6);
1402                         }
1403                 }
1404         } else {
1405                 struct sctp_laddr *laddr;
1406                 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1407                         if (laddr->ifa->ifa_addr->sa_family == AF_INET) {
1408                                 if (inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)
1409                                         cnt += sizeof(struct sockaddr_in6);
1410                                 else
1411                                         cnt += sizeof(struct sockaddr_in);
1412
1413                         } else if (laddr->ifa->ifa_addr->sa_family == AF_INET6)
1414                                 cnt += sizeof(struct sockaddr_in6);
1415                 }
1416         }
1417         return (cnt);
1418 }
1419
1420 static int
1421 sctp_do_connect_x(struct socket *so,
1422                   struct sctp_inpcb *inp,
1423                   struct mbuf *m,
1424 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
1425                   struct thread *p,
1426 #else
1427                   struct proc *p,
1428 #endif
1429                   int delay
1430         )
1431 {
1432         int error = 0;
1433         struct sctp_tcb *stcb = NULL;
1434         struct sockaddr *sa;
1435         int num_v6=0, num_v4=0, *totaddrp, totaddr, i, incr, at;
1436 #ifdef SCTP_DEBUG
1437         if (sctp_debug_on & SCTP_DEBUG_PCB1) {
1438                 printf("Connectx called\n");
1439         }
1440 #endif /* SCTP_DEBUG */
1441
1442         crit_enter();
1443         if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1444             (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1445                 /* We are already connected AND the TCP model */
1446                 crit_exit();
1447                 return (EADDRINUSE);
1448         }
1449         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1450                 SCTP_INP_RLOCK(inp);
1451                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1452                 SCTP_INP_RUNLOCK(inp);
1453         }
1454         if (stcb) {
1455                 crit_exit();
1456                 return (EALREADY);
1457
1458         }
1459         SCTP_ASOC_CREATE_LOCK(inp);
1460         if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
1461             (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1462                 SCTP_ASOC_CREATE_UNLOCK(inp);
1463                 crit_exit();
1464                 return (EFAULT);
1465         }
1466
1467         totaddrp = mtod(m, int *);
1468         totaddr = *totaddrp;
1469         sa = (struct sockaddr *)(totaddrp + 1);
1470         at = incr = 0;
1471         /* account and validate addresses */
1472         SCTP_INP_WLOCK(inp);
1473         SCTP_INP_INCR_REF(inp);
1474         SCTP_INP_WUNLOCK(inp);
1475         for (i = 0; i < totaddr; i++) {
1476                 if (sa->sa_family == AF_INET) {
1477                         num_v4++;
1478                         incr = sizeof(struct sockaddr_in);
1479                 } else if (sa->sa_family == AF_INET6) {
1480                         struct sockaddr_in6 *sin6;
1481                         sin6 = (struct sockaddr_in6 *)sa;
1482                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
1483                                 /* Must be non-mapped for connectx */
1484                                 SCTP_ASOC_CREATE_UNLOCK(inp);
1485                                 crit_exit();
1486                                 return EINVAL;
1487                         }
1488                         num_v6++;
1489                         incr = sizeof(struct sockaddr_in6);
1490                 } else {
1491                         totaddr = i;
1492                         break;
1493                 }
1494                 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
1495                 if (stcb != NULL) {
1496                         /* Already have or am bring up an association */
1497                         SCTP_ASOC_CREATE_UNLOCK(inp);
1498                         SCTP_TCB_UNLOCK(stcb);
1499                         crit_exit();
1500                         return (EALREADY);
1501                 }
1502                 if ((at + incr) > m->m_len) {
1503                         totaddr = i;
1504                         break;
1505                 }
1506                 sa = (struct sockaddr *)((caddr_t)sa + incr);
1507         }
1508         sa = (struct sockaddr *)(totaddrp + 1);
1509         SCTP_INP_WLOCK(inp);
1510         SCTP_INP_DECR_REF(inp);
1511         SCTP_INP_WUNLOCK(inp);
1512 #ifdef INET6
1513         if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1514             (num_v6 > 0)) {
1515                 crit_exit();
1516                 SCTP_INP_WUNLOCK(inp);
1517                 SCTP_ASOC_CREATE_UNLOCK(inp);
1518                 return (EINVAL);
1519         }
1520         if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1521             (num_v4 > 0)) {
1522                 struct in6pcb *inp6;
1523                 inp6 = (struct in6pcb *)inp;
1524                 if (
1525 #if defined(__OpenBSD__)
1526                         (0) /* we always do dual bind */
1527 #elif defined (__NetBSD__)
1528                         (inp6->in6p_flags & IN6P_IPV6_V6ONLY)
1529 #else
1530                         (inp6->inp_flags & IN6P_IPV6_V6ONLY)
1531 #endif
1532                         ) {
1533                         /*
1534                          * if IPV6_V6ONLY flag, ignore connections
1535                          * destined to a v4 addr or v4-mapped addr
1536                          */
1537                         SCTP_INP_WUNLOCK(inp);
1538                         SCTP_ASOC_CREATE_UNLOCK(inp);
1539                         crit_exit();
1540                         return EINVAL;
1541                 }
1542         }
1543 #endif /* INET6 */
1544         if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1545             SCTP_PCB_FLAGS_UNBOUND) {
1546                 /* Bind a ephemeral port */
1547                 SCTP_INP_WUNLOCK(inp);
1548                 error = sctp_inpcb_bind(so, NULL, p);
1549                 if (error) {
1550                         SCTP_ASOC_CREATE_UNLOCK(inp);
1551                         crit_exit();
1552                         return (error);
1553                 }
1554         } else {
1555                 SCTP_INP_WUNLOCK(inp);
1556         }
1557         /* We are GOOD to go */
1558         stcb = sctp_aloc_assoc(inp, sa, 1, &error, 0);
1559         if (stcb == NULL) {
1560                 /* Gak! no memory */
1561                 SCTP_ASOC_CREATE_UNLOCK(inp);
1562                 crit_exit();
1563                 return (error);
1564         }
1565         /* move to second address */
1566         if (sa->sa_family == AF_INET)
1567                 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1568         else
1569                 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1570
1571         for (i = 1; i < totaddr; i++) {
1572                 if (sa->sa_family == AF_INET) {
1573                         incr = sizeof(struct sockaddr_in);
1574                         if (sctp_add_remote_addr(stcb, sa, 0, 8)) {
1575                                 /* assoc gone no un-lock */
1576                                 sctp_free_assoc(inp, stcb);
1577                                 SCTP_ASOC_CREATE_UNLOCK(inp);
1578                                 crit_exit();
1579                                 return (ENOBUFS);
1580                         }
1581
1582                 } else if (sa->sa_family == AF_INET6) {
1583                         incr = sizeof(struct sockaddr_in6);
1584                         if (sctp_add_remote_addr(stcb, sa, 0, 8)) {
1585                                 /* assoc gone no un-lock */
1586                                 sctp_free_assoc(inp, stcb);
1587                                 SCTP_ASOC_CREATE_UNLOCK(inp);
1588                                 crit_exit();
1589                                 return (ENOBUFS);
1590                         }
1591                 }
1592                 sa = (struct sockaddr *)((caddr_t)sa + incr);
1593         }
1594         stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
1595         if (delay) {
1596                 /* doing delayed connection */
1597                 stcb->asoc.delayed_connection = 1;
1598                 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1599         } else {
1600                 SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1601                 sctp_send_initiate(inp, stcb);
1602         }
1603         SCTP_TCB_UNLOCK(stcb);
1604         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1605                 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1606                 /* Set the connected flag so we can queue data */
1607                 soisconnecting(so);
1608         }
1609         SCTP_ASOC_CREATE_UNLOCK(inp);
1610         crit_exit();
1611         return error;
1612 }
1613
1614
1615 static int
1616 sctp_optsget(struct socket *so,
1617              int opt,
1618              struct mbuf **mp,
1619 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
1620              struct thread *p
1621 #else
1622              struct proc *p
1623 #endif
1624         )
1625 {
1626         struct sctp_inpcb *inp;
1627         struct mbuf *m;
1628         int error, optval=0;
1629         struct sctp_tcb *stcb = NULL;
1630
1631         inp = (struct sctp_inpcb *)so->so_pcb;
1632         if (inp == 0)
1633                 return EINVAL;
1634         error = 0;
1635
1636         if (mp == NULL) {
1637 #ifdef SCTP_DEBUG
1638                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
1639                         printf("optsget:MP is NULL EINVAL\n");
1640                 }
1641 #endif /* SCTP_DEBUG */
1642                 return (EINVAL);
1643         }
1644         m = *mp;
1645         if (m == NULL) {
1646                 /* Got to have a mbuf */
1647 #ifdef SCTP_DEBUG
1648                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
1649                         printf("Huh no mbuf\n");
1650                 }
1651 #endif /* SCTP_DEBUG */
1652                 return (EINVAL);
1653         }
1654 #ifdef SCTP_DEBUG
1655         if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
1656                 printf("optsget opt:%lxx sz:%u\n", (unsigned long)opt,
1657                        m->m_len);
1658         }
1659 #endif /* SCTP_DEBUG */
1660
1661         switch (opt) {
1662         case SCTP_NODELAY:
1663         case SCTP_AUTOCLOSE:
1664         case SCTP_AUTO_ASCONF:
1665         case SCTP_DISABLE_FRAGMENTS:
1666         case SCTP_I_WANT_MAPPED_V4_ADDR:
1667 #ifdef SCTP_DEBUG
1668                 if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
1669                         printf("other stuff\n");
1670                 }
1671 #endif /* SCTP_DEBUG */
1672                 SCTP_INP_RLOCK(inp);
1673                 switch (opt) {
1674                 case SCTP_DISABLE_FRAGMENTS:
1675                         optval = inp->sctp_flags & SCTP_PCB_FLAGS_NO_FRAGMENT;
1676                         break;
1677                 case SCTP_I_WANT_MAPPED_V4_ADDR:
1678                         optval = inp->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
1679                         break;
1680                 case SCTP_AUTO_ASCONF:
1681                         optval = inp->sctp_flags & SCTP_PCB_FLAGS_AUTO_ASCONF;
1682                         break;
1683                 case SCTP_NODELAY:
1684                         optval = inp->sctp_flags & SCTP_PCB_FLAGS_NODELAY;
1685                         break;
1686                 case SCTP_AUTOCLOSE:
1687                         if ((inp->sctp_flags & SCTP_PCB_FLAGS_AUTOCLOSE) ==
1688                             SCTP_PCB_FLAGS_AUTOCLOSE)
1689                                 optval = inp->sctp_ep.auto_close_time;
1690                         else
1691                                 optval = 0;
1692                         break;
1693
1694                 default:
1695                         error = ENOPROTOOPT;
1696                 } /* end switch (sopt->sopt_name) */
1697                 if (opt != SCTP_AUTOCLOSE) {
1698                         /* make it an "on/off" value */
1699                         optval = (optval != 0);
1700                 }
1701                 if ((size_t)m->m_len < sizeof(int)) {
1702                         error = EINVAL;
1703                 }
1704                 SCTP_INP_RUNLOCK(inp);
1705                 if (error == 0) {
1706                         /* return the option value */
1707                         *mtod(m, int *) = optval;
1708                         m->m_len = sizeof(optval);
1709                 }
1710                 break;
1711         case SCTP_GET_ASOC_ID_LIST:
1712         {
1713                 struct sctp_assoc_ids *ids;
1714                 int cnt, at;
1715                 u_int16_t orig;
1716
1717                 if ((size_t)m->m_len < sizeof(struct sctp_assoc_ids)) {
1718                         error = EINVAL;
1719                         break;
1720                 }
1721                 ids = mtod(m, struct sctp_assoc_ids *);
1722                 cnt = 0;
1723                 SCTP_INP_RLOCK(inp);
1724                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1725                 if (stcb == NULL) {
1726                 none_out_now:
1727                         ids->asls_numb_present = 0;
1728                         ids->asls_more_to_get = 0;
1729                         SCTP_INP_RUNLOCK(inp);
1730                         break;
1731                 }
1732                 orig = ids->asls_assoc_start;
1733                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1734                 while( orig ) {
1735                         stcb = LIST_NEXT(stcb , sctp_tcblist);
1736                         orig--;
1737                         cnt--;
1738                 }
1739                 if ( stcb == NULL)
1740                         goto none_out_now;
1741
1742                 at = 0;
1743                 ids->asls_numb_present = 0;
1744                 ids->asls_more_to_get = 1;
1745                 while(at < MAX_ASOC_IDS_RET) {
1746                         ids->asls_assoc_id[at] = sctp_get_associd(stcb);
1747                         at++;
1748                         ids->asls_numb_present++;
1749                         stcb = LIST_NEXT(stcb , sctp_tcblist);
1750                         if (stcb == NULL) {
1751                                 ids->asls_more_to_get = 0;
1752                                 break;
1753                         }
1754                 }
1755                 SCTP_INP_RUNLOCK(inp);
1756         }
1757         break;
1758         case SCTP_GET_NONCE_VALUES:
1759         {
1760                 struct sctp_get_nonce_values *gnv;
1761                 if ((size_t)m->m_len < sizeof(struct sctp_get_nonce_values)) {
1762                         error = EINVAL;
1763                         break;
1764                 }
1765                 gnv = mtod(m, struct sctp_get_nonce_values *);
1766                 stcb = sctp_findassociation_ep_asocid(inp, gnv->gn_assoc_id);
1767                 if (stcb == NULL) {
1768                         error = ENOTCONN;
1769                 } else {
1770                         gnv->gn_peers_tag = stcb->asoc.peer_vtag;
1771                         gnv->gn_local_tag = stcb->asoc.my_vtag;
1772                         SCTP_TCB_UNLOCK(stcb);
1773                 }
1774
1775         }
1776         break;
1777         case SCTP_PEER_PUBLIC_KEY:
1778         case SCTP_MY_PUBLIC_KEY:
1779         case SCTP_SET_AUTH_CHUNKS:
1780         case SCTP_SET_AUTH_SECRET:
1781                 /* not supported yet and until we refine the draft */
1782                 error = EOPNOTSUPP;
1783                 break;
1784
1785         case SCTP_DELAYED_ACK_TIME:
1786         {
1787                 int32_t *tm;
1788                 if ((size_t)m->m_len < sizeof(int32_t)) {
1789                         error = EINVAL;
1790                         break;
1791                 }
1792                 tm = mtod(m, int32_t *);
1793
1794                 *tm = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
1795         }
1796         break;
1797
1798         case SCTP_GET_SNDBUF_USE:
1799                 if ((size_t)m->m_len < sizeof(struct sctp_sockstat)) {
1800                         error = EINVAL;
1801                 } else {
1802                         struct sctp_sockstat *ss;
1803                         struct sctp_tcb *stcb;
1804                         struct sctp_association *asoc;
1805                         ss = mtod(m, struct sctp_sockstat *);
1806                         stcb = sctp_findassociation_ep_asocid(inp, ss->ss_assoc_id);
1807                         if (stcb == NULL) {
1808                                 error = ENOTCONN;
1809                         } else {
1810                                 asoc = &stcb->asoc;
1811                                 ss->ss_total_sndbuf = (u_int32_t)asoc->total_output_queue_size;
1812                                 ss->ss_total_mbuf_sndbuf = (u_int32_t)asoc->total_output_mbuf_queue_size;
1813                                 ss->ss_total_recv_buf = (u_int32_t)(asoc->size_on_delivery_queue +
1814                                                                     asoc->size_on_reasm_queue +
1815                                                                     asoc->size_on_all_streams);
1816                                 SCTP_TCB_UNLOCK(stcb);
1817                                 error = 0;
1818                                 m->m_len = sizeof(struct sctp_sockstat);
1819                         }
1820                 }
1821                 break;
1822         case SCTP_MAXBURST:
1823         {
1824                 u_int8_t *burst;
1825                 burst = mtod(m, u_int8_t *);
1826                 SCTP_INP_RLOCK(inp);
1827                 *burst = inp->sctp_ep.max_burst;
1828                 SCTP_INP_RUNLOCK(inp);
1829                 m->m_len = sizeof(u_int8_t);
1830         }
1831         break;
1832         case SCTP_MAXSEG:
1833         {
1834                 u_int32_t *segsize;
1835                 sctp_assoc_t *assoc_id;
1836                 int ovh;
1837
1838                 if ((size_t)m->m_len < sizeof(u_int32_t)) {
1839                         error = EINVAL;
1840                         break;
1841                 }
1842                 if ((size_t)m->m_len < sizeof(sctp_assoc_t)) {
1843                         error = EINVAL;
1844                         break;
1845                 }
1846                 assoc_id = mtod(m, sctp_assoc_t *);
1847                 segsize = mtod(m, u_int32_t *);
1848                 m->m_len = sizeof(u_int32_t);
1849
1850                 if (((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1851                      (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) ||
1852                     (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
1853                         struct sctp_tcb *stcb;
1854                         SCTP_INP_RLOCK(inp);
1855                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
1856                         if (stcb) {
1857                                 SCTP_TCB_LOCK(stcb);
1858                                 SCTP_INP_RUNLOCK(inp);
1859                                 *segsize = sctp_get_frag_point(stcb, &stcb->asoc);
1860                                 SCTP_TCB_UNLOCK(stcb);
1861                         } else {
1862                                 SCTP_INP_RUNLOCK(inp);
1863                                 goto skipit;
1864                         }
1865                 } else {
1866                         stcb = sctp_findassociation_ep_asocid(inp, *assoc_id);
1867                         if (stcb) {
1868                                 *segsize = sctp_get_frag_point(stcb, &stcb->asoc);
1869                                 SCTP_TCB_UNLOCK(stcb);
1870                                 break;
1871                         }
1872                 skipit:
1873                         /* default is to get the max, if I
1874                          * can't calculate from an existing association.
1875                          */
1876                         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1877                                 ovh = SCTP_MED_OVERHEAD;
1878                         } else {
1879                                 ovh = SCTP_MED_V4_OVERHEAD;
1880                         }
1881                         *segsize = inp->sctp_frag_point - ovh;
1882                 }
1883         }
1884         break;
1885
1886         case SCTP_SET_DEBUG_LEVEL:
1887 #ifdef SCTP_DEBUG
1888         {
1889                 u_int32_t *level;
1890                 if ((size_t)m->m_len < sizeof(u_int32_t)) {
1891                         error = EINVAL;
1892                         break;
1893                 }
1894                 level = mtod(m, u_int32_t *);
1895                 error = 0;
1896                 *level = sctp_debug_on;
1897                 m->m_len = sizeof(u_int32_t);
1898                 printf("Returning DEBUG LEVEL %x is set\n",
1899                        (u_int)sctp_debug_on);
1900         }
1901 #else /* SCTP_DEBUG */
1902         error = EOPNOTSUPP;
1903 #endif
1904         break;
1905         case SCTP_GET_STAT_LOG:
1906 #ifdef SCTP_STAT_LOGGING
1907                 error = sctp_fill_stat_log(m);
1908 #else /* SCTP_DEBUG */
1909                 error = EOPNOTSUPP;
1910 #endif
1911                 break;
1912         case SCTP_GET_PEGS:
1913         {
1914                 u_int32_t *pt;
1915                 if ((size_t)m->m_len < sizeof(sctp_pegs)) {
1916                         error = EINVAL;
1917                         break;
1918                 }
1919                 pt = mtod(m, u_int32_t *);
1920                 memcpy(pt, sctp_pegs, sizeof(sctp_pegs));
1921                 m->m_len = sizeof(sctp_pegs);
1922         }
1923         break;
1924         case SCTP_EVENTS:
1925         {
1926                 struct sctp_event_subscribe *events;
1927 #ifdef SCTP_DEBUG
1928                 if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
1929                         printf("get events\n");
1930                 }
1931 #endif /* SCTP_DEBUG */
1932                 if ((size_t)m->m_len < sizeof(struct sctp_event_subscribe)) {
1933 #ifdef SCTP_DEBUG
1934                         if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
1935                                 printf("M->M_LEN is %d not %d\n",
1936                                        (int)m->m_len,
1937                                        (int)sizeof(struct sctp_event_subscribe));
1938                         }
1939 #endif /* SCTP_DEBUG */
1940                         error = EINVAL;
1941                         break;
1942                 }
1943                 events = mtod(m, struct sctp_event_subscribe *);
1944                 memset(events, 0, sizeof(events));
1945                 SCTP_INP_RLOCK(inp);
1946                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVDATAIOEVNT)
1947                         events->sctp_data_io_event = 1;
1948
1949                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVASSOCEVNT)
1950                         events->sctp_association_event = 1;
1951
1952                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVPADDREVNT)
1953                         events->sctp_address_event = 1;
1954
1955                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVSENDFAILEVNT)
1956                         events->sctp_send_failure_event = 1;
1957
1958                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVPEERERR)
1959                         events->sctp_peer_error_event = 1;
1960
1961                 if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT)
1962                         events->sctp_shutdown_event = 1;
1963
1964                 if (inp->sctp_flags & SCTP_PCB_FLAGS_PDAPIEVNT)
1965                         events->sctp_partial_delivery_event = 1;
1966
1967                 if (inp->sctp_flags & SCTP_PCB_FLAGS_ADAPTIONEVNT)
1968                         events->sctp_adaption_layer_event = 1;
1969
1970                 if (inp->sctp_flags & SCTP_PCB_FLAGS_STREAM_RESETEVNT)
1971                         events->sctp_stream_reset_events = 1;
1972                 SCTP_INP_RUNLOCK(inp);
1973                 m->m_len = sizeof(struct sctp_event_subscribe);
1974
1975         }
1976         break;
1977
1978         case SCTP_ADAPTION_LAYER:
1979                 if ((size_t)m->m_len < sizeof(int)) {
1980                         error = EINVAL;
1981                         break;
1982                 }
1983 #ifdef SCTP_DEBUG
1984                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
1985                         printf("getadaption ind\n");
1986                 }
1987 #endif /* SCTP_DEBUG */
1988                 SCTP_INP_RLOCK(inp);
1989                 *mtod(m, int *) = inp->sctp_ep.adaption_layer_indicator;
1990                 SCTP_INP_RUNLOCK(inp);
1991                 m->m_len = sizeof(int);
1992                 break;
1993         case SCTP_SET_INITIAL_DBG_SEQ:
1994                 if ((size_t)m->m_len < sizeof(int)) {
1995                         error = EINVAL;
1996                         break;
1997                 }
1998 #ifdef SCTP_DEBUG
1999                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2000                         printf("get initial dbg seq\n");
2001                 }
2002 #endif /* SCTP_DEBUG */
2003                 SCTP_INP_RLOCK(inp);
2004                 *mtod(m, int *) = inp->sctp_ep.initial_sequence_debug;
2005                 SCTP_INP_RUNLOCK(inp);
2006                 m->m_len = sizeof(int);
2007                 break;
2008         case SCTP_GET_LOCAL_ADDR_SIZE:
2009                 if ((size_t)m->m_len < sizeof(int)) {
2010                         error = EINVAL;
2011                         break;
2012                 }
2013 #ifdef SCTP_DEBUG
2014                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2015                         printf("get local sizes\n");
2016                 }
2017 #endif /* SCTP_DEBUG */
2018                 SCTP_INP_RLOCK(inp);
2019                 *mtod(m, int *) = sctp_count_max_addresses(inp);
2020                 SCTP_INP_RUNLOCK(inp);
2021                 m->m_len = sizeof(int);
2022                 break;
2023         case SCTP_GET_REMOTE_ADDR_SIZE:
2024         {
2025                 sctp_assoc_t *assoc_id;
2026                 u_int32_t *val, sz;
2027                 struct sctp_nets *net;
2028 #ifdef SCTP_DEBUG
2029                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2030                         printf("get remote size\n");
2031                 }
2032 #endif /* SCTP_DEBUG */
2033                 if ((size_t)m->m_len < sizeof(sctp_assoc_t)) {
2034 #ifdef SCTP_DEBUG
2035                         printf("m->m_len:%d not %d\n",
2036                                m->m_len, sizeof(sctp_assoc_t));
2037 #endif /* SCTP_DEBUG */
2038                         error = EINVAL;
2039                         break;
2040                 }
2041                 stcb = NULL;
2042                 val = mtod(m, u_int32_t *);
2043                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2044                         SCTP_INP_RLOCK(inp);
2045                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2046                         if (stcb)
2047                                 SCTP_TCB_LOCK(stcb);
2048                         SCTP_INP_RUNLOCK(inp);
2049                 }
2050                 if (stcb == NULL) {
2051                         assoc_id = mtod(m, sctp_assoc_t *);
2052                         stcb = sctp_findassociation_ep_asocid(inp, *assoc_id);
2053                 }
2054
2055                 if (stcb == NULL) {
2056                         error = EINVAL;
2057                         break;
2058                 }
2059                 *val = 0;
2060                 sz = 0;
2061                 /* Count the sizes */
2062                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2063                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
2064                             (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
2065                                 sz += sizeof(struct sockaddr_in6);
2066                         } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
2067                                 sz += sizeof(struct sockaddr_in);
2068                         } else {
2069                                 /* huh */
2070                                 break;
2071                         }
2072                 }
2073                 SCTP_TCB_UNLOCK(stcb);
2074                 *val = sz;
2075                 m->m_len = sizeof(u_int32_t);
2076         }
2077         break;
2078         case SCTP_GET_PEER_ADDRESSES:
2079                 /*
2080                  * Get the address information, an array
2081                  * is passed in to fill up we pack it.
2082                  */
2083         {
2084                 int cpsz, left;
2085                 struct sockaddr_storage *sas;
2086                 struct sctp_nets *net;
2087                 struct sctp_getaddresses *saddr;
2088 #ifdef SCTP_DEBUG
2089                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2090                         printf("get peer addresses\n");
2091                 }
2092 #endif /* SCTP_DEBUG */
2093                 if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) {
2094                         error = EINVAL;
2095                         break;
2096                 }
2097                 left = m->m_len - sizeof(struct sctp_getaddresses);
2098                 saddr = mtod(m, struct sctp_getaddresses *);
2099                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2100                         SCTP_INP_RLOCK(inp);
2101                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2102                         if (stcb)
2103                                 SCTP_TCB_LOCK(stcb);
2104                         SCTP_INP_RUNLOCK(inp);
2105                 } else
2106                         stcb = sctp_findassociation_ep_asocid(inp,
2107                                                               saddr->sget_assoc_id);
2108                 if (stcb == NULL) {
2109                         error = ENOENT;
2110                         break;
2111                 }
2112                 m->m_len = sizeof(struct sctp_getaddresses);
2113                 sas = (struct sockaddr_storage *)&saddr->addr[0];
2114
2115                 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2116                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) ||
2117                             (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET6)) {
2118                                 cpsz = sizeof(struct sockaddr_in6);
2119                         } else if (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET) {
2120                                 cpsz = sizeof(struct sockaddr_in);
2121                         } else {
2122                                 /* huh */
2123                                 break;
2124                         }
2125                         if (left < cpsz) {
2126                                 /* not enough room. */
2127 #ifdef SCTP_DEBUG
2128                                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2129                                         printf("Out of room\n");
2130                                 }
2131 #endif /* SCTP_DEBUG */
2132                                 break;
2133                         }
2134                         if ((stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_NEEDS_MAPPED_V4) &&
2135                             (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2136                                 /* Must map the address */
2137                                 in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2138                                                     (struct sockaddr_in6 *)sas);
2139                         } else {
2140                                 memcpy(sas, &net->ro._l_addr, cpsz);
2141                         }
2142                         ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2143
2144                         sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2145                         left -= cpsz;
2146                         m->m_len += cpsz;
2147 #ifdef SCTP_DEBUG
2148                         if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
2149                                 printf("left now:%d mlen:%d\n",
2150                                        left, m->m_len);
2151                         }
2152 #endif /* SCTP_DEBUG */
2153                 }
2154                 SCTP_TCB_UNLOCK(stcb);
2155         }
2156 #ifdef SCTP_DEBUG
2157         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2158                 printf("All done\n");
2159         }
2160 #endif /* SCTP_DEBUG */
2161         break;
2162         case SCTP_GET_LOCAL_ADDRESSES:
2163         {
2164                 int limit, actual;
2165                 struct sockaddr_storage *sas;
2166                 struct sctp_getaddresses *saddr;
2167 #ifdef SCTP_DEBUG
2168                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2169                         printf("get local addresses\n");
2170                 }
2171 #endif /* SCTP_DEBUG */
2172                 if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) {
2173                         error = EINVAL;
2174                         break;
2175                 }
2176                 saddr = mtod(m, struct sctp_getaddresses *);
2177
2178                 if (saddr->sget_assoc_id) {
2179                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2180                                 SCTP_INP_RLOCK(inp);
2181                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
2182                                 if (stcb)
2183                                         SCTP_TCB_LOCK(stcb);
2184                                 SCTP_INP_RUNLOCK(inp);
2185                         } else
2186                                 stcb = sctp_findassociation_ep_asocid(inp, saddr->sget_assoc_id);
2187
2188                 } else {
2189                         stcb = NULL;
2190                 }
2191                 /*
2192                  * assure that the TCP model does not need a assoc id
2193                  * once connected.
2194                  */
2195                 if ( (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) &&
2196                      (stcb == NULL) ) {
2197                         SCTP_INP_RLOCK(inp);
2198                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2199                         if (stcb)
2200                                 SCTP_TCB_LOCK(stcb);
2201                         SCTP_INP_RUNLOCK(inp);
2202                 }
2203                 sas = (struct sockaddr_storage *)&saddr->addr[0];
2204                 limit = m->m_len - sizeof(sctp_assoc_t);
2205                 actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2206                 SCTP_TCB_UNLOCK(stcb);
2207                 m->m_len = sizeof(struct sockaddr_storage) + actual;
2208         }
2209         break;
2210         case SCTP_PEER_ADDR_PARAMS:
2211         {
2212                 struct sctp_paddrparams *paddrp;
2213                 struct sctp_nets *net;
2214
2215 #ifdef SCTP_DEBUG
2216                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2217                         printf("Getting peer_addr_params\n");
2218                 }
2219 #endif /* SCTP_DEBUG */
2220                 if ((size_t)m->m_len < sizeof(struct sctp_paddrparams)) {
2221 #ifdef SCTP_DEBUG
2222                         if (sctp_debug_on & SCTP_DEBUG_USRREQ2) {
2223                                 printf("Hmm m->m_len:%d is to small\n",
2224                                        m->m_len);
2225                         }
2226 #endif /* SCTP_DEBUG */
2227                         error = EINVAL;
2228                         break;
2229                 }
2230                 paddrp = mtod(m, struct sctp_paddrparams *);
2231
2232                 net = NULL;
2233                 if (paddrp->spp_assoc_id) {
2234 #ifdef SCTP_DEBUG
2235                         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2236                                 printf("In spp_assoc_id find type\n");
2237                         }
2238 #endif /* SCTP_DEBUG */
2239                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2240                                 SCTP_INP_RLOCK(inp);
2241                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
2242                                 if (stcb) {
2243                                         SCTP_TCB_LOCK(stcb);
2244                                         net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2245                                 }
2246                                 SCTP_INP_RLOCK(inp);
2247                         } else {
2248                                 stcb = sctp_findassociation_ep_asocid(inp, paddrp->spp_assoc_id);
2249                         }
2250                         if (stcb == NULL) {
2251                                 error = ENOENT;
2252                                 break;
2253                         }
2254                 }
2255                 if (    (stcb == NULL) &&
2256                         ((((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET) ||
2257                          (((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET6))) {
2258                         /* Lookup via address */
2259 #ifdef SCTP_DEBUG
2260                         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2261                                 printf("Ok we need to lookup a param\n");
2262                         }
2263 #endif /* SCTP_DEBUG */
2264                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2265                                 SCTP_INP_RLOCK(inp);
2266                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
2267                                 if (stcb) {
2268                                         SCTP_TCB_LOCK(stcb);
2269                                         net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2270                                 }
2271                                 SCTP_INP_RUNLOCK(inp);
2272                         } else {
2273                                 SCTP_INP_WLOCK(inp);
2274                                 SCTP_INP_INCR_REF(inp);
2275                                 SCTP_INP_WUNLOCK(inp);
2276                                 stcb = sctp_findassociation_ep_addr(&inp,
2277                                                                     (struct sockaddr *)&paddrp->spp_address,
2278                                                                     &net, NULL, NULL);
2279                                 if (stcb == NULL) {
2280                                         SCTP_INP_WLOCK(inp);
2281                                         SCTP_INP_DECR_REF(inp);
2282                                         SCTP_INP_WUNLOCK(inp);
2283                                 }
2284                         }
2285
2286                         if (stcb == NULL) {
2287                                 error = ENOENT;
2288                                 break;
2289                         }
2290                 } else {
2291                         /* Effects the Endpoint */
2292 #ifdef SCTP_DEBUG
2293                         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2294                                 printf("User wants EP level info\n");
2295                         }
2296 #endif /* SCTP_DEBUG */
2297                         stcb = NULL;
2298                 }
2299                 if (stcb) {
2300                         /* Applys to the specific association */
2301 #ifdef SCTP_DEBUG
2302                         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2303                                 printf("In TCB side\n");
2304                         }
2305 #endif /* SCTP_DEBUG */
2306                         if (net) {
2307                                 paddrp->spp_pathmaxrxt = net->failure_threshold;
2308                         } else {
2309                                 /* No destination so return default value */
2310                                 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2311                         }
2312                         paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2313                         paddrp->spp_assoc_id = sctp_get_associd(stcb);
2314                         SCTP_TCB_UNLOCK(stcb);
2315                 } else {
2316                         /* Use endpoint defaults */
2317                         SCTP_INP_RLOCK(inp);
2318 #ifdef SCTP_DEBUG
2319                         if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2320                                 printf("In EP levle info\n");
2321                         }
2322 #endif /* SCTP_DEBUG */
2323                         paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2324                         paddrp->spp_hbinterval = inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT];
2325                         paddrp->spp_assoc_id = (sctp_assoc_t)0;
2326                         SCTP_INP_RUNLOCK(inp);
2327                 }
2328                 m->m_len = sizeof(struct sctp_paddrparams);
2329         }
2330         break;
2331         case SCTP_GET_PEER_ADDR_INFO:
2332         {
2333                 struct sctp_paddrinfo *paddri;
2334                 struct sctp_nets *net;
2335 #ifdef SCTP_DEBUG
2336                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2337                         printf("GetPEER ADDR_INFO\n");
2338                 }
2339 #endif /* SCTP_DEBUG */
2340                 if ((size_t)m->m_len < sizeof(struct sctp_paddrinfo)) {
2341                         error = EINVAL;
2342                         break;
2343                 }
2344                 paddri = mtod(m, struct sctp_paddrinfo *);
2345                 net = NULL;
2346                 if ((((struct sockaddr *)&paddri->spinfo_address)->sa_family == AF_INET) ||
2347                     (((struct sockaddr *)&paddri->spinfo_address)->sa_family == AF_INET6)) {
2348                         /* Lookup via address */
2349                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2350                                 SCTP_INP_RLOCK(inp);
2351                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
2352                                 if (stcb) {
2353                                         SCTP_TCB_LOCK(stcb);
2354                                         net = sctp_findnet(stcb,
2355                                                             (struct sockaddr *)&paddri->spinfo_address);
2356                                 }
2357                                 SCTP_INP_RUNLOCK(inp);
2358                         } else {
2359                                 SCTP_INP_WLOCK(inp);
2360                                 SCTP_INP_INCR_REF(inp);
2361                                 SCTP_INP_WUNLOCK(inp);
2362                                 stcb = sctp_findassociation_ep_addr(&inp,
2363                                     (struct sockaddr *)&paddri->spinfo_address,
2364                                     &net, NULL, NULL);
2365                                 if (stcb == NULL) {
2366                                         SCTP_INP_WLOCK(inp);
2367                                         SCTP_INP_DECR_REF(inp);
2368                                         SCTP_INP_WUNLOCK(inp);
2369                                 }
2370                         }
2371
2372                 } else {
2373                         stcb = NULL;
2374                 }
2375                 if ((stcb == NULL) || (net == NULL)) {
2376                         error = ENOENT;
2377                         break;
2378                 }
2379                 m->m_len = sizeof(struct sctp_paddrinfo);
2380                 paddri->spinfo_state = net->dest_state & (SCTP_REACHABLE_MASK|SCTP_ADDR_NOHB);
2381                 paddri->spinfo_cwnd = net->cwnd;
2382                 paddri->spinfo_srtt = ((net->lastsa >> 2) + net->lastsv) >> 1;
2383                 paddri->spinfo_rto = net->RTO;
2384                 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2385                 SCTP_TCB_UNLOCK(stcb);
2386         }
2387         break;
2388         case SCTP_PCB_STATUS:
2389         {
2390                 struct sctp_pcbinfo *spcb;
2391 #ifdef SCTP_DEBUG
2392                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2393                         printf("PCB status\n");
2394                 }
2395 #endif /* SCTP_DEBUG */
2396                 if ((size_t)m->m_len < sizeof(struct sctp_pcbinfo)) {
2397                         error = EINVAL;
2398                         break;
2399                 }
2400                 spcb = mtod(m, struct sctp_pcbinfo *);
2401                 sctp_fill_pcbinfo(spcb);
2402                 m->m_len = sizeof(struct sctp_pcbinfo);
2403         }
2404         break;
2405         case SCTP_STATUS:
2406         {
2407                 struct sctp_nets *net;
2408                 struct sctp_status *sstat;
2409 #ifdef SCTP_DEBUG
2410                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2411                         printf("SCTP status\n");
2412                 }
2413 #endif /* SCTP_DEBUG */
2414
2415                 if ((size_t)m->m_len < sizeof(struct sctp_status)) {
2416                         error = EINVAL;
2417                         break;
2418                 }
2419                 sstat = mtod(m, struct sctp_status *);
2420
2421                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2422                         SCTP_INP_RLOCK(inp);
2423                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2424                         if (stcb)
2425                                 SCTP_TCB_LOCK(stcb);
2426                         SCTP_INP_RUNLOCK(inp);
2427                 } else
2428                         stcb = sctp_findassociation_ep_asocid(inp, sstat->sstat_assoc_id);
2429
2430                 if (stcb == NULL) {
2431                         error = EINVAL;
2432                         break;
2433                 }
2434                 /*
2435                  * I think passing the state is fine since
2436                  * sctp_constants.h will be available to the user
2437                  * land.
2438                  */
2439                 sstat->sstat_state = stcb->asoc.state;
2440                 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2441                 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2442                 /*
2443                  * We can't include chunks that have been passed
2444                  * to the socket layer. Only things in queue.
2445                  */
2446                 sstat->sstat_penddata = (stcb->asoc.cnt_on_delivery_queue +
2447                                          stcb->asoc.cnt_on_reasm_queue +
2448                                          stcb->asoc.cnt_on_all_streams);
2449
2450
2451                 sstat->sstat_instrms = stcb->asoc.streamincnt;
2452                 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2453                 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
2454                 memcpy(&sstat->sstat_primary.spinfo_address,
2455                        &stcb->asoc.primary_destination->ro._l_addr,
2456                        ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
2457                 net = stcb->asoc.primary_destination;
2458                 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2459                 /*
2460                  * Again the user can get info from sctp_constants.h
2461                  * for what the state of the network is.
2462                  */
2463                 sstat->sstat_primary.spinfo_state = net->dest_state & SCTP_REACHABLE_MASK;
2464                 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2465                 sstat->sstat_primary.spinfo_srtt = net->lastsa;
2466                 sstat->sstat_primary.spinfo_rto = net->RTO;
2467                 sstat->sstat_primary.spinfo_mtu = net->mtu;
2468                 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2469                 SCTP_TCB_UNLOCK(stcb);
2470                 m->m_len = sizeof(*sstat);
2471         }
2472         break;
2473         case SCTP_RTOINFO:
2474         {
2475                 struct sctp_rtoinfo *srto;
2476 #ifdef SCTP_DEBUG
2477                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2478                         printf("RTO Info\n");
2479                 }
2480 #endif /* SCTP_DEBUG */
2481                 if ((size_t)m->m_len < sizeof(struct sctp_rtoinfo)) {
2482                         error = EINVAL;
2483                         break;
2484                 }
2485                 srto = mtod(m, struct sctp_rtoinfo *);
2486                 if (srto->srto_assoc_id == 0) {
2487                         /* Endpoint only please */
2488                         SCTP_INP_RLOCK(inp);
2489                         srto->srto_initial = inp->sctp_ep.initial_rto;
2490                         srto->srto_max = inp->sctp_ep.sctp_maxrto;
2491                         srto->srto_min = inp->sctp_ep.sctp_minrto;
2492                         SCTP_INP_RUNLOCK(inp);
2493                         break;
2494                 }
2495                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2496                         SCTP_INP_RLOCK(inp);
2497                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2498                         if (stcb)
2499                                 SCTP_TCB_LOCK(stcb);
2500                         SCTP_INP_RUNLOCK(inp);
2501                 } else
2502                         stcb = sctp_findassociation_ep_asocid(inp, srto->srto_assoc_id);
2503
2504                 if (stcb == NULL) {
2505                         error = EINVAL;
2506                         break;
2507                 }
2508                 srto->srto_initial = stcb->asoc.initial_rto;
2509                 srto->srto_max = stcb->asoc.maxrto;
2510                 srto->srto_min = stcb->asoc.minrto;
2511                 SCTP_TCB_UNLOCK(stcb);
2512                 m->m_len = sizeof(*srto);
2513         }
2514         break;
2515         case SCTP_ASSOCINFO:
2516         {
2517                 struct sctp_assocparams *sasoc;
2518 #ifdef SCTP_DEBUG
2519                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2520                         printf("Associnfo\n");
2521                 }
2522 #endif /* SCTP_DEBUG */
2523                 if ((size_t)m->m_len < sizeof(struct sctp_assocparams)) {
2524                         error = EINVAL;
2525                         break;
2526                 }
2527                 sasoc = mtod(m, struct sctp_assocparams *);
2528                 stcb = NULL;
2529
2530                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2531                         SCTP_INP_RLOCK(inp);
2532                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2533                         if (stcb)
2534                                 SCTP_TCB_LOCK(stcb);
2535                         SCTP_INP_RUNLOCK(inp);
2536                 }
2537                 if ((sasoc->sasoc_assoc_id) && (stcb == NULL)) {
2538                         stcb = sctp_findassociation_ep_asocid(inp,
2539                                                              sasoc->sasoc_assoc_id);
2540                         if (stcb == NULL) {
2541                                 error = ENOENT;
2542                                 break;
2543                         }
2544                 } else {
2545                         stcb = NULL;
2546                 }
2547
2548                 if (stcb) {
2549                         sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2550                         sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2551                         sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2552                         sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2553                         sasoc->sasoc_cookie_life = stcb->asoc.cookie_life;
2554                         SCTP_TCB_UNLOCK(stcb);
2555                 } else {
2556                         SCTP_INP_RLOCK(inp);
2557                         sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2558                         sasoc->sasoc_number_peer_destinations = 0;
2559                         sasoc->sasoc_peer_rwnd = 0;
2560                         sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
2561                         sasoc->sasoc_cookie_life = inp->sctp_ep.def_cookie_life;
2562                         SCTP_INP_RUNLOCK(inp);
2563                 }
2564                 m->m_len = sizeof(*sasoc);
2565         }
2566         break;
2567         case SCTP_DEFAULT_SEND_PARAM:
2568         {
2569                 struct sctp_sndrcvinfo *s_info;
2570
2571                 if (m->m_len != sizeof(struct sctp_sndrcvinfo)) {
2572                         error = EINVAL;
2573                         break;
2574                 }
2575                 s_info = mtod(m, struct sctp_sndrcvinfo *);
2576                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2577                         SCTP_INP_RLOCK(inp);
2578                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2579                         if (stcb)
2580                                 SCTP_TCB_LOCK(stcb);
2581                         SCTP_INP_RUNLOCK(inp);
2582                 } else
2583                         stcb = sctp_findassociation_ep_asocid(inp, s_info->sinfo_assoc_id);
2584
2585                 if (stcb == NULL) {
2586                         error = ENOENT;
2587                         break;
2588                 }
2589                 /* Copy it out */
2590                 *s_info = stcb->asoc.def_send;
2591                 SCTP_TCB_UNLOCK(stcb);
2592                 m->m_len = sizeof(*s_info);
2593         }
2594         case SCTP_INITMSG:
2595         {
2596                 struct sctp_initmsg *sinit;
2597 #ifdef SCTP_DEBUG
2598                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2599                         printf("initmsg\n");
2600                 }
2601 #endif /* SCTP_DEBUG */
2602                 if ((size_t)m->m_len < sizeof(struct sctp_initmsg)) {
2603                         error = EINVAL;
2604                         break;
2605                 }
2606                 sinit = mtod(m, struct sctp_initmsg *);
2607                 SCTP_INP_RLOCK(inp);
2608                 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2609                 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2610                 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2611                 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2612                 SCTP_INP_RUNLOCK(inp);
2613                 m->m_len = sizeof(*sinit);
2614         }
2615         break;
2616         case SCTP_PRIMARY_ADDR:
2617                 /* we allow a "get" operation on this */
2618         {
2619                 struct sctp_setprim *ssp;
2620
2621 #ifdef SCTP_DEBUG
2622                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2623                         printf("setprimary\n");
2624                 }
2625 #endif /* SCTP_DEBUG */
2626                 if ((size_t)m->m_len < sizeof(struct sctp_setprim)) {
2627                         error = EINVAL;
2628                         break;
2629                 }
2630                 ssp = mtod(m, struct sctp_setprim *);
2631                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2632                         SCTP_INP_RLOCK(inp);
2633                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2634                         if (stcb)
2635                                 SCTP_TCB_LOCK(stcb);
2636                         SCTP_INP_RUNLOCK(inp);
2637                 } else {
2638                         stcb = sctp_findassociation_ep_asocid(inp, ssp->ssp_assoc_id);
2639                         if (stcb == NULL) {
2640                                 /* one last shot, try it by the address in */
2641                                 struct sctp_nets *net;
2642
2643                                 SCTP_INP_WLOCK(inp);
2644                                 SCTP_INP_INCR_REF(inp);
2645                                 SCTP_INP_WUNLOCK(inp);
2646                                 stcb = sctp_findassociation_ep_addr(&inp,
2647                                                             (struct sockaddr *)&ssp->ssp_addr,
2648                                                             &net, NULL, NULL);
2649                                 if (stcb == NULL) {
2650                                         SCTP_INP_WLOCK(inp);
2651                                         SCTP_INP_DECR_REF(inp);
2652                                         SCTP_INP_WUNLOCK(inp);
2653                                 }
2654                         }
2655                         if (stcb == NULL) {
2656                                 error = EINVAL;
2657                                 break;
2658                         }
2659                 }
2660                 /* simply copy out the sockaddr_storage... */
2661                 memcpy(&ssp->ssp_addr,
2662                        &stcb->asoc.primary_destination->ro._l_addr,
2663                        ((struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr)->sa_len);
2664                 SCTP_TCB_UNLOCK(stcb);
2665                 m->m_len = sizeof(*ssp);
2666         }
2667         break;
2668         default:
2669                 error = ENOPROTOOPT;
2670                 m->m_len = 0;
2671                 break;
2672         } /* end switch (sopt->sopt_name) */
2673         return (error);
2674 }
2675
2676 static int
2677 sctp_optsset(struct socket *so,
2678              int opt,
2679              struct mbuf **mp,
2680 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
2681              struct thread *p
2682 #else
2683              struct proc *p
2684 #endif
2685         )
2686 {
2687         int error, *mopt, set_opt;
2688         struct mbuf *m;
2689         struct sctp_tcb *stcb = NULL;
2690         struct sctp_inpcb *inp;
2691
2692         if (mp == NULL) {
2693 #ifdef SCTP_DEBUG
2694                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
2695                         printf("optsset:MP is NULL EINVAL\n");
2696                 }
2697 #endif /* SCTP_DEBUG */
2698                 return (EINVAL);
2699         }
2700         m = *mp;
2701         if (m == NULL)
2702                 return (EINVAL);
2703
2704         inp = (struct sctp_inpcb *)so->so_pcb;
2705         if (inp == 0)
2706                 return EINVAL;
2707
2708         error = 0;
2709         switch (opt) {
2710         case SCTP_NODELAY:
2711         case SCTP_AUTOCLOSE:
2712         case SCTP_AUTO_ASCONF:
2713         case SCTP_DISABLE_FRAGMENTS:
2714         case SCTP_I_WANT_MAPPED_V4_ADDR:
2715                 /* copy in the option value */
2716                 if ((size_t)m->m_len < sizeof(int)) {
2717                         error = EINVAL;
2718                         break;
2719                 }
2720                 mopt = mtod(m, int *);
2721                 set_opt = 0;
2722                 if (error)
2723                         break;
2724                 switch (opt) {
2725                 case SCTP_DISABLE_FRAGMENTS:
2726                         set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
2727                         break;
2728                 case SCTP_AUTO_ASCONF:
2729                         set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
2730                         break;
2731
2732                 case SCTP_I_WANT_MAPPED_V4_ADDR:
2733                         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2734                                 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
2735                         } else {
2736                                 return (EINVAL);
2737                         }
2738                         break;
2739                 case SCTP_NODELAY:
2740                         set_opt = SCTP_PCB_FLAGS_NODELAY;
2741                         break;
2742                 case SCTP_AUTOCLOSE:
2743                         set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
2744                         /*
2745                          * The value is in ticks.
2746                          * Note this does not effect old associations, only
2747                          * new ones.
2748                          */
2749                         inp->sctp_ep.auto_close_time = (*mopt * hz);
2750                         break;
2751                 }
2752                 SCTP_INP_WLOCK(inp);
2753                 if (*mopt != 0) {
2754                         inp->sctp_flags |= set_opt;
2755                 } else {
2756                         inp->sctp_flags &= ~set_opt;
2757                 }
2758                 SCTP_INP_WUNLOCK(inp);
2759                 break;
2760         case SCTP_MY_PUBLIC_KEY:    /* set my public key */
2761         case SCTP_SET_AUTH_CHUNKS:  /* set the authenticated chunks required */
2762         case SCTP_SET_AUTH_SECRET:  /* set the actual secret for the endpoint */
2763                 /* not supported yet and until we refine the draft */
2764                 error = EOPNOTSUPP;
2765                 break;
2766
2767         case SCTP_CLR_STAT_LOG:
2768 #ifdef SCTP_STAT_LOGGING
2769                 sctp_clr_stat_log();
2770 #else
2771                 error = EOPNOTSUPP;
2772 #endif
2773                 break;
2774         case SCTP_DELAYED_ACK_TIME:
2775         {
2776                 int32_t *tm;
2777                 if ((size_t)m->m_len < sizeof(int32_t)) {
2778                         error = EINVAL;
2779                         break;
2780                 }
2781                 tm = mtod(m, int32_t *);
2782
2783                 if ((*tm < 10) || (*tm > 500)) {
2784                         /* can't be smaller than 10ms */
2785                         /* MUST NOT be larger than 500ms */
2786                         error = EINVAL;
2787                         break;
2788                 }
2789                 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(*tm);
2790         }
2791                 break;
2792         case SCTP_RESET_STREAMS:
2793         {
2794                 struct sctp_stream_reset *strrst;
2795                 uint8_t two_way, not_peer;
2796
2797                 if ((size_t)m->m_len < sizeof(struct sctp_stream_reset)) {
2798                         error = EINVAL;
2799                         break;
2800                 }
2801                 strrst = mtod(m, struct sctp_stream_reset *);
2802
2803                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2804                         SCTP_INP_RLOCK(inp);
2805                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2806                         if (stcb)
2807                                 SCTP_TCB_LOCK(stcb);
2808                         SCTP_INP_RUNLOCK(inp);
2809                 } else
2810                         stcb = sctp_findassociation_ep_asocid(inp, strrst->strrst_assoc_id);
2811                 if (stcb == NULL) {
2812                         error = ENOENT;
2813                         break;
2814                 }
2815                 if (stcb->asoc.peer_supports_strreset == 0) {
2816                         /* Peer does not support it,
2817                          * we return protocol not supported since
2818                          * this is true for this feature and this
2819                          * peer, not the socket request in general.
2820                          */
2821                         error = EPROTONOSUPPORT;
2822                         SCTP_TCB_UNLOCK(stcb);
2823                         break;
2824                 }
2825
2826 /* Having re-thought this code I added as I write the I-D there
2827  * is NO need for it. The peer, if we are requesting a stream-reset
2828  * will send a request to us but will itself do what we do, take
2829  * and copy off the "reset information" we send and queue TSN's
2830  * larger than the send-next in our response message. Thus they
2831  * will handle it.
2832  */
2833 /*              if (stcb->asoc.sending_seq != (stcb->asoc.last_acked_seq + 1)) {*/
2834                 /* Must have all sending data ack'd before we
2835                  * start this procedure. This is a bit restrictive
2836                  * and we SHOULD work on changing this so ONLY the
2837                  * streams being RESET get held up. So, a reset-all
2838                  * would require this.. but a reset specific just
2839                  * needs to be sure that the ones being reset have
2840                  * nothing on the send_queue. For now we will
2841                  * skip this more detailed method and do a course
2842                  * way.. i.e. nothing pending ... for future FIX ME!
2843                  */
2844 /*                      error = EBUSY;*/
2845 /*                      break;*/
2846 /*              }*/
2847
2848                 if (stcb->asoc.stream_reset_outstanding) {
2849                         error = EALREADY;
2850                         SCTP_TCB_UNLOCK(stcb);
2851                         break;
2852                 }
2853                 if (strrst->strrst_flags == SCTP_RESET_LOCAL_RECV) {
2854                         two_way = 0;
2855                         not_peer = 0;
2856                 } else if (strrst->strrst_flags == SCTP_RESET_LOCAL_SEND) {
2857                         two_way = 1;
2858                         not_peer = 1;
2859                 } else if (strrst->strrst_flags == SCTP_RESET_BOTH) {
2860                         two_way = 1;
2861                         not_peer = 0;
2862                 } else {
2863                         error = EINVAL;
2864                         SCTP_TCB_UNLOCK(stcb);
2865                         break;
2866                 }
2867                 sctp_send_str_reset_req(stcb, strrst->strrst_num_streams,
2868                                         strrst->strrst_list, two_way, not_peer);
2869                 crit_enter();
2870                 sctp_chunk_output(inp, stcb, 12);
2871                 SCTP_TCB_UNLOCK(stcb);
2872                 crit_exit();
2873
2874         }
2875         break;
2876         case SCTP_RESET_PEGS:
2877                 memset(sctp_pegs, 0, sizeof(sctp_pegs));
2878                 error = 0;
2879                 break;
2880         case SCTP_CONNECT_X:
2881                 if ((size_t)m->m_len < (sizeof(int) + sizeof(struct sockaddr_in))) {
2882                         error = EINVAL;
2883                         break;
2884                 }
2885                 error = sctp_do_connect_x(so, inp, m, p, 0);
2886                 break;
2887
2888         case SCTP_CONNECT_X_DELAYED:
2889                 if ((size_t)m->m_len < (sizeof(int) + sizeof(struct sockaddr_in))) {
2890                         error = EINVAL;
2891                         break;
2892                 }
2893                 error = sctp_do_connect_x(so, inp, m, p, 1);
2894                 break;
2895
2896         case SCTP_CONNECT_X_COMPLETE:
2897         {
2898                 struct sockaddr *sa;
2899                 struct sctp_nets *net;
2900                 if ((size_t)m->m_len < sizeof(struct sockaddr_in)) {
2901                         error = EINVAL;
2902                         break;
2903                 }
2904                 sa = mtod(m, struct sockaddr *);
2905                 /* find tcb */
2906                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
2907                         SCTP_INP_RLOCK(inp);
2908                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
2909                         if (stcb) {
2910                                 SCTP_TCB_LOCK(stcb);
2911                                 net = sctp_findnet(stcb, sa);
2912                         }
2913                         SCTP_INP_RUNLOCK(inp);
2914                 } else {
2915                         SCTP_INP_WLOCK(inp);
2916                         SCTP_INP_INCR_REF(inp);
2917                         SCTP_INP_WUNLOCK(inp);
2918                         stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
2919                         if (stcb == NULL) {
2920                                 SCTP_INP_WLOCK(inp);
2921                                 SCTP_INP_DECR_REF(inp);
2922                                 SCTP_INP_WUNLOCK(inp);
2923                         }
2924                 }
2925
2926                 if (stcb == NULL) {
2927                         error = ENOENT;
2928                         break;
2929                 }
2930                 if (stcb->asoc.delayed_connection == 1) {
2931                         stcb->asoc.delayed_connection = 0;
2932                         SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
2933                         sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
2934                         sctp_send_initiate(inp, stcb);
2935                 } else {
2936                         /* already expired or did not use delayed connectx */
2937                         error = EALREADY;
2938                 }
2939                 SCTP_TCB_UNLOCK(stcb);
2940         }
2941         break;
2942         case SCTP_MAXBURST:
2943         {
2944                 u_int8_t *burst;
2945                 SCTP_INP_WLOCK(inp);
2946                 burst = mtod(m, u_int8_t *);
2947                 if (*burst) {
2948                         inp->sctp_ep.max_burst = *burst;
2949                 }
2950                 SCTP_INP_WUNLOCK(inp);
2951         }
2952         break;
2953         case SCTP_MAXSEG:
2954         {
2955                 u_int32_t *segsize;
2956                 int ovh;
2957                 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2958                         ovh = SCTP_MED_OVERHEAD;
2959                 } else {
2960                         ovh = SCTP_MED_V4_OVERHEAD;
2961                 }
2962                 segsize = mtod(m, u_int32_t *);
2963                 if (*segsize < 1) {
2964                         error = EINVAL;
2965                         break;
2966                 }
2967                 SCTP_INP_WLOCK(inp);
2968                 inp->sctp_frag_point = (*segsize+ovh);
2969                 if (inp->sctp_frag_point < MHLEN) {
2970                         inp->sctp_frag_point = MHLEN;
2971                 }
2972                 SCTP_INP_WUNLOCK(inp);
2973         }
2974         break;
2975         case SCTP_SET_DEBUG_LEVEL:
2976 #ifdef SCTP_DEBUG
2977         {
2978                 u_int32_t *level;
2979                 if ((size_t)m->m_len < sizeof(u_int32_t)) {
2980                         error = EINVAL;
2981                         break;
2982                 }
2983                 level = mtod(m, u_int32_t *);
2984                 error = 0;
2985                 sctp_debug_on = (*level & (SCTP_DEBUG_ALL |
2986                                            SCTP_DEBUG_NOISY));
2987                 printf("SETTING DEBUG LEVEL to %x\n",
2988                        (u_int)sctp_debug_on);
2989
2990         }
2991 #else
2992         error = EOPNOTSUPP;
2993 #endif /* SCTP_DEBUG */
2994         break;
2995         case SCTP_EVENTS:
2996         {
2997                 struct sctp_event_subscribe *events;
2998                 if ((size_t)m->m_len < sizeof(struct sctp_event_subscribe)) {
2999                         error = EINVAL;
3000                         break;
3001                 }
3002                 SCTP_INP_WLOCK(inp);
3003                 events = mtod(m, struct sctp_event_subscribe *);
3004                 if (events->sctp_data_io_event) {
3005                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVDATAIOEVNT;
3006                 } else {
3007                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVDATAIOEVNT;
3008                 }
3009
3010                 if (events->sctp_association_event) {
3011                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVASSOCEVNT;
3012                 } else {
3013                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVASSOCEVNT;
3014                 }
3015
3016                 if (events->sctp_address_event) {
3017                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVPADDREVNT;
3018                 } else {
3019                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVPADDREVNT;
3020                 }
3021
3022                 if (events->sctp_send_failure_event) {
3023                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3024                 } else {
3025                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
3026                 }
3027
3028                 if (events->sctp_peer_error_event) {
3029                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVPEERERR;
3030                 } else {
3031                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVPEERERR;
3032                 }
3033
3034                 if (events->sctp_shutdown_event) {
3035                         inp->sctp_flags |= SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3036                 } else {
3037                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
3038                 }
3039
3040                 if (events->sctp_partial_delivery_event) {
3041                         inp->sctp_flags |= SCTP_PCB_FLAGS_PDAPIEVNT;
3042                 } else {
3043                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_PDAPIEVNT;
3044                 }
3045
3046                 if (events->sctp_adaption_layer_event) {
3047                         inp->sctp_flags |= SCTP_PCB_FLAGS_ADAPTIONEVNT;
3048                 } else {
3049                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_ADAPTIONEVNT;
3050                 }
3051
3052                 if (events->sctp_stream_reset_events) {
3053                         inp->sctp_flags |= SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3054                 } else {
3055                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_STREAM_RESETEVNT;
3056                 }
3057                 SCTP_INP_WUNLOCK(inp);
3058         }
3059         break;
3060
3061         case SCTP_ADAPTION_LAYER:
3062         {
3063                 struct sctp_setadaption *adap_bits;
3064                 if ((size_t)m->m_len < sizeof(struct sctp_setadaption)) {
3065                         error = EINVAL;
3066                         break;
3067                 }
3068                 SCTP_INP_WLOCK(inp);
3069                 adap_bits = mtod(m, struct sctp_setadaption *);
3070                 inp->sctp_ep.adaption_layer_indicator = adap_bits->ssb_adaption_ind;
3071                 SCTP_INP_WUNLOCK(inp);
3072         }
3073         break;
3074         case SCTP_SET_INITIAL_DBG_SEQ:
3075         {
3076                 u_int32_t *vvv;
3077                 if ((size_t)m->m_len < sizeof(u_int32_t)) {
3078                         error = EINVAL;
3079                         break;
3080                 }
3081                 SCTP_INP_WLOCK(inp);
3082                 vvv = mtod(m, u_int32_t *);
3083                 inp->sctp_ep.initial_sequence_debug = *vvv;
3084                 SCTP_INP_WUNLOCK(inp);
3085         }
3086         break;
3087         case SCTP_DEFAULT_SEND_PARAM:
3088         {
3089                 struct sctp_sndrcvinfo *s_info;
3090
3091                 if (m->m_len != sizeof(struct sctp_sndrcvinfo)) {
3092                         error = EINVAL;
3093                         break;
3094                 }
3095                 s_info = mtod(m, struct sctp_sndrcvinfo *);
3096
3097                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3098                         SCTP_INP_RLOCK(inp);
3099                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
3100                         if (stcb)
3101                                 SCTP_TCB_LOCK(stcb);
3102                         SCTP_INP_RUNLOCK(inp);
3103                 } else
3104                         stcb = sctp_findassociation_ep_asocid(inp, s_info->sinfo_assoc_id);
3105
3106                 if (stcb == NULL) {
3107                         error = ENOENT;
3108                         break;
3109                 }
3110                 /* Validate things */
3111                 if (s_info->sinfo_stream > stcb->asoc.streamoutcnt) {
3112                         SCTP_TCB_UNLOCK(stcb);
3113                         error = EINVAL;
3114                         break;
3115                 }
3116                 /* Mask off the flags that are allowed */
3117                 s_info->sinfo_flags = (s_info->sinfo_flags &
3118                                        (MSG_UNORDERED | MSG_ADDR_OVER |
3119                                         MSG_PR_SCTP_TTL | MSG_PR_SCTP_BUF));
3120                 /* Copy it in */
3121                 stcb->asoc.def_send = *s_info;
3122                 SCTP_TCB_UNLOCK(stcb);
3123         }
3124         break;
3125         case SCTP_PEER_ADDR_PARAMS:
3126         {
3127                 struct sctp_paddrparams *paddrp;
3128                 struct sctp_nets *net;
3129                 if ((size_t)m->m_len < sizeof(struct sctp_paddrparams)) {
3130                         error = EINVAL;
3131                         break;
3132                 }
3133                 paddrp = mtod(m, struct sctp_paddrparams *);
3134                 net = NULL;
3135                 if (paddrp->spp_assoc_id) {
3136                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3137                                 SCTP_INP_RLOCK(inp);
3138                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
3139                                 if (stcb) {
3140                                         SCTP_TCB_LOCK(stcb);
3141                                         net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
3142                                 }
3143                                 SCTP_INP_RUNLOCK(inp);
3144                         } else
3145                                 stcb = sctp_findassociation_ep_asocid(inp, paddrp->spp_assoc_id);
3146                         if (stcb == NULL) {
3147                                 error = ENOENT;
3148                                 break;
3149                         }
3150
3151                 }
3152                 if ((stcb == NULL) &&
3153                     ((((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET) ||
3154                      (((struct sockaddr *)&paddrp->spp_address)->sa_family == AF_INET6))) {
3155                         /* Lookup via address */
3156                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3157                                 SCTP_INP_RLOCK(inp);
3158                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
3159                                 if (stcb) {
3160                                         SCTP_TCB_LOCK(stcb);
3161                                         net = sctp_findnet(stcb,
3162                                                            (struct sockaddr *)&paddrp->spp_address);
3163                                 }
3164                                 SCTP_INP_RUNLOCK(inp);
3165                         } else {
3166                                 SCTP_INP_WLOCK(inp);
3167                                 SCTP_INP_INCR_REF(inp);
3168                                 SCTP_INP_WUNLOCK(inp);
3169                                 stcb = sctp_findassociation_ep_addr(&inp,
3170                                                                     (struct sockaddr *)&paddrp->spp_address,
3171                                                                     &net, NULL, NULL);
3172                                 if (stcb == NULL) {
3173                                         SCTP_INP_WLOCK(inp);
3174                                         SCTP_INP_DECR_REF(inp);
3175                                         SCTP_INP_WUNLOCK(inp);
3176                                 }
3177                         }
3178                 } else {
3179                         /* Effects the Endpoint */
3180                         stcb = NULL;
3181                 }
3182                 if (stcb) {
3183                         /* Applies to the specific association */
3184                         if (paddrp->spp_pathmaxrxt) {
3185                                 if (net) {
3186                                         if (paddrp->spp_pathmaxrxt)
3187                                                 net->failure_threshold = paddrp->spp_pathmaxrxt;
3188                                 } else {
3189                                         if (paddrp->spp_pathmaxrxt)
3190                                                 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
3191                                 }
3192                         }
3193                         if ((paddrp->spp_hbinterval != 0) && (paddrp->spp_hbinterval != 0xffffffff)) {
3194                                 /* Just a set */
3195                                 int old;
3196                                 if (net) {
3197                                         net->dest_state &= ~SCTP_ADDR_NOHB;
3198                                 } else {
3199                                         old = stcb->asoc.heart_beat_delay;
3200                                         stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
3201                                         if (old == 0) {
3202                                                 /* Turn back on the timer */
3203                                                 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
3204                                         }
3205                                 }
3206                         } else if (paddrp->spp_hbinterval == 0xffffffff) {
3207                                 /* on demand HB */
3208                                 sctp_send_hb(stcb, 1, net);
3209                         } else {
3210                                 if (net == NULL) {
3211                                         /* off on association */
3212                                         if (stcb->asoc.heart_beat_delay) {
3213                                                 int cnt_of_unconf = 0;
3214                                                 struct sctp_nets *lnet;
3215                                                 TAILQ_FOREACH(lnet, &stcb->asoc.nets, sctp_next) {
3216                                                         if (lnet->dest_state & SCTP_ADDR_UNCONFIRMED) {
3217                                                                 cnt_of_unconf++;
3218                                                         }
3219                                                 }
3220                                                 /* stop the timer ONLY if we have no unconfirmed addresses
3221                                                  */
3222                                                 if (cnt_of_unconf == 0)
3223                                                         sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
3224                                         }
3225                                         stcb->asoc.heart_beat_delay = 0;
3226                                 } else {
3227                                         net->dest_state |= SCTP_ADDR_NOHB;
3228                                 }
3229                         }
3230                         SCTP_TCB_UNLOCK(stcb);
3231                 } else {
3232                         /* Use endpoint defaults */
3233                         SCTP_INP_WLOCK(inp);
3234                         if (paddrp->spp_pathmaxrxt)
3235                                 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
3236                         if (paddrp->spp_hbinterval != SCTP_ISSUE_HB)
3237                                 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = paddrp->spp_hbinterval;
3238                         SCTP_INP_WUNLOCK(inp);
3239                 }
3240         }
3241         break;
3242         case SCTP_RTOINFO:
3243         {
3244                 struct sctp_rtoinfo *srto;
3245                 if ((size_t)m->m_len < sizeof(struct sctp_rtoinfo)) {
3246                         error = EINVAL;
3247                         break;
3248                 }
3249                 srto = mtod(m, struct sctp_rtoinfo *);
3250                 if (srto->srto_assoc_id == 0) {
3251                         SCTP_INP_WLOCK(inp);
3252                         /* If we have a null asoc, its default for the endpoint */
3253                         if (srto->srto_initial > 10)
3254                                 inp->sctp_ep.initial_rto = srto->srto_initial;
3255                         if (srto->srto_max > 10)
3256                                 inp->sctp_ep.sctp_maxrto = srto->srto_max;
3257                         if (srto->srto_min > 10)
3258                                 inp->sctp_ep.sctp_minrto = srto->srto_min;
3259                         SCTP_INP_WUNLOCK(inp);
3260                         break;
3261                 }
3262                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3263                         SCTP_INP_RLOCK(inp);
3264                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
3265                         if (stcb)
3266                                 SCTP_TCB_LOCK(stcb);
3267                         SCTP_INP_RUNLOCK(inp);
3268                 } else
3269                         stcb = sctp_findassociation_ep_asocid(inp, srto->srto_assoc_id);
3270                 if (stcb == NULL) {
3271                         error = EINVAL;
3272                         break;
3273                 }
3274                 /* Set in ms we hope :-) */
3275                 if (srto->srto_initial > 10)
3276                         stcb->asoc.initial_rto = srto->srto_initial;
3277                 if (srto->srto_max > 10)
3278                         stcb->asoc.maxrto = srto->srto_max;
3279                 if (srto->srto_min > 10)
3280                         stcb->asoc.minrto = srto->srto_min;
3281                 SCTP_TCB_UNLOCK(stcb);
3282         }
3283         break;
3284         case SCTP_ASSOCINFO:
3285         {
3286                 struct sctp_assocparams *sasoc;
3287
3288                 if ((size_t)m->m_len < sizeof(struct sctp_assocparams)) {
3289                         error = EINVAL;
3290                         break;
3291                 }
3292                 sasoc = mtod(m, struct sctp_assocparams *);
3293                 if (sasoc->sasoc_assoc_id) {
3294                         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3295                                 SCTP_INP_RLOCK(inp);
3296                                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
3297                                 if (stcb)
3298                                         SCTP_TCB_LOCK(stcb);
3299                                 SCTP_INP_RUNLOCK(inp);
3300                         } else
3301                                 stcb = sctp_findassociation_ep_asocid(inp,
3302                                                                       sasoc->sasoc_assoc_id);
3303                         if (stcb == NULL) {
3304                                 error = ENOENT;
3305                                 break;
3306                         }
3307
3308                 } else {
3309                         stcb = NULL;
3310                 }
3311                 if (stcb) {
3312                         if (sasoc->sasoc_asocmaxrxt)
3313                                 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
3314                         sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
3315                         sasoc->sasoc_peer_rwnd = 0;
3316                         sasoc->sasoc_local_rwnd = 0;
3317                         if (stcb->asoc.cookie_life)
3318                                 stcb->asoc.cookie_life = sasoc->sasoc_cookie_life;
3319                         SCTP_TCB_UNLOCK(stcb);
3320                 } else {
3321                         SCTP_INP_WLOCK(inp);
3322                         if (sasoc->sasoc_asocmaxrxt)
3323                                 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
3324                         sasoc->sasoc_number_peer_destinations = 0;
3325                         sasoc->sasoc_peer_rwnd = 0;
3326                         sasoc->sasoc_local_rwnd = 0;
3327                         if (sasoc->sasoc_cookie_life)
3328                                 inp->sctp_ep.def_cookie_life = sasoc->sasoc_cookie_life;
3329                         SCTP_INP_WUNLOCK(inp);
3330                 }
3331         }
3332         break;
3333         case SCTP_INITMSG:
3334         {
3335                 struct sctp_initmsg *sinit;
3336
3337                 if ((size_t)m->m_len < sizeof(struct sctp_initmsg)) {
3338                         error = EINVAL;
3339                         break;
3340                 }
3341                 sinit = mtod(m, struct sctp_initmsg *);
3342                 SCTP_INP_WLOCK(inp);
3343                 if (sinit->sinit_num_ostreams)
3344                         inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
3345
3346                 if (sinit->sinit_max_instreams)
3347                         inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
3348
3349                 if (sinit->sinit_max_attempts)
3350                         inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
3351
3352                 if (sinit->sinit_max_init_timeo > 10)
3353                         /* We must be at least a 100ms (we set in ticks) */
3354                         inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
3355                 SCTP_INP_WUNLOCK(inp);
3356         }
3357         break;
3358         case SCTP_PRIMARY_ADDR:
3359         {
3360                 struct sctp_setprim *spa;
3361                 struct sctp_nets *net, *lnet;
3362                 if ((size_t)m->m_len < sizeof(struct sctp_setprim)) {
3363                         error = EINVAL;
3364                         break;
3365                 }
3366                 spa = mtod(m, struct sctp_setprim *);
3367
3368                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3369                         SCTP_INP_RLOCK(inp);
3370                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
3371                         if (stcb) {
3372                                 SCTP_TCB_LOCK(stcb);
3373                         } else {
3374                                 error = EINVAL;
3375                                 break;
3376                         }
3377                         SCTP_INP_RUNLOCK(inp);
3378                 } else
3379                         stcb = sctp_findassociation_ep_asocid(inp, spa->ssp_assoc_id);
3380                 if (stcb == NULL) {
3381                         /* One last shot */
3382                         SCTP_INP_WLOCK(inp);
3383                         SCTP_INP_INCR_REF(inp);
3384                         SCTP_INP_WUNLOCK(inp);
3385                         stcb = sctp_findassociation_ep_addr(&inp,
3386                                                             (struct sockaddr *)&spa->ssp_addr,
3387                                                             &net, NULL, NULL);
3388                         if (stcb == NULL) {
3389                                 SCTP_INP_WLOCK(inp);
3390                                 SCTP_INP_DECR_REF(inp);
3391                                 SCTP_INP_WUNLOCK(inp);
3392                                 error = EINVAL;
3393                                 break;
3394                         }
3395                 } else {
3396                         /* find the net, associd or connected lookup type */
3397                         net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
3398                         if (net == NULL) {
3399                                 SCTP_TCB_UNLOCK(stcb);
3400                                 error = EINVAL;
3401                                 break;
3402                         }
3403                 }
3404                 if ((net != stcb->asoc.primary_destination) &&
3405                     (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
3406                         /* Ok we need to set it */
3407                         lnet = stcb->asoc.primary_destination;
3408                         lnet->next_tsn_at_change = net->next_tsn_at_change = stcb->asoc.sending_seq;
3409                         if (sctp_set_primary_addr(stcb,
3410                                                   (struct sockaddr *)NULL,
3411                                                   net) == 0) {
3412                                 if (net->dest_state & SCTP_ADDR_SWITCH_PRIMARY) {
3413                                         net->dest_state |= SCTP_ADDR_DOUBLE_SWITCH;
3414                                 }
3415                                 net->dest_state |= SCTP_ADDR_SWITCH_PRIMARY;
3416                         }
3417                 }
3418                 SCTP_TCB_UNLOCK(stcb);
3419         }
3420         break;
3421
3422         case SCTP_SET_PEER_PRIMARY_ADDR:
3423         {
3424                 struct sctp_setpeerprim *sspp;
3425                 if ((size_t)m->m_len < sizeof(struct sctp_setpeerprim)) {
3426                         error = EINVAL;
3427                         break;
3428                 }
3429                 sspp = mtod(m, struct sctp_setpeerprim *);
3430
3431
3432                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3433                         SCTP_INP_RLOCK(inp);
3434                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
3435                         if (stcb)
3436                                 SCTP_TCB_UNLOCK(stcb);
3437                         SCTP_INP_RUNLOCK(inp);
3438                 } else
3439                         stcb = sctp_findassociation_ep_asocid(inp, sspp->sspp_assoc_id);
3440                 if (stcb == NULL) {
3441                         error = EINVAL;
3442                         break;
3443                 }
3444                 if (sctp_set_primary_ip_address_sa(stcb, (struct sockaddr *)&sspp->sspp_addr) != 0) {
3445                         error = EINVAL;
3446                 }
3447                 SCTP_TCB_UNLOCK(stcb);
3448         }
3449         break;
3450         case SCTP_BINDX_ADD_ADDR:
3451         {
3452                 struct sctp_getaddresses *addrs;
3453                 struct sockaddr *addr_touse;
3454                 struct sockaddr_in sin;
3455                 /* see if we're bound all already! */
3456                 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3457                         error = EINVAL;
3458                         break;
3459                 }
3460                 if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) {
3461                         error = EINVAL;
3462                         break;
3463                 }
3464                 addrs = mtod(m, struct sctp_getaddresses *);
3465                 addr_touse = addrs->addr;
3466                 if (addrs->addr->sa_family == AF_INET6) {
3467                         struct sockaddr_in6 *sin6;
3468                         sin6 = (struct sockaddr_in6 *)addr_touse;
3469                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3470                                 in6_sin6_2_sin(&sin, sin6);
3471                                 addr_touse = (struct sockaddr *)&sin;
3472                         }
3473                 }
3474                 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
3475                         if (p == NULL) {
3476                                 /* Can't get proc for Net/Open BSD */
3477                                 error = EINVAL;
3478                                 break;
3479                         }
3480                         error = sctp_inpcb_bind(so, addr_touse, p);
3481                         break;
3482                 }
3483                 /* No locks required here since bind and mgmt_ep_sa all
3484                  * do their own locking. If we do something for the FIX:
3485                  * below we may need to lock in that case.
3486                  */
3487                 if (addrs->sget_assoc_id == 0) {
3488                         /* add the address */
3489                         struct sctp_inpcb  *lep;
3490                         ((struct sockaddr_in *)addr_touse)->sin_port = inp->sctp_lport;
3491                         lep = sctp_pcb_findep(addr_touse, 1, 0);
3492                         if (lep != NULL) {
3493                                 /* We must decrement the refcount
3494                                  * since we have the ep already and
3495                                  * are binding. No remove going on
3496                                  * here.
3497                                  */
3498                                 SCTP_INP_WLOCK(inp);
3499                                 SCTP_INP_DECR_REF(inp);
3500                                 SCTP_INP_WUNLOCK(inp);
3501                         }
3502                         if (lep == inp) {
3503                                 /* already bound to it.. ok */
3504                                 break;
3505                         } else if (lep == NULL) {
3506                                 ((struct sockaddr_in *)addr_touse)->sin_port = 0;
3507                                 error = sctp_addr_mgmt_ep_sa(inp, addr_touse,
3508                                                              SCTP_ADD_IP_ADDRESS);
3509                         } else {
3510                                 error = EADDRNOTAVAIL;
3511                         }
3512                         if (error)
3513                                 break;
3514
3515                 } else {
3516                         /* FIX: decide whether we allow assoc based bindx */
3517                 }
3518         }
3519         break;
3520         case SCTP_BINDX_REM_ADDR:
3521         {
3522                 struct sctp_getaddresses *addrs;
3523                 struct sockaddr *addr_touse;
3524                 struct sockaddr_in sin;
3525                 /* see if we're bound all already! */
3526                 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3527                         error = EINVAL;
3528                         break;
3529                 }
3530                 if ((size_t)m->m_len < sizeof(struct sctp_getaddresses)) {
3531                         error = EINVAL;
3532                         break;
3533                 }
3534                 addrs = mtod(m, struct sctp_getaddresses *);
3535                 addr_touse = addrs->addr;
3536                 if (addrs->addr->sa_family == AF_INET6) {
3537                         struct sockaddr_in6 *sin6;
3538                         sin6 = (struct sockaddr_in6 *)addr_touse;
3539                         if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
3540                                 in6_sin6_2_sin(&sin, sin6);
3541                                 addr_touse = (struct sockaddr *)&sin;
3542                         }
3543                 }
3544                 /* No lock required mgmt_ep_sa does its own locking. If
3545                  * the FIX: below is ever changed we may need to
3546                  * lock before calling association level binding.
3547                  */
3548                 if (addrs->sget_assoc_id == 0) {
3549                         /* delete the address */
3550                         sctp_addr_mgmt_ep_sa(inp, addr_touse,
3551                                              SCTP_DEL_IP_ADDRESS);
3552                 } else {
3553                         /* FIX: decide whether we allow assoc based bindx */
3554                 }
3555         }
3556         break;
3557         default:
3558                 error = ENOPROTOOPT;
3559                 break;
3560         } /* end switch (opt) */
3561         return (error);
3562 }
3563
3564
3565 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
3566 int
3567 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
3568 {
3569         struct mbuf *m = NULL;
3570         struct sctp_inpcb *inp;
3571         int error;
3572
3573         inp = (struct sctp_inpcb *)so->so_pcb;
3574         crit_enter();
3575         if (inp == 0) {
3576                 crit_exit();
3577                 /* I made the same as TCP since we are not setup? */
3578                 return (ECONNRESET);
3579         }
3580         if (sopt->sopt_level != IPPROTO_SCTP) {
3581                 /* wrong proto level... send back up to IP */
3582 #ifdef INET6
3583                 if (INP_CHECK_SOCKAF(so, AF_INET6))
3584                         error = ip6_ctloutput(so, sopt);
3585                 else
3586 #endif /* INET6 */
3587                         error = ip_ctloutput(so, sopt);
3588                 crit_exit();
3589                 return (error);
3590         }
3591         if (sopt->sopt_valsize > MCLBYTES) {
3592                 /*
3593                  * Restrict us down to a cluster size, that's all we can
3594                  * pass either way...
3595                  */
3596                 sopt->sopt_valsize = MCLBYTES;
3597         }
3598         if (sopt->sopt_valsize) {
3599
3600                 m = m_get(MB_WAIT, MT_DATA);
3601                 if (sopt->sopt_valsize > MLEN) {
3602                         MCLGET(m, MB_DONTWAIT);
3603                         if ((m->m_flags & M_EXT) == 0) {
3604                                 sctp_m_freem(m);
3605                                 crit_exit();
3606                                 return (ENOBUFS);
3607                         }
3608                 }
3609                 error = sooptcopyin(sopt, mtod(m, caddr_t), sopt->sopt_valsize,
3610                                     sopt->sopt_valsize);
3611                 if (error) {
3612                         (void) m_free(m);
3613                         goto out;
3614                 }
3615                 m->m_len = sopt->sopt_valsize;
3616         }
3617         if (sopt->sopt_dir == SOPT_SET) {
3618 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
3619                 error = sctp_optsset(so, sopt->sopt_name, &m, sopt->sopt_td);
3620 #else
3621                 error = sctp_optsset(so, sopt->sopt_name, &m, sopt->sopt_p);
3622 #endif
3623         } else if (sopt->sopt_dir == SOPT_GET) {
3624 #if (defined (__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
3625                 error = sctp_optsget(so, sopt->sopt_name, &m, sopt->sopt_td);
3626 #else
3627                 error = sctp_optsget(so, sopt->sopt_name, &m, sopt->sopt_p);
3628 #endif
3629         } else {
3630                 error = EINVAL;
3631         }
3632         if ( (error == 0) && (m != NULL)) {
3633                 error = sooptcopyout(sopt, mtod(m, caddr_t), m->m_len);
3634                 sctp_m_freem(m);
3635         } else if (m != NULL) {
3636                 sctp_m_freem(m);
3637         }
3638  out:
3639         crit_exit();
3640         return (error);
3641 }
3642
3643 #else
3644 /* NetBSD and OpenBSD */
3645 int
3646 sctp_ctloutput(op, so, level, optname, mp)
3647      int op;
3648      struct socket *so;
3649      int level, optname;
3650      struct mbuf **mp;
3651 {
3652         int s, error;
3653         struct inpcb *inp;
3654 #ifdef INET6
3655         struct in6pcb *in6p;
3656 #endif
3657         int family;     /* family of the socket */
3658
3659         family = so->so_proto->pr_domain->dom_family;
3660         error = 0;
3661         crit_exit();
3662         switch (family) {
3663         case PF_INET:
3664                 inp = sotoinpcb(so);
3665 #ifdef INET6
3666                 in6p = NULL;
3667 #endif
3668                 break;
3669 #ifdef INET6
3670         case PF_INET6:
3671                 inp = NULL;
3672                 in6p = sotoin6pcb(so);
3673                 break;
3674 #endif
3675         default:
3676                 crit_exit();
3677                 return EAFNOSUPPORT;
3678         }
3679 #ifndef INET6
3680         if (inp == NULL)
3681 #else
3682                 if (inp == NULL && in6p == NULL)
3683 #endif
3684                 {
3685                         crit_exit();
3686                         if (op == PRCO_SETOPT && *mp)
3687                                 (void) m_free(*mp);
3688                         return (ECONNRESET);
3689                 }
3690         if (level != IPPROTO_SCTP) {
3691                 switch (family) {
3692                 case PF_INET:
3693                         error = ip_ctloutput(op, so, level, optname, mp);
3694                         break;
3695 #ifdef INET6
3696                 case PF_INET6:
3697                         error = ip6_ctloutput(op, so, level, optname, mp);
3698                         break;
3699 #endif
3700                 }
3701                 crit_exit();
3702                 return (error);
3703         }
3704         /* Ok if we reach here it is a SCTP option we hope */
3705         if (op == PRCO_SETOPT) {
3706                 error = sctp_optsset(so, optname, mp, (struct proc *)NULL);
3707                 if (*mp)
3708                         (void) m_free(*mp);
3709         } else if (op ==  PRCO_GETOPT) {
3710                 error = sctp_optsget(so, optname, mp, (struct proc *)NULL);
3711         } else {
3712                 error = EINVAL;
3713         }
3714         crit_exit();
3715         return (error);
3716 }
3717
3718 #endif
3719
3720 static int
3721 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
3722 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
3723 {
3724 #else
3725 #if defined(__FreeBSD__) || defined(__APPLE__)
3726 sctp_connect(struct socket *so, struct sockaddr *addr, struct proc *p)
3727 {
3728 #else
3729 sctp_connect(struct socket *so, struct mbuf *nam, struct proc *p)
3730 {
3731         struct sockaddr *addr = mtod(nam, struct sockaddr *);
3732 #endif
3733 #endif
3734         int error = 0;
3735         struct sctp_inpcb *inp;
3736         struct sctp_tcb *stcb;
3737
3738 #ifdef SCTP_DEBUG
3739         if (sctp_debug_on & SCTP_DEBUG_PCB1) {
3740                 printf("Connect called in SCTP to ");
3741                 sctp_print_address(addr);
3742                 printf("Port %d\n", ntohs(((struct sockaddr_in *)addr)->sin_port));
3743         }
3744 #endif /* SCTP_DEBUG */
3745         crit_enter();
3746         inp = (struct sctp_inpcb *)so->so_pcb;
3747         if (inp == 0) {
3748                 crit_exit();
3749                 /* I made the same as TCP since we are not setup? */
3750                 return (ECONNRESET);
3751         }
3752         SCTP_ASOC_CREATE_LOCK(inp);
3753         SCTP_INP_WLOCK(inp);
3754         if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) ||
3755             (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
3756                 /* Should I really unlock ? */
3757                 SCTP_INP_WUNLOCK(inp);
3758                 SCTP_ASOC_CREATE_UNLOCK(inp);
3759                 crit_exit();
3760                 return (EFAULT);
3761         }
3762 #ifdef INET6
3763         if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
3764             (addr->sa_family == AF_INET6)) {
3765                 SCTP_INP_WUNLOCK(inp);
3766                 SCTP_ASOC_CREATE_UNLOCK(inp);
3767                 crit_exit();
3768                 return (EINVAL);
3769         }
3770 #endif /* INET6 */
3771         if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
3772             SCTP_PCB_FLAGS_UNBOUND) {
3773                 /* Bind a ephemeral port */
3774                 SCTP_INP_WUNLOCK(inp);
3775                 error = sctp_inpcb_bind(so, NULL, p);
3776                 if (error) {
3777                         SCTP_ASOC_CREATE_UNLOCK(inp);
3778                         crit_exit();
3779                         return (error);
3780                 }
3781                 SCTP_INP_WLOCK(inp);
3782         }
3783         /* Now do we connect? */
3784         if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
3785             (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
3786                 /* We are already connected AND the TCP model */
3787                 crit_exit();
3788                 SCTP_INP_WUNLOCK(inp);
3789                 SCTP_ASOC_CREATE_UNLOCK(inp);
3790                 return (EADDRINUSE);
3791         }
3792         if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
3793                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
3794                 if (stcb)
3795                         SCTP_TCB_UNLOCK(stcb);
3796                 SCTP_INP_WUNLOCK(inp);
3797         } else {
3798                 SCTP_INP_INCR_REF(inp);
3799                 SCTP_INP_WUNLOCK(inp);
3800                 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
3801                 if (stcb == NULL) {
3802                         SCTP_INP_WLOCK(inp);
3803                         SCTP_INP_DECR_REF(inp);
3804                         SCTP_INP_WUNLOCK(inp);
3805                 }
3806         }
3807         if (stcb != NULL) {
3808                 /* Already have or am bring up an association */
3809                 SCTP_ASOC_CREATE_UNLOCK(inp);
3810                 SCTP_TCB_UNLOCK(stcb);
3811                 crit_exit();
3812                 return (EALREADY);
3813         }
3814         /* We are GOOD to go */
3815         stcb = sctp_aloc_assoc(inp, addr, 1, &error, 0);
3816         if (stcb == NULL) {
3817                 /* Gak! no memory */
3818                 crit_exit();
3819                 return (error);
3820         }
3821         if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
3822                 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
3823                 /* Set the connected flag so we can queue data */
3824                 soisconnecting(so);
3825         }
3826         stcb->asoc.state = SCTP_STATE_COOKIE_WAIT;
3827         SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
3828         sctp_send_initiate(inp, stcb);
3829         SCTP_ASOC_CREATE_UNLOCK(inp);
3830         SCTP_TCB_UNLOCK(stcb);
3831         crit_exit();
3832         return error;
3833 }
3834
3835 int
3836 sctp_usr_recvd(struct socket *so, int flags)
3837 {
3838         struct sctp_socket_q_list *sq=NULL;
3839         /*
3840          * The user has received some data, we may be able to stuff more
3841          * up the socket. And we need to possibly update the rwnd.
3842          */
3843         struct sctp_inpcb *inp;
3844         struct sctp_tcb *stcb=NULL;
3845
3846         inp = (struct sctp_inpcb *)so->so_pcb;
3847 #ifdef SCTP_DEBUG
3848         if (sctp_debug_on & SCTP_DEBUG_USRREQ2)
3849                 printf("Read for so:%x inp:%x Flags:%x\n",
3850                        (u_int)so, (u_int)inp, (u_int)flags);
3851 #endif
3852
3853         if (inp == 0) {
3854                 /* I made the same as TCP since we are not setup? */
3855 #ifdef SCTP_DEBUG
3856                 if (sctp_debug_on & SCTP_DEBUG_USRREQ2)
3857                         printf("Nope, connection reset\n");
3858 #endif
3859                 return (ECONNRESET);
3860         }
3861         crit_enter();
3862         /*
3863          * Grab the first one on the list. It will re-insert itself if
3864          * it runs out of room
3865          */
3866         SCTP_INP_WLOCK(inp);
3867         if ((flags & MSG_EOR) && ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0)
3868             && ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
3869                 /* Ok the other part of our grubby tracking
3870                  * stuff for our horrible layer violation that
3871                  * the tsvwg thinks is ok for sctp_peeloff.. gak!
3872                  * We must update the next vtag pending on the
3873                  * socket buffer (if any).
3874                  */
3875                 inp->sctp_vtag_first = sctp_get_first_vtag_from_sb(so);
3876                 sq = TAILQ_FIRST(&inp->sctp_queue_list);
3877                 if (sq) {
3878                         stcb = sq->tcb;
3879                 } else {
3880                         stcb = NULL;
3881                 }
3882         } else {
3883                 stcb = LIST_FIRST(&inp->sctp_asoc_list);
3884         }
3885         if (stcb)
3886                 SCTP_TCB_LOCK(stcb);
3887         if (stcb) {
3888                 long incr;
3889                 /* all code in normal stcb path assumes
3890                  * that you have a tcb_lock only. Thus
3891                  * we must release the inp write lock.
3892                  */
3893                 if (flags & MSG_EOR) {
3894                         if (((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0)
3895                            && ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
3896                                 stcb = sctp_remove_from_socket_q(inp);
3897                         }
3898 #ifdef SCTP_DEBUG
3899                         if (sctp_debug_on & SCTP_DEBUG_USRREQ2)
3900                                 printf("remove from socket queue for inp:%x tcbret:%x\n",
3901                                        (u_int)inp, (u_int)stcb);
3902 #endif
3903
3904                         stcb->asoc.my_rwnd_control_len = sctp_sbspace_sub(stcb->asoc.my_rwnd_control_len,
3905                                                                           sizeof(struct mbuf));
3906                         if (inp->sctp_flags & SCTP_PCB_FLAGS_RECVDATAIOEVNT) {
3907                                 stcb->asoc.my_rwnd_control_len = sctp_sbspace_sub(stcb->asoc.my_rwnd_control_len,
3908                                                                                   CMSG_LEN(sizeof(struct sctp_sndrcvinfo)));
3909                         }
3910                 }
3911                 if ((TAILQ_EMPTY(&stcb->asoc.delivery_queue) == 0) ||
3912                     (TAILQ_EMPTY(&stcb->asoc.reasmqueue) == 0)) {
3913                         /* Deliver if there is something to be delivered */
3914                         sctp_service_queues(stcb, &stcb->asoc, 1);
3915                 }
3916                 sctp_set_rwnd(stcb, &stcb->asoc);
3917                 /* if we increase by 1 or more MTU's (smallest MTUs of all
3918                  * nets) we send a window update sack
3919                  */
3920                 incr = stcb->asoc.my_rwnd - stcb->asoc.my_last_reported_rwnd;
3921                 if (incr < 0) {
3922                         incr = 0;
3923                 }
3924                 if (((uint32_t)incr >= (stcb->asoc.smallest_mtu * SCTP_SEG_TO_RWND_UPD)) ||
3925                     ((((uint32_t)incr)*SCTP_SCALE_OF_RWND_TO_UPD) >= so->so_rcv.sb_hiwat)) {
3926                         if (callout_pending(&stcb->asoc.dack_timer.timer)) {
3927                                 /* If the timer is up, stop it */
3928                                 sctp_timer_stop(SCTP_TIMER_TYPE_RECV,
3929                                                 stcb->sctp_ep, stcb, NULL);
3930                         }
3931                         /* Send the sack, with the new rwnd */
3932                         sctp_send_sack(stcb);
3933                         /* Now do the output */
3934                         sctp_chunk_output(inp, stcb, 10);
3935                 }
3936         } else {
3937                 if ((( sq ) && (flags & MSG_EOR) && ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0))
3938                     && ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
3939                         stcb = sctp_remove_from_socket_q(inp);
3940                 }
3941         }
3942         SOCKBUF_LOCK(&so->so_rcv);
3943         if (( so->so_rcv.sb_mb == NULL ) &&
3944             (TAILQ_EMPTY(&inp->sctp_queue_list) == 0)) {
3945                 int sq_cnt=0;
3946 #ifdef SCTP_DEBUG
3947                 if (sctp_debug_on & SCTP_DEBUG_USRREQ2)
3948                         printf("Something off, inp:%x so->so_rcv->sb_mb is empty and sockq is not.. cleaning\n",
3949                                (u_int)inp);
3950 #endif
3951                 if (((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0)
3952                    && ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
3953                         int done_yet;
3954                         done_yet = TAILQ_EMPTY(&inp->sctp_queue_list);
3955                         while (!done_yet) {
3956                                 sq_cnt++;
3957                                 (void)sctp_remove_from_socket_q(inp);
3958                                 done_yet = TAILQ_EMPTY(&inp->sctp_queue_list);
3959                         }
3960                 }
3961 #ifdef SCTP_DEBUG
3962                 if (sctp_debug_on & SCTP_DEBUG_USRREQ2)
3963                         printf("Cleaned up %d sockq's\n", sq_cnt);
3964 #endif
3965         }
3966         SOCKBUF_UNLOCK(&so->so_rcv);
3967         if (stcb)
3968                 SCTP_TCB_UNLOCK(stcb);
3969         SCTP_INP_WUNLOCK(inp);
3970         crit_exit();
3971         return (0);
3972 }
3973
3974 int
3975 #if (defined(__FreeBSD__) && __FreeBSD_version >= 500000) || defined(__DragonFly__)
3976 sctp_listen(struct socket *so, struct thread *p)
3977 #else
3978 sctp_listen(struct socket *so, struct proc *p)
3979 #endif
3980 {
3981         /*
3982          * Note this module depends on the protocol processing being
3983          * called AFTER any socket level flags and backlog are applied
3984          * to the socket. The traditional way that the socket flags are
3985          * applied is AFTER protocol processing. We have made a change
3986          * to the sys/kern/uipc_socket.c module to reverse this but this
3987          * MUST be in place if the socket API for SCTP is to work properly.
3988          */
3989         int error = 0;
3990         struct sctp_inpcb *inp;
3991
3992         crit_enter();
3993         inp = (struct sctp_inpcb *)so->so_pcb;
3994         if (inp == 0) {
3995                 crit_exit();
3996                 /* I made the same as TCP since we are not setup? */
3997                 return (ECONNRESET);
3998         }
3999         SCTP_INP_RLOCK(inp);
4000         if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
4001             (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
4002                 /* We are already connected AND the TCP model */
4003                 crit_exit();
4004                 SCTP_INP_RUNLOCK(inp);
4005                 return (EADDRINUSE);
4006         }
4007         if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
4008                 /* We must do a bind. */
4009                 SCTP_INP_RUNLOCK(inp);
4010                 if ((error = sctp_inpcb_bind(so, NULL, p))) {
4011                         /* bind error, probably perm */
4012                         crit_exit();
4013                         return (error);
4014                 }
4015         } else {
4016                 SCTP_INP_RUNLOCK(inp);
4017         }
4018         SOCK_LOCK(so);
4019         SCTP_INP_WLOCK(inp);
4020         if (inp->sctp_socket->so_qlimit) {
4021                 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
4022                         /*
4023                          * For the UDP model we must TURN OFF the ACCEPT
4024                          * flags since we do NOT allow the accept() call.
4025                          * The TCP model (when present) will do accept which
4026                          * then prohibits connect().
4027                          */
4028                         inp->sctp_socket->so_options &= ~SO_ACCEPTCONN;
4029                 }
4030                 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
4031         } else {
4032                 if (inp->sctp_flags & SCTP_PCB_FLAGS_ACCEPTING) {
4033                         /*
4034                          * Turning off the listen flags if the backlog is
4035                          * set to 0 (i.e. qlimit is 0).
4036                          */
4037                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
4038                 }
4039                 inp->sctp_socket->so_options &= ~SO_ACCEPTCONN;
4040         }
4041         SCTP_INP_WUNLOCK(inp);
4042         SOCK_UNLOCK(so);
4043         crit_exit();
4044         return (error);
4045 }
4046
4047 int
4048 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4049 sctp_accept(struct socket *so, struct sockaddr **addr)
4050 {
4051 #else
4052 sctp_accept(struct socket *so, struct mbuf *nam)
4053 {
4054         struct sockaddr *addr = mtod(nam, struct sockaddr *);
4055 #endif
4056         struct sctp_tcb *stcb;
4057         struct sockaddr *prim;
4058         struct sctp_inpcb *inp;
4059
4060         crit_enter();
4061         inp = (struct sctp_inpcb *)so->so_pcb;
4062
4063         if (inp == 0) {
4064                 crit_exit();
4065                 return (ECONNRESET);
4066         }
4067         SCTP_INP_RLOCK(inp);
4068         if (so->so_state & SS_ISDISCONNECTED) {
4069                 crit_exit();
4070                 SCTP_INP_RUNLOCK(inp);
4071                 return (ECONNABORTED);
4072         }
4073         stcb = LIST_FIRST(&inp->sctp_asoc_list);
4074         if (stcb == NULL) {
4075                 crit_exit();
4076                 SCTP_INP_RUNLOCK(inp);
4077                 return (ECONNRESET);
4078         }
4079         SCTP_TCB_LOCK(stcb);
4080         SCTP_INP_RUNLOCK(inp);
4081         prim = (struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr;
4082         if (prim->sa_family == AF_INET) {
4083                 struct sockaddr_in *sin;
4084 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4085                 MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME,
4086                        M_WAITOK | M_ZERO);
4087 #else
4088                 sin = (struct sockaddr_in *)addr;
4089                 bzero((caddr_t)sin, sizeof (*sin));
4090 #endif
4091                 sin->sin_family = AF_INET;
4092                 sin->sin_len = sizeof(*sin);
4093                 sin->sin_port = ((struct sockaddr_in *)prim)->sin_port;
4094                 sin->sin_addr = ((struct sockaddr_in *)prim)->sin_addr;
4095 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4096                 *addr = (struct sockaddr *)sin;
4097 #else
4098                 nam->m_len = sizeof(*sin);
4099 #endif
4100         } else {
4101                 struct sockaddr_in6 *sin6;
4102 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4103                 MALLOC(sin6, struct sockaddr_in6 *, sizeof *sin6, M_SONAME,
4104                        M_WAITOK | M_ZERO);
4105 #else
4106                 sin6 = (struct sockaddr_in6 *)addr;
4107 #endif
4108                 bzero((caddr_t)sin6, sizeof (*sin6));
4109                 sin6->sin6_family = AF_INET6;
4110                 sin6->sin6_len = sizeof(*sin6);
4111                 sin6->sin6_port = ((struct sockaddr_in6 *)prim)->sin6_port;
4112
4113                 sin6->sin6_addr = ((struct sockaddr_in6 *)prim)->sin6_addr;
4114                 if (IN6_IS_SCOPE_LINKLOCAL(&sin6->sin6_addr))
4115                         /*      sin6->sin6_scope_id = ntohs(sin6->sin6_addr.s6_addr16[1]);*/
4116                         in6_recoverscope(sin6, &sin6->sin6_addr, NULL);  /* skip ifp check */
4117                 else
4118                         sin6->sin6_scope_id = 0;        /*XXX*/
4119 #if defined(__FreeBSD__) || defined (__APPLE__) || defined(__DragonFly__)
4120                 *addr= (struct sockaddr *)sin6;
4121 #else
4122                 nam->m_len = sizeof(*sin6);
4123 #endif
4124         }
4125         /* Wake any delayed sleep action */
4126         SCTP_TCB_UNLOCK(stcb);
4127         SCTP_INP_WLOCK(inp);
4128         if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
4129                 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
4130                 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
4131                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
4132 #if defined(__NetBSD__)
4133                         if (sowritable(inp->sctp_socket))
4134                                 sowwakeup(inp->sctp_socket);
4135 #else
4136                         if (sowriteable(inp->sctp_socket))
4137                                 sowwakeup(inp->sctp_socket);
4138 #endif
4139                 }
4140                 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
4141                         inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
4142                         if (soreadable(inp->sctp_socket))
4143                                 sorwakeup(inp->sctp_socket);
4144                 }
4145
4146         }
4147         SCTP_INP_WUNLOCK(inp);
4148         crit_exit();
4149         return (0);
4150 }
4151
4152 int
4153 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4154 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
4155 #else
4156 sctp_ingetaddr(struct socket *so, struct mbuf *nam)
4157 #endif
4158 {
4159 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4160         struct sockaddr_in *sin;
4161 #else
4162         struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
4163 #endif
4164         struct sctp_inpcb *inp;
4165         /*
4166          * Do the malloc first in case it blocks.
4167          */
4168 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4169         MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK |
4170                M_ZERO);
4171 #else
4172         nam->m_len = sizeof(*sin);
4173         memset(sin, 0, sizeof(*sin));
4174 #endif
4175         sin->sin_family = AF_INET;
4176         sin->sin_len = sizeof(*sin);
4177         crit_enter();
4178         inp = (struct sctp_inpcb *)so->so_pcb;
4179         if (!inp) {
4180                 crit_exit();
4181 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4182                 FREE(sin, M_SONAME);
4183 #endif
4184                 return ECONNRESET;
4185         }
4186         SCTP_INP_RLOCK(inp);
4187         sin->sin_port = inp->sctp_lport;
4188         if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
4189                 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4190                         struct sctp_tcb *stcb;
4191                         struct sockaddr_in *sin_a;
4192                         struct sctp_nets *net;
4193                         int fnd;
4194
4195                         stcb = LIST_FIRST(&inp->sctp_asoc_list);
4196                         if (stcb == NULL) {
4197                                 goto notConn;
4198                         }
4199                         fnd = 0;
4200                         sin_a = NULL;
4201                         SCTP_TCB_LOCK(stcb);
4202                         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4203                                 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
4204                                 if (sin_a->sin_family == AF_INET) {
4205                                         fnd = 1;
4206                                         break;
4207                                 }
4208                         }
4209                         if ((!fnd) || (sin_a == NULL)) {
4210                                 /* punt */
4211                                 SCTP_TCB_UNLOCK(stcb);
4212                                 goto notConn;
4213                         }
4214                         sin->sin_addr = sctp_ipv4_source_address_selection(inp,
4215                             stcb, (struct route *)&net->ro, net, 0);
4216                         SCTP_TCB_UNLOCK(stcb);
4217                 } else {
4218                         /* For the bound all case you get back 0 */
4219                 notConn:
4220                         sin->sin_addr.s_addr = 0;
4221                 }
4222
4223         } else {
4224                 /* Take the first IPv4 address in the list */
4225                 struct sctp_laddr *laddr;
4226                 int fnd = 0;
4227                 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
4228                         if (laddr->ifa->ifa_addr->sa_family == AF_INET) {
4229                                 struct sockaddr_in *sin_a;
4230                                 sin_a = (struct sockaddr_in *)laddr->ifa->ifa_addr;
4231                                 sin->sin_addr = sin_a->sin_addr;
4232                                 fnd = 1;
4233                                 break;
4234                         }
4235                 }
4236                 if (!fnd) {
4237                         crit_exit();
4238 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4239                         FREE(sin, M_SONAME);
4240 #endif
4241                         SCTP_INP_RUNLOCK(inp);
4242                         return ENOENT;
4243                 }
4244         }
4245         SCTP_INP_RUNLOCK(inp);
4246         crit_exit();
4247 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4248         (*addr) = (struct sockaddr *)sin;
4249 #endif
4250         return (0);
4251 }
4252
4253 int
4254 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4255 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
4256 {
4257         struct sockaddr_in *sin = (struct sockaddr_in *)*addr;
4258 #else
4259 sctp_peeraddr(struct socket *so, struct mbuf *nam)
4260 {
4261         struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);
4262 #endif
4263         int fnd;
4264         struct sockaddr_in *sin_a;
4265         struct sctp_inpcb *inp;
4266         struct sctp_tcb *stcb;
4267         struct sctp_nets *net;
4268
4269         /* Do the malloc first in case it blocks. */
4270         inp = (struct sctp_inpcb *)so->so_pcb;
4271         if ((inp == NULL) ||
4272             ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
4273                 /* UDP type and listeners will drop out here */
4274                 return (ENOTCONN);
4275         }
4276         crit_enter();
4277
4278 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4279         MALLOC(sin, struct sockaddr_in *, sizeof *sin, M_SONAME, M_WAITOK |
4280                M_ZERO);
4281 #else
4282         nam->m_len = sizeof(*sin);
4283         memset(sin, 0, sizeof(*sin));
4284 #endif
4285         sin->sin_family = AF_INET;
4286         sin->sin_len = sizeof(*sin);
4287
4288         /* We must recapture incase we blocked */
4289         inp = (struct sctp_inpcb *)so->so_pcb;
4290         if (!inp) {
4291                 crit_exit();
4292 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4293                 FREE(sin, M_SONAME);
4294 #endif
4295                 return ECONNRESET;
4296         }
4297         SCTP_INP_RLOCK(inp);
4298         stcb = LIST_FIRST(&inp->sctp_asoc_list);
4299         if (stcb)
4300                 SCTP_TCB_LOCK(stcb);
4301         SCTP_INP_RUNLOCK(inp);
4302         if (stcb == NULL) {
4303                 crit_exit();
4304 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4305                 FREE(sin, M_SONAME);
4306 #endif
4307                 return ECONNRESET;
4308         }
4309         fnd = 0;
4310         TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4311                 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
4312                 if (sin_a->sin_family == AF_INET) {
4313                         fnd = 1;
4314                         sin->sin_port = stcb->rport;
4315                         sin->sin_addr = sin_a->sin_addr;
4316                         break;
4317                 }
4318         }
4319         SCTP_TCB_UNLOCK(stcb);
4320         if (!fnd) {
4321                 /* No IPv4 address */
4322                 crit_exit();
4323 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4324                 FREE(sin, M_SONAME);
4325 #endif
4326                 return ENOENT;
4327         }
4328         crit_exit();
4329         return (0);
4330 }
4331
4332 #if defined(__FreeBSD__) || defined(__APPLE__) || defined(__DragonFly__)
4333 struct pr_usrreqs sctp_usrreqs = {
4334         sctp_abort,
4335         sctp_accept,
4336         sctp_attach,
4337         sctp_bind,
4338         sctp_connect,
4339         pru_connect2_notsupp,
4340         in_control,
4341         sctp_detach,
4342         sctp_disconnect,
4343         sctp_listen,
4344         sctp_peeraddr,
4345         sctp_usr_recvd,
4346         pru_rcvoob_notsupp,
4347         sctp_send,
4348         pru_sense_null,
4349         sctp_shutdown,
4350         sctp_ingetaddr,
4351         sctp_sosend,
4352         soreceive,
4353         sopoll
4354 };
4355
4356 #else
4357 #if defined(__NetBSD__)
4358 int
4359 sctp_usrreq(so, req, m, nam, control, p)
4360      struct socket *so;
4361      int req;
4362      struct mbuf *m, *nam, *control;
4363      struct proc *p;
4364 {
4365 #else
4366 int
4367 sctp_usrreq(so, req, m, nam, control)
4368      struct socket *so;
4369      int req;
4370      struct mbuf *m, *nam, *control;
4371 {
4372         struct proc *p = curproc;
4373 #endif
4374         int error = 0;
4375         int family;
4376
4377         family = so->so_proto->pr_domain->dom_family;
4378
4379         crit_enter();
4380         if (req == PRU_CONTROL) {
4381                 switch (family) {
4382                 case PF_INET:
4383                         error = in_control(so, (long)m, (caddr_t)nam,
4384                             (struct ifnet *)control
4385 #if defined(__NetBSD__)
4386                             , p
4387 #endif
4388                             );
4389                         break;
4390 #ifdef INET6
4391                 case PF_INET6:
4392                         error = in6_control(so, (long)m, (caddr_t)nam,
4393                             (struct ifnet *)control, p);
4394                         break;
4395 #endif
4396                 default:
4397                         error =  EAFNOSUPPORT;
4398                 }
4399                 crit_exit();
4400                 return (error);
4401         }
4402 #ifdef __NetBSD__
4403         if (req == PRU_PURGEIF) {
4404                 struct ifnet *ifn;
4405                 struct ifaddr *ifa;
4406                 ifn = (struct ifnet *)control;
4407                 TAILQ_FOREACH(ifa, &ifn->if_addrlist, ifa_list) {
4408                         if (ifa->ifa_addr->sa_family == family) {
4409                                 sctp_delete_ip_address(ifa);
4410                         }
4411                 }
4412                 switch (family) {
4413                 case PF_INET:
4414                         in_purgeif (ifn);
4415                         break;
4416 #ifdef INET6
4417                 case PF_INET6:
4418                         in6_purgeif (ifn);
4419                         break;
4420 #endif /* INET6 */
4421                 default:
4422                         crit_exit();
4423                         return (EAFNOSUPPORT);
4424                 }
4425                 crit_exit();
4426                 return (0);
4427         }
4428 #endif
4429         switch (req) {
4430         case PRU_ATTACH:
4431                 error = sctp_attach(so, family, p);
4432                 break;
4433         case PRU_DETACH:
4434                 error = sctp_detach(so);
4435                 break;
4436         case PRU_BIND:
4437                 if (nam == NULL) {
4438                         crit_exit();
4439                         return (EINVAL);
4440                 }
4441                 error  = sctp_bind(so, nam, p);
4442                 break;
4443         case PRU_LISTEN:
4444                 error = sctp_listen(so, p);
4445                 break;
4446         case PRU_CONNECT:
4447                 if (nam == NULL) {
4448                         crit_exit();
4449                         return (EINVAL);
4450                 }
4451                 error = sctp_connect(so, nam, p);
4452                 break;
4453         case PRU_DISCONNECT:
4454                 error = sctp_disconnect(so);
4455                 break;
4456         case PRU_ACCEPT:
4457                 if (nam == NULL) {
4458                         crit_exit();
4459                         return (EINVAL);
4460                 }
4461                 error = sctp_accept(so, nam);
4462         break;
4463         case PRU_SHUTDOWN:
4464                 error = sctp_shutdown(so);
4465                 break;
4466
4467         case PRU_RCVD:
4468                 /*
4469                  * For Open and Net BSD, this is real
4470                  * ugly. The mbuf *nam that is passed
4471                  * (by soreceive()) is the int flags c
4472                  * ast as a (mbuf *) yuck!
4473                  */
4474                 error = sctp_usr_recvd(so, (int)((long)nam));
4475                 break;
4476
4477         case PRU_SEND:
4478                 /* Flags are ignored */
4479 #ifdef SCTP_DEBUG
4480                 if (sctp_debug_on & SCTP_DEBUG_USRREQ1) {
4481                         printf("Send called on V4 side\n");
4482                 }
4483 #endif
4484                 {
4485                     struct sockaddr *addr;
4486                     if (nam == NULL)
4487                         addr = NULL;
4488                     else
4489                         addr = mtod(nam, struct sockaddr *);
4490
4491                     error = sctp_send(so, 0, m, addr, control, p);
4492                 }
4493                 break;
4494         case PRU_ABORT:
4495                 error = sctp_abort(so);
4496                 break;
4497
4498         case PRU_SENSE:
4499                 error = 0;
4500                 break;
4501         case PRU_RCVOOB:
4502                 error = EAFNOSUPPORT;
4503                 break;
4504         case PRU_SENDOOB:
4505                 error = EAFNOSUPPORT;
4506                 break;
4507         case PRU_PEERADDR:
4508                 error = sctp_peeraddr(so, nam);
4509                 break;
4510         case PRU_SOCKADDR:
4511                 error = sctp_ingetaddr(so, nam);
4512                 break;
4513         case PRU_SLOWTIMO:
4514                 error = 0;
4515                 break;
4516         default:
4517                 break;
4518         }
4519         crit_exit();
4520         return (error);
4521 }
4522 #endif
4523
4524 /* #if defined(__NetBSD__) || defined(__OpenBSD__) */
4525 #if __OpenBSD__
4526 /*
4527  * Sysctl for sctp variables.
4528  */
4529 int
4530 sctp_sysctl(name, namelen, oldp, oldlenp, newp, newlen)
4531         int *name;
4532         u_int namelen;
4533         void *oldp;
4534         size_t *oldlenp;
4535         void *newp;
4536         size_t newlen;
4537 {
4538
4539         /* All sysctl names at this level are terminal. */
4540         if (namelen != 1)
4541                 return (ENOTDIR);
4542 sysctl_int();
4543
4544         switch (name[0]) {
4545         case SCTPCTL_MAXDGRAM:
4546                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4547                      &sctp_sendspace));
4548         case SCTPCTL_RECVSPACE:
4549                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4550                     &sctp_recvspace));
4551         case SCTPCTL_AUTOASCONF:
4552                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4553                     &sctp_auto_asconf));
4554         case SCTPCTL_ECN_ENABLE:
4555                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4556                                    &sctp_ecn));
4557         case SCTPCTL_ECN_NONCE:
4558                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4559                                    &sctp_ecn_nonce));
4560         case SCTPCTL_STRICT_SACK:
4561                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4562                                    &sctp_strict_sacks));
4563         case SCTPCTL_NOCSUM_LO:
4564                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4565                                    &sctp_no_csum_on_loopback));
4566         case SCTPCTL_STRICT_INIT:
4567                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4568                                    &sctp_strict_init));
4569         case SCTPCTL_PEER_CHK_OH:
4570                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4571                                    &sctp_peer_chunk_oh));
4572         case SCTPCTL_MAXBURST:
4573                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4574                                    &sctp_max_burst_default));
4575         case SCTPCTL_MAXCHUNKONQ:
4576                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4577                                    &sctp_max_chunks_on_queue));
4578         case SCTPCTL_DELAYED_SACK:
4579                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4580                                    &sctp_delayed_sack_time_default));
4581         case SCTPCTL_HB_INTERVAL:
4582                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4583                                    &sctp_heartbeat_interval_default));
4584         case SCTPCTL_PMTU_RAISE:
4585                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4586                                    &sctp_pmtu_raise_time_default));
4587         case SCTPCTL_SHUTDOWN_GUARD:
4588                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4589                                    &sctp_shutdown_guard_time_default));
4590         case SCTPCTL_SECRET_LIFETIME:
4591                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4592                                    &sctp_secret_lifetime_default));
4593         case SCTPCTL_RTO_MAX:
4594                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4595                                    &sctp_rto_max_default));
4596         case SCTPCTL_RTO_MIN:
4597                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4598                                    &sctp_rto_min_default));
4599         case SCTPCTL_RTO_INITIAL:
4600                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4601                                    &sctp_rto_initial_default));
4602         case SCTPCTL_INIT_RTO_MAX:
4603                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4604                                    &sctp_init_rto_max_default));
4605         case SCTPCTL_COOKIE_LIFE:
4606                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4607                                    &sctp_valid_cookie_life_default));
4608         case SCTPCTL_INIT_RTX_MAX:
4609                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4610                                    &sctp_init_rtx_max_default));
4611         case SCTPCTL_ASSOC_RTX_MAX:
4612                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4613                                    &sctp_assoc_rtx_max_default));
4614         case SCTPCTL_PATH_RTX_MAX:
4615                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4616                                    &sctp_path_rtx_max_default));
4617         case SCTPCTL_NR_OUTGOING_STREAMS:
4618                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4619                                    &sctp_nr_outgoing_streams_default));
4620 #ifdef SCTP_DEBUG
4621         case SCTPCTL_DEBUG:
4622                 return (sysctl_int(oldp, oldlenp, newp, newlen,
4623                                    &sctp_debug_on));
4624 #endif
4625         default:
4626                 return (ENOPROTOOPT);
4627         }
4628         /* NOTREACHED */
4629 }
4630 #endif
4631 #if __NetBSD__
4632 /*
4633  * Sysctl for sctp variables.
4634  */
4635 SYSCTL_SETUP(sysctl_net_inet_sctp_setup, "sysctl net.inet.sctp subtree setup")
4636 {
4637
4638         sysctl_createv(clog, 0, NULL, NULL,
4639                        CTLFLAG_PERMANENT,
4640                        CTLTYPE_NODE, "net", NULL,
4641                        NULL, 0, NULL, 0,
4642                        CTL_NET, CTL_EOL);
4643         sysctl_createv(clog, 0, NULL, NULL,
4644                        CTLFLAG_PERMANENT,
4645                        CTLTYPE_NODE, "inet", NULL,
4646                        NULL, 0, NULL, 0,
4647                        CTL_NET, PF_INET, CTL_EOL);
4648         sysctl_createv(clog, 0, NULL, NULL,
4649                        CTLFLAG_PERMANENT,
4650                        CTLTYPE_NODE, "sctp",
4651                        SYSCTL_DESCR("sctp related settings"),
4652                        NULL, 0, NULL, 0,
4653                        CTL_NET, PF_INET, IPPROTO_SCTP, CTL_EOL);
4654
4655        sysctl_createv(clog, 0, NULL, NULL,
4656                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4657                        CTLTYPE_INT, "maxdgram",
4658                        SYSCTL_DESCR("Maximum outgoing SCTP buffer size"),
4659                        NULL, 0, &sctp_sendspace, 0,
4660                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_MAXDGRAM,
4661                        CTL_EOL);
4662
4663        sysctl_createv(clog, 0, NULL, NULL,
4664                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4665                        CTLTYPE_INT, "recvspace",
4666                        SYSCTL_DESCR("Maximum incoming SCTP buffer size"),
4667                        NULL, 0, &sctp_recvspace, 0,
4668                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_RECVSPACE,
4669                        CTL_EOL);
4670
4671        sysctl_createv(clog, 0, NULL, NULL,
4672                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4673                        CTLTYPE_INT, "autoasconf",
4674                        SYSCTL_DESCR("Enable SCTP Auto-ASCONF"),
4675                        NULL, 0, &sctp_auto_asconf, 0,
4676                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_AUTOASCONF,
4677                        CTL_EOL);
4678
4679        sysctl_createv(clog, 0, NULL, NULL,
4680                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4681                        CTLTYPE_INT, "ecn_enable",
4682                        SYSCTL_DESCR("Enable SCTP ECN"),
4683                        NULL, 0, &sctp_ecn, 0,
4684                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_ECN_ENABLE,
4685                        CTL_EOL);
4686
4687        sysctl_createv(clog, 0, NULL, NULL,
4688                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4689                        CTLTYPE_INT, "ecn_nonce",
4690                        SYSCTL_DESCR("Enable SCTP ECN Nonce"),
4691                        NULL, 0, &sctp_ecn_nonce, 0,
4692                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_ECN_NONCE,
4693                        CTL_EOL);
4694
4695        sysctl_createv(clog, 0, NULL, NULL,
4696                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4697                        CTLTYPE_INT, "strict_sack",
4698                        SYSCTL_DESCR("Enable SCTP Strict SACK checking"),
4699                        NULL, 0, &sctp_strict_sacks, 0,
4700                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_STRICT_SACK,
4701                        CTL_EOL);
4702
4703        sysctl_createv(clog, 0, NULL, NULL,
4704                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4705                        CTLTYPE_INT, "loopback_nocsum",
4706                        SYSCTL_DESCR("Enable NO Csum on packets sent on loopback"),
4707                        NULL, 0, &sctp_no_csum_on_loopback, 0,
4708                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_NOCSUM_LO,
4709                        CTL_EOL);
4710
4711        sysctl_createv(clog, 0, NULL, NULL,
4712                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4713                        CTLTYPE_INT, "strict_init",
4714                        SYSCTL_DESCR("Enable strict INIT/INIT-ACK singleton enforcement"),
4715                        NULL, 0, &sctp_strict_init, 0,
4716                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_STRICT_INIT,
4717                        CTL_EOL);
4718
4719        sysctl_createv(clog, 0, NULL, NULL,
4720                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4721                        CTLTYPE_INT, "peer_chkoh",
4722                        SYSCTL_DESCR("Amount to debit peers rwnd per chunk sent"),
4723                        NULL, 0, &sctp_peer_chunk_oh, 0,
4724                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_PEER_CHK_OH,
4725                        CTL_EOL);
4726
4727        sysctl_createv(clog, 0, NULL, NULL,
4728                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4729                        CTLTYPE_INT, "maxburst",
4730                        SYSCTL_DESCR("Default max burst for sctp endpoints"),
4731                        NULL, 0, &sctp_max_burst_default, 0,
4732                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_MAXBURST,
4733                        CTL_EOL);
4734
4735        sysctl_createv(clog, 0, NULL, NULL,
4736                        CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
4737                        CTLTYPE_INT, "maxchunks",
4738                        SYSCTL_DESCR("Default max chunks on queue per asoc"),
4739                        NULL, 0, &sctp_max_chunks_on_queue, 0,
4740                        CTL_NET, PF_INET, IPPROTO_SCTP, SCTPCTL_MAXCHUNKONQ,
4741                        CTL_EOL);
4742
4743 }
4744 #endif