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