1 /*-
2 * Copyright (c) 2001-2008, by Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2008-2012, by Randall Stewart. All rights reserved.
4 * Copyright (c) 2008-2012, by Michael Tuexen. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * a) Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 *
12 * b) Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in
14 * the documentation and/or other materials provided with the distribution.
15 *
16 * c) Neither the name of Cisco Systems, Inc. nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
30 * THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD: releng/10.1/sys/netinet/sctp_usrreq.c 277808 2015-01-27 19:37:02Z delphij $");
35
36 #include <netinet/sctp_os.h>
37 #include <sys/proc.h>
38 #include <netinet/sctp_pcb.h>
39 #include <netinet/sctp_header.h>
40 #include <netinet/sctp_var.h>
41 #ifdef INET6
42 #endif
43 #include <netinet/sctp_sysctl.h>
44 #include <netinet/sctp_output.h>
45 #include <netinet/sctp_uio.h>
46 #include <netinet/sctp_asconf.h>
47 #include <netinet/sctputil.h>
48 #include <netinet/sctp_indata.h>
49 #include <netinet/sctp_timer.h>
50 #include <netinet/sctp_auth.h>
51 #include <netinet/sctp_bsd_addr.h>
52 #include <netinet/udp.h>
53
54
55
56 extern struct sctp_cc_functions sctp_cc_functions[];
57 extern struct sctp_ss_functions sctp_ss_functions[];
58
59 void
60 sctp_init(void)
61 {
62 u_long sb_max_adj;
63
64 /* Initialize and modify the sysctled variables */
65 sctp_init_sysctls();
66 if ((nmbclusters / 8) > SCTP_ASOC_MAX_CHUNKS_ON_QUEUE)
67 SCTP_BASE_SYSCTL(sctp_max_chunks_on_queue) = (nmbclusters / 8);
68 /*
69 * Allow a user to take no more than 1/2 the number of clusters or
70 * the SB_MAX whichever is smaller for the send window.
71 */
72 sb_max_adj = (u_long)((u_quad_t) (SB_MAX) * MCLBYTES / (MSIZE + MCLBYTES));
73 SCTP_BASE_SYSCTL(sctp_sendspace) = min(sb_max_adj,
74 (((uint32_t) nmbclusters / 2) * SCTP_DEFAULT_MAXSEGMENT));
75 /*
76 * Now for the recv window, should we take the same amount? or
77 * should I do 1/2 the SB_MAX instead in the SB_MAX min above. For
78 * now I will just copy.
79 */
80 SCTP_BASE_SYSCTL(sctp_recvspace) = SCTP_BASE_SYSCTL(sctp_sendspace);
81 SCTP_BASE_VAR(first_time) = 0;
82 SCTP_BASE_VAR(sctp_pcb_initialized) = 0;
83 sctp_pcb_init();
84 #if defined(SCTP_PACKET_LOGGING)
85 SCTP_BASE_VAR(packet_log_writers) = 0;
86 SCTP_BASE_VAR(packet_log_end) = 0;
87 bzero(&SCTP_BASE_VAR(packet_log_buffer), SCTP_PACKET_LOG_SIZE);
88 #endif
89 }
90
91 void
92 sctp_finish(void)
93 {
94 sctp_pcb_finish();
95 }
96
97
98
99 void
100 sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
101 {
102 struct sctp_tmit_chunk *chk;
103 uint16_t overhead;
104
105 /* Adjust that too */
106 stcb->asoc.smallest_mtu = nxtsz;
107 /* now off to subtract IP_DF flag if needed */
108 overhead = IP_HDR_SIZE;
109 if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
110 overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
111 }
112 TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
113 if ((chk->send_size + overhead) > nxtsz) {
114 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
115 }
116 }
117 TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
118 if ((chk->send_size + overhead) > nxtsz) {
119 /*
120 * For this guy we also mark for immediate resend
121 * since we sent to big of chunk
122 */
123 chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
124 if (chk->sent < SCTP_DATAGRAM_RESEND) {
125 sctp_flight_size_decrease(chk);
126 sctp_total_flight_decrease(stcb, chk);
127 }
128 if (chk->sent != SCTP_DATAGRAM_RESEND) {
129 sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
130 }
131 chk->sent = SCTP_DATAGRAM_RESEND;
132 chk->rec.data.doing_fast_retransmit = 0;
133 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
134 sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
135 chk->whoTo->flight_size,
136 chk->book_size,
137 (uintptr_t) chk->whoTo,
138 chk->rec.data.TSN_seq);
139 }
140 /* Clear any time so NO RTT is being done */
141 chk->do_rtt = 0;
142 }
143 }
144 }
145
146 #ifdef INET
147 static void
148 sctp_notify_mbuf(struct sctp_inpcb *inp,
149 struct sctp_tcb *stcb,
150 struct sctp_nets *net,
151 struct ip *ip,
152 struct sctphdr *sh)
153 {
154 struct icmp *icmph;
155 int totsz, tmr_stopped = 0;
156 uint16_t nxtsz;
157
158 /* protection */
159 if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
160 (ip == NULL) || (sh == NULL)) {
161 if (stcb != NULL) {
162 SCTP_TCB_UNLOCK(stcb);
163 }
164 return;
165 }
166 /* First job is to verify the vtag matches what I would send */
167 if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
168 SCTP_TCB_UNLOCK(stcb);
169 return;
170 }
171 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
172 sizeof(struct ip)));
173 if (icmph->icmp_type != ICMP_UNREACH) {
174 /* We only care about unreachable */
175 SCTP_TCB_UNLOCK(stcb);
176 return;
177 }
178 if (icmph->icmp_code != ICMP_UNREACH_NEEDFRAG) {
179 /* not a unreachable message due to frag. */
180 SCTP_TCB_UNLOCK(stcb);
181 return;
182 }
183 totsz = ntohs(ip->ip_len);
184
185 nxtsz = ntohs(icmph->icmp_nextmtu);
186 if (nxtsz == 0) {
187 /*
188 * old type router that does not tell us what the next size
189 * mtu is. Rats we will have to guess (in a educated fashion
190 * of course)
191 */
192 nxtsz = sctp_get_prev_mtu(totsz);
193 }
194 /* Stop any PMTU timer */
195 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
196 tmr_stopped = 1;
197 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
198 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_1);
199 }
200 /* Adjust destination size limit */
201 if (net->mtu > nxtsz) {
202 net->mtu = nxtsz;
203 if (net->port) {
204 net->mtu -= sizeof(struct udphdr);
205 }
206 }
207 /* now what about the ep? */
208 if (stcb->asoc.smallest_mtu > nxtsz) {
209 sctp_pathmtu_adjustment(stcb, nxtsz);
210 }
211 if (tmr_stopped)
212 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
213
214 SCTP_TCB_UNLOCK(stcb);
215 }
216
217 void
218 sctp_notify(struct sctp_inpcb *inp,
219 struct ip *ip,
220 struct sctphdr *sh,
221 struct sockaddr *to,
222 struct sctp_tcb *stcb,
223 struct sctp_nets *net)
224 {
225 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
226 struct socket *so;
227
228 #endif
229 struct icmp *icmph;
230
231 /* protection */
232 if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
233 (sh == NULL) || (to == NULL)) {
234 if (stcb)
235 SCTP_TCB_UNLOCK(stcb);
236 return;
237 }
238 /* First job is to verify the vtag matches what I would send */
239 if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
240 SCTP_TCB_UNLOCK(stcb);
241 return;
242 }
243 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
244 sizeof(struct ip)));
245 if (icmph->icmp_type != ICMP_UNREACH) {
246 /* We only care about unreachable */
247 SCTP_TCB_UNLOCK(stcb);
248 return;
249 }
250 if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
251 (icmph->icmp_code == ICMP_UNREACH_HOST) ||
252 (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
253 (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
254 (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
255 (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
256 (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
257 (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
258
259 /*
260 * Hmm reachablity problems we must examine closely. If its
261 * not reachable, we may have lost a network. Or if there is
262 * NO protocol at the other end named SCTP. well we consider
263 * it a OOTB abort.
264 */
265 if (net->dest_state & SCTP_ADDR_REACHABLE) {
266 /* Ok that destination is NOT reachable */
267 net->dest_state &= ~SCTP_ADDR_REACHABLE;
268 net->dest_state &= ~SCTP_ADDR_PF;
269 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
270 stcb, 0,
271 (void *)net, SCTP_SO_NOT_LOCKED);
272 }
273 SCTP_TCB_UNLOCK(stcb);
274 } else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
275 (icmph->icmp_code == ICMP_UNREACH_PORT)) {
276 /*
277 * Here the peer is either playing tricks on us, including
278 * an address that belongs to someone who does not support
279 * SCTP OR was a userland implementation that shutdown and
280 * now is dead. In either case treat it like a OOTB abort
281 * with no TCB
282 */
283 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
284 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
285 so = SCTP_INP_SO(inp);
286 atomic_add_int(&stcb->asoc.refcnt, 1);
287 SCTP_TCB_UNLOCK(stcb);
288 SCTP_SOCKET_LOCK(so, 1);
289 SCTP_TCB_LOCK(stcb);
290 atomic_subtract_int(&stcb->asoc.refcnt, 1);
291 #endif
292 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
293 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
294 SCTP_SOCKET_UNLOCK(so, 1);
295 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
296 #endif
297 /* no need to unlock here, since the TCB is gone */
298 } else {
299 SCTP_TCB_UNLOCK(stcb);
300 }
301 }
302
303 #endif
304
305 #ifdef INET
306 void
307 sctp_ctlinput(cmd, sa, vip)
308 int cmd;
309 struct sockaddr *sa;
310 void *vip;
311 {
312 struct ip *ip = vip;
313 struct sctphdr *sh;
314 uint32_t vrf_id;
315
316 /* FIX, for non-bsd is this right? */
317 vrf_id = SCTP_DEFAULT_VRFID;
318 if (sa->sa_family != AF_INET ||
319 ((struct sockaddr_in *)sa)->sin_addr.s_addr == INADDR_ANY) {
320 return;
321 }
322 if (PRC_IS_REDIRECT(cmd)) {
323 ip = 0;
324 } else if ((unsigned)cmd >= PRC_NCMDS || inetctlerrmap[cmd] == 0) {
325 return;
326 }
327 if (ip) {
328 struct sctp_inpcb *inp = NULL;
329 struct sctp_tcb *stcb = NULL;
330 struct sctp_nets *net = NULL;
331 struct sockaddr_in to, from;
332
333 sh = (struct sctphdr *)((caddr_t)ip + (ip->ip_hl << 2));
334 bzero(&to, sizeof(to));
335 bzero(&from, sizeof(from));
336 from.sin_family = to.sin_family = AF_INET;
337 from.sin_len = to.sin_len = sizeof(to);
338 from.sin_port = sh->src_port;
339 from.sin_addr = ip->ip_src;
340 to.sin_port = sh->dest_port;
341 to.sin_addr = ip->ip_dst;
342
343 /*
344 * 'to' holds the dest of the packet that failed to be sent.
345 * 'from' holds our local endpoint address. Thus we reverse
346 * the to and the from in the lookup.
347 */
348 stcb = sctp_findassociation_addr_sa((struct sockaddr *)&to,
349 (struct sockaddr *)&from,
350 &inp, &net, 1, vrf_id);
351 if (stcb != NULL && inp && (inp->sctp_socket != NULL)) {
352 if (cmd != PRC_MSGSIZE) {
353 sctp_notify(inp, ip, sh,
354 (struct sockaddr *)&to, stcb,
355 net);
356 } else {
357 /* handle possible ICMP size messages */
358 sctp_notify_mbuf(inp, stcb, net, ip, sh);
359 }
360 } else {
361 if ((stcb == NULL) && (inp != NULL)) {
362 /* reduce ref-count */
363 SCTP_INP_WLOCK(inp);
364 SCTP_INP_DECR_REF(inp);
365 SCTP_INP_WUNLOCK(inp);
366 }
367 if (stcb) {
368 SCTP_TCB_UNLOCK(stcb);
369 }
370 }
371 }
372 return;
373 }
374
375 #endif
376
377 static int
378 sctp_getcred(SYSCTL_HANDLER_ARGS)
379 {
380 struct xucred xuc;
381 struct sockaddr_in addrs[2];
382 struct sctp_inpcb *inp;
383 struct sctp_nets *net;
384 struct sctp_tcb *stcb;
385 int error;
386 uint32_t vrf_id;
387
388 /* FIX, for non-bsd is this right? */
389 vrf_id = SCTP_DEFAULT_VRFID;
390
391 error = priv_check(req->td, PRIV_NETINET_GETCRED);
392
393 if (error)
394 return (error);
395
396 error = SYSCTL_IN(req, addrs, sizeof(addrs));
397 if (error)
398 return (error);
399
400 stcb = sctp_findassociation_addr_sa(sintosa(&addrs[1]),
401 sintosa(&addrs[0]),
402 &inp, &net, 1, vrf_id);
403 if (stcb == NULL || inp == NULL || inp->sctp_socket == NULL) {
404 if ((inp != NULL) && (stcb == NULL)) {
405 /* reduce ref-count */
406 SCTP_INP_WLOCK(inp);
407 SCTP_INP_DECR_REF(inp);
408 goto cred_can_cont;
409 }
410 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
411 error = ENOENT;
412 goto out;
413 }
414 SCTP_TCB_UNLOCK(stcb);
415 /*
416 * We use the write lock here, only since in the error leg we need
417 * it. If we used RLOCK, then we would have to
418 * wlock/decr/unlock/rlock. Which in theory could create a hole.
419 * Better to use higher wlock.
420 */
421 SCTP_INP_WLOCK(inp);
422 cred_can_cont:
423 error = cr_canseesocket(req->td->td_ucred, inp->sctp_socket);
424 if (error) {
425 SCTP_INP_WUNLOCK(inp);
426 goto out;
427 }
428 cru2x(inp->sctp_socket->so_cred, &xuc);
429 SCTP_INP_WUNLOCK(inp);
430 error = SYSCTL_OUT(req, &xuc, sizeof(struct xucred));
431 out:
432 return (error);
433 }
434
435 SYSCTL_PROC(_net_inet_sctp, OID_AUTO, getcred, CTLTYPE_OPAQUE | CTLFLAG_RW,
436 0, 0, sctp_getcred, "S,ucred", "Get the ucred of a SCTP connection");
437
438
439 #ifdef INET
440 static void
441 sctp_abort(struct socket *so)
442 {
443 struct sctp_inpcb *inp;
444 uint32_t flags;
445
446 inp = (struct sctp_inpcb *)so->so_pcb;
447 if (inp == NULL) {
448 return;
449 }
450 sctp_must_try_again:
451 flags = inp->sctp_flags;
452 #ifdef SCTP_LOG_CLOSING
453 sctp_log_closing(inp, NULL, 17);
454 #endif
455 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
456 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
457 #ifdef SCTP_LOG_CLOSING
458 sctp_log_closing(inp, NULL, 16);
459 #endif
460 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
461 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
462 SOCK_LOCK(so);
463 SCTP_SB_CLEAR(so->so_snd);
464 /*
465 * same for the rcv ones, they are only here for the
466 * accounting/select.
467 */
468 SCTP_SB_CLEAR(so->so_rcv);
469
470 /* Now null out the reference, we are completely detached. */
471 so->so_pcb = NULL;
472 SOCK_UNLOCK(so);
473 } else {
474 flags = inp->sctp_flags;
475 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
476 goto sctp_must_try_again;
477 }
478 }
479 return;
480 }
481
482 static int
483 sctp_attach(struct socket *so, int proto SCTP_UNUSED, struct thread *p SCTP_UNUSED)
484 {
485 struct sctp_inpcb *inp;
486 struct inpcb *ip_inp;
487 int error;
488 uint32_t vrf_id = SCTP_DEFAULT_VRFID;
489
490 #ifdef IPSEC
491 uint32_t flags;
492
493 #endif
494
495 inp = (struct sctp_inpcb *)so->so_pcb;
496 if (inp != 0) {
497 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
498 return (EINVAL);
499 }
500 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) {
501 error = SCTP_SORESERVE(so, SCTP_BASE_SYSCTL(sctp_sendspace), SCTP_BASE_SYSCTL(sctp_recvspace));
502 if (error) {
503 return (error);
504 }
505 }
506 error = sctp_inpcb_alloc(so, vrf_id);
507 if (error) {
508 return (error);
509 }
510 inp = (struct sctp_inpcb *)so->so_pcb;
511 SCTP_INP_WLOCK(inp);
512 inp->sctp_flags &= ~SCTP_PCB_FLAGS_BOUND_V6; /* I'm not v6! */
513 ip_inp = &inp->ip_inp.inp;
514 ip_inp->inp_vflag |= INP_IPV4;
515 ip_inp->inp_ip_ttl = MODULE_GLOBAL(ip_defttl);
516 #ifdef IPSEC
517 error = ipsec_init_policy(so, &ip_inp->inp_sp);
518 #ifdef SCTP_LOG_CLOSING
519 sctp_log_closing(inp, NULL, 17);
520 #endif
521 if (error != 0) {
522 try_again:
523 flags = inp->sctp_flags;
524 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
525 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
526 #ifdef SCTP_LOG_CLOSING
527 sctp_log_closing(inp, NULL, 15);
528 #endif
529 SCTP_INP_WUNLOCK(inp);
530 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
531 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
532 } else {
533 flags = inp->sctp_flags;
534 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
535 goto try_again;
536 } else {
537 SCTP_INP_WUNLOCK(inp);
538 }
539 }
540 return (error);
541 }
542 #endif /* IPSEC */
543 SCTP_INP_WUNLOCK(inp);
544 return (0);
545 }
546
547 static int
548 sctp_bind(struct socket *so, struct sockaddr *addr, struct thread *p)
549 {
550 struct sctp_inpcb *inp;
551
552 inp = (struct sctp_inpcb *)so->so_pcb;
553 if (inp == NULL) {
554 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
555 return (EINVAL);
556 }
557 if (addr != NULL) {
558 if ((addr->sa_family != AF_INET) ||
559 (addr->sa_len != sizeof(struct sockaddr_in))) {
560 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
561 return (EINVAL);
562 }
563 }
564 return (sctp_inpcb_bind(so, addr, NULL, p));
565 }
566
567 #endif
568 void
569 sctp_close(struct socket *so)
570 {
571 struct sctp_inpcb *inp;
572 uint32_t flags;
573
574 inp = (struct sctp_inpcb *)so->so_pcb;
575 if (inp == NULL)
576 return;
577
578 /*
579 * Inform all the lower layer assoc that we are done.
580 */
581 sctp_must_try_again:
582 flags = inp->sctp_flags;
583 #ifdef SCTP_LOG_CLOSING
584 sctp_log_closing(inp, NULL, 17);
585 #endif
586 if (((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
587 (atomic_cmpset_int(&inp->sctp_flags, flags, (flags | SCTP_PCB_FLAGS_SOCKET_GONE | SCTP_PCB_FLAGS_CLOSE_IP)))) {
588 if (((so->so_options & SO_LINGER) && (so->so_linger == 0)) ||
589 (so->so_rcv.sb_cc > 0)) {
590 #ifdef SCTP_LOG_CLOSING
591 sctp_log_closing(inp, NULL, 13);
592 #endif
593 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_ABORT,
594 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
595 } else {
596 #ifdef SCTP_LOG_CLOSING
597 sctp_log_closing(inp, NULL, 14);
598 #endif
599 sctp_inpcb_free(inp, SCTP_FREE_SHOULD_USE_GRACEFUL_CLOSE,
600 SCTP_CALLED_AFTER_CMPSET_OFCLOSE);
601 }
602 /*
603 * The socket is now detached, no matter what the state of
604 * the SCTP association.
605 */
606 SOCK_LOCK(so);
607 SCTP_SB_CLEAR(so->so_snd);
608 /*
609 * same for the rcv ones, they are only here for the
610 * accounting/select.
611 */
612 SCTP_SB_CLEAR(so->so_rcv);
613
614 /* Now null out the reference, we are completely detached. */
615 so->so_pcb = NULL;
616 SOCK_UNLOCK(so);
617 } else {
618 flags = inp->sctp_flags;
619 if ((flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) {
620 goto sctp_must_try_again;
621 }
622 }
623 return;
624 }
625
626
627 int
628 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
629 struct mbuf *control, struct thread *p);
630
631
632 int
633 sctp_sendm(struct socket *so, int flags, struct mbuf *m, struct sockaddr *addr,
634 struct mbuf *control, struct thread *p)
635 {
636 struct sctp_inpcb *inp;
637 int error;
638
639 inp = (struct sctp_inpcb *)so->so_pcb;
640 if (inp == NULL) {
641 if (control) {
642 sctp_m_freem(control);
643 control = NULL;
644 }
645 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
646 sctp_m_freem(m);
647 return (EINVAL);
648 }
649 /* Got to have an to address if we are NOT a connected socket */
650 if ((addr == NULL) &&
651 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) ||
652 (inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE))) {
653 goto connected_type;
654 } else if (addr == NULL) {
655 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
656 error = EDESTADDRREQ;
657 sctp_m_freem(m);
658 if (control) {
659 sctp_m_freem(control);
660 control = NULL;
661 }
662 return (error);
663 }
664 #ifdef INET6
665 if (addr->sa_family != AF_INET) {
666 /* must be a v4 address! */
667 SCTP_LTRACE_ERR_RET_PKT(m, inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EDESTADDRREQ);
668 sctp_m_freem(m);
669 if (control) {
670 sctp_m_freem(control);
671 control = NULL;
672 }
673 error = EDESTADDRREQ;
674 return (error);
675 }
676 #endif /* INET6 */
677 connected_type:
678 /* now what about control */
679 if (control) {
680 if (inp->control) {
681 SCTP_PRINTF("huh? control set?\n");
682 sctp_m_freem(inp->control);
683 inp->control = NULL;
684 }
685 inp->control = control;
686 }
687 /* Place the data */
688 if (inp->pkt) {
689 SCTP_BUF_NEXT(inp->pkt_last) = m;
690 inp->pkt_last = m;
691 } else {
692 inp->pkt_last = inp->pkt = m;
693 }
694 if (
695 /* FreeBSD uses a flag passed */
696 ((flags & PRUS_MORETOCOME) == 0)
697 ) {
698 /*
699 * note with the current version this code will only be used
700 * by OpenBSD-- NetBSD, FreeBSD, and MacOS have methods for
701 * re-defining sosend to use the sctp_sosend. One can
702 * optionally switch back to this code (by changing back the
703 * definitions) but this is not advisable. This code is used
704 * by FreeBSD when sending a file with sendfile() though.
705 */
706 int ret;
707
708 ret = sctp_output(inp, inp->pkt, addr, inp->control, p, flags);
709 inp->pkt = NULL;
710 inp->control = NULL;
711 return (ret);
712 } else {
713 return (0);
714 }
715 }
716
717 int
718 sctp_disconnect(struct socket *so)
719 {
720 struct sctp_inpcb *inp;
721
722 inp = (struct sctp_inpcb *)so->so_pcb;
723 if (inp == NULL) {
724 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
725 return (ENOTCONN);
726 }
727 SCTP_INP_RLOCK(inp);
728 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
729 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
730 if (LIST_EMPTY(&inp->sctp_asoc_list)) {
731 /* No connection */
732 SCTP_INP_RUNLOCK(inp);
733 return (0);
734 } else {
735 struct sctp_association *asoc;
736 struct sctp_tcb *stcb;
737
738 stcb = LIST_FIRST(&inp->sctp_asoc_list);
739 if (stcb == NULL) {
740 SCTP_INP_RUNLOCK(inp);
741 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
742 return (EINVAL);
743 }
744 SCTP_TCB_LOCK(stcb);
745 asoc = &stcb->asoc;
746 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
747 /* We are about to be freed, out of here */
748 SCTP_TCB_UNLOCK(stcb);
749 SCTP_INP_RUNLOCK(inp);
750 return (0);
751 }
752 if (((so->so_options & SO_LINGER) &&
753 (so->so_linger == 0)) ||
754 (so->so_rcv.sb_cc > 0)) {
755 if (SCTP_GET_STATE(asoc) !=
756 SCTP_STATE_COOKIE_WAIT) {
757 /* Left with Data unread */
758 struct mbuf *err;
759
760 err = sctp_get_mbuf_for_msg(sizeof(struct sctp_paramhdr), 0, M_NOWAIT, 1, MT_DATA);
761 if (err) {
762 /*
763 * Fill in the user
764 * initiated abort
765 */
766 struct sctp_paramhdr *ph;
767
768 ph = mtod(err, struct sctp_paramhdr *);
769 SCTP_BUF_LEN(err) = sizeof(struct sctp_paramhdr);
770 ph->param_type = htons(SCTP_CAUSE_USER_INITIATED_ABT);
771 ph->param_length = htons(SCTP_BUF_LEN(err));
772 }
773 sctp_send_abort_tcb(stcb, err, SCTP_SO_LOCKED);
774 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
775 }
776 SCTP_INP_RUNLOCK(inp);
777 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
778 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
779 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
780 }
781 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_3);
782 /* No unlock tcb assoc is gone */
783 return (0);
784 }
785 if (TAILQ_EMPTY(&asoc->send_queue) &&
786 TAILQ_EMPTY(&asoc->sent_queue) &&
787 (asoc->stream_queue_cnt == 0)) {
788 /* there is nothing queued to send, so done */
789 if (asoc->locked_on_sending) {
790 goto abort_anyway;
791 }
792 if ((SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) &&
793 (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_ACK_SENT)) {
794 /* only send SHUTDOWN 1st time thru */
795 struct sctp_nets *netp;
796
797 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
798 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
799 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
800 }
801 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
802 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
803 sctp_stop_timers_for_shutdown(stcb);
804 if (stcb->asoc.alternate) {
805 netp = stcb->asoc.alternate;
806 } else {
807 netp = stcb->asoc.primary_destination;
808 }
809 sctp_send_shutdown(stcb, netp);
810 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
811 stcb->sctp_ep, stcb, netp);
812 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
813 stcb->sctp_ep, stcb, netp);
814 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
815 }
816 } else {
817 /*
818 * we still got (or just got) data to send,
819 * so set SHUTDOWN_PENDING
820 */
821 /*
822 * XXX sockets draft says that SCTP_EOF
823 * should be sent with no data. currently,
824 * we will allow user data to be sent first
825 * and move to SHUTDOWN-PENDING
826 */
827 struct sctp_nets *netp;
828
829 if (stcb->asoc.alternate) {
830 netp = stcb->asoc.alternate;
831 } else {
832 netp = stcb->asoc.primary_destination;
833 }
834
835 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
836 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
837 netp);
838 if (asoc->locked_on_sending) {
839 /* Locked to send out the data */
840 struct sctp_stream_queue_pending *sp;
841
842 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
843 if (sp == NULL) {
844 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
845 asoc->locked_on_sending->stream_no);
846 } else {
847 if ((sp->length == 0) && (sp->msg_is_complete == 0))
848 asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
849 }
850 }
851 if (TAILQ_EMPTY(&asoc->send_queue) &&
852 TAILQ_EMPTY(&asoc->sent_queue) &&
853 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
854 struct mbuf *op_err;
855
856 abort_anyway:
857 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
858 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_4;
859 sctp_send_abort_tcb(stcb, op_err, SCTP_SO_LOCKED);
860 SCTP_STAT_INCR_COUNTER32(sctps_aborted);
861 if ((SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_OPEN) ||
862 (SCTP_GET_STATE(&stcb->asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
863 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
864 }
865 SCTP_INP_RUNLOCK(inp);
866 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_5);
867 return (0);
868 } else {
869 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
870 }
871 }
872 soisdisconnecting(so);
873 SCTP_TCB_UNLOCK(stcb);
874 SCTP_INP_RUNLOCK(inp);
875 return (0);
876 }
877 /* not reached */
878 } else {
879 /* UDP model does not support this */
880 SCTP_INP_RUNLOCK(inp);
881 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
882 return (EOPNOTSUPP);
883 }
884 }
885
886 int
887 sctp_flush(struct socket *so, int how)
888 {
889 /*
890 * We will just clear out the values and let subsequent close clear
891 * out the data, if any. Note if the user did a shutdown(SHUT_RD)
892 * they will not be able to read the data, the socket will block
893 * that from happening.
894 */
895 struct sctp_inpcb *inp;
896
897 inp = (struct sctp_inpcb *)so->so_pcb;
898 if (inp == NULL) {
899 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
900 return (EINVAL);
901 }
902 SCTP_INP_RLOCK(inp);
903 /* For the 1 to many model this does nothing */
904 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
905 SCTP_INP_RUNLOCK(inp);
906 return (0);
907 }
908 SCTP_INP_RUNLOCK(inp);
909 if ((how == PRU_FLUSH_RD) || (how == PRU_FLUSH_RDWR)) {
910 /*
911 * First make sure the sb will be happy, we don't use these
912 * except maybe the count
913 */
914 SCTP_INP_WLOCK(inp);
915 SCTP_INP_READ_LOCK(inp);
916 inp->sctp_flags |= SCTP_PCB_FLAGS_SOCKET_CANT_READ;
917 SCTP_INP_READ_UNLOCK(inp);
918 SCTP_INP_WUNLOCK(inp);
919 so->so_rcv.sb_cc = 0;
920 so->so_rcv.sb_mbcnt = 0;
921 so->so_rcv.sb_mb = NULL;
922 }
923 if ((how == PRU_FLUSH_WR) || (how == PRU_FLUSH_RDWR)) {
924 /*
925 * First make sure the sb will be happy, we don't use these
926 * except maybe the count
927 */
928 so->so_snd.sb_cc = 0;
929 so->so_snd.sb_mbcnt = 0;
930 so->so_snd.sb_mb = NULL;
931
932 }
933 return (0);
934 }
935
936 int
937 sctp_shutdown(struct socket *so)
938 {
939 struct sctp_inpcb *inp;
940
941 inp = (struct sctp_inpcb *)so->so_pcb;
942 if (inp == NULL) {
943 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
944 return (EINVAL);
945 }
946 SCTP_INP_RLOCK(inp);
947 /* For UDP model this is a invalid call */
948 if (!((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
949 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL))) {
950 /* Restore the flags that the soshutdown took away. */
951 SOCKBUF_LOCK(&so->so_rcv);
952 so->so_rcv.sb_state &= ~SBS_CANTRCVMORE;
953 SOCKBUF_UNLOCK(&so->so_rcv);
954 /* This proc will wakeup for read and do nothing (I hope) */
955 SCTP_INP_RUNLOCK(inp);
956 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
957 return (EOPNOTSUPP);
958 }
959 /*
960 * Ok if we reach here its the TCP model and it is either a SHUT_WR
961 * or SHUT_RDWR. This means we put the shutdown flag against it.
962 */
963 {
964 struct sctp_tcb *stcb;
965 struct sctp_association *asoc;
966
967 if ((so->so_state &
968 (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
969 SCTP_INP_RUNLOCK(inp);
970 return (ENOTCONN);
971 }
972 socantsendmore(so);
973
974 stcb = LIST_FIRST(&inp->sctp_asoc_list);
975 if (stcb == NULL) {
976 /*
977 * Ok we hit the case that the shutdown call was
978 * made after an abort or something. Nothing to do
979 * now.
980 */
981 SCTP_INP_RUNLOCK(inp);
982 return (0);
983 }
984 SCTP_TCB_LOCK(stcb);
985 asoc = &stcb->asoc;
986 if (TAILQ_EMPTY(&asoc->send_queue) &&
987 TAILQ_EMPTY(&asoc->sent_queue) &&
988 (asoc->stream_queue_cnt == 0)) {
989 if (asoc->locked_on_sending) {
990 goto abort_anyway;
991 }
992 /* there is nothing queued to send, so I'm done... */
993 if (SCTP_GET_STATE(asoc) != SCTP_STATE_SHUTDOWN_SENT) {
994 /* only send SHUTDOWN the first time through */
995 struct sctp_nets *netp;
996
997 if ((SCTP_GET_STATE(asoc) == SCTP_STATE_OPEN) ||
998 (SCTP_GET_STATE(asoc) == SCTP_STATE_SHUTDOWN_RECEIVED)) {
999 SCTP_STAT_DECR_GAUGE32(sctps_currestab);
1000 }
1001 SCTP_SET_STATE(asoc, SCTP_STATE_SHUTDOWN_SENT);
1002 SCTP_CLEAR_SUBSTATE(asoc, SCTP_STATE_SHUTDOWN_PENDING);
1003 sctp_stop_timers_for_shutdown(stcb);
1004 if (stcb->asoc.alternate) {
1005 netp = stcb->asoc.alternate;
1006 } else {
1007 netp = stcb->asoc.primary_destination;
1008 }
1009 sctp_send_shutdown(stcb, netp);
1010 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWN,
1011 stcb->sctp_ep, stcb, netp);
1012 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD,
1013 stcb->sctp_ep, stcb, netp);
1014 sctp_chunk_output(stcb->sctp_ep, stcb, SCTP_OUTPUT_FROM_T3, SCTP_SO_LOCKED);
1015 }
1016 } else {
1017 /*
1018 * we still got (or just got) data to send, so set
1019 * SHUTDOWN_PENDING
1020 */
1021 struct sctp_nets *netp;
1022
1023 if (stcb->asoc.alternate) {
1024 netp = stcb->asoc.alternate;
1025 } else {
1026 netp = stcb->asoc.primary_destination;
1027 }
1028
1029 asoc->state |= SCTP_STATE_SHUTDOWN_PENDING;
1030 sctp_timer_start(SCTP_TIMER_TYPE_SHUTDOWNGUARD, stcb->sctp_ep, stcb,
1031 netp);
1032
1033 if (asoc->locked_on_sending) {
1034 /* Locked to send out the data */
1035 struct sctp_stream_queue_pending *sp;
1036
1037 sp = TAILQ_LAST(&asoc->locked_on_sending->outqueue, sctp_streamhead);
1038 if (sp == NULL) {
1039 SCTP_PRINTF("Error, sp is NULL, locked on sending is non-null strm:%d\n",
1040 asoc->locked_on_sending->stream_no);
1041 } else {
1042 if ((sp->length == 0) && (sp->msg_is_complete == 0)) {
1043 asoc->state |= SCTP_STATE_PARTIAL_MSG_LEFT;
1044 }
1045 }
1046 }
1047 if (TAILQ_EMPTY(&asoc->send_queue) &&
1048 TAILQ_EMPTY(&asoc->sent_queue) &&
1049 (asoc->state & SCTP_STATE_PARTIAL_MSG_LEFT)) {
1050 struct mbuf *op_err;
1051
1052 abort_anyway:
1053 op_err = sctp_generate_cause(SCTP_CAUSE_USER_INITIATED_ABT, "");
1054 stcb->sctp_ep->last_abort_code = SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6;
1055 sctp_abort_an_association(stcb->sctp_ep, stcb,
1056 op_err, SCTP_SO_LOCKED);
1057 goto skip_unlock;
1058 } else {
1059 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
1060 }
1061 }
1062 SCTP_TCB_UNLOCK(stcb);
1063 }
1064 skip_unlock:
1065 SCTP_INP_RUNLOCK(inp);
1066 return (0);
1067 }
1068
1069 /*
1070 * copies a "user" presentable address and removes embedded scope, etc.
1071 * returns 0 on success, 1 on error
1072 */
1073 static uint32_t
1074 sctp_fill_user_address(struct sockaddr_storage *ss, struct sockaddr *sa)
1075 {
1076 #ifdef INET6
1077 struct sockaddr_in6 lsa6;
1078
1079 sa = (struct sockaddr *)sctp_recover_scope((struct sockaddr_in6 *)sa,
1080 &lsa6);
1081 #endif
1082 memcpy(ss, sa, sa->sa_len);
1083 return (0);
1084 }
1085
1086
1087
1088 /*
1089 * NOTE: assumes addr lock is held
1090 */
1091 static size_t
1092 sctp_fill_up_addresses_vrf(struct sctp_inpcb *inp,
1093 struct sctp_tcb *stcb,
1094 size_t limit,
1095 struct sockaddr_storage *sas,
1096 uint32_t vrf_id)
1097 {
1098 struct sctp_ifn *sctp_ifn;
1099 struct sctp_ifa *sctp_ifa;
1100 size_t actual;
1101 int loopback_scope;
1102
1103 #if defined(INET)
1104 int ipv4_local_scope, ipv4_addr_legal;
1105
1106 #endif
1107 #if defined(INET6)
1108 int local_scope, site_scope, ipv6_addr_legal;
1109
1110 #endif
1111 struct sctp_vrf *vrf;
1112
1113 actual = 0;
1114 if (limit <= 0)
1115 return (actual);
1116
1117 if (stcb) {
1118 /* Turn on all the appropriate scope */
1119 loopback_scope = stcb->asoc.scope.loopback_scope;
1120 #if defined(INET)
1121 ipv4_local_scope = stcb->asoc.scope.ipv4_local_scope;
1122 ipv4_addr_legal = stcb->asoc.scope.ipv4_addr_legal;
1123 #endif
1124 #if defined(INET6)
1125 local_scope = stcb->asoc.scope.local_scope;
1126 site_scope = stcb->asoc.scope.site_scope;
1127 ipv6_addr_legal = stcb->asoc.scope.ipv6_addr_legal;
1128 #endif
1129 } else {
1130 /* Use generic values for endpoints. */
1131 loopback_scope = 1;
1132 #if defined(INET)
1133 ipv4_local_scope = 1;
1134 #endif
1135 #if defined(INET6)
1136 local_scope = 1;
1137 site_scope = 1;
1138 #endif
1139 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
1140 #if defined(INET6)
1141 ipv6_addr_legal = 1;
1142 #endif
1143 #if defined(INET)
1144 if (SCTP_IPV6_V6ONLY(inp)) {
1145 ipv4_addr_legal = 0;
1146 } else {
1147 ipv4_addr_legal = 1;
1148 }
1149 #endif
1150 } else {
1151 #if defined(INET6)
1152 ipv6_addr_legal = 0;
1153 #endif
1154 #if defined(INET)
1155 ipv4_addr_legal = 1;
1156 #endif
1157 }
1158 }
1159 vrf = sctp_find_vrf(vrf_id);
1160 if (vrf == NULL) {
1161 return (0);
1162 }
1163 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1164 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1165 if ((loopback_scope == 0) &&
1166 SCTP_IFN_IS_IFT_LOOP(sctp_ifn)) {
1167 /* Skip loopback if loopback_scope not set */
1168 continue;
1169 }
1170 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1171 if (stcb) {
1172 /*
1173 * For the BOUND-ALL case, the list
1174 * associated with a TCB is Always
1175 * considered a reverse list.. i.e.
1176 * it lists addresses that are NOT
1177 * part of the association. If this
1178 * is one of those we must skip it.
1179 */
1180 if (sctp_is_addr_restricted(stcb,
1181 sctp_ifa)) {
1182 continue;
1183 }
1184 }
1185 switch (sctp_ifa->address.sa.sa_family) {
1186 #ifdef INET
1187 case AF_INET:
1188 if (ipv4_addr_legal) {
1189 struct sockaddr_in *sin;
1190
1191 sin = &sctp_ifa->address.sin;
1192 if (sin->sin_addr.s_addr == 0) {
1193 /*
1194 * we skip
1195 * unspecifed
1196 * addresses
1197 */
1198 continue;
1199 }
1200 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
1201 &sin->sin_addr) != 0) {
1202 continue;
1203 }
1204 if ((ipv4_local_scope == 0) &&
1205 (IN4_ISPRIVATE_ADDRESS(&sin->sin_addr))) {
1206 continue;
1207 }
1208 #ifdef INET6
1209 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
1210 in6_sin_2_v4mapsin6(sin, (struct sockaddr_in6 *)sas);
1211 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1212 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(struct sockaddr_in6));
1213 actual += sizeof(struct sockaddr_in6);
1214 } else {
1215 #endif
1216 memcpy(sas, sin, sizeof(*sin));
1217 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1218 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin));
1219 actual += sizeof(*sin);
1220 #ifdef INET6
1221 }
1222 #endif
1223 if (actual >= limit) {
1224 return (actual);
1225 }
1226 } else {
1227 continue;
1228 }
1229 break;
1230 #endif
1231 #ifdef INET6
1232 case AF_INET6:
1233 if (ipv6_addr_legal) {
1234 struct sockaddr_in6 *sin6;
1235
1236 sin6 = &sctp_ifa->address.sin6;
1237 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
1238 /*
1239 * we skip
1240 * unspecifed
1241 * addresses
1242 */
1243 continue;
1244 }
1245 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
1246 &sin6->sin6_addr) != 0) {
1247 continue;
1248 }
1249 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
1250 if (local_scope == 0)
1251 continue;
1252 if (sin6->sin6_scope_id == 0) {
1253 if (sa6_recoverscope(sin6) != 0)
1254 /*
1255 *
1256 * bad
1257 *
1258 * li
1259 * nk
1260 *
1261 * loc
1262 * al
1263 *
1264 * add
1265 * re
1266 * ss
1267 * */
1268 continue;
1269 }
1270 }
1271 if ((site_scope == 0) &&
1272 (IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr))) {
1273 continue;
1274 }
1275 memcpy(sas, sin6, sizeof(*sin6));
1276 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1277 sas = (struct sockaddr_storage *)((caddr_t)sas + sizeof(*sin6));
1278 actual += sizeof(*sin6);
1279 if (actual >= limit) {
1280 return (actual);
1281 }
1282 } else {
1283 continue;
1284 }
1285 break;
1286 #endif
1287 default:
1288 /* TSNH */
1289 break;
1290 }
1291 }
1292 }
1293 } else {
1294 struct sctp_laddr *laddr;
1295
1296 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1297 if (stcb) {
1298 if (sctp_is_addr_restricted(stcb, laddr->ifa)) {
1299 continue;
1300 }
1301 }
1302 if (sctp_fill_user_address(sas, &laddr->ifa->address.sa))
1303 continue;
1304 switch (laddr->ifa->address.sa.sa_family) {
1305 #ifdef INET
1306 case AF_INET:
1307 ((struct sockaddr_in *)sas)->sin_port = inp->sctp_lport;
1308 break;
1309 #endif
1310 #ifdef INET6
1311 case AF_INET6:
1312 ((struct sockaddr_in6 *)sas)->sin6_port = inp->sctp_lport;
1313 break;
1314 #endif
1315 default:
1316 /* TSNH */
1317 break;
1318 }
1319 sas = (struct sockaddr_storage *)((caddr_t)sas +
1320 laddr->ifa->address.sa.sa_len);
1321 actual += laddr->ifa->address.sa.sa_len;
1322 if (actual >= limit) {
1323 return (actual);
1324 }
1325 }
1326 }
1327 return (actual);
1328 }
1329
1330 static size_t
1331 sctp_fill_up_addresses(struct sctp_inpcb *inp,
1332 struct sctp_tcb *stcb,
1333 size_t limit,
1334 struct sockaddr_storage *sas)
1335 {
1336 size_t size = 0;
1337
1338 SCTP_IPI_ADDR_RLOCK();
1339 /* fill up addresses for the endpoint's default vrf */
1340 size = sctp_fill_up_addresses_vrf(inp, stcb, limit, sas,
1341 inp->def_vrf_id);
1342 SCTP_IPI_ADDR_RUNLOCK();
1343 return (size);
1344 }
1345
1346 /*
1347 * NOTE: assumes addr lock is held
1348 */
1349 static int
1350 sctp_count_max_addresses_vrf(struct sctp_inpcb *inp, uint32_t vrf_id)
1351 {
1352 int cnt = 0;
1353 struct sctp_vrf *vrf = NULL;
1354
1355 /*
1356 * In both sub-set bound an bound_all cases we return the MAXIMUM
1357 * number of addresses that you COULD get. In reality the sub-set
1358 * bound may have an exclusion list for a given TCB OR in the
1359 * bound-all case a TCB may NOT include the loopback or other
1360 * addresses as well.
1361 */
1362 vrf = sctp_find_vrf(vrf_id);
1363 if (vrf == NULL) {
1364 return (0);
1365 }
1366 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1367 struct sctp_ifn *sctp_ifn;
1368 struct sctp_ifa *sctp_ifa;
1369
1370 LIST_FOREACH(sctp_ifn, &vrf->ifnlist, next_ifn) {
1371 LIST_FOREACH(sctp_ifa, &sctp_ifn->ifalist, next_ifa) {
1372 /* Count them if they are the right type */
1373 switch (sctp_ifa->address.sa.sa_family) {
1374 #ifdef INET
1375 case AF_INET:
1376 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1377 cnt += sizeof(struct sockaddr_in6);
1378 else
1379 cnt += sizeof(struct sockaddr_in);
1380 break;
1381 #endif
1382 #ifdef INET6
1383 case AF_INET6:
1384 cnt += sizeof(struct sockaddr_in6);
1385 break;
1386 #endif
1387 default:
1388 break;
1389 }
1390 }
1391 }
1392 } else {
1393 struct sctp_laddr *laddr;
1394
1395 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
1396 switch (laddr->ifa->address.sa.sa_family) {
1397 #ifdef INET
1398 case AF_INET:
1399 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4))
1400 cnt += sizeof(struct sockaddr_in6);
1401 else
1402 cnt += sizeof(struct sockaddr_in);
1403 break;
1404 #endif
1405 #ifdef INET6
1406 case AF_INET6:
1407 cnt += sizeof(struct sockaddr_in6);
1408 break;
1409 #endif
1410 default:
1411 break;
1412 }
1413 }
1414 }
1415 return (cnt);
1416 }
1417
1418 static int
1419 sctp_count_max_addresses(struct sctp_inpcb *inp)
1420 {
1421 int cnt = 0;
1422
1423 SCTP_IPI_ADDR_RLOCK();
1424 /* count addresses for the endpoint's default VRF */
1425 cnt = sctp_count_max_addresses_vrf(inp, inp->def_vrf_id);
1426 SCTP_IPI_ADDR_RUNLOCK();
1427 return (cnt);
1428 }
1429
1430 static int
1431 sctp_do_connect_x(struct socket *so, struct sctp_inpcb *inp, void *optval,
1432 size_t optsize, void *p, int delay)
1433 {
1434 int error = 0;
1435 int creat_lock_on = 0;
1436 struct sctp_tcb *stcb = NULL;
1437 struct sockaddr *sa;
1438 int num_v6 = 0, num_v4 = 0, *totaddrp, totaddr;
1439 uint32_t vrf_id;
1440 int bad_addresses = 0;
1441 sctp_assoc_t *a_id;
1442
1443 SCTPDBG(SCTP_DEBUG_PCB1, "Connectx called\n");
1444
1445 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
1446 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
1447 /* We are already connected AND the TCP model */
1448 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
1449 return (EADDRINUSE);
1450 }
1451 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
1452 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
1453 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1454 return (EINVAL);
1455 }
1456 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
1457 SCTP_INP_RLOCK(inp);
1458 stcb = LIST_FIRST(&inp->sctp_asoc_list);
1459 SCTP_INP_RUNLOCK(inp);
1460 }
1461 if (stcb) {
1462 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1463 return (EALREADY);
1464 }
1465 SCTP_INP_INCR_REF(inp);
1466 SCTP_ASOC_CREATE_LOCK(inp);
1467 creat_lock_on = 1;
1468 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
1469 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
1470 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
1471 error = EFAULT;
1472 goto out_now;
1473 }
1474 totaddrp = (int *)optval;
1475 totaddr = *totaddrp;
1476 sa = (struct sockaddr *)(totaddrp + 1);
1477 stcb = sctp_connectx_helper_find(inp, sa, &totaddr, &num_v4, &num_v6, &error, (optsize - sizeof(int)), &bad_addresses);
1478 if ((stcb != NULL) || bad_addresses) {
1479 /* Already have or am bring up an association */
1480 SCTP_ASOC_CREATE_UNLOCK(inp);
1481 creat_lock_on = 0;
1482 if (stcb)
1483 SCTP_TCB_UNLOCK(stcb);
1484 if (bad_addresses == 0) {
1485 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
1486 error = EALREADY;
1487 }
1488 goto out_now;
1489 }
1490 #ifdef INET6
1491 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
1492 (num_v6 > 0)) {
1493 error = EINVAL;
1494 goto out_now;
1495 }
1496 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
1497 (num_v4 > 0)) {
1498 struct in6pcb *inp6;
1499
1500 inp6 = (struct in6pcb *)inp;
1501 if (SCTP_IPV6_V6ONLY(inp6)) {
1502 /*
1503 * if IPV6_V6ONLY flag, ignore connections destined
1504 * to a v4 addr or v4-mapped addr
1505 */
1506 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1507 error = EINVAL;
1508 goto out_now;
1509 }
1510 }
1511 #endif /* INET6 */
1512 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
1513 SCTP_PCB_FLAGS_UNBOUND) {
1514 /* Bind a ephemeral port */
1515 error = sctp_inpcb_bind(so, NULL, NULL, p);
1516 if (error) {
1517 goto out_now;
1518 }
1519 }
1520 /* FIX ME: do we want to pass in a vrf on the connect call? */
1521 vrf_id = inp->def_vrf_id;
1522
1523
1524 /* We are GOOD to go */
1525 stcb = sctp_aloc_assoc(inp, sa, &error, 0, vrf_id,
1526 (struct thread *)p
1527 );
1528 if (stcb == NULL) {
1529 /* Gak! no memory */
1530 goto out_now;
1531 }
1532 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1533 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1534 /* Set the connected flag so we can queue data */
1535 soisconnecting(so);
1536 }
1537 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
1538 /* move to second address */
1539 switch (sa->sa_family) {
1540 #ifdef INET
1541 case AF_INET:
1542 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in));
1543 break;
1544 #endif
1545 #ifdef INET6
1546 case AF_INET6:
1547 sa = (struct sockaddr *)((caddr_t)sa + sizeof(struct sockaddr_in6));
1548 break;
1549 #endif
1550 default:
1551 break;
1552 }
1553
1554 error = 0;
1555 sctp_connectx_helper_add(stcb, sa, (totaddr - 1), &error);
1556 /* Fill in the return id */
1557 if (error) {
1558 (void)sctp_free_assoc(inp, stcb, SCTP_PCBFREE_FORCE, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_6);
1559 goto out_now;
1560 }
1561 a_id = (sctp_assoc_t *) optval;
1562 *a_id = sctp_get_associd(stcb);
1563
1564 /* initialize authentication parameters for the assoc */
1565 sctp_initialize_auth_params(inp, stcb);
1566
1567 if (delay) {
1568 /* doing delayed connection */
1569 stcb->asoc.delayed_connection = 1;
1570 sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, stcb->asoc.primary_destination);
1571 } else {
1572 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
1573 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
1574 }
1575 SCTP_TCB_UNLOCK(stcb);
1576 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
1577 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
1578 /* Set the connected flag so we can queue data */
1579 soisconnecting(so);
1580 }
1581 out_now:
1582 if (creat_lock_on) {
1583 SCTP_ASOC_CREATE_UNLOCK(inp);
1584 }
1585 SCTP_INP_DECR_REF(inp);
1586 return (error);
1587 }
1588
1589 #define SCTP_FIND_STCB(inp, stcb, assoc_id) { \
1590 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||\
1591 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { \
1592 SCTP_INP_RLOCK(inp); \
1593 stcb = LIST_FIRST(&inp->sctp_asoc_list); \
1594 if (stcb) { \
1595 SCTP_TCB_LOCK(stcb); \
1596 } \
1597 SCTP_INP_RUNLOCK(inp); \
1598 } else if (assoc_id > SCTP_ALL_ASSOC) { \
1599 stcb = sctp_findassociation_ep_asocid(inp, assoc_id, 1); \
1600 if (stcb == NULL) { \
1601 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); \
1602 error = ENOENT; \
1603 break; \
1604 } \
1605 } else { \
1606 stcb = NULL; \
1607 } \
1608 }
1609
1610
1611 #define SCTP_CHECK_AND_CAST(destp, srcp, type, size) {\
1612 if (size < sizeof(type)) { \
1613 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); \
1614 error = EINVAL; \
1615 break; \
1616 } else { \
1617 destp = (type *)srcp; \
1618 } \
1619 }
1620
1621 static int
1622 sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
1623 void *p)
1624 {
1625 struct sctp_inpcb *inp = NULL;
1626 int error, val = 0;
1627 struct sctp_tcb *stcb = NULL;
1628
1629 if (optval == NULL) {
1630 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1631 return (EINVAL);
1632 }
1633 inp = (struct sctp_inpcb *)so->so_pcb;
1634 if (inp == NULL) {
1635 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1636 return EINVAL;
1637 }
1638 error = 0;
1639
1640 switch (optname) {
1641 case SCTP_NODELAY:
1642 case SCTP_AUTOCLOSE:
1643 case SCTP_EXPLICIT_EOR:
1644 case SCTP_AUTO_ASCONF:
1645 case SCTP_DISABLE_FRAGMENTS:
1646 case SCTP_I_WANT_MAPPED_V4_ADDR:
1647 case SCTP_USE_EXT_RCVINFO:
1648 SCTP_INP_RLOCK(inp);
1649 switch (optname) {
1650 case SCTP_DISABLE_FRAGMENTS:
1651 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NO_FRAGMENT);
1652 break;
1653 case SCTP_I_WANT_MAPPED_V4_ADDR:
1654 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4);
1655 break;
1656 case SCTP_AUTO_ASCONF:
1657 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
1658 /* only valid for bound all sockets */
1659 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTO_ASCONF);
1660 } else {
1661 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1662 error = EINVAL;
1663 goto flags_out;
1664 }
1665 break;
1666 case SCTP_EXPLICIT_EOR:
1667 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXPLICIT_EOR);
1668 break;
1669 case SCTP_NODELAY:
1670 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NODELAY);
1671 break;
1672 case SCTP_USE_EXT_RCVINFO:
1673 val = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_EXT_RCVINFO);
1674 break;
1675 case SCTP_AUTOCLOSE:
1676 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTOCLOSE))
1677 val = TICKS_TO_SEC(inp->sctp_ep.auto_close_time);
1678 else
1679 val = 0;
1680 break;
1681
1682 default:
1683 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
1684 error = ENOPROTOOPT;
1685 } /* end switch (sopt->sopt_name) */
1686 if (*optsize < sizeof(val)) {
1687 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1688 error = EINVAL;
1689 }
1690 flags_out:
1691 SCTP_INP_RUNLOCK(inp);
1692 if (error == 0) {
1693 /* return the option value */
1694 *(int *)optval = val;
1695 *optsize = sizeof(val);
1696 }
1697 break;
1698 case SCTP_GET_PACKET_LOG:
1699 {
1700 #ifdef SCTP_PACKET_LOGGING
1701 uint8_t *target;
1702 int ret;
1703
1704 SCTP_CHECK_AND_CAST(target, optval, uint8_t, *optsize);
1705 ret = sctp_copy_out_packet_log(target, (int)*optsize);
1706 *optsize = ret;
1707 #else
1708 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1709 error = EOPNOTSUPP;
1710 #endif
1711 break;
1712 }
1713 case SCTP_REUSE_PORT:
1714 {
1715 uint32_t *value;
1716
1717 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
1718 /* Can't do this for a 1-m socket */
1719 error = EINVAL;
1720 break;
1721 }
1722 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1723 *value = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
1724 *optsize = sizeof(uint32_t);
1725 break;
1726 }
1727 case SCTP_PARTIAL_DELIVERY_POINT:
1728 {
1729 uint32_t *value;
1730
1731 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1732 *value = inp->partial_delivery_point;
1733 *optsize = sizeof(uint32_t);
1734 break;
1735 }
1736 case SCTP_FRAGMENT_INTERLEAVE:
1737 {
1738 uint32_t *value;
1739
1740 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1741 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) {
1742 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS)) {
1743 *value = SCTP_FRAG_LEVEL_2;
1744 } else {
1745 *value = SCTP_FRAG_LEVEL_1;
1746 }
1747 } else {
1748 *value = SCTP_FRAG_LEVEL_0;
1749 }
1750 *optsize = sizeof(uint32_t);
1751 break;
1752 }
1753 case SCTP_CMT_ON_OFF:
1754 {
1755 struct sctp_assoc_value *av;
1756
1757 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1758 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1759 if (stcb) {
1760 av->assoc_value = stcb->asoc.sctp_cmt_on_off;
1761 SCTP_TCB_UNLOCK(stcb);
1762 } else {
1763 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1764 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1765 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1766 SCTP_INP_RLOCK(inp);
1767 av->assoc_value = inp->sctp_cmt_on_off;
1768 SCTP_INP_RUNLOCK(inp);
1769 } else {
1770 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1771 error = EINVAL;
1772 }
1773 }
1774 if (error == 0) {
1775 *optsize = sizeof(struct sctp_assoc_value);
1776 }
1777 break;
1778 }
1779 case SCTP_PLUGGABLE_CC:
1780 {
1781 struct sctp_assoc_value *av;
1782
1783 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1784 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1785 if (stcb) {
1786 av->assoc_value = stcb->asoc.congestion_control_module;
1787 SCTP_TCB_UNLOCK(stcb);
1788 } else {
1789 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1790 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1791 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1792 SCTP_INP_RLOCK(inp);
1793 av->assoc_value = inp->sctp_ep.sctp_default_cc_module;
1794 SCTP_INP_RUNLOCK(inp);
1795 } else {
1796 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1797 error = EINVAL;
1798 }
1799 }
1800 if (error == 0) {
1801 *optsize = sizeof(struct sctp_assoc_value);
1802 }
1803 break;
1804 }
1805 case SCTP_CC_OPTION:
1806 {
1807 struct sctp_cc_option *cc_opt;
1808
1809 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, *optsize);
1810 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
1811 if (stcb == NULL) {
1812 error = EINVAL;
1813 } else {
1814 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
1815 error = ENOTSUP;
1816 } else {
1817 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 0, cc_opt);
1818 *optsize = sizeof(struct sctp_cc_option);
1819 }
1820 SCTP_TCB_UNLOCK(stcb);
1821 }
1822 break;
1823 }
1824 case SCTP_PLUGGABLE_SS:
1825 {
1826 struct sctp_assoc_value *av;
1827
1828 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1829 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1830 if (stcb) {
1831 av->assoc_value = stcb->asoc.stream_scheduling_module;
1832 SCTP_TCB_UNLOCK(stcb);
1833 } else {
1834 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1835 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1836 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1837 SCTP_INP_RLOCK(inp);
1838 av->assoc_value = inp->sctp_ep.sctp_default_ss_module;
1839 SCTP_INP_RUNLOCK(inp);
1840 } else {
1841 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1842 error = EINVAL;
1843 }
1844 }
1845 if (error == 0) {
1846 *optsize = sizeof(struct sctp_assoc_value);
1847 }
1848 break;
1849 }
1850 case SCTP_SS_VALUE:
1851 {
1852 struct sctp_stream_value *av;
1853
1854 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, *optsize);
1855 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1856 if (stcb) {
1857 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
1858 (stcb->asoc.ss_functions.sctp_ss_get_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
1859 &av->stream_value) < 0)) {
1860 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1861 error = EINVAL;
1862 } else {
1863 *optsize = sizeof(struct sctp_stream_value);
1864 }
1865 SCTP_TCB_UNLOCK(stcb);
1866 } else {
1867 /*
1868 * Can't get stream value without
1869 * association
1870 */
1871 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1872 error = EINVAL;
1873 }
1874 break;
1875 }
1876 case SCTP_GET_ADDR_LEN:
1877 {
1878 struct sctp_assoc_value *av;
1879
1880 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1881 error = EINVAL;
1882 #ifdef INET
1883 if (av->assoc_value == AF_INET) {
1884 av->assoc_value = sizeof(struct sockaddr_in);
1885 error = 0;
1886 }
1887 #endif
1888 #ifdef INET6
1889 if (av->assoc_value == AF_INET6) {
1890 av->assoc_value = sizeof(struct sockaddr_in6);
1891 error = 0;
1892 }
1893 #endif
1894 if (error) {
1895 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1896 } else {
1897 *optsize = sizeof(struct sctp_assoc_value);
1898 }
1899 break;
1900 }
1901 case SCTP_GET_ASSOC_NUMBER:
1902 {
1903 uint32_t *value, cnt;
1904
1905 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
1906 cnt = 0;
1907 SCTP_INP_RLOCK(inp);
1908 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1909 cnt++;
1910 }
1911 SCTP_INP_RUNLOCK(inp);
1912 *value = cnt;
1913 *optsize = sizeof(uint32_t);
1914 break;
1915 }
1916 case SCTP_GET_ASSOC_ID_LIST:
1917 {
1918 struct sctp_assoc_ids *ids;
1919 unsigned int at, limit;
1920
1921 SCTP_CHECK_AND_CAST(ids, optval, struct sctp_assoc_ids, *optsize);
1922 at = 0;
1923 limit = (*optsize - sizeof(uint32_t)) / sizeof(sctp_assoc_t);
1924 SCTP_INP_RLOCK(inp);
1925 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
1926 if (at < limit) {
1927 ids->gaids_assoc_id[at++] = sctp_get_associd(stcb);
1928 } else {
1929 error = EINVAL;
1930 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1931 break;
1932 }
1933 }
1934 SCTP_INP_RUNLOCK(inp);
1935 if (error == 0) {
1936 ids->gaids_number_of_ids = at;
1937 *optsize = ((at * sizeof(sctp_assoc_t)) + sizeof(uint32_t));
1938 }
1939 break;
1940 }
1941 case SCTP_CONTEXT:
1942 {
1943 struct sctp_assoc_value *av;
1944
1945 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
1946 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
1947
1948 if (stcb) {
1949 av->assoc_value = stcb->asoc.context;
1950 SCTP_TCB_UNLOCK(stcb);
1951 } else {
1952 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
1953 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
1954 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
1955 SCTP_INP_RLOCK(inp);
1956 av->assoc_value = inp->sctp_context;
1957 SCTP_INP_RUNLOCK(inp);
1958 } else {
1959 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
1960 error = EINVAL;
1961 }
1962 }
1963 if (error == 0) {
1964 *optsize = sizeof(struct sctp_assoc_value);
1965 }
1966 break;
1967 }
1968 case SCTP_VRF_ID:
1969 {
1970 uint32_t *default_vrfid;
1971
1972 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, *optsize);
1973 *default_vrfid = inp->def_vrf_id;
1974 *optsize = sizeof(uint32_t);
1975 break;
1976 }
1977 case SCTP_GET_ASOC_VRF:
1978 {
1979 struct sctp_assoc_value *id;
1980
1981 SCTP_CHECK_AND_CAST(id, optval, struct sctp_assoc_value, *optsize);
1982 SCTP_FIND_STCB(inp, stcb, id->assoc_id);
1983 if (stcb == NULL) {
1984 error = EINVAL;
1985 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
1986 } else {
1987 id->assoc_value = stcb->asoc.vrf_id;
1988 *optsize = sizeof(struct sctp_assoc_value);
1989 }
1990 break;
1991 }
1992 case SCTP_GET_VRF_IDS:
1993 {
1994 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
1995 error = EOPNOTSUPP;
1996 break;
1997 }
1998 case SCTP_GET_NONCE_VALUES:
1999 {
2000 struct sctp_get_nonce_values *gnv;
2001
2002 SCTP_CHECK_AND_CAST(gnv, optval, struct sctp_get_nonce_values, *optsize);
2003 SCTP_FIND_STCB(inp, stcb, gnv->gn_assoc_id);
2004
2005 if (stcb) {
2006 gnv->gn_peers_tag = stcb->asoc.peer_vtag;
2007 gnv->gn_local_tag = stcb->asoc.my_vtag;
2008 SCTP_TCB_UNLOCK(stcb);
2009 *optsize = sizeof(struct sctp_get_nonce_values);
2010 } else {
2011 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2012 error = ENOTCONN;
2013 }
2014 break;
2015 }
2016 case SCTP_DELAYED_SACK:
2017 {
2018 struct sctp_sack_info *sack;
2019
2020 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, *optsize);
2021 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
2022 if (stcb) {
2023 sack->sack_delay = stcb->asoc.delayed_ack;
2024 sack->sack_freq = stcb->asoc.sack_freq;
2025 SCTP_TCB_UNLOCK(stcb);
2026 } else {
2027 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2028 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2029 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC)) {
2030 SCTP_INP_RLOCK(inp);
2031 sack->sack_delay = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV]);
2032 sack->sack_freq = inp->sctp_ep.sctp_sack_freq;
2033 SCTP_INP_RUNLOCK(inp);
2034 } else {
2035 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2036 error = EINVAL;
2037 }
2038 }
2039 if (error == 0) {
2040 *optsize = sizeof(struct sctp_sack_info);
2041 }
2042 break;
2043 }
2044 case SCTP_GET_SNDBUF_USE:
2045 {
2046 struct sctp_sockstat *ss;
2047
2048 SCTP_CHECK_AND_CAST(ss, optval, struct sctp_sockstat, *optsize);
2049 SCTP_FIND_STCB(inp, stcb, ss->ss_assoc_id);
2050
2051 if (stcb) {
2052 ss->ss_total_sndbuf = stcb->asoc.total_output_queue_size;
2053 ss->ss_total_recv_buf = (stcb->asoc.size_on_reasm_queue +
2054 stcb->asoc.size_on_all_streams);
2055 SCTP_TCB_UNLOCK(stcb);
2056 *optsize = sizeof(struct sctp_sockstat);
2057 } else {
2058 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2059 error = ENOTCONN;
2060 }
2061 break;
2062 }
2063 case SCTP_MAX_BURST:
2064 {
2065 struct sctp_assoc_value *av;
2066
2067 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2068 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2069
2070 if (stcb) {
2071 av->assoc_value = stcb->asoc.max_burst;
2072 SCTP_TCB_UNLOCK(stcb);
2073 } else {
2074 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2075 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2076 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2077 SCTP_INP_RLOCK(inp);
2078 av->assoc_value = inp->sctp_ep.max_burst;
2079 SCTP_INP_RUNLOCK(inp);
2080 } else {
2081 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2082 error = EINVAL;
2083 }
2084 }
2085 if (error == 0) {
2086 *optsize = sizeof(struct sctp_assoc_value);
2087 }
2088 break;
2089 }
2090 case SCTP_MAXSEG:
2091 {
2092 struct sctp_assoc_value *av;
2093 int ovh;
2094
2095 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
2096 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
2097
2098 if (stcb) {
2099 av->assoc_value = sctp_get_frag_point(stcb, &stcb->asoc);
2100 SCTP_TCB_UNLOCK(stcb);
2101 } else {
2102 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2103 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2104 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
2105 SCTP_INP_RLOCK(inp);
2106 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2107 ovh = SCTP_MED_OVERHEAD;
2108 } else {
2109 ovh = SCTP_MED_V4_OVERHEAD;
2110 }
2111 if (inp->sctp_frag_point >= SCTP_DEFAULT_MAXSEGMENT)
2112 av->assoc_value = 0;
2113 else
2114 av->assoc_value = inp->sctp_frag_point - ovh;
2115 SCTP_INP_RUNLOCK(inp);
2116 } else {
2117 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2118 error = EINVAL;
2119 }
2120 }
2121 if (error == 0) {
2122 *optsize = sizeof(struct sctp_assoc_value);
2123 }
2124 break;
2125 }
2126 case SCTP_GET_STAT_LOG:
2127 error = sctp_fill_stat_log(optval, optsize);
2128 break;
2129 case SCTP_EVENTS:
2130 {
2131 struct sctp_event_subscribe *events;
2132
2133 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, *optsize);
2134 memset(events, 0, sizeof(struct sctp_event_subscribe));
2135 SCTP_INP_RLOCK(inp);
2136 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT))
2137 events->sctp_data_io_event = 1;
2138
2139 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT))
2140 events->sctp_association_event = 1;
2141
2142 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT))
2143 events->sctp_address_event = 1;
2144
2145 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT))
2146 events->sctp_send_failure_event = 1;
2147
2148 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR))
2149 events->sctp_peer_error_event = 1;
2150
2151 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT))
2152 events->sctp_shutdown_event = 1;
2153
2154 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT))
2155 events->sctp_partial_delivery_event = 1;
2156
2157 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT))
2158 events->sctp_adaptation_layer_event = 1;
2159
2160 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT))
2161 events->sctp_authentication_event = 1;
2162
2163 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT))
2164 events->sctp_sender_dry_event = 1;
2165
2166 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT))
2167 events->sctp_stream_reset_event = 1;
2168 SCTP_INP_RUNLOCK(inp);
2169 *optsize = sizeof(struct sctp_event_subscribe);
2170 break;
2171 }
2172 case SCTP_ADAPTATION_LAYER:
2173 {
2174 uint32_t *value;
2175
2176 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2177
2178 SCTP_INP_RLOCK(inp);
2179 *value = inp->sctp_ep.adaptation_layer_indicator;
2180 SCTP_INP_RUNLOCK(inp);
2181 *optsize = sizeof(uint32_t);
2182 break;
2183 }
2184 case SCTP_SET_INITIAL_DBG_SEQ:
2185 {
2186 uint32_t *value;
2187
2188 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2189 SCTP_INP_RLOCK(inp);
2190 *value = inp->sctp_ep.initial_sequence_debug;
2191 SCTP_INP_RUNLOCK(inp);
2192 *optsize = sizeof(uint32_t);
2193 break;
2194 }
2195 case SCTP_GET_LOCAL_ADDR_SIZE:
2196 {
2197 uint32_t *value;
2198
2199 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2200 SCTP_INP_RLOCK(inp);
2201 *value = sctp_count_max_addresses(inp);
2202 SCTP_INP_RUNLOCK(inp);
2203 *optsize = sizeof(uint32_t);
2204 break;
2205 }
2206 case SCTP_GET_REMOTE_ADDR_SIZE:
2207 {
2208 uint32_t *value;
2209 size_t size;
2210 struct sctp_nets *net;
2211
2212 SCTP_CHECK_AND_CAST(value, optval, uint32_t, *optsize);
2213 /* FIXME MT: change to sctp_assoc_value? */
2214 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
2215
2216 if (stcb) {
2217 size = 0;
2218 /* Count the sizes */
2219 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2220 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2221 size += sizeof(struct sockaddr_in6);
2222 } else {
2223 switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2224 #ifdef INET
2225 case AF_INET:
2226 size += sizeof(struct sockaddr_in);
2227 break;
2228 #endif
2229 #ifdef INET6
2230 case AF_INET6:
2231 size += sizeof(struct sockaddr_in6);
2232 break;
2233 #endif
2234 default:
2235 break;
2236 }
2237 }
2238 }
2239 SCTP_TCB_UNLOCK(stcb);
2240 *value = (uint32_t) size;
2241 *optsize = sizeof(uint32_t);
2242 } else {
2243 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
2244 error = ENOTCONN;
2245 }
2246 break;
2247 }
2248 case SCTP_GET_PEER_ADDRESSES:
2249 /*
2250 * Get the address information, an array is passed in to
2251 * fill up we pack it.
2252 */
2253 {
2254 size_t cpsz, left;
2255 struct sockaddr_storage *sas;
2256 struct sctp_nets *net;
2257 struct sctp_getaddresses *saddr;
2258
2259 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2260 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2261
2262 if (stcb) {
2263 left = (*optsize) - sizeof(struct sctp_getaddresses);
2264 *optsize = sizeof(struct sctp_getaddresses);
2265 sas = (struct sockaddr_storage *)&saddr->addr[0];
2266
2267 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
2268 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) {
2269 cpsz = sizeof(struct sockaddr_in6);
2270 } else {
2271 switch (((struct sockaddr *)&net->ro._l_addr)->sa_family) {
2272 #ifdef INET
2273 case AF_INET:
2274 cpsz = sizeof(struct sockaddr_in);
2275 break;
2276 #endif
2277 #ifdef INET6
2278 case AF_INET6:
2279 cpsz = sizeof(struct sockaddr_in6);
2280 break;
2281 #endif
2282 default:
2283 cpsz = 0;
2284 break;
2285 }
2286 }
2287 if (cpsz == 0) {
2288 break;
2289 }
2290 if (left < cpsz) {
2291 /* not enough room. */
2292 break;
2293 }
2294 #if defined(INET) && defined(INET6)
2295 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_NEEDS_MAPPED_V4)) &&
2296 (((struct sockaddr *)&net->ro._l_addr)->sa_family == AF_INET)) {
2297 /* Must map the address */
2298 in6_sin_2_v4mapsin6((struct sockaddr_in *)&net->ro._l_addr,
2299 (struct sockaddr_in6 *)sas);
2300 } else {
2301 #endif
2302 memcpy(sas, &net->ro._l_addr, cpsz);
2303 #if defined(INET) && defined(INET6)
2304 }
2305 #endif
2306 ((struct sockaddr_in *)sas)->sin_port = stcb->rport;
2307
2308 sas = (struct sockaddr_storage *)((caddr_t)sas + cpsz);
2309 left -= cpsz;
2310 *optsize += cpsz;
2311 }
2312 SCTP_TCB_UNLOCK(stcb);
2313 } else {
2314 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2315 error = ENOENT;
2316 }
2317 break;
2318 }
2319 case SCTP_GET_LOCAL_ADDRESSES:
2320 {
2321 size_t limit, actual;
2322 struct sockaddr_storage *sas;
2323 struct sctp_getaddresses *saddr;
2324
2325 SCTP_CHECK_AND_CAST(saddr, optval, struct sctp_getaddresses, *optsize);
2326 SCTP_FIND_STCB(inp, stcb, saddr->sget_assoc_id);
2327
2328 sas = (struct sockaddr_storage *)&saddr->addr[0];
2329 limit = *optsize - sizeof(sctp_assoc_t);
2330 actual = sctp_fill_up_addresses(inp, stcb, limit, sas);
2331 if (stcb) {
2332 SCTP_TCB_UNLOCK(stcb);
2333 }
2334 *optsize = sizeof(struct sockaddr_storage) + actual;
2335 break;
2336 }
2337 case SCTP_PEER_ADDR_PARAMS:
2338 {
2339 struct sctp_paddrparams *paddrp;
2340 struct sctp_nets *net;
2341
2342 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, *optsize);
2343 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
2344
2345 net = NULL;
2346 if (stcb) {
2347 net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
2348 } else {
2349 /*
2350 * We increment here since
2351 * sctp_findassociation_ep_addr() wil do a
2352 * decrement if it finds the stcb as long as
2353 * the locked tcb (last argument) is NOT a
2354 * TCB.. aka NULL.
2355 */
2356 SCTP_INP_INCR_REF(inp);
2357 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddrp->spp_address, &net, NULL, NULL);
2358 if (stcb == NULL) {
2359 SCTP_INP_DECR_REF(inp);
2360 }
2361 }
2362 if (stcb && (net == NULL)) {
2363 struct sockaddr *sa;
2364
2365 sa = (struct sockaddr *)&paddrp->spp_address;
2366 #ifdef INET
2367 if (sa->sa_family == AF_INET) {
2368 struct sockaddr_in *sin;
2369
2370 sin = (struct sockaddr_in *)sa;
2371 if (sin->sin_addr.s_addr) {
2372 error = EINVAL;
2373 SCTP_TCB_UNLOCK(stcb);
2374 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2375 break;
2376 }
2377 } else
2378 #endif
2379 #ifdef INET6
2380 if (sa->sa_family == AF_INET6) {
2381 struct sockaddr_in6 *sin6;
2382
2383 sin6 = (struct sockaddr_in6 *)sa;
2384 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
2385 error = EINVAL;
2386 SCTP_TCB_UNLOCK(stcb);
2387 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2388 break;
2389 }
2390 } else
2391 #endif
2392 {
2393 error = EAFNOSUPPORT;
2394 SCTP_TCB_UNLOCK(stcb);
2395 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2396 break;
2397 }
2398 }
2399 if (stcb) {
2400 /* Applies to the specific association */
2401 paddrp->spp_flags = 0;
2402 if (net) {
2403 int ovh;
2404
2405 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
2406 ovh = SCTP_MED_OVERHEAD;
2407 } else {
2408 ovh = SCTP_MED_V4_OVERHEAD;
2409 }
2410
2411 paddrp->spp_hbinterval = net->heart_beat_delay;
2412 paddrp->spp_pathmaxrxt = net->failure_threshold;
2413 paddrp->spp_pathmtu = net->mtu - ovh;
2414 /* get flags for HB */
2415 if (net->dest_state & SCTP_ADDR_NOHB) {
2416 paddrp->spp_flags |= SPP_HB_DISABLE;
2417 } else {
2418 paddrp->spp_flags |= SPP_HB_ENABLE;
2419 }
2420 /* get flags for PMTU */
2421 if (net->dest_state & SCTP_ADDR_NO_PMTUD) {
2422 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2423 } else {
2424 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2425 }
2426 if (net->dscp & 0x01) {
2427 paddrp->spp_dscp = net->dscp & 0xfc;
2428 paddrp->spp_flags |= SPP_DSCP;
2429 }
2430 #ifdef INET6
2431 if ((net->ro._l_addr.sa.sa_family == AF_INET6) &&
2432 (net->flowlabel & 0x80000000)) {
2433 paddrp->spp_ipv6_flowlabel = net->flowlabel & 0x000fffff;
2434 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2435 }
2436 #endif
2437 } else {
2438 /*
2439 * No destination so return default
2440 * value
2441 */
2442 paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
2443 paddrp->spp_pathmtu = sctp_get_frag_point(stcb, &stcb->asoc);
2444 if (stcb->asoc.default_dscp & 0x01) {
2445 paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
2446 paddrp->spp_flags |= SPP_DSCP;
2447 }
2448 #ifdef INET6
2449 if (stcb->asoc.default_flowlabel & 0x80000000) {
2450 paddrp->spp_ipv6_flowlabel = stcb->asoc.default_flowlabel & 0x000fffff;
2451 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2452 }
2453 #endif
2454 /* default settings should be these */
2455 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2456 paddrp->spp_flags |= SPP_HB_DISABLE;
2457 } else {
2458 paddrp->spp_flags |= SPP_HB_ENABLE;
2459 }
2460 if (sctp_stcb_is_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2461 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2462 } else {
2463 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2464 }
2465 paddrp->spp_hbinterval = stcb->asoc.heart_beat_delay;
2466 }
2467 paddrp->spp_assoc_id = sctp_get_associd(stcb);
2468 SCTP_TCB_UNLOCK(stcb);
2469 } else {
2470 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2471 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2472 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
2473 /* Use endpoint defaults */
2474 SCTP_INP_RLOCK(inp);
2475 paddrp->spp_pathmaxrxt = inp->sctp_ep.def_net_failure;
2476 paddrp->spp_hbinterval = TICKS_TO_MSEC(inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT]);
2477 paddrp->spp_assoc_id = SCTP_FUTURE_ASSOC;
2478 /* get inp's default */
2479 if (inp->sctp_ep.default_dscp & 0x01) {
2480 paddrp->spp_dscp = inp->sctp_ep.default_dscp & 0xfc;
2481 paddrp->spp_flags |= SPP_DSCP;
2482 }
2483 #ifdef INET6
2484 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) &&
2485 (inp->sctp_ep.default_flowlabel & 0x80000000)) {
2486 paddrp->spp_ipv6_flowlabel = inp->sctp_ep.default_flowlabel & 0x000fffff;
2487 paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
2488 }
2489 #endif
2490 /* can't return this */
2491 paddrp->spp_pathmtu = 0;
2492
2493 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
2494 paddrp->spp_flags |= SPP_HB_ENABLE;
2495 } else {
2496 paddrp->spp_flags |= SPP_HB_DISABLE;
2497 }
2498 if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD)) {
2499 paddrp->spp_flags |= SPP_PMTUD_ENABLE;
2500 } else {
2501 paddrp->spp_flags |= SPP_PMTUD_DISABLE;
2502 }
2503 SCTP_INP_RUNLOCK(inp);
2504 } else {
2505 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2506 error = EINVAL;
2507 }
2508 }
2509 if (error == 0) {
2510 *optsize = sizeof(struct sctp_paddrparams);
2511 }
2512 break;
2513 }
2514 case SCTP_GET_PEER_ADDR_INFO:
2515 {
2516 struct sctp_paddrinfo *paddri;
2517 struct sctp_nets *net;
2518
2519 SCTP_CHECK_AND_CAST(paddri, optval, struct sctp_paddrinfo, *optsize);
2520 SCTP_FIND_STCB(inp, stcb, paddri->spinfo_assoc_id);
2521
2522 net = NULL;
2523 if (stcb) {
2524 net = sctp_findnet(stcb, (struct sockaddr *)&paddri->spinfo_address);
2525 } else {
2526 /*
2527 * We increment here since
2528 * sctp_findassociation_ep_addr() wil do a
2529 * decrement if it finds the stcb as long as
2530 * the locked tcb (last argument) is NOT a
2531 * TCB.. aka NULL.
2532 */
2533 SCTP_INP_INCR_REF(inp);
2534 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&paddri->spinfo_address, &net, NULL, NULL);
2535 if (stcb == NULL) {
2536 SCTP_INP_DECR_REF(inp);
2537 }
2538 }
2539
2540 if ((stcb) && (net)) {
2541 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2542 /* It's unconfirmed */
2543 paddri->spinfo_state = SCTP_UNCONFIRMED;
2544 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2545 /* It's active */
2546 paddri->spinfo_state = SCTP_ACTIVE;
2547 } else {
2548 /* It's inactive */
2549 paddri->spinfo_state = SCTP_INACTIVE;
2550 }
2551 paddri->spinfo_cwnd = net->cwnd;
2552 paddri->spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2553 paddri->spinfo_rto = net->RTO;
2554 paddri->spinfo_assoc_id = sctp_get_associd(stcb);
2555 paddri->spinfo_mtu = net->mtu;
2556 SCTP_TCB_UNLOCK(stcb);
2557 *optsize = sizeof(struct sctp_paddrinfo);
2558 } else {
2559 if (stcb) {
2560 SCTP_TCB_UNLOCK(stcb);
2561 }
2562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2563 error = ENOENT;
2564 }
2565 break;
2566 }
2567 case SCTP_PCB_STATUS:
2568 {
2569 struct sctp_pcbinfo *spcb;
2570
2571 SCTP_CHECK_AND_CAST(spcb, optval, struct sctp_pcbinfo, *optsize);
2572 sctp_fill_pcbinfo(spcb);
2573 *optsize = sizeof(struct sctp_pcbinfo);
2574 break;
2575 }
2576 case SCTP_STATUS:
2577 {
2578 struct sctp_nets *net;
2579 struct sctp_status *sstat;
2580
2581 SCTP_CHECK_AND_CAST(sstat, optval, struct sctp_status, *optsize);
2582 SCTP_FIND_STCB(inp, stcb, sstat->sstat_assoc_id);
2583
2584 if (stcb == NULL) {
2585 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2586 error = EINVAL;
2587 break;
2588 }
2589 /*
2590 * I think passing the state is fine since
2591 * sctp_constants.h will be available to the user
2592 * land.
2593 */
2594 sstat->sstat_state = stcb->asoc.state;
2595 sstat->sstat_assoc_id = sctp_get_associd(stcb);
2596 sstat->sstat_rwnd = stcb->asoc.peers_rwnd;
2597 sstat->sstat_unackdata = stcb->asoc.sent_queue_cnt;
2598 /*
2599 * We can't include chunks that have been passed to
2600 * the socket layer. Only things in queue.
2601 */
2602 sstat->sstat_penddata = (stcb->asoc.cnt_on_reasm_queue +
2603 stcb->asoc.cnt_on_all_streams);
2604
2605
2606 sstat->sstat_instrms = stcb->asoc.streamincnt;
2607 sstat->sstat_outstrms = stcb->asoc.streamoutcnt;
2608 sstat->sstat_fragmentation_point = sctp_get_frag_point(stcb, &stcb->asoc);
2609 memcpy(&sstat->sstat_primary.spinfo_address,
2610 &stcb->asoc.primary_destination->ro._l_addr,
2611 ((struct sockaddr *)(&stcb->asoc.primary_destination->ro._l_addr))->sa_len);
2612 net = stcb->asoc.primary_destination;
2613 ((struct sockaddr_in *)&sstat->sstat_primary.spinfo_address)->sin_port = stcb->rport;
2614 /*
2615 * Again the user can get info from sctp_constants.h
2616 * for what the state of the network is.
2617 */
2618 if (net->dest_state & SCTP_ADDR_UNCONFIRMED) {
2619 /* It's unconfirmed */
2620 sstat->sstat_primary.spinfo_state = SCTP_UNCONFIRMED;
2621 } else if (net->dest_state & SCTP_ADDR_REACHABLE) {
2622 /* It's active */
2623 sstat->sstat_primary.spinfo_state = SCTP_ACTIVE;
2624 } else {
2625 /* It's inactive */
2626 sstat->sstat_primary.spinfo_state = SCTP_INACTIVE;
2627 }
2628 sstat->sstat_primary.spinfo_cwnd = net->cwnd;
2629 sstat->sstat_primary.spinfo_srtt = net->lastsa >> SCTP_RTT_SHIFT;
2630 sstat->sstat_primary.spinfo_rto = net->RTO;
2631 sstat->sstat_primary.spinfo_mtu = net->mtu;
2632 sstat->sstat_primary.spinfo_assoc_id = sctp_get_associd(stcb);
2633 SCTP_TCB_UNLOCK(stcb);
2634 *optsize = sizeof(struct sctp_status);
2635 break;
2636 }
2637 case SCTP_RTOINFO:
2638 {
2639 struct sctp_rtoinfo *srto;
2640
2641 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, *optsize);
2642 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
2643
2644 if (stcb) {
2645 srto->srto_initial = stcb->asoc.initial_rto;
2646 srto->srto_max = stcb->asoc.maxrto;
2647 srto->srto_min = stcb->asoc.minrto;
2648 SCTP_TCB_UNLOCK(stcb);
2649 } else {
2650 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2651 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2652 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
2653 SCTP_INP_RLOCK(inp);
2654 srto->srto_initial = inp->sctp_ep.initial_rto;
2655 srto->srto_max = inp->sctp_ep.sctp_maxrto;
2656 srto->srto_min = inp->sctp_ep.sctp_minrto;
2657 SCTP_INP_RUNLOCK(inp);
2658 } else {
2659 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2660 error = EINVAL;
2661 }
2662 }
2663 if (error == 0) {
2664 *optsize = sizeof(struct sctp_rtoinfo);
2665 }
2666 break;
2667 }
2668 case SCTP_TIMEOUTS:
2669 {
2670 struct sctp_timeouts *stimo;
2671
2672 SCTP_CHECK_AND_CAST(stimo, optval, struct sctp_timeouts, *optsize);
2673 SCTP_FIND_STCB(inp, stcb, stimo->stimo_assoc_id);
2674
2675 if (stcb) {
2676 stimo->stimo_init = stcb->asoc.timoinit;
2677 stimo->stimo_data = stcb->asoc.timodata;
2678 stimo->stimo_sack = stcb->asoc.timosack;
2679 stimo->stimo_shutdown = stcb->asoc.timoshutdown;
2680 stimo->stimo_heartbeat = stcb->asoc.timoheartbeat;
2681 stimo->stimo_cookie = stcb->asoc.timocookie;
2682 stimo->stimo_shutdownack = stcb->asoc.timoshutdownack;
2683 SCTP_TCB_UNLOCK(stcb);
2684 *optsize = sizeof(struct sctp_timeouts);
2685 } else {
2686 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2687 error = EINVAL;
2688 }
2689 break;
2690 }
2691 case SCTP_ASSOCINFO:
2692 {
2693 struct sctp_assocparams *sasoc;
2694
2695 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, *optsize);
2696 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
2697
2698 if (stcb) {
2699 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(stcb->asoc.cookie_life);
2700 sasoc->sasoc_asocmaxrxt = stcb->asoc.max_send_times;
2701 sasoc->sasoc_number_peer_destinations = stcb->asoc.numnets;
2702 sasoc->sasoc_peer_rwnd = stcb->asoc.peers_rwnd;
2703 sasoc->sasoc_local_rwnd = stcb->asoc.my_rwnd;
2704 SCTP_TCB_UNLOCK(stcb);
2705 } else {
2706 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2707 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2708 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
2709 SCTP_INP_RLOCK(inp);
2710 sasoc->sasoc_cookie_life = TICKS_TO_MSEC(inp->sctp_ep.def_cookie_life);
2711 sasoc->sasoc_asocmaxrxt = inp->sctp_ep.max_send_times;
2712 sasoc->sasoc_number_peer_destinations = 0;
2713 sasoc->sasoc_peer_rwnd = 0;
2714 sasoc->sasoc_local_rwnd = sbspace(&inp->sctp_socket->so_rcv);
2715 SCTP_INP_RUNLOCK(inp);
2716 } else {
2717 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2718 error = EINVAL;
2719 }
2720 }
2721 if (error == 0) {
2722 *optsize = sizeof(struct sctp_assocparams);
2723 }
2724 break;
2725 }
2726 case SCTP_DEFAULT_SEND_PARAM:
2727 {
2728 struct sctp_sndrcvinfo *s_info;
2729
2730 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, *optsize);
2731 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
2732
2733 if (stcb) {
2734 memcpy(s_info, &stcb->asoc.def_send, sizeof(stcb->asoc.def_send));
2735 SCTP_TCB_UNLOCK(stcb);
2736 } else {
2737 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2738 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2739 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC)) {
2740 SCTP_INP_RLOCK(inp);
2741 memcpy(s_info, &inp->def_send, sizeof(inp->def_send));
2742 SCTP_INP_RUNLOCK(inp);
2743 } else {
2744 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2745 error = EINVAL;
2746 }
2747 }
2748 if (error == 0) {
2749 *optsize = sizeof(struct sctp_sndrcvinfo);
2750 }
2751 break;
2752 }
2753 case SCTP_INITMSG:
2754 {
2755 struct sctp_initmsg *sinit;
2756
2757 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, *optsize);
2758 SCTP_INP_RLOCK(inp);
2759 sinit->sinit_num_ostreams = inp->sctp_ep.pre_open_stream_count;
2760 sinit->sinit_max_instreams = inp->sctp_ep.max_open_streams_intome;
2761 sinit->sinit_max_attempts = inp->sctp_ep.max_init_times;
2762 sinit->sinit_max_init_timeo = inp->sctp_ep.initial_init_rto_max;
2763 SCTP_INP_RUNLOCK(inp);
2764 *optsize = sizeof(struct sctp_initmsg);
2765 break;
2766 }
2767 case SCTP_PRIMARY_ADDR:
2768 /* we allow a "get" operation on this */
2769 {
2770 struct sctp_setprim *ssp;
2771
2772 SCTP_CHECK_AND_CAST(ssp, optval, struct sctp_setprim, *optsize);
2773 SCTP_FIND_STCB(inp, stcb, ssp->ssp_assoc_id);
2774
2775 if (stcb) {
2776 /* simply copy out the sockaddr_storage... */
2777 size_t len;
2778
2779 len = *optsize;
2780 if (len > stcb->asoc.primary_destination->ro._l_addr.sa.sa_len)
2781 len = stcb->asoc.primary_destination->ro._l_addr.sa.sa_len;
2782
2783 memcpy(&ssp->ssp_addr,
2784 &stcb->asoc.primary_destination->ro._l_addr,
2785 len);
2786 SCTP_TCB_UNLOCK(stcb);
2787 *optsize = sizeof(struct sctp_setprim);
2788 } else {
2789 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2790 error = EINVAL;
2791 }
2792 break;
2793 }
2794 case SCTP_HMAC_IDENT:
2795 {
2796 struct sctp_hmacalgo *shmac;
2797 sctp_hmaclist_t *hmaclist;
2798 uint32_t size;
2799 int i;
2800
2801 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, *optsize);
2802
2803 SCTP_INP_RLOCK(inp);
2804 hmaclist = inp->sctp_ep.local_hmacs;
2805 if (hmaclist == NULL) {
2806 /* no HMACs to return */
2807 *optsize = sizeof(*shmac);
2808 SCTP_INP_RUNLOCK(inp);
2809 break;
2810 }
2811 /* is there room for all of the hmac ids? */
2812 size = sizeof(*shmac) + (hmaclist->num_algo *
2813 sizeof(shmac->shmac_idents[0]));
2814 if ((size_t)(*optsize) < size) {
2815 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2816 error = EINVAL;
2817 SCTP_INP_RUNLOCK(inp);
2818 break;
2819 }
2820 /* copy in the list */
2821 shmac->shmac_number_of_idents = hmaclist->num_algo;
2822 for (i = 0; i < hmaclist->num_algo; i++) {
2823 shmac->shmac_idents[i] = hmaclist->hmac[i];
2824 }
2825 SCTP_INP_RUNLOCK(inp);
2826 *optsize = size;
2827 break;
2828 }
2829 case SCTP_AUTH_ACTIVE_KEY:
2830 {
2831 struct sctp_authkeyid *scact;
2832
2833 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, *optsize);
2834 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
2835
2836 if (stcb) {
2837 /* get the active key on the assoc */
2838 scact->scact_keynumber = stcb->asoc.authinfo.active_keyid;
2839 SCTP_TCB_UNLOCK(stcb);
2840 } else {
2841 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2842 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2843 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC)) {
2844 /* get the endpoint active key */
2845 SCTP_INP_RLOCK(inp);
2846 scact->scact_keynumber = inp->sctp_ep.default_keyid;
2847 SCTP_INP_RUNLOCK(inp);
2848 } else {
2849 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2850 error = EINVAL;
2851 }
2852 }
2853 if (error == 0) {
2854 *optsize = sizeof(struct sctp_authkeyid);
2855 }
2856 break;
2857 }
2858 case SCTP_LOCAL_AUTH_CHUNKS:
2859 {
2860 struct sctp_authchunks *sac;
2861 sctp_auth_chklist_t *chklist = NULL;
2862 size_t size = 0;
2863
2864 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2865 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2866
2867 if (stcb) {
2868 /* get off the assoc */
2869 chklist = stcb->asoc.local_auth_chunks;
2870 /* is there enough space? */
2871 size = sctp_auth_get_chklist_size(chklist);
2872 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2873 error = EINVAL;
2874 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2875 } else {
2876 /* copy in the chunks */
2877 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2878 sac->gauth_number_of_chunks = (uint32_t) size;
2879 *optsize = sizeof(struct sctp_authchunks) + size;
2880 }
2881 SCTP_TCB_UNLOCK(stcb);
2882 } else {
2883 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
2884 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
2885 (sac->gauth_assoc_id == SCTP_FUTURE_ASSOC)) {
2886 /* get off the endpoint */
2887 SCTP_INP_RLOCK(inp);
2888 chklist = inp->sctp_ep.local_auth_chunks;
2889 /* is there enough space? */
2890 size = sctp_auth_get_chklist_size(chklist);
2891 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2892 error = EINVAL;
2893 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2894 } else {
2895 /* copy in the chunks */
2896 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2897 sac->gauth_number_of_chunks = (uint32_t) size;
2898 *optsize = sizeof(struct sctp_authchunks) + size;
2899 }
2900 SCTP_INP_RUNLOCK(inp);
2901 } else {
2902 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2903 error = EINVAL;
2904 }
2905 }
2906 break;
2907 }
2908 case SCTP_PEER_AUTH_CHUNKS:
2909 {
2910 struct sctp_authchunks *sac;
2911 sctp_auth_chklist_t *chklist = NULL;
2912 size_t size = 0;
2913
2914 SCTP_CHECK_AND_CAST(sac, optval, struct sctp_authchunks, *optsize);
2915 SCTP_FIND_STCB(inp, stcb, sac->gauth_assoc_id);
2916
2917 if (stcb) {
2918 /* get off the assoc */
2919 chklist = stcb->asoc.peer_auth_chunks;
2920 /* is there enough space? */
2921 size = sctp_auth_get_chklist_size(chklist);
2922 if (*optsize < (sizeof(struct sctp_authchunks) + size)) {
2923 error = EINVAL;
2924 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
2925 } else {
2926 /* copy in the chunks */
2927 (void)sctp_serialize_auth_chunks(chklist, sac->gauth_chunks);
2928 sac->gauth_number_of_chunks = (uint32_t) size;
2929 *optsize = sizeof(struct sctp_authchunks) + size;
2930 }
2931 SCTP_TCB_UNLOCK(stcb);
2932 } else {
2933 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
2934 error = ENOENT;
2935 }
2936 break;
2937 }
2938 case SCTP_EVENT:
2939 {
2940 struct sctp_event *event;
2941 uint32_t event_type;
2942
2943 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, *optsize);
2944 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
2945
2946 switch (event->se_type) {
2947 case SCTP_ASSOC_CHANGE:
2948 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
2949 break;
2950 case SCTP_PEER_ADDR_CHANGE:
2951 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
2952 break;
2953 case SCTP_REMOTE_ERROR:
2954 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
2955 break;
2956 case SCTP_SEND_FAILED:
2957 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
2958 break;
2959 case SCTP_SHUTDOWN_EVENT:
2960 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
2961 break;
2962 case SCTP_ADAPTATION_INDICATION:
2963 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
2964 break;
2965 case SCTP_PARTIAL_DELIVERY_EVENT:
2966 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
2967 break;
2968 case SCTP_AUTHENTICATION_EVENT:
2969 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
2970 break;
2971 case SCTP_STREAM_RESET_EVENT:
2972 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
2973 break;
2974 case SCTP_SENDER_DRY_EVENT:
2975 event_type = SCTP_PCB_FLAGS_DRYEVNT;
2976 break;
2977 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
2978 event_type = 0;
2979 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
2980 error = ENOTSUP;
2981 break;
2982 case SCTP_ASSOC_RESET_EVENT:
2983 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
2984 break;
2985 case SCTP_STREAM_CHANGE_EVENT:
2986 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
2987 break;
2988 case SCTP_SEND_FAILED_EVENT:
2989 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
2990 break;
2991 default:
2992 event_type = 0;
2993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
2994 error = EINVAL;
2995 break;
2996 }
2997 if (event_type > 0) {
2998 if (stcb) {
2999 event->se_on = sctp_stcb_is_feature_on(inp, stcb, event_type);
3000 SCTP_TCB_UNLOCK(stcb);
3001 } else {
3002 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3003 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3004 (event->se_assoc_id == SCTP_FUTURE_ASSOC)) {
3005 SCTP_INP_RLOCK(inp);
3006 event->se_on = sctp_is_feature_on(inp, event_type);
3007 SCTP_INP_RUNLOCK(inp);
3008 } else {
3009 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3010 error = EINVAL;
3011 }
3012 }
3013 }
3014 if (error == 0) {
3015 *optsize = sizeof(struct sctp_event);
3016 }
3017 break;
3018 }
3019 case SCTP_RECVRCVINFO:
3020 {
3021 int onoff;
3022
3023 if (*optsize < sizeof(int)) {
3024 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3025 error = EINVAL;
3026 } else {
3027 SCTP_INP_RLOCK(inp);
3028 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
3029 SCTP_INP_RUNLOCK(inp);
3030 }
3031 if (error == 0) {
3032 /* return the option value */
3033 *(int *)optval = onoff;
3034 *optsize = sizeof(int);
3035 }
3036 break;
3037 }
3038 case SCTP_RECVNXTINFO:
3039 {
3040 int onoff;
3041
3042 if (*optsize < sizeof(int)) {
3043 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3044 error = EINVAL;
3045 } else {
3046 SCTP_INP_RLOCK(inp);
3047 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
3048 SCTP_INP_RUNLOCK(inp);
3049 }
3050 if (error == 0) {
3051 /* return the option value */
3052 *(int *)optval = onoff;
3053 *optsize = sizeof(int);
3054 }
3055 break;
3056 }
3057 case SCTP_DEFAULT_SNDINFO:
3058 {
3059 struct sctp_sndinfo *info;
3060
3061 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize);
3062 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
3063
3064 if (stcb) {
3065 info->snd_sid = stcb->asoc.def_send.sinfo_stream;
3066 info->snd_flags = stcb->asoc.def_send.sinfo_flags;
3067 info->snd_flags &= 0xfff0;
3068 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid;
3069 info->snd_context = stcb->asoc.def_send.sinfo_context;
3070 SCTP_TCB_UNLOCK(stcb);
3071 } else {
3072 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3073 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3074 (info->snd_assoc_id == SCTP_FUTURE_ASSOC)) {
3075 SCTP_INP_RLOCK(inp);
3076 info->snd_sid = inp->def_send.sinfo_stream;
3077 info->snd_flags = inp->def_send.sinfo_flags;
3078 info->snd_flags &= 0xfff0;
3079 info->snd_ppid = inp->def_send.sinfo_ppid;
3080 info->snd_context = inp->def_send.sinfo_context;
3081 SCTP_INP_RUNLOCK(inp);
3082 } else {
3083 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3084 error = EINVAL;
3085 }
3086 }
3087 if (error == 0) {
3088 *optsize = sizeof(struct sctp_sndinfo);
3089 }
3090 break;
3091 }
3092 case SCTP_DEFAULT_PRINFO:
3093 {
3094 struct sctp_default_prinfo *info;
3095
3096 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize);
3097 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
3098
3099 if (stcb) {
3100 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
3101 info->pr_value = stcb->asoc.def_send.sinfo_timetolive;
3102 SCTP_TCB_UNLOCK(stcb);
3103 } else {
3104 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3105 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3106 (info->pr_assoc_id == SCTP_FUTURE_ASSOC)) {
3107 SCTP_INP_RLOCK(inp);
3108 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
3109 info->pr_value = inp->def_send.sinfo_timetolive;
3110 SCTP_INP_RUNLOCK(inp);
3111 } else {
3112 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3113 error = EINVAL;
3114 }
3115 }
3116 if (error == 0) {
3117 *optsize = sizeof(struct sctp_default_prinfo);
3118 }
3119 break;
3120 }
3121 case SCTP_PEER_ADDR_THLDS:
3122 {
3123 struct sctp_paddrthlds *thlds;
3124 struct sctp_nets *net;
3125
3126 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize);
3127 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
3128
3129 net = NULL;
3130 if (stcb) {
3131 net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
3132 } else {
3133 /*
3134 * We increment here since
3135 * sctp_findassociation_ep_addr() wil do a
3136 * decrement if it finds the stcb as long as
3137 * the locked tcb (last argument) is NOT a
3138 * TCB.. aka NULL.
3139 */
3140 SCTP_INP_INCR_REF(inp);
3141 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&thlds->spt_address, &net, NULL, NULL);
3142 if (stcb == NULL) {
3143 SCTP_INP_DECR_REF(inp);
3144 }
3145 }
3146 if (stcb && (net == NULL)) {
3147 struct sockaddr *sa;
3148
3149 sa = (struct sockaddr *)&thlds->spt_address;
3150 #ifdef INET
3151 if (sa->sa_family == AF_INET) {
3152 struct sockaddr_in *sin;
3153
3154 sin = (struct sockaddr_in *)sa;
3155 if (sin->sin_addr.s_addr) {
3156 error = EINVAL;
3157 SCTP_TCB_UNLOCK(stcb);
3158 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3159 break;
3160 }
3161 } else
3162 #endif
3163 #ifdef INET6
3164 if (sa->sa_family == AF_INET6) {
3165 struct sockaddr_in6 *sin6;
3166
3167 sin6 = (struct sockaddr_in6 *)sa;
3168 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3169 error = EINVAL;
3170 SCTP_TCB_UNLOCK(stcb);
3171 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3172 break;
3173 }
3174 } else
3175 #endif
3176 {
3177 error = EAFNOSUPPORT;
3178 SCTP_TCB_UNLOCK(stcb);
3179 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3180 break;
3181 }
3182 }
3183 if (stcb) {
3184 if (net) {
3185 thlds->spt_pathmaxrxt = net->failure_threshold;
3186 thlds->spt_pathpfthld = net->pf_threshold;
3187 } else {
3188 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure;
3189 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold;
3190 }
3191 thlds->spt_assoc_id = sctp_get_associd(stcb);
3192 SCTP_TCB_UNLOCK(stcb);
3193 } else {
3194 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3195 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3196 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
3197 /* Use endpoint defaults */
3198 SCTP_INP_RLOCK(inp);
3199 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure;
3200 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold;
3201 SCTP_INP_RUNLOCK(inp);
3202 } else {
3203 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3204 error = EINVAL;
3205 }
3206 }
3207 if (error == 0) {
3208 *optsize = sizeof(struct sctp_paddrthlds);
3209 }
3210 break;
3211 }
3212 case SCTP_REMOTE_UDP_ENCAPS_PORT:
3213 {
3214 struct sctp_udpencaps *encaps;
3215 struct sctp_nets *net;
3216
3217 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize);
3218 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
3219
3220 if (stcb) {
3221 net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
3222 } else {
3223 /*
3224 * We increment here since
3225 * sctp_findassociation_ep_addr() wil do a
3226 * decrement if it finds the stcb as long as
3227 * the locked tcb (last argument) is NOT a
3228 * TCB.. aka NULL.
3229 */
3230 net = NULL;
3231 SCTP_INP_INCR_REF(inp);
3232 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
3233 if (stcb == NULL) {
3234 SCTP_INP_DECR_REF(inp);
3235 }
3236 }
3237 if (stcb && (net == NULL)) {
3238 struct sockaddr *sa;
3239
3240 sa = (struct sockaddr *)&encaps->sue_address;
3241 #ifdef INET
3242 if (sa->sa_family == AF_INET) {
3243 struct sockaddr_in *sin;
3244
3245 sin = (struct sockaddr_in *)sa;
3246 if (sin->sin_addr.s_addr) {
3247 error = EINVAL;
3248 SCTP_TCB_UNLOCK(stcb);
3249 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3250 break;
3251 }
3252 } else
3253 #endif
3254 #ifdef INET6
3255 if (sa->sa_family == AF_INET6) {
3256 struct sockaddr_in6 *sin6;
3257
3258 sin6 = (struct sockaddr_in6 *)sa;
3259 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
3260 error = EINVAL;
3261 SCTP_TCB_UNLOCK(stcb);
3262 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3263 break;
3264 }
3265 } else
3266 #endif
3267 {
3268 error = EAFNOSUPPORT;
3269 SCTP_TCB_UNLOCK(stcb);
3270 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
3271 break;
3272 }
3273 }
3274 if (stcb) {
3275 if (net) {
3276 encaps->sue_port = net->port;
3277 } else {
3278 encaps->sue_port = stcb->asoc.port;
3279 }
3280 SCTP_TCB_UNLOCK(stcb);
3281 } else {
3282 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3283 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3284 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
3285 SCTP_INP_RLOCK(inp);
3286 encaps->sue_port = inp->sctp_ep.port;
3287 SCTP_INP_RUNLOCK(inp);
3288 } else {
3289 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3290 error = EINVAL;
3291 }
3292 }
3293 if (error == 0) {
3294 *optsize = sizeof(struct sctp_udpencaps);
3295 }
3296 break;
3297 }
3298 case SCTP_ECN_SUPPORTED:
3299 {
3300 struct sctp_assoc_value *av;
3301
3302 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3303 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3304
3305 if (stcb) {
3306 av->assoc_value = stcb->asoc.ecn_supported;
3307 SCTP_TCB_UNLOCK(stcb);
3308 } else {
3309 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3310 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3311 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3312 SCTP_INP_RLOCK(inp);
3313 av->assoc_value = inp->ecn_supported;
3314 SCTP_INP_RUNLOCK(inp);
3315 } else {
3316 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3317 error = EINVAL;
3318 }
3319 }
3320 if (error == 0) {
3321 *optsize = sizeof(struct sctp_assoc_value);
3322 }
3323 break;
3324 }
3325 case SCTP_PR_SUPPORTED:
3326 {
3327 struct sctp_assoc_value *av;
3328
3329 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3330 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3331
3332 if (stcb) {
3333 av->assoc_value = stcb->asoc.prsctp_supported;
3334 SCTP_TCB_UNLOCK(stcb);
3335 } else {
3336 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3337 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3338 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3339 SCTP_INP_RLOCK(inp);
3340 av->assoc_value = inp->prsctp_supported;
3341 SCTP_INP_RUNLOCK(inp);
3342 } else {
3343 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3344 error = EINVAL;
3345 }
3346 }
3347 if (error == 0) {
3348 *optsize = sizeof(struct sctp_assoc_value);
3349 }
3350 break;
3351 }
3352 case SCTP_AUTH_SUPPORTED:
3353 {
3354 struct sctp_assoc_value *av;
3355
3356 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3357 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3358
3359 if (stcb) {
3360 av->assoc_value = stcb->asoc.auth_supported;
3361 SCTP_TCB_UNLOCK(stcb);
3362 } else {
3363 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3364 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3365 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3366 SCTP_INP_RLOCK(inp);
3367 av->assoc_value = inp->auth_supported;
3368 SCTP_INP_RUNLOCK(inp);
3369 } else {
3370 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3371 error = EINVAL;
3372 }
3373 }
3374 if (error == 0) {
3375 *optsize = sizeof(struct sctp_assoc_value);
3376 }
3377 break;
3378 }
3379 case SCTP_ASCONF_SUPPORTED:
3380 {
3381 struct sctp_assoc_value *av;
3382
3383 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3384 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3385
3386 if (stcb) {
3387 av->assoc_value = stcb->asoc.asconf_supported;
3388 SCTP_TCB_UNLOCK(stcb);
3389 } else {
3390 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3391 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3392 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3393 SCTP_INP_RLOCK(inp);
3394 av->assoc_value = inp->asconf_supported;
3395 SCTP_INP_RUNLOCK(inp);
3396 } else {
3397 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3398 error = EINVAL;
3399 }
3400 }
3401 if (error == 0) {
3402 *optsize = sizeof(struct sctp_assoc_value);
3403 }
3404 break;
3405 }
3406 case SCTP_RECONFIG_SUPPORTED:
3407 {
3408 struct sctp_assoc_value *av;
3409
3410 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3411 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3412
3413 if (stcb) {
3414 av->assoc_value = stcb->asoc.reconfig_supported;
3415 SCTP_TCB_UNLOCK(stcb);
3416 } else {
3417 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3418 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3419 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3420 SCTP_INP_RLOCK(inp);
3421 av->assoc_value = inp->reconfig_supported;
3422 SCTP_INP_RUNLOCK(inp);
3423 } else {
3424 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3425 error = EINVAL;
3426 }
3427 }
3428 if (error == 0) {
3429 *optsize = sizeof(struct sctp_assoc_value);
3430 }
3431 break;
3432 }
3433 case SCTP_NRSACK_SUPPORTED:
3434 {
3435 struct sctp_assoc_value *av;
3436
3437 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3438 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3439
3440 if (stcb) {
3441 av->assoc_value = stcb->asoc.nrsack_supported;
3442 SCTP_TCB_UNLOCK(stcb);
3443 } else {
3444 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3445 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3446 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3447 SCTP_INP_RLOCK(inp);
3448 av->assoc_value = inp->nrsack_supported;
3449 SCTP_INP_RUNLOCK(inp);
3450 } else {
3451 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3452 error = EINVAL;
3453 }
3454 }
3455 if (error == 0) {
3456 *optsize = sizeof(struct sctp_assoc_value);
3457 }
3458 break;
3459 }
3460 case SCTP_PKTDROP_SUPPORTED:
3461 {
3462 struct sctp_assoc_value *av;
3463
3464 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3465 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3466
3467 if (stcb) {
3468 av->assoc_value = stcb->asoc.pktdrop_supported;
3469 SCTP_TCB_UNLOCK(stcb);
3470 } else {
3471 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3472 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3473 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3474 SCTP_INP_RLOCK(inp);
3475 av->assoc_value = inp->pktdrop_supported;
3476 SCTP_INP_RUNLOCK(inp);
3477 } else {
3478 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3479 error = EINVAL;
3480 }
3481 }
3482 if (error == 0) {
3483 *optsize = sizeof(struct sctp_assoc_value);
3484 }
3485 break;
3486 }
3487 case SCTP_ENABLE_STREAM_RESET:
3488 {
3489 struct sctp_assoc_value *av;
3490
3491 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize);
3492 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3493
3494 if (stcb) {
3495 av->assoc_value = (uint32_t) stcb->asoc.local_strreset_support;
3496 SCTP_TCB_UNLOCK(stcb);
3497 } else {
3498 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3499 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3500 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
3501 SCTP_INP_RLOCK(inp);
3502 av->assoc_value = (uint32_t) inp->local_strreset_support;
3503 SCTP_INP_RUNLOCK(inp);
3504 } else {
3505 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3506 error = EINVAL;
3507 }
3508 }
3509 if (error == 0) {
3510 *optsize = sizeof(struct sctp_assoc_value);
3511 }
3512 break;
3513 }
3514 case SCTP_PR_STREAM_STATUS:
3515 {
3516 struct sctp_prstatus *sprstat;
3517 uint16_t sid;
3518 uint16_t policy;
3519
3520 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3521 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3522
3523 sid = sprstat->sprstat_sid;
3524 policy = sprstat->sprstat_policy;
3525 #if defined(SCTP_DETAILED_STR_STATS)
3526 if ((stcb != NULL) &&
3527 (policy != SCTP_PR_SCTP_NONE) &&
3528 (sid < stcb->asoc.streamoutcnt) &&
3529 ((policy == SCTP_PR_SCTP_ALL) ||
3530 (PR_SCTP_VALID_POLICY(policy)))) {
3531 #else
3532 if ((stcb != NULL) &&
3533 (policy != SCTP_PR_SCTP_NONE) &&
3534 (sid < stcb->asoc.streamoutcnt) &&
3535 (policy == SCTP_PR_SCTP_ALL)) {
3536 #endif
3537 if (policy == SCTP_PR_SCTP_ALL) {
3538 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0];
3539 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0];
3540 } else {
3541 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy];
3542 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy];
3543 }
3544 SCTP_TCB_UNLOCK(stcb);
3545 *optsize = sizeof(struct sctp_prstatus);
3546 } else {
3547 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3548 error = EINVAL;
3549 }
3550 break;
3551 }
3552 case SCTP_PR_ASSOC_STATUS:
3553 {
3554 struct sctp_prstatus *sprstat;
3555 uint16_t policy;
3556
3557 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize);
3558 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id);
3559
3560 policy = sprstat->sprstat_policy;
3561 if ((stcb != NULL) &&
3562 (policy != SCTP_PR_SCTP_NONE) &&
3563 ((policy == SCTP_PR_SCTP_ALL) ||
3564 (PR_SCTP_VALID_POLICY(policy)))) {
3565 if (policy == SCTP_PR_SCTP_ALL) {
3566 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0];
3567 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0];
3568 } else {
3569 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy];
3570 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy];
3571 }
3572 SCTP_TCB_UNLOCK(stcb);
3573 *optsize = sizeof(struct sctp_prstatus);
3574 } else {
3575 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3576 error = EINVAL;
3577 }
3578 break;
3579 }
3580 default:
3581 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3582 error = ENOPROTOOPT;
3583 break;
3584 } /* end switch (sopt->sopt_name) */
3585 if (error) {
3586 *optsize = 0;
3587 }
3588 return (error);
3589 }
3590
3591 static int
3592 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3593 void *p)
3594 {
3595 int error, set_opt;
3596 uint32_t *mopt;
3597 struct sctp_tcb *stcb = NULL;
3598 struct sctp_inpcb *inp = NULL;
3599 uint32_t vrf_id;
3600
3601 if (optval == NULL) {
3602 SCTP_PRINTF("optval is NULL\n");
3603 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3604 return (EINVAL);
3605 }
3606 inp = (struct sctp_inpcb *)so->so_pcb;
3607 if (inp == NULL) {
3608 SCTP_PRINTF("inp is NULL?\n");
3609 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3610 return (EINVAL);
3611 }
3612 vrf_id = inp->def_vrf_id;
3613
3614 error = 0;
3615 switch (optname) {
3616 case SCTP_NODELAY:
3617 case SCTP_AUTOCLOSE:
3618 case SCTP_AUTO_ASCONF:
3619 case SCTP_EXPLICIT_EOR:
3620 case SCTP_DISABLE_FRAGMENTS:
3621 case SCTP_USE_EXT_RCVINFO:
3622 case SCTP_I_WANT_MAPPED_V4_ADDR:
3623 /* copy in the option value */
3624 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3625 set_opt = 0;
3626 if (error)
3627 break;
3628 switch (optname) {
3629 case SCTP_DISABLE_FRAGMENTS:
3630 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3631 break;
3632 case SCTP_AUTO_ASCONF:
3633 /*
3634 * NOTE: we don't really support this flag
3635 */
3636 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3637 /* only valid for bound all sockets */
3638 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3639 (*mopt != 0)) {
3640 /* forbidden by admin */
3641 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3642 return (EPERM);
3643 }
3644 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3645 } else {
3646 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3647 return (EINVAL);
3648 }
3649 break;
3650 case SCTP_EXPLICIT_EOR:
3651 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3652 break;
3653 case SCTP_USE_EXT_RCVINFO:
3654 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3655 break;
3656 case SCTP_I_WANT_MAPPED_V4_ADDR:
3657 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3658 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3659 } else {
3660 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3661 return (EINVAL);
3662 }
3663 break;
3664 case SCTP_NODELAY:
3665 set_opt = SCTP_PCB_FLAGS_NODELAY;
3666 break;
3667 case SCTP_AUTOCLOSE:
3668 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3669 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3670 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3671 return (EINVAL);
3672 }
3673 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3674 /*
3675 * The value is in ticks. Note this does not effect
3676 * old associations, only new ones.
3677 */
3678 inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3679 break;
3680 }
3681 SCTP_INP_WLOCK(inp);
3682 if (*mopt != 0) {
3683 sctp_feature_on(inp, set_opt);
3684 } else {
3685 sctp_feature_off(inp, set_opt);
3686 }
3687 SCTP_INP_WUNLOCK(inp);
3688 break;
3689 case SCTP_REUSE_PORT:
3690 {
3691 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3692 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3693 /* Can't set it after we are bound */
3694 error = EINVAL;
3695 break;
3696 }
3697 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3698 /* Can't do this for a 1-m socket */
3699 error = EINVAL;
3700 break;
3701 }
3702 if (optval)
3703 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3704 else
3705 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3706 break;
3707 }
3708 case SCTP_PARTIAL_DELIVERY_POINT:
3709 {
3710 uint32_t *value;
3711
3712 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3713 if (*value > SCTP_SB_LIMIT_RCV(so)) {
3714 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3715 error = EINVAL;
3716 break;
3717 }
3718 inp->partial_delivery_point = *value;
3719 break;
3720 }
3721 case SCTP_FRAGMENT_INTERLEAVE:
3722 /* not yet until we re-write sctp_recvmsg() */
3723 {
3724 uint32_t *level;
3725
3726 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3727 if (*level == SCTP_FRAG_LEVEL_2) {
3728 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3729 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3730 } else if (*level == SCTP_FRAG_LEVEL_1) {
3731 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3732 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3733 } else if (*level == SCTP_FRAG_LEVEL_0) {
3734 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3735 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3736
3737 } else {
3738 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3739 error = EINVAL;
3740 }
3741 break;
3742 }
3743 case SCTP_CMT_ON_OFF:
3744 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3745 struct sctp_assoc_value *av;
3746
3747 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3748 if (av->assoc_value > SCTP_CMT_MAX) {
3749 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3750 error = EINVAL;
3751 break;
3752 }
3753 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3754 if (stcb) {
3755 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3756 SCTP_TCB_UNLOCK(stcb);
3757 } else {
3758 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3759 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3760 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3761 (av->assoc_id == SCTP_ALL_ASSOC)) {
3762 SCTP_INP_WLOCK(inp);
3763 inp->sctp_cmt_on_off = av->assoc_value;
3764 SCTP_INP_WUNLOCK(inp);
3765 }
3766 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3767 (av->assoc_id == SCTP_ALL_ASSOC)) {
3768 SCTP_INP_RLOCK(inp);
3769 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3770 SCTP_TCB_LOCK(stcb);
3771 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3772 SCTP_TCB_UNLOCK(stcb);
3773 }
3774 SCTP_INP_RUNLOCK(inp);
3775 }
3776 }
3777 } else {
3778 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3779 error = ENOPROTOOPT;
3780 }
3781 break;
3782 case SCTP_PLUGGABLE_CC:
3783 {
3784 struct sctp_assoc_value *av;
3785 struct sctp_nets *net;
3786
3787 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3788 if ((av->assoc_value != SCTP_CC_RFC2581) &&
3789 (av->assoc_value != SCTP_CC_HSTCP) &&
3790 (av->assoc_value != SCTP_CC_HTCP) &&
3791 (av->assoc_value != SCTP_CC_RTCC)) {
3792 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3793 error = EINVAL;
3794 break;
3795 }
3796 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3797 if (stcb) {
3798 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3799 stcb->asoc.congestion_control_module = av->assoc_value;
3800 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3801 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3802 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3803 }
3804 }
3805 SCTP_TCB_UNLOCK(stcb);
3806 } else {
3807 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3808 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3809 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3810 (av->assoc_id == SCTP_ALL_ASSOC)) {
3811 SCTP_INP_WLOCK(inp);
3812 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3813 SCTP_INP_WUNLOCK(inp);
3814 }
3815 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3816 (av->assoc_id == SCTP_ALL_ASSOC)) {
3817 SCTP_INP_RLOCK(inp);
3818 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3819 SCTP_TCB_LOCK(stcb);
3820 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3821 stcb->asoc.congestion_control_module = av->assoc_value;
3822 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3823 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3824 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3825 }
3826 }
3827 SCTP_TCB_UNLOCK(stcb);
3828 }
3829 SCTP_INP_RUNLOCK(inp);
3830 }
3831 }
3832 break;
3833 }
3834 case SCTP_CC_OPTION:
3835 {
3836 struct sctp_cc_option *cc_opt;
3837
3838 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3839 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3840 if (stcb == NULL) {
3841 if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3842 SCTP_INP_RLOCK(inp);
3843 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3844 SCTP_TCB_LOCK(stcb);
3845 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3846 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3847 }
3848 SCTP_TCB_UNLOCK(stcb);
3849 }
3850 SCTP_INP_RUNLOCK(inp);
3851 } else {
3852 error = EINVAL;
3853 }
3854 } else {
3855 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3856 error = ENOTSUP;
3857 } else {
3858 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3859 cc_opt);
3860 }
3861 SCTP_TCB_UNLOCK(stcb);
3862 }
3863 break;
3864 }
3865 case SCTP_PLUGGABLE_SS:
3866 {
3867 struct sctp_assoc_value *av;
3868
3869 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3870 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3871 (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3872 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3873 (av->assoc_value != SCTP_SS_PRIORITY) &&
3874 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3875 (av->assoc_value != SCTP_SS_FIRST_COME)) {
3876 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3877 error = EINVAL;
3878 break;
3879 }
3880 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3881 if (stcb) {
3882 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3883 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3884 stcb->asoc.stream_scheduling_module = av->assoc_value;
3885 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3886 SCTP_TCB_UNLOCK(stcb);
3887 } else {
3888 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3889 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3890 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3891 (av->assoc_id == SCTP_ALL_ASSOC)) {
3892 SCTP_INP_WLOCK(inp);
3893 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3894 SCTP_INP_WUNLOCK(inp);
3895 }
3896 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3897 (av->assoc_id == SCTP_ALL_ASSOC)) {
3898 SCTP_INP_RLOCK(inp);
3899 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3900 SCTP_TCB_LOCK(stcb);
3901 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3902 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3903 stcb->asoc.stream_scheduling_module = av->assoc_value;
3904 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3905 SCTP_TCB_UNLOCK(stcb);
3906 }
3907 SCTP_INP_RUNLOCK(inp);
3908 }
3909 }
3910 break;
3911 }
3912 case SCTP_SS_VALUE:
3913 {
3914 struct sctp_stream_value *av;
3915
3916 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3917 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3918 if (stcb) {
3919 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
3920 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3921 av->stream_value) < 0)) {
3922 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3923 error = EINVAL;
3924 }
3925 SCTP_TCB_UNLOCK(stcb);
3926 } else {
3927 if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3928 SCTP_INP_RLOCK(inp);
3929 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3930 SCTP_TCB_LOCK(stcb);
3931 if (av->stream_id < stcb->asoc.streamoutcnt) {
3932 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3933 &stcb->asoc,
3934 &stcb->asoc.strmout[av->stream_id],
3935 av->stream_value);
3936 }
3937 SCTP_TCB_UNLOCK(stcb);
3938 }
3939 SCTP_INP_RUNLOCK(inp);
3940
3941 } else {
3942 /*
3943 * Can't set stream value without
3944 * association
3945 */
3946 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3947 error = EINVAL;
3948 }
3949 }
3950 break;
3951 }
3952 case SCTP_CLR_STAT_LOG:
3953 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3954 error = EOPNOTSUPP;
3955 break;
3956 case SCTP_CONTEXT:
3957 {
3958 struct sctp_assoc_value *av;
3959
3960 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3961 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3962
3963 if (stcb) {
3964 stcb->asoc.context = av->assoc_value;
3965 SCTP_TCB_UNLOCK(stcb);
3966 } else {
3967 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3968 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3969 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3970 (av->assoc_id == SCTP_ALL_ASSOC)) {
3971 SCTP_INP_WLOCK(inp);
3972 inp->sctp_context = av->assoc_value;
3973 SCTP_INP_WUNLOCK(inp);
3974 }
3975 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3976 (av->assoc_id == SCTP_ALL_ASSOC)) {
3977 SCTP_INP_RLOCK(inp);
3978 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3979 SCTP_TCB_LOCK(stcb);
3980 stcb->asoc.context = av->assoc_value;
3981 SCTP_TCB_UNLOCK(stcb);
3982 }
3983 SCTP_INP_RUNLOCK(inp);
3984 }
3985 }
3986 break;
3987 }
3988 case SCTP_VRF_ID:
3989 {
3990 uint32_t *default_vrfid;
3991
3992 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3993 if (*default_vrfid > SCTP_MAX_VRF_ID) {
3994 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3995 error = EINVAL;
3996 break;
3997 }
3998 inp->def_vrf_id = *default_vrfid;
3999 break;
4000 }
4001 case SCTP_DEL_VRF_ID:
4002 {
4003 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4004 error = EOPNOTSUPP;
4005 break;
4006 }
4007 case SCTP_ADD_VRF_ID:
4008 {
4009 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4010 error = EOPNOTSUPP;
4011 break;
4012 }
4013 case SCTP_DELAYED_SACK:
4014 {
4015 struct sctp_sack_info *sack;
4016
4017 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
4018 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
4019 if (sack->sack_delay) {
4020 if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
4021 sack->sack_delay = SCTP_MAX_SACK_DELAY;
4022 if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
4023 sack->sack_delay = TICKS_TO_MSEC(1);
4024 }
4025 }
4026 if (stcb) {
4027 if (sack->sack_delay) {
4028 stcb->asoc.delayed_ack = sack->sack_delay;
4029 }
4030 if (sack->sack_freq) {
4031 stcb->asoc.sack_freq = sack->sack_freq;
4032 }
4033 SCTP_TCB_UNLOCK(stcb);
4034 } else {
4035 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4036 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4037 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
4038 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4039 SCTP_INP_WLOCK(inp);
4040 if (sack->sack_delay) {
4041 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
4042 }
4043 if (sack->sack_freq) {
4044 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
4045 }
4046 SCTP_INP_WUNLOCK(inp);
4047 }
4048 if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
4049 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
4050 SCTP_INP_RLOCK(inp);
4051 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4052 SCTP_TCB_LOCK(stcb);
4053 if (sack->sack_delay) {
4054 stcb->asoc.delayed_ack = sack->sack_delay;
4055 }
4056 if (sack->sack_freq) {
4057 stcb->asoc.sack_freq = sack->sack_freq;
4058 }
4059 SCTP_TCB_UNLOCK(stcb);
4060 }
4061 SCTP_INP_RUNLOCK(inp);
4062 }
4063 }
4064 break;
4065 }
4066 case SCTP_AUTH_CHUNK:
4067 {
4068 struct sctp_authchunk *sauth;
4069
4070 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
4071
4072 SCTP_INP_WLOCK(inp);
4073 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
4074 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4075 error = EINVAL;
4076 }
4077 SCTP_INP_WUNLOCK(inp);
4078 break;
4079 }
4080 case SCTP_AUTH_KEY:
4081 {
4082 struct sctp_authkey *sca;
4083 struct sctp_keyhead *shared_keys;
4084 sctp_sharedkey_t *shared_key;
4085 sctp_key_t *key = NULL;
4086 size_t size;
4087
4088 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
4089 if (sca->sca_keylength == 0) {
4090 size = optsize - sizeof(struct sctp_authkey);
4091 } else {
4092 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
4093 size = sca->sca_keylength;
4094 } else {
4095 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4096 error = EINVAL;
4097 break;
4098 }
4099 }
4100 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
4101
4102 if (stcb) {
4103 shared_keys = &stcb->asoc.shared_keys;
4104 /* clear the cached keys for this key id */
4105 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4106 /*
4107 * create the new shared key and
4108 * insert/replace it
4109 */
4110 if (size > 0) {
4111 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4112 if (key == NULL) {
4113 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4114 error = ENOMEM;
4115 SCTP_TCB_UNLOCK(stcb);
4116 break;
4117 }
4118 }
4119 shared_key = sctp_alloc_sharedkey();
4120 if (shared_key == NULL) {
4121 sctp_free_key(key);
4122 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4123 error = ENOMEM;
4124 SCTP_TCB_UNLOCK(stcb);
4125 break;
4126 }
4127 shared_key->key = key;
4128 shared_key->keyid = sca->sca_keynumber;
4129 error = sctp_insert_sharedkey(shared_keys, shared_key);
4130 SCTP_TCB_UNLOCK(stcb);
4131 } else {
4132 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4133 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4134 (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
4135 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4136 SCTP_INP_WLOCK(inp);
4137 shared_keys = &inp->sctp_ep.shared_keys;
4138 /*
4139 * clear the cached keys on all
4140 * assocs for this key id
4141 */
4142 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
4143 /*
4144 * create the new shared key and
4145 * insert/replace it
4146 */
4147 if (size > 0) {
4148 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4149 if (key == NULL) {
4150 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4151 error = ENOMEM;
4152 SCTP_INP_WUNLOCK(inp);
4153 break;
4154 }
4155 }
4156 shared_key = sctp_alloc_sharedkey();
4157 if (shared_key == NULL) {
4158 sctp_free_key(key);
4159 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4160 error = ENOMEM;
4161 SCTP_INP_WUNLOCK(inp);
4162 break;
4163 }
4164 shared_key->key = key;
4165 shared_key->keyid = sca->sca_keynumber;
4166 error = sctp_insert_sharedkey(shared_keys, shared_key);
4167 SCTP_INP_WUNLOCK(inp);
4168 }
4169 if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
4170 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
4171 SCTP_INP_RLOCK(inp);
4172 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4173 SCTP_TCB_LOCK(stcb);
4174 shared_keys = &stcb->asoc.shared_keys;
4175 /*
4176 * clear the cached keys for
4177 * this key id
4178 */
4179 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
4180 /*
4181 * create the new shared key
4182 * and insert/replace it
4183 */
4184 if (size > 0) {
4185 key = sctp_set_key(sca->sca_key, (uint32_t) size);
4186 if (key == NULL) {
4187 SCTP_TCB_UNLOCK(stcb);
4188 continue;
4189 }
4190 }
4191 shared_key = sctp_alloc_sharedkey();
4192 if (shared_key == NULL) {
4193 sctp_free_key(key);
4194 SCTP_TCB_UNLOCK(stcb);
4195 continue;
4196 }
4197 shared_key->key = key;
4198 shared_key->keyid = sca->sca_keynumber;
4199 error = sctp_insert_sharedkey(shared_keys, shared_key);
4200 SCTP_TCB_UNLOCK(stcb);
4201 }
4202 SCTP_INP_RUNLOCK(inp);
4203 }
4204 }
4205 break;
4206 }
4207 case SCTP_HMAC_IDENT:
4208 {
4209 struct sctp_hmacalgo *shmac;
4210 sctp_hmaclist_t *hmaclist;
4211 uint16_t hmacid;
4212 uint32_t i;
4213
4214 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
4215 if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) ||
4216 (shmac->shmac_number_of_idents > 0xffff)) {
4217 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4218 error = EINVAL;
4219 break;
4220 }
4221 hmaclist = sctp_alloc_hmaclist((uint16_t) shmac->shmac_number_of_idents);
4222 if (hmaclist == NULL) {
4223 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
4224 error = ENOMEM;
4225 break;
4226 }
4227 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
4228 hmacid = shmac->shmac_idents[i];
4229 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
4230 /* invalid HMACs were found */ ;
4231 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4232 error = EINVAL;
4233 sctp_free_hmaclist(hmaclist);
4234 goto sctp_set_hmac_done;
4235 }
4236 }
4237 for (i = 0; i < hmaclist->num_algo; i++) {
4238 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
4239 /* already in list */
4240 break;
4241 }
4242 }
4243 if (i == hmaclist->num_algo) {
4244 /* not found in list */
4245 sctp_free_hmaclist(hmaclist);
4246 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4247 error = EINVAL;
4248 break;
4249 }
4250 /* set it on the endpoint */
4251 SCTP_INP_WLOCK(inp);
4252 if (inp->sctp_ep.local_hmacs)
4253 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
4254 inp->sctp_ep.local_hmacs = hmaclist;
4255 SCTP_INP_WUNLOCK(inp);
4256 sctp_set_hmac_done:
4257 break;
4258 }
4259 case SCTP_AUTH_ACTIVE_KEY:
4260 {
4261 struct sctp_authkeyid *scact;
4262
4263 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4264 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4265
4266 /* set the active key on the right place */
4267 if (stcb) {
4268 /* set the active key on the assoc */
4269 if (sctp_auth_setactivekey(stcb,
4270 scact->scact_keynumber)) {
4271 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4272 SCTP_FROM_SCTP_USRREQ,
4273 EINVAL);
4274 error = EINVAL;
4275 }
4276 SCTP_TCB_UNLOCK(stcb);
4277 } else {
4278 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4279 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4280 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4281 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4282 SCTP_INP_WLOCK(inp);
4283 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4284 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4285 error = EINVAL;
4286 }
4287 SCTP_INP_WUNLOCK(inp);
4288 }
4289 if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4290 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4291 SCTP_INP_RLOCK(inp);
4292 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4293 SCTP_TCB_LOCK(stcb);
4294 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4295 SCTP_TCB_UNLOCK(stcb);
4296 }
4297 SCTP_INP_RUNLOCK(inp);
4298 }
4299 }
4300 break;
4301 }
4302 case SCTP_AUTH_DELETE_KEY:
4303 {
4304 struct sctp_authkeyid *scdel;
4305
4306 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4307 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4308
4309 /* delete the key from the right place */
4310 if (stcb) {
4311 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4312 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4313 error = EINVAL;
4314 }
4315 SCTP_TCB_UNLOCK(stcb);
4316 } else {
4317 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4318 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4319 (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4320 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4321 SCTP_INP_WLOCK(inp);
4322 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4323 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4324 error = EINVAL;
4325 }
4326 SCTP_INP_WUNLOCK(inp);
4327 }
4328 if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4329 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4330 SCTP_INP_RLOCK(inp);
4331 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4332 SCTP_TCB_LOCK(stcb);
4333 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4334 SCTP_TCB_UNLOCK(stcb);
4335 }
4336 SCTP_INP_RUNLOCK(inp);
4337 }
4338 }
4339 break;
4340 }
4341 case SCTP_AUTH_DEACTIVATE_KEY:
4342 {
4343 struct sctp_authkeyid *keyid;
4344
4345 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4346 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4347
4348 /* deactivate the key from the right place */
4349 if (stcb) {
4350 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4351 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4352 error = EINVAL;
4353 }
4354 SCTP_TCB_UNLOCK(stcb);
4355 } else {
4356 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4357 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4358 (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4359 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4360 SCTP_INP_WLOCK(inp);
4361 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4362 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4363 error = EINVAL;
4364 }
4365 SCTP_INP_WUNLOCK(inp);
4366 }
4367 if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4368 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4369 SCTP_INP_RLOCK(inp);
4370 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4371 SCTP_TCB_LOCK(stcb);
4372 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4373 SCTP_TCB_UNLOCK(stcb);
4374 }
4375 SCTP_INP_RUNLOCK(inp);
4376 }
4377 }
4378 break;
4379 }
4380 case SCTP_ENABLE_STREAM_RESET:
4381 {
4382 struct sctp_assoc_value *av;
4383
4384 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4385 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4386 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4387 error = EINVAL;
4388 break;
4389 }
4390 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4391 if (stcb) {
4392 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4393 SCTP_TCB_UNLOCK(stcb);
4394 } else {
4395 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4396 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4397 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4398 (av->assoc_id == SCTP_ALL_ASSOC)) {
4399 SCTP_INP_WLOCK(inp);
4400 inp->local_strreset_support = (uint8_t) av->assoc_value;
4401 SCTP_INP_WUNLOCK(inp);
4402 }
4403 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4404 (av->assoc_id == SCTP_ALL_ASSOC)) {
4405 SCTP_INP_RLOCK(inp);
4406 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4407 SCTP_TCB_LOCK(stcb);
4408 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4409 SCTP_TCB_UNLOCK(stcb);
4410 }
4411 SCTP_INP_RUNLOCK(inp);
4412 }
4413 }
4414 break;
4415 }
4416 case SCTP_RESET_STREAMS:
4417 {
4418 struct sctp_reset_streams *strrst;
4419 int i, send_out = 0;
4420 int send_in = 0;
4421
4422 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4423 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4424 if (stcb == NULL) {
4425 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4426 error = ENOENT;
4427 break;
4428 }
4429 if (stcb->asoc.reconfig_supported == 0) {
4430 /*
4431 * Peer does not support the chunk type.
4432 */
4433 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4434 error = EOPNOTSUPP;
4435 SCTP_TCB_UNLOCK(stcb);
4436 break;
4437 }
4438 if (sizeof(struct sctp_reset_streams) +
4439 strrst->srs_number_streams * sizeof(uint16_t) > optsize) {
4440 error = EINVAL;
4441 SCTP_TCB_UNLOCK(stcb);
4442 break;
4443 }
4444 if (stcb->asoc.stream_reset_outstanding) {
4445 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4446 error = EALREADY;
4447 SCTP_TCB_UNLOCK(stcb);
4448 break;
4449 }
4450 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4451 send_in = 1;
4452 }
4453 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4454 send_out = 1;
4455 }
4456 if ((send_in == 0) && (send_out == 0)) {
4457 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4458 error = EINVAL;
4459 SCTP_TCB_UNLOCK(stcb);
4460 break;
4461 }
4462 for (i = 0; i < strrst->srs_number_streams; i++) {
4463 if ((send_in) &&
4464 (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4465 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4466 error = EINVAL;
4467 break;
4468 }
4469 if ((send_out) &&
4470 (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4471 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4472 error = EINVAL;
4473 break;
4474 }
4475 }
4476 if (error) {
4477 SCTP_TCB_UNLOCK(stcb);
4478 break;
4479 }
4480 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4481 strrst->srs_stream_list,
4482 send_out, send_in, 0, 0, 0, 0, 0);
4483
4484 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4485 SCTP_TCB_UNLOCK(stcb);
4486 break;
4487 }
4488 case SCTP_ADD_STREAMS:
4489 {
4490 struct sctp_add_streams *stradd;
4491 uint8_t addstream = 0;
4492 uint16_t add_o_strmcnt = 0;
4493 uint16_t add_i_strmcnt = 0;
4494
4495 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4496 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4497 if (stcb == NULL) {
4498 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4499 error = ENOENT;
4500 break;
4501 }
4502 if (stcb->asoc.reconfig_supported == 0) {
4503 /*
4504 * Peer does not support the chunk type.
4505 */
4506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4507 error = EOPNOTSUPP;
4508 SCTP_TCB_UNLOCK(stcb);
4509 break;
4510 }
4511 if (stcb->asoc.stream_reset_outstanding) {
4512 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4513 error = EALREADY;
4514 SCTP_TCB_UNLOCK(stcb);
4515 break;
4516 }
4517 if ((stradd->sas_outstrms == 0) &&
4518 (stradd->sas_instrms == 0)) {
4519 error = EINVAL;
4520 goto skip_stuff;
4521 }
4522 if (stradd->sas_outstrms) {
4523 addstream = 1;
4524 /* We allocate here */
4525 add_o_strmcnt = stradd->sas_outstrms;
4526 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4527 /* You can't have more than 64k */
4528 error = EINVAL;
4529 goto skip_stuff;
4530 }
4531 }
4532 if (stradd->sas_instrms) {
4533 int cnt;
4534
4535 addstream |= 2;
4536 /*
4537 * We allocate inside
4538 * sctp_send_str_reset_req()
4539 */
4540 add_i_strmcnt = stradd->sas_instrms;
4541 cnt = add_i_strmcnt;
4542 cnt += stcb->asoc.streamincnt;
4543 if (cnt > 0x0000ffff) {
4544 /* You can't have more than 64k */
4545 error = EINVAL;
4546 goto skip_stuff;
4547 }
4548 if (cnt > (int)stcb->asoc.max_inbound_streams) {
4549 /* More than you are allowed */
4550 error = EINVAL;
4551 goto skip_stuff;
4552 }
4553 }
4554 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4555 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4556 skip_stuff:
4557 SCTP_TCB_UNLOCK(stcb);
4558 break;
4559 }
4560 case SCTP_RESET_ASSOC:
4561 {
4562 uint32_t *value;
4563
4564 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4565 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4566 if (stcb == NULL) {
4567 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4568 error = ENOENT;
4569 break;
4570 }
4571 if (stcb->asoc.reconfig_supported == 0) {
4572 /*
4573 * Peer does not support the chunk type.
4574 */
4575 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4576 error = EOPNOTSUPP;
4577 SCTP_TCB_UNLOCK(stcb);
4578 break;
4579 }
4580 if (stcb->asoc.stream_reset_outstanding) {
4581 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4582 error = EALREADY;
4583 SCTP_TCB_UNLOCK(stcb);
4584 break;
4585 }
4586 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
4587 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4588 SCTP_TCB_UNLOCK(stcb);
4589 break;
4590 }
4591 case SCTP_CONNECT_X:
4592 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4593 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4594 error = EINVAL;
4595 break;
4596 }
4597 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4598 break;
4599 case SCTP_CONNECT_X_DELAYED:
4600 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4601 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4602 error = EINVAL;
4603 break;
4604 }
4605 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4606 break;
4607 case SCTP_CONNECT_X_COMPLETE:
4608 {
4609 struct sockaddr *sa;
4610 struct sctp_nets *net;
4611
4612 /* FIXME MT: check correct? */
4613 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4614
4615 /* find tcb */
4616 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4617 SCTP_INP_RLOCK(inp);
4618 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4619 if (stcb) {
4620 SCTP_TCB_LOCK(stcb);
4621 net = sctp_findnet(stcb, sa);
4622 }
4623 SCTP_INP_RUNLOCK(inp);
4624 } else {
4625 /*
4626 * We increment here since
4627 * sctp_findassociation_ep_addr() wil do a
4628 * decrement if it finds the stcb as long as
4629 * the locked tcb (last argument) is NOT a
4630 * TCB.. aka NULL.
4631 */
4632 SCTP_INP_INCR_REF(inp);
4633 stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4634 if (stcb == NULL) {
4635 SCTP_INP_DECR_REF(inp);
4636 }
4637 }
4638
4639 if (stcb == NULL) {
4640 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4641 error = ENOENT;
4642 break;
4643 }
4644 if (stcb->asoc.delayed_connection == 1) {
4645 stcb->asoc.delayed_connection = 0;
4646 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4647 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4648 stcb->asoc.primary_destination,
4649 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4650 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4651 } else {
4652 /*
4653 * already expired or did not use delayed
4654 * connectx
4655 */
4656 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4657 error = EALREADY;
4658 }
4659 SCTP_TCB_UNLOCK(stcb);
4660 break;
4661 }
4662 case SCTP_MAX_BURST:
4663 {
4664 struct sctp_assoc_value *av;
4665
4666 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4667 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4668
4669 if (stcb) {
4670 stcb->asoc.max_burst = av->assoc_value;
4671 SCTP_TCB_UNLOCK(stcb);
4672 } else {
4673 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4674 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4675 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4676 (av->assoc_id == SCTP_ALL_ASSOC)) {
4677 SCTP_INP_WLOCK(inp);
4678 inp->sctp_ep.max_burst = av->assoc_value;
4679 SCTP_INP_WUNLOCK(inp);
4680 }
4681 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4682 (av->assoc_id == SCTP_ALL_ASSOC)) {
4683 SCTP_INP_RLOCK(inp);
4684 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4685 SCTP_TCB_LOCK(stcb);
4686 stcb->asoc.max_burst = av->assoc_value;
4687 SCTP_TCB_UNLOCK(stcb);
4688 }
4689 SCTP_INP_RUNLOCK(inp);
4690 }
4691 }
4692 break;
4693 }
4694 case SCTP_MAXSEG:
4695 {
4696 struct sctp_assoc_value *av;
4697 int ovh;
4698
4699 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4700 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4701
4702 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4703 ovh = SCTP_MED_OVERHEAD;
4704 } else {
4705 ovh = SCTP_MED_V4_OVERHEAD;
4706 }
4707 if (stcb) {
4708 if (av->assoc_value) {
4709 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4710 } else {
4711 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4712 }
4713 SCTP_TCB_UNLOCK(stcb);
4714 } else {
4715 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4716 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4717 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4718 SCTP_INP_WLOCK(inp);
4719 /*
4720 * FIXME MT: I think this is not in
4721 * tune with the API ID
4722 */
4723 if (av->assoc_value) {
4724 inp->sctp_frag_point = (av->assoc_value + ovh);
4725 } else {
4726 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4727 }
4728 SCTP_INP_WUNLOCK(inp);
4729 } else {
4730 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4731 error = EINVAL;
4732 }
4733 }
4734 break;
4735 }
4736 case SCTP_EVENTS:
4737 {
4738 struct sctp_event_subscribe *events;
4739
4740 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4741
4742 SCTP_INP_WLOCK(inp);
4743 if (events->sctp_data_io_event) {
4744 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4745 } else {
4746 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4747 }
4748
4749 if (events->sctp_association_event) {
4750 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4751 } else {
4752 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4753 }
4754
4755 if (events->sctp_address_event) {
4756 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4757 } else {
4758 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4759 }
4760
4761 if (events->sctp_send_failure_event) {
4762 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4763 } else {
4764 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4765 }
4766
4767 if (events->sctp_peer_error_event) {
4768 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4769 } else {
4770 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4771 }
4772
4773 if (events->sctp_shutdown_event) {
4774 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4775 } else {
4776 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4777 }
4778
4779 if (events->sctp_partial_delivery_event) {
4780 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4781 } else {
4782 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4783 }
4784
4785 if (events->sctp_adaptation_layer_event) {
4786 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4787 } else {
4788 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4789 }
4790
4791 if (events->sctp_authentication_event) {
4792 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4793 } else {
4794 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4795 }
4796
4797 if (events->sctp_sender_dry_event) {
4798 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4799 } else {
4800 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4801 }
4802
4803 if (events->sctp_stream_reset_event) {
4804 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4805 } else {
4806 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4807 }
4808 SCTP_INP_WUNLOCK(inp);
4809
4810 SCTP_INP_RLOCK(inp);
4811 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4812 SCTP_TCB_LOCK(stcb);
4813 if (events->sctp_association_event) {
4814 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4815 } else {
4816 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4817 }
4818 if (events->sctp_address_event) {
4819 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4820 } else {
4821 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4822 }
4823 if (events->sctp_send_failure_event) {
4824 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4825 } else {
4826 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4827 }
4828 if (events->sctp_peer_error_event) {
4829 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4830 } else {
4831 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4832 }
4833 if (events->sctp_shutdown_event) {
4834 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4835 } else {
4836 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4837 }
4838 if (events->sctp_partial_delivery_event) {
4839 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4840 } else {
4841 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4842 }
4843 if (events->sctp_adaptation_layer_event) {
4844 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4845 } else {
4846 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4847 }
4848 if (events->sctp_authentication_event) {
4849 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4850 } else {
4851 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4852 }
4853 if (events->sctp_sender_dry_event) {
4854 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4855 } else {
4856 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4857 }
4858 if (events->sctp_stream_reset_event) {
4859 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4860 } else {
4861 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4862 }
4863 SCTP_TCB_UNLOCK(stcb);
4864 }
4865 /*
4866 * Send up the sender dry event only for 1-to-1
4867 * style sockets.
4868 */
4869 if (events->sctp_sender_dry_event) {
4870 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4871 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4872 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4873 if (stcb) {
4874 SCTP_TCB_LOCK(stcb);
4875 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4876 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4877 (stcb->asoc.stream_queue_cnt == 0)) {
4878 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4879 }
4880 SCTP_TCB_UNLOCK(stcb);
4881 }
4882 }
4883 }
4884 SCTP_INP_RUNLOCK(inp);
4885 break;
4886 }
4887 case SCTP_ADAPTATION_LAYER:
4888 {
4889 struct sctp_setadaptation *adap_bits;
4890
4891 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4892 SCTP_INP_WLOCK(inp);
4893 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4894 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
4895 SCTP_INP_WUNLOCK(inp);
4896 break;
4897 }
4898 #ifdef SCTP_DEBUG
4899 case SCTP_SET_INITIAL_DBG_SEQ:
4900 {
4901 uint32_t *vvv;
4902
4903 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4904 SCTP_INP_WLOCK(inp);
4905 inp->sctp_ep.initial_sequence_debug = *vvv;
4906 SCTP_INP_WUNLOCK(inp);
4907 break;
4908 }
4909 #endif
4910 case SCTP_DEFAULT_SEND_PARAM:
4911 {
4912 struct sctp_sndrcvinfo *s_info;
4913
4914 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4915 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4916
4917 if (stcb) {
4918 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4919 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4920 } else {
4921 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4922 error = EINVAL;
4923 }
4924 SCTP_TCB_UNLOCK(stcb);
4925 } else {
4926 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4927 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4928 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4929 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4930 SCTP_INP_WLOCK(inp);
4931 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4932 SCTP_INP_WUNLOCK(inp);
4933 }
4934 if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4935 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4936 SCTP_INP_RLOCK(inp);
4937 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4938 SCTP_TCB_LOCK(stcb);
4939 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4940 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4941 }
4942 SCTP_TCB_UNLOCK(stcb);
4943 }
4944 SCTP_INP_RUNLOCK(inp);
4945 }
4946 }
4947 break;
4948 }
4949 case SCTP_PEER_ADDR_PARAMS:
4950 {
4951 struct sctp_paddrparams *paddrp;
4952 struct sctp_nets *net;
4953
4954 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4955 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4956 net = NULL;
4957 if (stcb) {
4958 net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4959 } else {
4960 /*
4961 * We increment here since
4962 * sctp_findassociation_ep_addr() wil do a
4963 * decrement if it finds the stcb as long as
4964 * the locked tcb (last argument) is NOT a
4965 * TCB.. aka NULL.
4966 */
4967 SCTP_INP_INCR_REF(inp);
4968 stcb = sctp_findassociation_ep_addr(&inp,
4969 (struct sockaddr *)&paddrp->spp_address,
4970 &net, NULL, NULL);
4971 if (stcb == NULL) {
4972 SCTP_INP_DECR_REF(inp);
4973 }
4974 }
4975 if (stcb && (net == NULL)) {
4976 struct sockaddr *sa;
4977
4978 sa = (struct sockaddr *)&paddrp->spp_address;
4979 #ifdef INET
4980 if (sa->sa_family == AF_INET) {
4981
4982 struct sockaddr_in *sin;
4983
4984 sin = (struct sockaddr_in *)sa;
4985 if (sin->sin_addr.s_addr) {
4986 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4987 SCTP_TCB_UNLOCK(stcb);
4988 error = EINVAL;
4989 break;
4990 }
4991 } else
4992 #endif
4993 #ifdef INET6
4994 if (sa->sa_family == AF_INET6) {
4995 struct sockaddr_in6 *sin6;
4996
4997 sin6 = (struct sockaddr_in6 *)sa;
4998 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4999 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5000 SCTP_TCB_UNLOCK(stcb);
5001 error = EINVAL;
5002 break;
5003 }
5004 } else
5005 #endif
5006 {
5007 error = EAFNOSUPPORT;
5008 SCTP_TCB_UNLOCK(stcb);
5009 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5010 break;
5011 }
5012 }
5013 /* sanity checks */
5014 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5015 if (stcb)
5016 SCTP_TCB_UNLOCK(stcb);
5017 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5018 return (EINVAL);
5019 }
5020 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5021 if (stcb)
5022 SCTP_TCB_UNLOCK(stcb);
5023 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5024 return (EINVAL);
5025 }
5026 if (stcb) {
5027 /************************TCB SPECIFIC SET ******************/
5028 /*
5029 * do we change the timer for HB, we run
5030 * only one?
5031 */
5032 int ovh = 0;
5033
5034 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5035 ovh = SCTP_MED_OVERHEAD;
5036 } else {
5037 ovh = SCTP_MED_V4_OVERHEAD;
5038 }
5039
5040 /* network sets ? */
5041 if (net) {
5042 /************************NET SPECIFIC SET ******************/
5043 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5044 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
5045 !(net->dest_state & SCTP_ADDR_NOHB)) {
5046 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5047 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5048 }
5049 net->dest_state |= SCTP_ADDR_NOHB;
5050 }
5051 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5052 if (paddrp->spp_hbinterval) {
5053 net->heart_beat_delay = paddrp->spp_hbinterval;
5054 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5055 net->heart_beat_delay = 0;
5056 }
5057 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5058 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5059 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5060 net->dest_state &= ~SCTP_ADDR_NOHB;
5061 }
5062 if (paddrp->spp_flags & SPP_HB_DEMAND) {
5063 /* on demand HB */
5064 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5065 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5066 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5067 }
5068 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5069 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5070 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5071 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5072 }
5073 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5074 net->mtu = paddrp->spp_pathmtu + ovh;
5075 if (net->mtu < stcb->asoc.smallest_mtu) {
5076 sctp_pathmtu_adjustment(stcb, net->mtu);
5077 }
5078 }
5079 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5080 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5081 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5082 }
5083 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5084 }
5085 if (paddrp->spp_pathmaxrxt) {
5086 if (net->dest_state & SCTP_ADDR_PF) {
5087 if (net->error_count > paddrp->spp_pathmaxrxt) {
5088 net->dest_state &= ~SCTP_ADDR_PF;
5089 }
5090 } else {
5091 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5092 (net->error_count > net->pf_threshold)) {
5093 net->dest_state |= SCTP_ADDR_PF;
5094 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5095 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5096 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5097 }
5098 }
5099 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5100 if (net->error_count > paddrp->spp_pathmaxrxt) {
5101 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5102 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5103 }
5104 } else {
5105 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5106 net->dest_state |= SCTP_ADDR_REACHABLE;
5107 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5108 }
5109 }
5110 net->failure_threshold = paddrp->spp_pathmaxrxt;
5111 }
5112 if (paddrp->spp_flags & SPP_DSCP) {
5113 net->dscp = paddrp->spp_dscp & 0xfc;
5114 net->dscp |= 0x01;
5115 }
5116 #ifdef INET6
5117 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5118 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5119 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5120 net->flowlabel |= 0x80000000;
5121 }
5122 }
5123 #endif
5124 } else {
5125 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5126 if (paddrp->spp_pathmaxrxt) {
5127 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5128 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5129 if (net->dest_state & SCTP_ADDR_PF) {
5130 if (net->error_count > paddrp->spp_pathmaxrxt) {
5131 net->dest_state &= ~SCTP_ADDR_PF;
5132 }
5133 } else {
5134 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5135 (net->error_count > net->pf_threshold)) {
5136 net->dest_state |= SCTP_ADDR_PF;
5137 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5138 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5139 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5140 }
5141 }
5142 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5143 if (net->error_count > paddrp->spp_pathmaxrxt) {
5144 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5145 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5146 }
5147 } else {
5148 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5149 net->dest_state |= SCTP_ADDR_REACHABLE;
5150 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5151 }
5152 }
5153 net->failure_threshold = paddrp->spp_pathmaxrxt;
5154 }
5155 }
5156 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5157 if (paddrp->spp_hbinterval) {
5158 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5159 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5160 stcb->asoc.heart_beat_delay = 0;
5161 }
5162 /* Turn back on the timer */
5163 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5164 if (paddrp->spp_hbinterval) {
5165 net->heart_beat_delay = paddrp->spp_hbinterval;
5166 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5167 net->heart_beat_delay = 0;
5168 }
5169 if (net->dest_state & SCTP_ADDR_NOHB) {
5170 net->dest_state &= ~SCTP_ADDR_NOHB;
5171 }
5172 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5173 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5174 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5175 }
5176 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5177 }
5178 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5179 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5180 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
5181 net->dest_state |= SCTP_ADDR_NOHB;
5182 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
5183 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5184 }
5185 }
5186 }
5187 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5188 }
5189 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
5190 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5191 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5192 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5193 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5194 }
5195 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5196 net->mtu = paddrp->spp_pathmtu + ovh;
5197 if (net->mtu < stcb->asoc.smallest_mtu) {
5198 sctp_pathmtu_adjustment(stcb, net->mtu);
5199 }
5200 }
5201 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5202 }
5203 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5204 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5205 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5206 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5207 }
5208 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5209 }
5210 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5211 }
5212 if (paddrp->spp_flags & SPP_DSCP) {
5213 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5214 net->dscp = paddrp->spp_dscp & 0xfc;
5215 net->dscp |= 0x01;
5216 }
5217 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5218 stcb->asoc.default_dscp |= 0x01;
5219 }
5220 #ifdef INET6
5221 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5222 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5223 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5224 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5225 net->flowlabel |= 0x80000000;
5226 }
5227 }
5228 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5229 stcb->asoc.default_flowlabel |= 0x80000000;
5230 }
5231 #endif
5232 }
5233 SCTP_TCB_UNLOCK(stcb);
5234 } else {
5235 /************************NO TCB, SET TO default stuff ******************/
5236 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5237 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5238 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
5239 SCTP_INP_WLOCK(inp);
5240 /*
5241 * For the TOS/FLOWLABEL stuff you
5242 * set it with the options on the
5243 * socket
5244 */
5245 if (paddrp->spp_pathmaxrxt) {
5246 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5247 }
5248 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5249 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5250 else if (paddrp->spp_hbinterval) {
5251 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5252 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5253 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5254 }
5255 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5256 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5257 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5258 } else if (paddrp->spp_hbinterval) {
5259 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
5260 }
5261 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5262 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5263 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5264 }
5265 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5266 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5267 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5268 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5269 }
5270 if (paddrp->spp_flags & SPP_DSCP) {
5271 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5272 inp->sctp_ep.default_dscp |= 0x01;
5273 }
5274 #ifdef INET6
5275 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5276 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5277 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5278 inp->sctp_ep.default_flowlabel |= 0x80000000;
5279 }
5280 }
5281 #endif
5282 SCTP_INP_WUNLOCK(inp);
5283 } else {
5284 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5285 error = EINVAL;
5286 }
5287 }
5288 break;
5289 }
5290 case SCTP_RTOINFO:
5291 {
5292 struct sctp_rtoinfo *srto;
5293 uint32_t new_init, new_min, new_max;
5294
5295 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5296 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5297
5298 if (stcb) {
5299 if (srto->srto_initial)
5300 new_init = srto->srto_initial;
5301 else
5302 new_init = stcb->asoc.initial_rto;
5303 if (srto->srto_max)
5304 new_max = srto->srto_max;
5305 else
5306 new_max = stcb->asoc.maxrto;
5307 if (srto->srto_min)
5308 new_min = srto->srto_min;
5309 else
5310 new_min = stcb->asoc.minrto;
5311 if ((new_min <= new_init) && (new_init <= new_max)) {
5312 stcb->asoc.initial_rto = new_init;
5313 stcb->asoc.maxrto = new_max;
5314 stcb->asoc.minrto = new_min;
5315 } else {
5316 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5317 error = EINVAL;
5318 }
5319 SCTP_TCB_UNLOCK(stcb);
5320 } else {
5321 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5322 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5323 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5324 SCTP_INP_WLOCK(inp);
5325 if (srto->srto_initial)
5326 new_init = srto->srto_initial;
5327 else
5328 new_init = inp->sctp_ep.initial_rto;
5329 if (srto->srto_max)
5330 new_max = srto->srto_max;
5331 else
5332 new_max = inp->sctp_ep.sctp_maxrto;
5333 if (srto->srto_min)
5334 new_min = srto->srto_min;
5335 else
5336 new_min = inp->sctp_ep.sctp_minrto;
5337 if ((new_min <= new_init) && (new_init <= new_max)) {
5338 inp->sctp_ep.initial_rto = new_init;
5339 inp->sctp_ep.sctp_maxrto = new_max;
5340 inp->sctp_ep.sctp_minrto = new_min;
5341 } else {
5342 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5343 error = EINVAL;
5344 }
5345 SCTP_INP_WUNLOCK(inp);
5346 } else {
5347 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5348 error = EINVAL;
5349 }
5350 }
5351 break;
5352 }
5353 case SCTP_ASSOCINFO:
5354 {
5355 struct sctp_assocparams *sasoc;
5356
5357 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5358 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5359 if (sasoc->sasoc_cookie_life) {
5360 /* boundary check the cookie life */
5361 if (sasoc->sasoc_cookie_life < 1000)
5362 sasoc->sasoc_cookie_life = 1000;
5363 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5364 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5365 }
5366 }
5367 if (stcb) {
5368 if (sasoc->sasoc_asocmaxrxt)
5369 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5370 if (sasoc->sasoc_cookie_life) {
5371 stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5372 }
5373 SCTP_TCB_UNLOCK(stcb);
5374 } else {
5375 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5376 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5377 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5378 SCTP_INP_WLOCK(inp);
5379 if (sasoc->sasoc_asocmaxrxt)
5380 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5381 if (sasoc->sasoc_cookie_life) {
5382 inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5383 }
5384 SCTP_INP_WUNLOCK(inp);
5385 } else {
5386 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5387 error = EINVAL;
5388 }
5389 }
5390 break;
5391 }
5392 case SCTP_INITMSG:
5393 {
5394 struct sctp_initmsg *sinit;
5395
5396 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5397 SCTP_INP_WLOCK(inp);
5398 if (sinit->sinit_num_ostreams)
5399 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5400
5401 if (sinit->sinit_max_instreams)
5402 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5403
5404 if (sinit->sinit_max_attempts)
5405 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5406
5407 if (sinit->sinit_max_init_timeo)
5408 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5409 SCTP_INP_WUNLOCK(inp);
5410 break;
5411 }
5412 case SCTP_PRIMARY_ADDR:
5413 {
5414 struct sctp_setprim *spa;
5415 struct sctp_nets *net;
5416
5417 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5418 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5419
5420 net = NULL;
5421 if (stcb) {
5422 net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5423 } else {
5424 /*
5425 * We increment here since
5426 * sctp_findassociation_ep_addr() wil do a
5427 * decrement if it finds the stcb as long as
5428 * the locked tcb (last argument) is NOT a
5429 * TCB.. aka NULL.
5430 */
5431 SCTP_INP_INCR_REF(inp);
5432 stcb = sctp_findassociation_ep_addr(&inp,
5433 (struct sockaddr *)&spa->ssp_addr,
5434 &net, NULL, NULL);
5435 if (stcb == NULL) {
5436 SCTP_INP_DECR_REF(inp);
5437 }
5438 }
5439
5440 if ((stcb) && (net)) {
5441 if ((net != stcb->asoc.primary_destination) &&
5442 (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5443 /* Ok we need to set it */
5444 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5445 if ((stcb->asoc.alternate) &&
5446 (!(net->dest_state & SCTP_ADDR_PF)) &&
5447 (net->dest_state & SCTP_ADDR_REACHABLE)) {
5448 sctp_free_remote_addr(stcb->asoc.alternate);
5449 stcb->asoc.alternate = NULL;
5450 }
5451 }
5452 }
5453 } else {
5454 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5455 error = EINVAL;
5456 }
5457 if (stcb) {
5458 SCTP_TCB_UNLOCK(stcb);
5459 }
5460 break;
5461 }
5462 case SCTP_SET_DYNAMIC_PRIMARY:
5463 {
5464 union sctp_sockstore *ss;
5465
5466 error = priv_check(curthread,
5467 PRIV_NETINET_RESERVEDPORT);
5468 if (error)
5469 break;
5470
5471 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5472 /* SUPER USER CHECK? */
5473 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5474 break;
5475 }
5476 case SCTP_SET_PEER_PRIMARY_ADDR:
5477 {
5478 struct sctp_setpeerprim *sspp;
5479
5480 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5481 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5482 if (stcb != NULL) {
5483 struct sctp_ifa *ifa;
5484
5485 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5486 stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5487 if (ifa == NULL) {
5488 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5489 error = EINVAL;
5490 goto out_of_it;
5491 }
5492 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5493 /*
5494 * Must validate the ifa found is in
5495 * our ep
5496 */
5497 struct sctp_laddr *laddr;
5498 int found = 0;
5499
5500 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5501 if (laddr->ifa == NULL) {
5502 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5503 __FUNCTION__);
5504 continue;
5505 }
5506 if (laddr->ifa == ifa) {
5507 found = 1;
5508 break;
5509 }
5510 }
5511 if (!found) {
5512 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5513 error = EINVAL;
5514 goto out_of_it;
5515 }
5516 } else {
5517 switch (sspp->sspp_addr.ss_family) {
5518 #ifdef INET
5519 case AF_INET:
5520 {
5521 struct sockaddr_in *sin;
5522
5523 sin = (struct sockaddr_in *)&sspp->sspp_addr;
5524 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5525 &sin->sin_addr) != 0) {
5526 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5527 error = EINVAL;
5528 goto out_of_it;
5529 }
5530 break;
5531 }
5532 #endif
5533 #ifdef INET6
5534 case AF_INET6:
5535 {
5536 struct sockaddr_in6 *sin6;
5537
5538 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5539 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5540 &sin6->sin6_addr) != 0) {
5541 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5542 error = EINVAL;
5543 goto out_of_it;
5544 }
5545 break;
5546 }
5547 #endif
5548 default:
5549 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5550 error = EINVAL;
5551 goto out_of_it;
5552 }
5553 }
5554 if (sctp_set_primary_ip_address_sa(stcb,
5555 (struct sockaddr *)&sspp->sspp_addr) != 0) {
5556 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5557 error = EINVAL;
5558 }
5559 out_of_it:
5560 SCTP_TCB_UNLOCK(stcb);
5561 } else {
5562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5563 error = EINVAL;
5564 }
5565 break;
5566 }
5567 case SCTP_BINDX_ADD_ADDR:
5568 {
5569 struct sctp_getaddresses *addrs;
5570 struct thread *td;
5571
5572 td = (struct thread *)p;
5573 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5574 optsize);
5575 #ifdef INET
5576 if (addrs->addr->sa_family == AF_INET) {
5577 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5578 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5579 error = EINVAL;
5580 break;
5581 }
5582 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5583 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5584 break;
5585 }
5586 } else
5587 #endif
5588 #ifdef INET6
5589 if (addrs->addr->sa_family == AF_INET6) {
5590 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5591 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5592 error = EINVAL;
5593 break;
5594 }
5595 if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5596 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5597 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5598 break;
5599 }
5600 } else
5601 #endif
5602 {
5603 error = EAFNOSUPPORT;
5604 break;
5605 }
5606 sctp_bindx_add_address(so, inp, addrs->addr,
5607 addrs->sget_assoc_id, vrf_id,
5608 &error, p);
5609 break;
5610 }
5611 case SCTP_BINDX_REM_ADDR:
5612 {
5613 struct sctp_getaddresses *addrs;
5614 struct thread *td;
5615
5616 td = (struct thread *)p;
5617
5618 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5619 #ifdef INET
5620 if (addrs->addr->sa_family == AF_INET) {
5621 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5622 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5623 error = EINVAL;
5624 break;
5625 }
5626 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5627 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5628 break;
5629 }
5630 } else
5631 #endif
5632 #ifdef INET6
5633 if (addrs->addr->sa_family == AF_INET6) {
5634 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5635 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5636 error = EINVAL;
5637 break;
5638 }
5639 if (td != NULL &&
5640 (error = prison_local_ip6(td->td_ucred,
5641 &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5642 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5643 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5644 break;
5645 }
5646 } else
5647 #endif
5648 {
5649 error = EAFNOSUPPORT;
5650 break;
5651 }
5652 sctp_bindx_delete_address(inp, addrs->addr,
5653 addrs->sget_assoc_id, vrf_id,
5654 &error);
5655 break;
5656 }
5657 case SCTP_EVENT:
5658 {
5659 struct sctp_event *event;
5660 uint32_t event_type;
5661
5662 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5663 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5664 switch (event->se_type) {
5665 case SCTP_ASSOC_CHANGE:
5666 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5667 break;
5668 case SCTP_PEER_ADDR_CHANGE:
5669 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5670 break;
5671 case SCTP_REMOTE_ERROR:
5672 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5673 break;
5674 case SCTP_SEND_FAILED:
5675 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5676 break;
5677 case SCTP_SHUTDOWN_EVENT:
5678 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5679 break;
5680 case SCTP_ADAPTATION_INDICATION:
5681 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5682 break;
5683 case SCTP_PARTIAL_DELIVERY_EVENT:
5684 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5685 break;
5686 case SCTP_AUTHENTICATION_EVENT:
5687 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5688 break;
5689 case SCTP_STREAM_RESET_EVENT:
5690 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5691 break;
5692 case SCTP_SENDER_DRY_EVENT:
5693 event_type = SCTP_PCB_FLAGS_DRYEVNT;
5694 break;
5695 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5696 event_type = 0;
5697 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5698 error = ENOTSUP;
5699 break;
5700 case SCTP_ASSOC_RESET_EVENT:
5701 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
5702 break;
5703 case SCTP_STREAM_CHANGE_EVENT:
5704 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
5705 break;
5706 case SCTP_SEND_FAILED_EVENT:
5707 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
5708 break;
5709 default:
5710 event_type = 0;
5711 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5712 error = EINVAL;
5713 break;
5714 }
5715 if (event_type > 0) {
5716 if (stcb) {
5717 if (event->se_on) {
5718 sctp_stcb_feature_on(inp, stcb, event_type);
5719 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5720 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5721 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5722 (stcb->asoc.stream_queue_cnt == 0)) {
5723 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5724 }
5725 }
5726 } else {
5727 sctp_stcb_feature_off(inp, stcb, event_type);
5728 }
5729 SCTP_TCB_UNLOCK(stcb);
5730 } else {
5731 /*
5732 * We don't want to send up a storm
5733 * of events, so return an error for
5734 * sender dry events
5735 */
5736 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5737 ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5738 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5739 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5740 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5741 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5742 error = ENOTSUP;
5743 break;
5744 }
5745 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5746 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5747 (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5748 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5749 SCTP_INP_WLOCK(inp);
5750 if (event->se_on) {
5751 sctp_feature_on(inp, event_type);
5752 } else {
5753 sctp_feature_off(inp, event_type);
5754 }
5755 SCTP_INP_WUNLOCK(inp);
5756 }
5757 if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5758 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5759 SCTP_INP_RLOCK(inp);
5760 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5761 SCTP_TCB_LOCK(stcb);
5762 if (event->se_on) {
5763 sctp_stcb_feature_on(inp, stcb, event_type);
5764 } else {
5765 sctp_stcb_feature_off(inp, stcb, event_type);
5766 }
5767 SCTP_TCB_UNLOCK(stcb);
5768 }
5769 SCTP_INP_RUNLOCK(inp);
5770 }
5771 }
5772 }
5773 break;
5774 }
5775 case SCTP_RECVRCVINFO:
5776 {
5777 int *onoff;
5778
5779 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5780 SCTP_INP_WLOCK(inp);
5781 if (*onoff != 0) {
5782 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5783 } else {
5784 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5785 }
5786 SCTP_INP_WUNLOCK(inp);
5787 break;
5788 }
5789 case SCTP_RECVNXTINFO:
5790 {
5791 int *onoff;
5792
5793 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5794 SCTP_INP_WLOCK(inp);
5795 if (*onoff != 0) {
5796 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5797 } else {
5798 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5799 }
5800 SCTP_INP_WUNLOCK(inp);
5801 break;
5802 }
5803 case SCTP_DEFAULT_SNDINFO:
5804 {
5805 struct sctp_sndinfo *info;
5806 uint16_t policy;
5807
5808 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5809 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5810
5811 if (stcb) {
5812 if (info->snd_sid < stcb->asoc.streamoutcnt) {
5813 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5814 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5815 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5816 stcb->asoc.def_send.sinfo_flags |= policy;
5817 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5818 stcb->asoc.def_send.sinfo_context = info->snd_context;
5819 } else {
5820 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5821 error = EINVAL;
5822 }
5823 SCTP_TCB_UNLOCK(stcb);
5824 } else {
5825 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5826 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5827 (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5828 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5829 SCTP_INP_WLOCK(inp);
5830 inp->def_send.sinfo_stream = info->snd_sid;
5831 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5832 inp->def_send.sinfo_flags = info->snd_flags;
5833 inp->def_send.sinfo_flags |= policy;
5834 inp->def_send.sinfo_ppid = info->snd_ppid;
5835 inp->def_send.sinfo_context = info->snd_context;
5836 SCTP_INP_WUNLOCK(inp);
5837 }
5838 if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5839 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5840 SCTP_INP_RLOCK(inp);
5841 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5842 SCTP_TCB_LOCK(stcb);
5843 if (info->snd_sid < stcb->asoc.streamoutcnt) {
5844 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5845 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5846 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5847 stcb->asoc.def_send.sinfo_flags |= policy;
5848 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5849 stcb->asoc.def_send.sinfo_context = info->snd_context;
5850 }
5851 SCTP_TCB_UNLOCK(stcb);
5852 }
5853 SCTP_INP_RUNLOCK(inp);
5854 }
5855 }
5856 break;
5857 }
5858 case SCTP_DEFAULT_PRINFO:
5859 {
5860 struct sctp_default_prinfo *info;
5861
5862 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5863 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5864
5865 if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5866 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5867 error = EINVAL;
5868 break;
5869 }
5870 if (stcb) {
5871 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5872 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5873 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5874 SCTP_TCB_UNLOCK(stcb);
5875 } else {
5876 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5877 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5878 (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5879 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5880 SCTP_INP_WLOCK(inp);
5881 inp->def_send.sinfo_flags &= 0xfff0;
5882 inp->def_send.sinfo_flags |= info->pr_policy;
5883 inp->def_send.sinfo_timetolive = info->pr_value;
5884 SCTP_INP_WUNLOCK(inp);
5885 }
5886 if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5887 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5888 SCTP_INP_RLOCK(inp);
5889 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5890 SCTP_TCB_LOCK(stcb);
5891 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5892 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5893 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5894 SCTP_TCB_UNLOCK(stcb);
5895 }
5896 SCTP_INP_RUNLOCK(inp);
5897 }
5898 }
5899 break;
5900 }
5901 case SCTP_PEER_ADDR_THLDS:
5902 /* Applies to the specific association */
5903 {
5904 struct sctp_paddrthlds *thlds;
5905 struct sctp_nets *net;
5906
5907 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5908 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5909 net = NULL;
5910 if (stcb) {
5911 net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
5912 } else {
5913 /*
5914 * We increment here since
5915 * sctp_findassociation_ep_addr() wil do a
5916 * decrement if it finds the stcb as long as
5917 * the locked tcb (last argument) is NOT a
5918 * TCB.. aka NULL.
5919 */
5920 SCTP_INP_INCR_REF(inp);
5921 stcb = sctp_findassociation_ep_addr(&inp,
5922 (struct sockaddr *)&thlds->spt_address,
5923 &net, NULL, NULL);
5924 if (stcb == NULL) {
5925 SCTP_INP_DECR_REF(inp);
5926 }
5927 }
5928 if (stcb && (net == NULL)) {
5929 struct sockaddr *sa;
5930
5931 sa = (struct sockaddr *)&thlds->spt_address;
5932 #ifdef INET
5933 if (sa->sa_family == AF_INET) {
5934
5935 struct sockaddr_in *sin;
5936
5937 sin = (struct sockaddr_in *)sa;
5938 if (sin->sin_addr.s_addr) {
5939 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5940 SCTP_TCB_UNLOCK(stcb);
5941 error = EINVAL;
5942 break;
5943 }
5944 } else
5945 #endif
5946 #ifdef INET6
5947 if (sa->sa_family == AF_INET6) {
5948 struct sockaddr_in6 *sin6;
5949
5950 sin6 = (struct sockaddr_in6 *)sa;
5951 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5952 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5953 SCTP_TCB_UNLOCK(stcb);
5954 error = EINVAL;
5955 break;
5956 }
5957 } else
5958 #endif
5959 {
5960 error = EAFNOSUPPORT;
5961 SCTP_TCB_UNLOCK(stcb);
5962 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5963 break;
5964 }
5965 }
5966 if (stcb) {
5967 if (net) {
5968 if (net->dest_state & SCTP_ADDR_PF) {
5969 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5970 (net->failure_threshold <= thlds->spt_pathpfthld)) {
5971 net->dest_state &= ~SCTP_ADDR_PF;
5972 }
5973 } else {
5974 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5975 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5976 net->dest_state |= SCTP_ADDR_PF;
5977 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5978 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5979 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5980 }
5981 }
5982 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5983 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5984 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5985 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5986 }
5987 } else {
5988 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5989 net->dest_state |= SCTP_ADDR_REACHABLE;
5990 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5991 }
5992 }
5993 net->failure_threshold = thlds->spt_pathmaxrxt;
5994 net->pf_threshold = thlds->spt_pathpfthld;
5995 } else {
5996 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5997 if (net->dest_state & SCTP_ADDR_PF) {
5998 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5999 (net->failure_threshold <= thlds->spt_pathpfthld)) {
6000 net->dest_state &= ~SCTP_ADDR_PF;
6001 }
6002 } else {
6003 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
6004 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
6005 net->dest_state |= SCTP_ADDR_PF;
6006 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6007 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
6008 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6009 }
6010 }
6011 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6012 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
6013 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6014 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6015 }
6016 } else {
6017 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
6018 net->dest_state |= SCTP_ADDR_REACHABLE;
6019 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6020 }
6021 }
6022 net->failure_threshold = thlds->spt_pathmaxrxt;
6023 net->pf_threshold = thlds->spt_pathpfthld;
6024 }
6025 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6026 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6027 }
6028 } else {
6029 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6030 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6031 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
6032 SCTP_INP_WLOCK(inp);
6033 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6034 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6035 SCTP_INP_WUNLOCK(inp);
6036 } else {
6037 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6038 error = EINVAL;
6039 }
6040 }
6041 break;
6042 }
6043 case SCTP_REMOTE_UDP_ENCAPS_PORT:
6044 {
6045 struct sctp_udpencaps *encaps;
6046 struct sctp_nets *net;
6047
6048 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6049 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6050 if (stcb) {
6051 net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
6052 } else {
6053 /*
6054 * We increment here since
6055 * sctp_findassociation_ep_addr() wil do a
6056 * decrement if it finds the stcb as long as
6057 * the locked tcb (last argument) is NOT a
6058 * TCB.. aka NULL.
6059 */
6060 net = NULL;
6061 SCTP_INP_INCR_REF(inp);
6062 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
6063 if (stcb == NULL) {
6064 SCTP_INP_DECR_REF(inp);
6065 }
6066 }
6067 if (stcb && (net == NULL)) {
6068 struct sockaddr *sa;
6069
6070 sa = (struct sockaddr *)&encaps->sue_address;
6071 #ifdef INET
6072 if (sa->sa_family == AF_INET) {
6073
6074 struct sockaddr_in *sin;
6075
6076 sin = (struct sockaddr_in *)sa;
6077 if (sin->sin_addr.s_addr) {
6078 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6079 SCTP_TCB_UNLOCK(stcb);
6080 error = EINVAL;
6081 break;
6082 }
6083 } else
6084 #endif
6085 #ifdef INET6
6086 if (sa->sa_family == AF_INET6) {
6087 struct sockaddr_in6 *sin6;
6088
6089 sin6 = (struct sockaddr_in6 *)sa;
6090 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6091 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6092 SCTP_TCB_UNLOCK(stcb);
6093 error = EINVAL;
6094 break;
6095 }
6096 } else
6097 #endif
6098 {
6099 error = EAFNOSUPPORT;
6100 SCTP_TCB_UNLOCK(stcb);
6101 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6102 break;
6103 }
6104 }
6105 if (stcb) {
6106 if (net) {
6107 net->port = encaps->sue_port;
6108 } else {
6109 stcb->asoc.port = encaps->sue_port;
6110 }
6111 SCTP_TCB_UNLOCK(stcb);
6112 } else {
6113 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6114 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6115 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
6116 SCTP_INP_WLOCK(inp);
6117 inp->sctp_ep.port = encaps->sue_port;
6118 SCTP_INP_WUNLOCK(inp);
6119 } else {
6120 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6121 error = EINVAL;
6122 }
6123 }
6124 break;
6125 }
6126 case SCTP_ECN_SUPPORTED:
6127 {
6128 struct sctp_assoc_value *av;
6129
6130 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6131 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6132
6133 if (stcb) {
6134 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6135 error = EINVAL;
6136 SCTP_TCB_UNLOCK(stcb);
6137 } else {
6138 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6139 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6140 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6141 SCTP_INP_WLOCK(inp);
6142 if (av->assoc_value == 0) {
6143 inp->ecn_supported = 0;
6144 } else {
6145 inp->ecn_supported = 1;
6146 }
6147 SCTP_INP_WUNLOCK(inp);
6148 } else {
6149 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6150 error = EINVAL;
6151 }
6152 }
6153 break;
6154 }
6155 case SCTP_PR_SUPPORTED:
6156 {
6157 struct sctp_assoc_value *av;
6158
6159 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6160 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6161
6162 if (stcb) {
6163 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6164 error = EINVAL;
6165 SCTP_TCB_UNLOCK(stcb);
6166 } else {
6167 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6168 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6169 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6170 SCTP_INP_WLOCK(inp);
6171 if (av->assoc_value == 0) {
6172 inp->prsctp_supported = 0;
6173 } else {
6174 inp->prsctp_supported = 1;
6175 }
6176 SCTP_INP_WUNLOCK(inp);
6177 } else {
6178 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6179 error = EINVAL;
6180 }
6181 }
6182 break;
6183 }
6184 case SCTP_AUTH_SUPPORTED:
6185 {
6186 struct sctp_assoc_value *av;
6187
6188 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6189 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6190
6191 if (stcb) {
6192 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6193 error = EINVAL;
6194 SCTP_TCB_UNLOCK(stcb);
6195 } else {
6196 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6197 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6198 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6199 if ((av->assoc_value == 0) &&
6200 (inp->asconf_supported == 1)) {
6201 /*
6202 * AUTH is required for
6203 * ASCONF
6204 */
6205 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6206 error = EINVAL;
6207 } else {
6208 SCTP_INP_WLOCK(inp);
6209 if (av->assoc_value == 0) {
6210 inp->auth_supported = 0;
6211 } else {
6212 inp->auth_supported = 1;
6213 }
6214 SCTP_INP_WUNLOCK(inp);
6215 }
6216 } else {
6217 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6218 error = EINVAL;
6219 }
6220 }
6221 break;
6222 }
6223 case SCTP_ASCONF_SUPPORTED:
6224 {
6225 struct sctp_assoc_value *av;
6226
6227 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6228 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6229
6230 if (stcb) {
6231 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6232 error = EINVAL;
6233 SCTP_TCB_UNLOCK(stcb);
6234 } else {
6235 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6236 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6237 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6238 if ((av->assoc_value != 0) &&
6239 (inp->auth_supported == 0)) {
6240 /*
6241 * AUTH is required for
6242 * ASCONF
6243 */
6244 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6245 error = EINVAL;
6246 } else {
6247 SCTP_INP_WLOCK(inp);
6248 if (av->assoc_value == 0) {
6249 inp->asconf_supported = 0;
6250 sctp_auth_delete_chunk(SCTP_ASCONF,
6251 inp->sctp_ep.local_auth_chunks);
6252 sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6253 inp->sctp_ep.local_auth_chunks);
6254 } else {
6255 inp->asconf_supported = 1;
6256 sctp_auth_add_chunk(SCTP_ASCONF,
6257 inp->sctp_ep.local_auth_chunks);
6258 sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6259 inp->sctp_ep.local_auth_chunks);
6260 }
6261 SCTP_INP_WUNLOCK(inp);
6262 }
6263 } else {
6264 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6265 error = EINVAL;
6266 }
6267 }
6268 break;
6269 }
6270 case SCTP_RECONFIG_SUPPORTED:
6271 {
6272 struct sctp_assoc_value *av;
6273
6274 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6275 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6276
6277 if (stcb) {
6278 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6279 error = EINVAL;
6280 SCTP_TCB_UNLOCK(stcb);
6281 } else {
6282 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6283 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6284 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6285 SCTP_INP_WLOCK(inp);
6286 if (av->assoc_value == 0) {
6287 inp->reconfig_supported = 0;
6288 } else {
6289 inp->reconfig_supported = 1;
6290 }
6291 SCTP_INP_WUNLOCK(inp);
6292 } else {
6293 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6294 error = EINVAL;
6295 }
6296 }
6297 break;
6298 }
6299 case SCTP_NRSACK_SUPPORTED:
6300 {
6301 struct sctp_assoc_value *av;
6302
6303 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6304 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6305
6306 if (stcb) {
6307 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6308 error = EINVAL;
6309 SCTP_TCB_UNLOCK(stcb);
6310 } else {
6311 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6312 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6313 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6314 SCTP_INP_WLOCK(inp);
6315 if (av->assoc_value == 0) {
6316 inp->nrsack_supported = 0;
6317 } else {
6318 inp->nrsack_supported = 1;
6319 }
6320 SCTP_INP_WUNLOCK(inp);
6321 } else {
6322 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6323 error = EINVAL;
6324 }
6325 }
6326 break;
6327 }
6328 case SCTP_PKTDROP_SUPPORTED:
6329 {
6330 struct sctp_assoc_value *av;
6331
6332 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6333 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6334
6335 if (stcb) {
6336 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6337 error = EINVAL;
6338 SCTP_TCB_UNLOCK(stcb);
6339 } else {
6340 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6341 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6342 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
6343 SCTP_INP_WLOCK(inp);
6344 if (av->assoc_value == 0) {
6345 inp->pktdrop_supported = 0;
6346 } else {
6347 inp->pktdrop_supported = 1;
6348 }
6349 SCTP_INP_WUNLOCK(inp);
6350 } else {
6351 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6352 error = EINVAL;
6353 }
6354 }
6355 break;
6356 }
6357 default:
6358 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6359 error = ENOPROTOOPT;
6360 break;
6361 } /* end switch (opt) */
6362 return (error);
6363 }
6364
6365 int
6366 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6367 {
6368 void *optval = NULL;
6369 size_t optsize = 0;
6370 void *p;
6371 int error = 0;
6372
6373 if (sopt->sopt_level != IPPROTO_SCTP) {
6374 /* wrong proto level... send back up to IP */
6375 #ifdef INET6
6376 if (INP_CHECK_SOCKAF(so, AF_INET6))
6377 error = ip6_ctloutput(so, sopt);
6378 #endif /* INET6 */
6379 #if defined(INET) && defined(INET6)
6380 else
6381 #endif
6382 #ifdef INET
6383 error = ip_ctloutput(so, sopt);
6384 #endif
6385 return (error);
6386 }
6387 optsize = sopt->sopt_valsize;
6388 if (optsize) {
6389 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6390 if (optval == NULL) {
6391 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6392 return (ENOBUFS);
6393 }
6394 error = sooptcopyin(sopt, optval, optsize, optsize);
6395 if (error) {
6396 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6397 goto out;
6398 }
6399 }
6400 p = (void *)sopt->sopt_td;
6401 if (sopt->sopt_dir == SOPT_SET) {
6402 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6403 } else if (sopt->sopt_dir == SOPT_GET) {
6404 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6405 } else {
6406 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6407 error = EINVAL;
6408 }
6409 if ((error == 0) && (optval != NULL)) {
6410 error = sooptcopyout(sopt, optval, optsize);
6411 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6412 } else if (optval != NULL) {
6413 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6414 }
6415 out:
6416 return (error);
6417 }
6418
6419 #ifdef INET
6420 static int
6421 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6422 {
6423 int error = 0;
6424 int create_lock_on = 0;
6425 uint32_t vrf_id;
6426 struct sctp_inpcb *inp;
6427 struct sctp_tcb *stcb = NULL;
6428
6429 inp = (struct sctp_inpcb *)so->so_pcb;
6430 if (inp == NULL) {
6431 /* I made the same as TCP since we are not setup? */
6432 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6433 return (ECONNRESET);
6434 }
6435 if (addr == NULL) {
6436 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6437 return EINVAL;
6438 }
6439 switch (addr->sa_family) {
6440 #ifdef INET6
6441 case AF_INET6:
6442 {
6443 struct sockaddr_in6 *sin6p;
6444
6445 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6446 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6447 return (EINVAL);
6448 }
6449 sin6p = (struct sockaddr_in6 *)addr;
6450 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
6451 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6452 return (error);
6453 }
6454 break;
6455 }
6456 #endif
6457 #ifdef INET
6458 case AF_INET:
6459 {
6460 struct sockaddr_in *sinp;
6461
6462 if (addr->sa_len != sizeof(struct sockaddr_in)) {
6463 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6464 return (EINVAL);
6465 }
6466 sinp = (struct sockaddr_in *)addr;
6467 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
6468 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6469 return (error);
6470 }
6471 break;
6472 }
6473 #endif
6474 default:
6475 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6476 return (EAFNOSUPPORT);
6477 }
6478 SCTP_INP_INCR_REF(inp);
6479 SCTP_ASOC_CREATE_LOCK(inp);
6480 create_lock_on = 1;
6481
6482
6483 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
6484 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
6485 /* Should I really unlock ? */
6486 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
6487 error = EFAULT;
6488 goto out_now;
6489 }
6490 #ifdef INET6
6491 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
6492 (addr->sa_family == AF_INET6)) {
6493 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6494 error = EINVAL;
6495 goto out_now;
6496 }
6497 #endif
6498 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6499 SCTP_PCB_FLAGS_UNBOUND) {
6500 /* Bind a ephemeral port */
6501 error = sctp_inpcb_bind(so, NULL, NULL, p);
6502 if (error) {
6503 goto out_now;
6504 }
6505 }
6506 /* Now do we connect? */
6507 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6508 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6509 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6510 error = EINVAL;
6511 goto out_now;
6512 }
6513 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6514 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6515 /* We are already connected AND the TCP model */
6516 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6517 error = EADDRINUSE;
6518 goto out_now;
6519 }
6520 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6521 SCTP_INP_RLOCK(inp);
6522 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6523 SCTP_INP_RUNLOCK(inp);
6524 } else {
6525 /*
6526 * We increment here since sctp_findassociation_ep_addr()
6527 * will do a decrement if it finds the stcb as long as the
6528 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6529 */
6530 SCTP_INP_INCR_REF(inp);
6531 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6532 if (stcb == NULL) {
6533 SCTP_INP_DECR_REF(inp);
6534 } else {
6535 SCTP_TCB_UNLOCK(stcb);
6536 }
6537 }
6538 if (stcb != NULL) {
6539 /* Already have or am bring up an association */
6540 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6541 error = EALREADY;
6542 goto out_now;
6543 }
6544 vrf_id = inp->def_vrf_id;
6545 /* We are GOOD to go */
6546 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6547 if (stcb == NULL) {
6548 /* Gak! no memory */
6549 goto out_now;
6550 }
6551 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6552 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6553 /* Set the connected flag so we can queue data */
6554 soisconnecting(so);
6555 }
6556 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6557 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6558
6559 /* initialize authentication parameters for the assoc */
6560 sctp_initialize_auth_params(inp, stcb);
6561
6562 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6563 SCTP_TCB_UNLOCK(stcb);
6564 out_now:
6565 if (create_lock_on) {
6566 SCTP_ASOC_CREATE_UNLOCK(inp);
6567 }
6568 SCTP_INP_DECR_REF(inp);
6569 return (error);
6570 }
6571
6572 #endif
6573
6574 int
6575 sctp_listen(struct socket *so, int backlog, struct thread *p)
6576 {
6577 /*
6578 * Note this module depends on the protocol processing being called
6579 * AFTER any socket level flags and backlog are applied to the
6580 * socket. The traditional way that the socket flags are applied is
6581 * AFTER protocol processing. We have made a change to the
6582 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
6583 * place if the socket API for SCTP is to work properly.
6584 */
6585
6586 int error = 0;
6587 struct sctp_inpcb *inp;
6588
6589 inp = (struct sctp_inpcb *)so->so_pcb;
6590 if (inp == NULL) {
6591 /* I made the same as TCP since we are not setup? */
6592 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6593 return (ECONNRESET);
6594 }
6595 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6596 /* See if we have a listener */
6597 struct sctp_inpcb *tinp;
6598 union sctp_sockstore store;
6599
6600 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6601 /* not bound all */
6602 struct sctp_laddr *laddr;
6603
6604 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6605 memcpy(&store, &laddr->ifa->address, sizeof(store));
6606 switch (store.sa.sa_family) {
6607 #ifdef INET
6608 case AF_INET:
6609 store.sin.sin_port = inp->sctp_lport;
6610 break;
6611 #endif
6612 #ifdef INET6
6613 case AF_INET6:
6614 store.sin6.sin6_port = inp->sctp_lport;
6615 break;
6616 #endif
6617 default:
6618 break;
6619 }
6620 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6621 if (tinp && (tinp != inp) &&
6622 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6623 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6624 (tinp->sctp_socket->so_qlimit)) {
6625 /*
6626 * we have a listener already and
6627 * its not this inp.
6628 */
6629 SCTP_INP_DECR_REF(tinp);
6630 return (EADDRINUSE);
6631 } else if (tinp) {
6632 SCTP_INP_DECR_REF(tinp);
6633 }
6634 }
6635 } else {
6636 /* Setup a local addr bound all */
6637 memset(&store, 0, sizeof(store));
6638 #ifdef INET6
6639 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6640 store.sa.sa_family = AF_INET6;
6641 store.sa.sa_len = sizeof(struct sockaddr_in6);
6642 }
6643 #endif
6644 #ifdef INET
6645 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6646 store.sa.sa_family = AF_INET;
6647 store.sa.sa_len = sizeof(struct sockaddr_in);
6648 }
6649 #endif
6650 switch (store.sa.sa_family) {
6651 #ifdef INET
6652 case AF_INET:
6653 store.sin.sin_port = inp->sctp_lport;
6654 break;
6655 #endif
6656 #ifdef INET6
6657 case AF_INET6:
6658 store.sin6.sin6_port = inp->sctp_lport;
6659 break;
6660 #endif
6661 default:
6662 break;
6663 }
6664 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6665 if (tinp && (tinp != inp) &&
6666 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6667 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6668 (tinp->sctp_socket->so_qlimit)) {
6669 /*
6670 * we have a listener already and its not
6671 * this inp.
6672 */
6673 SCTP_INP_DECR_REF(tinp);
6674 return (EADDRINUSE);
6675 } else if (tinp) {
6676 SCTP_INP_DECR_REF(inp);
6677 }
6678 }
6679 }
6680 SCTP_INP_RLOCK(inp);
6681 #ifdef SCTP_LOCK_LOGGING
6682 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6683 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6684 }
6685 #endif
6686 SOCK_LOCK(so);
6687 error = solisten_proto_check(so);
6688 if (error) {
6689 SOCK_UNLOCK(so);
6690 SCTP_INP_RUNLOCK(inp);
6691 return (error);
6692 }
6693 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6694 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6695 /*
6696 * The unlucky case - We are in the tcp pool with this guy.
6697 * - Someone else is in the main inp slot. - We must move
6698 * this guy (the listener) to the main slot - We must then
6699 * move the guy that was listener to the TCP Pool.
6700 */
6701 if (sctp_swap_inpcb_for_listen(inp)) {
6702 goto in_use;
6703 }
6704 }
6705 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6706 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6707 /* We are already connected AND the TCP model */
6708 in_use:
6709 SCTP_INP_RUNLOCK(inp);
6710 SOCK_UNLOCK(so);
6711 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6712 return (EADDRINUSE);
6713 }
6714 SCTP_INP_RUNLOCK(inp);
6715 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6716 /* We must do a bind. */
6717 SOCK_UNLOCK(so);
6718 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6719 /* bind error, probably perm */
6720 return (error);
6721 }
6722 SOCK_LOCK(so);
6723 }
6724 /* It appears for 7.0 and on, we must always call this. */
6725 solisten_proto(so, backlog);
6726 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6727 /* remove the ACCEPTCONN flag for one-to-many sockets */
6728 so->so_options &= ~SO_ACCEPTCONN;
6729 }
6730 if (backlog == 0) {
6731 /* turning off listen */
6732 so->so_options &= ~SO_ACCEPTCONN;
6733 }
6734 SOCK_UNLOCK(so);
6735 return (error);
6736 }
6737
6738 static int sctp_defered_wakeup_cnt = 0;
6739
6740 int
6741 sctp_accept(struct socket *so, struct sockaddr **addr)
6742 {
6743 struct sctp_tcb *stcb;
6744 struct sctp_inpcb *inp;
6745 union sctp_sockstore store;
6746
6747 #ifdef INET6
6748 int error;
6749
6750 #endif
6751 inp = (struct sctp_inpcb *)so->so_pcb;
6752
6753 if (inp == NULL) {
6754 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6755 return (ECONNRESET);
6756 }
6757 SCTP_INP_RLOCK(inp);
6758 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6759 SCTP_INP_RUNLOCK(inp);
6760 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6761 return (EOPNOTSUPP);
6762 }
6763 if (so->so_state & SS_ISDISCONNECTED) {
6764 SCTP_INP_RUNLOCK(inp);
6765 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6766 return (ECONNABORTED);
6767 }
6768 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6769 if (stcb == NULL) {
6770 SCTP_INP_RUNLOCK(inp);
6771 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6772 return (ECONNRESET);
6773 }
6774 SCTP_TCB_LOCK(stcb);
6775 SCTP_INP_RUNLOCK(inp);
6776 store = stcb->asoc.primary_destination->ro._l_addr;
6777 stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6778 SCTP_TCB_UNLOCK(stcb);
6779 switch (store.sa.sa_family) {
6780 #ifdef INET
6781 case AF_INET:
6782 {
6783 struct sockaddr_in *sin;
6784
6785 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6786 if (sin == NULL)
6787 return (ENOMEM);
6788 sin->sin_family = AF_INET;
6789 sin->sin_len = sizeof(*sin);
6790 sin->sin_port = store.sin.sin_port;
6791 sin->sin_addr = store.sin.sin_addr;
6792 *addr = (struct sockaddr *)sin;
6793 break;
6794 }
6795 #endif
6796 #ifdef INET6
6797 case AF_INET6:
6798 {
6799 struct sockaddr_in6 *sin6;
6800
6801 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6802 if (sin6 == NULL)
6803 return (ENOMEM);
6804 sin6->sin6_family = AF_INET6;
6805 sin6->sin6_len = sizeof(*sin6);
6806 sin6->sin6_port = store.sin6.sin6_port;
6807 sin6->sin6_addr = store.sin6.sin6_addr;
6808 if ((error = sa6_recoverscope(sin6)) != 0) {
6809 SCTP_FREE_SONAME(sin6);
6810 return (error);
6811 }
6812 *addr = (struct sockaddr *)sin6;
6813 break;
6814 }
6815 #endif
6816 default:
6817 /* TSNH */
6818 break;
6819 }
6820 /* Wake any delayed sleep action */
6821 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6822 SCTP_INP_WLOCK(inp);
6823 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6824 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6825 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6826 SCTP_INP_WUNLOCK(inp);
6827 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6828 if (sowriteable(inp->sctp_socket)) {
6829 sowwakeup_locked(inp->sctp_socket);
6830 } else {
6831 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6832 }
6833 SCTP_INP_WLOCK(inp);
6834 }
6835 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6836 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6837 SCTP_INP_WUNLOCK(inp);
6838 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6839 if (soreadable(inp->sctp_socket)) {
6840 sctp_defered_wakeup_cnt++;
6841 sorwakeup_locked(inp->sctp_socket);
6842 } else {
6843 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6844 }
6845 SCTP_INP_WLOCK(inp);
6846 }
6847 SCTP_INP_WUNLOCK(inp);
6848 }
6849 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6850 SCTP_TCB_LOCK(stcb);
6851 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6852 }
6853 return (0);
6854 }
6855
6856 #ifdef INET
6857 int
6858 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6859 {
6860 struct sockaddr_in *sin;
6861 uint32_t vrf_id;
6862 struct sctp_inpcb *inp;
6863 struct sctp_ifa *sctp_ifa;
6864
6865 /*
6866 * Do the malloc first in case it blocks.
6867 */
6868 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6869 if (sin == NULL)
6870 return (ENOMEM);
6871 sin->sin_family = AF_INET;
6872 sin->sin_len = sizeof(*sin);
6873 inp = (struct sctp_inpcb *)so->so_pcb;
6874 if (!inp) {
6875 SCTP_FREE_SONAME(sin);
6876 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6877 return (ECONNRESET);
6878 }
6879 SCTP_INP_RLOCK(inp);
6880 sin->sin_port = inp->sctp_lport;
6881 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6882 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6883 struct sctp_tcb *stcb;
6884 struct sockaddr_in *sin_a;
6885 struct sctp_nets *net;
6886 int fnd;
6887
6888 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6889 if (stcb == NULL) {
6890 goto notConn;
6891 }
6892 fnd = 0;
6893 sin_a = NULL;
6894 SCTP_TCB_LOCK(stcb);
6895 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6896 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6897 if (sin_a == NULL)
6898 /* this will make coverity happy */
6899 continue;
6900
6901 if (sin_a->sin_family == AF_INET) {
6902 fnd = 1;
6903 break;
6904 }
6905 }
6906 if ((!fnd) || (sin_a == NULL)) {
6907 /* punt */
6908 SCTP_TCB_UNLOCK(stcb);
6909 goto notConn;
6910 }
6911 vrf_id = inp->def_vrf_id;
6912 sctp_ifa = sctp_source_address_selection(inp,
6913 stcb,
6914 (sctp_route_t *) & net->ro,
6915 net, 0, vrf_id);
6916 if (sctp_ifa) {
6917 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6918 sctp_free_ifa(sctp_ifa);
6919 }
6920 SCTP_TCB_UNLOCK(stcb);
6921 } else {
6922 /* For the bound all case you get back 0 */
6923 notConn:
6924 sin->sin_addr.s_addr = 0;
6925 }
6926
6927 } else {
6928 /* Take the first IPv4 address in the list */
6929 struct sctp_laddr *laddr;
6930 int fnd = 0;
6931
6932 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6933 if (laddr->ifa->address.sa.sa_family == AF_INET) {
6934 struct sockaddr_in *sin_a;
6935
6936 sin_a = &laddr->ifa->address.sin;
6937 sin->sin_addr = sin_a->sin_addr;
6938 fnd = 1;
6939 break;
6940 }
6941 }
6942 if (!fnd) {
6943 SCTP_FREE_SONAME(sin);
6944 SCTP_INP_RUNLOCK(inp);
6945 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6946 return (ENOENT);
6947 }
6948 }
6949 SCTP_INP_RUNLOCK(inp);
6950 (*addr) = (struct sockaddr *)sin;
6951 return (0);
6952 }
6953
6954 int
6955 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6956 {
6957 struct sockaddr_in *sin;
6958 int fnd;
6959 struct sockaddr_in *sin_a;
6960 struct sctp_inpcb *inp;
6961 struct sctp_tcb *stcb;
6962 struct sctp_nets *net;
6963
6964 /* Do the malloc first in case it blocks. */
6965 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6966 if (sin == NULL)
6967 return (ENOMEM);
6968 sin->sin_family = AF_INET;
6969 sin->sin_len = sizeof(*sin);
6970
6971 inp = (struct sctp_inpcb *)so->so_pcb;
6972 if ((inp == NULL) ||
6973 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6974 /* UDP type and listeners will drop out here */
6975 SCTP_FREE_SONAME(sin);
6976 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6977 return (ENOTCONN);
6978 }
6979 SCTP_INP_RLOCK(inp);
6980 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6981 if (stcb) {
6982 SCTP_TCB_LOCK(stcb);
6983 }
6984 SCTP_INP_RUNLOCK(inp);
6985 if (stcb == NULL) {
6986 SCTP_FREE_SONAME(sin);
6987 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6988 return (ECONNRESET);
6989 }
6990 fnd = 0;
6991 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6992 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6993 if (sin_a->sin_family == AF_INET) {
6994 fnd = 1;
6995 sin->sin_port = stcb->rport;
6996 sin->sin_addr = sin_a->sin_addr;
6997 break;
6998 }
6999 }
7000 SCTP_TCB_UNLOCK(stcb);
7001 if (!fnd) {
7002 /* No IPv4 address */
7003 SCTP_FREE_SONAME(sin);
7004 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7005 return (ENOENT);
7006 }
7007 (*addr) = (struct sockaddr *)sin;
7008 return (0);
7009 }
7010
7011 struct pr_usrreqs sctp_usrreqs = {
7012 .pru_abort = sctp_abort,
7013 .pru_accept = sctp_accept,
7014 .pru_attach = sctp_attach,
7015 .pru_bind = sctp_bind,
7016 .pru_connect = sctp_connect,
7017 .pru_control = in_control,
7018 .pru_close = sctp_close,
7019 .pru_detach = sctp_close,
7020 .pru_sopoll = sopoll_generic,
7021 .pru_flush = sctp_flush,
7022 .pru_disconnect = sctp_disconnect,
7023 .pru_listen = sctp_listen,
7024 .pru_peeraddr = sctp_peeraddr,
7025 .pru_send = sctp_sendm,
7026 .pru_shutdown = sctp_shutdown,
7027 .pru_sockaddr = sctp_ingetaddr,
7028 .pru_sosend = sctp_sosend,
7029 .pru_soreceive = sctp_soreceive
7030 };
7031
7032 #endif
Cache object: f2617a5a0334281b08e5f8f94c988911
|