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