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