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