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: stable/9/sys/netinet/sctp_usrreq.c 277807 2015-01-27 19:36:08Z 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
sctp_init(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
sctp_finish(void)92 sctp_finish(void)
93 {
94 sctp_pcb_finish();
95 }
96
97
98
99 void
sctp_pathmtu_adjustment(struct sctp_tcb * stcb,uint16_t nxtsz)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
sctp_notify_mbuf(struct sctp_inpcb * inp,struct sctp_tcb * stcb,struct sctp_nets * net,struct ip * ip,struct sctphdr * sh)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 = 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 #endif
218
219 void
sctp_notify(struct sctp_inpcb * inp,struct ip * ip,struct sctphdr * sh,struct sockaddr * to,struct sctp_tcb * stcb,struct sctp_nets * net)220 sctp_notify(struct sctp_inpcb *inp,
221 struct ip *ip,
222 struct sctphdr *sh,
223 struct sockaddr *to,
224 struct sctp_tcb *stcb,
225 struct sctp_nets *net)
226 {
227 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
228 struct socket *so;
229
230 #endif
231 struct icmp *icmph;
232
233 /* protection */
234 if ((inp == NULL) || (stcb == NULL) || (net == NULL) ||
235 (sh == NULL) || (to == NULL)) {
236 if (stcb)
237 SCTP_TCB_UNLOCK(stcb);
238 return;
239 }
240 /* First job is to verify the vtag matches what I would send */
241 if (ntohl(sh->v_tag) != (stcb->asoc.peer_vtag)) {
242 SCTP_TCB_UNLOCK(stcb);
243 return;
244 }
245 icmph = (struct icmp *)((caddr_t)ip - (sizeof(struct icmp) -
246 sizeof(struct ip)));
247 if (icmph->icmp_type != ICMP_UNREACH) {
248 /* We only care about unreachable */
249 SCTP_TCB_UNLOCK(stcb);
250 return;
251 }
252 if ((icmph->icmp_code == ICMP_UNREACH_NET) ||
253 (icmph->icmp_code == ICMP_UNREACH_HOST) ||
254 (icmph->icmp_code == ICMP_UNREACH_NET_UNKNOWN) ||
255 (icmph->icmp_code == ICMP_UNREACH_HOST_UNKNOWN) ||
256 (icmph->icmp_code == ICMP_UNREACH_ISOLATED) ||
257 (icmph->icmp_code == ICMP_UNREACH_NET_PROHIB) ||
258 (icmph->icmp_code == ICMP_UNREACH_HOST_PROHIB) ||
259 (icmph->icmp_code == ICMP_UNREACH_FILTER_PROHIB)) {
260
261 /*
262 * Hmm reachablity problems we must examine closely. If its
263 * not reachable, we may have lost a network. Or if there is
264 * NO protocol at the other end named SCTP. well we consider
265 * it a OOTB abort.
266 */
267 if (net->dest_state & SCTP_ADDR_REACHABLE) {
268 /* Ok that destination is NOT reachable */
269 net->dest_state &= ~SCTP_ADDR_REACHABLE;
270 net->dest_state &= ~SCTP_ADDR_PF;
271 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN,
272 stcb, 0,
273 (void *)net, SCTP_SO_NOT_LOCKED);
274 }
275 SCTP_TCB_UNLOCK(stcb);
276 } else if ((icmph->icmp_code == ICMP_UNREACH_PROTOCOL) ||
277 (icmph->icmp_code == ICMP_UNREACH_PORT)) {
278 /*
279 * Here the peer is either playing tricks on us, including
280 * an address that belongs to someone who does not support
281 * SCTP OR was a userland implementation that shutdown and
282 * now is dead. In either case treat it like a OOTB abort
283 * with no TCB
284 */
285 sctp_abort_notification(stcb, 1, 0, NULL, SCTP_SO_NOT_LOCKED);
286 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
287 so = SCTP_INP_SO(inp);
288 atomic_add_int(&stcb->asoc.refcnt, 1);
289 SCTP_TCB_UNLOCK(stcb);
290 SCTP_SOCKET_LOCK(so, 1);
291 SCTP_TCB_LOCK(stcb);
292 atomic_subtract_int(&stcb->asoc.refcnt, 1);
293 #endif
294 (void)sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_2);
295 #if defined(__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
296 SCTP_SOCKET_UNLOCK(so, 1);
297 /* SCTP_TCB_UNLOCK(stcb); MT: I think this is not needed. */
298 #endif
299 /* no need to unlock here, since the TCB is gone */
300 } else {
301 SCTP_TCB_UNLOCK(stcb);
302 }
303 }
304
305 #ifdef INET
306 void
sctp_ctlinput(cmd,sa,vip)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
sctp_getcred(SYSCTL_HANDLER_ARGS)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
sctp_abort(struct socket * so)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
sctp_attach(struct socket * so,int proto SCTP_UNUSED,struct thread * p SCTP_UNUSED)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
sctp_bind(struct socket * so,struct sockaddr * addr,struct thread * p)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
sctp_close(struct socket * so)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
sctp_sendm(struct socket * so,int flags,struct mbuf * m,struct sockaddr * addr,struct mbuf * control,struct thread * p)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
sctp_disconnect(struct socket * so)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_DONTWAIT, 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
sctp_flush(struct socket * so,int how)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
sctp_shutdown(struct socket * so)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
sctp_fill_user_address(struct sockaddr_storage * ss,struct sockaddr * sa)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
sctp_fill_up_addresses_vrf(struct sctp_inpcb * inp,struct sctp_tcb * stcb,size_t limit,struct sockaddr_storage * sas,uint32_t vrf_id)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 = (struct sockaddr_in *)&sctp_ifa->address.sa;
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 = (struct sockaddr_in6 *)&sctp_ifa->address.sa;
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
sctp_fill_up_addresses(struct sctp_inpcb * inp,struct sctp_tcb * stcb,size_t limit,struct sockaddr_storage * sas)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
sctp_count_max_addresses_vrf(struct sctp_inpcb * inp,uint32_t vrf_id)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
sctp_count_max_addresses(struct sctp_inpcb * inp)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
sctp_do_connect_x(struct socket * so,struct sctp_inpcb * inp,void * optval,size_t optsize,void * p,int delay)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
sctp_getopt(struct socket * so,int optname,void * optval,size_t * optsize,void * p)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_ENABLE_STREAM_RESET:
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 = (uint32_t) stcb->asoc.local_strreset_support;
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 = (uint32_t) inp->local_strreset_support;
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 default:
3326 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3327 error = ENOPROTOOPT;
3328 break;
3329 } /* end switch (sopt->sopt_name) */
3330 if (error) {
3331 *optsize = 0;
3332 }
3333 return (error);
3334 }
3335
3336 static int
sctp_setopt(struct socket * so,int optname,void * optval,size_t optsize,void * p)3337 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
3338 void *p)
3339 {
3340 int error, set_opt;
3341 uint32_t *mopt;
3342 struct sctp_tcb *stcb = NULL;
3343 struct sctp_inpcb *inp = NULL;
3344 uint32_t vrf_id;
3345
3346 if (optval == NULL) {
3347 SCTP_PRINTF("optval is NULL\n");
3348 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3349 return (EINVAL);
3350 }
3351 inp = (struct sctp_inpcb *)so->so_pcb;
3352 if (inp == NULL) {
3353 SCTP_PRINTF("inp is NULL?\n");
3354 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3355 return (EINVAL);
3356 }
3357 vrf_id = inp->def_vrf_id;
3358
3359 error = 0;
3360 switch (optname) {
3361 case SCTP_NODELAY:
3362 case SCTP_AUTOCLOSE:
3363 case SCTP_AUTO_ASCONF:
3364 case SCTP_EXPLICIT_EOR:
3365 case SCTP_DISABLE_FRAGMENTS:
3366 case SCTP_USE_EXT_RCVINFO:
3367 case SCTP_I_WANT_MAPPED_V4_ADDR:
3368 /* copy in the option value */
3369 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3370 set_opt = 0;
3371 if (error)
3372 break;
3373 switch (optname) {
3374 case SCTP_DISABLE_FRAGMENTS:
3375 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT;
3376 break;
3377 case SCTP_AUTO_ASCONF:
3378 /*
3379 * NOTE: we don't really support this flag
3380 */
3381 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
3382 /* only valid for bound all sockets */
3383 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) &&
3384 (*mopt != 0)) {
3385 /* forbidden by admin */
3386 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM);
3387 return (EPERM);
3388 }
3389 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF;
3390 } else {
3391 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3392 return (EINVAL);
3393 }
3394 break;
3395 case SCTP_EXPLICIT_EOR:
3396 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR;
3397 break;
3398 case SCTP_USE_EXT_RCVINFO:
3399 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO;
3400 break;
3401 case SCTP_I_WANT_MAPPED_V4_ADDR:
3402 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
3403 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4;
3404 } else {
3405 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3406 return (EINVAL);
3407 }
3408 break;
3409 case SCTP_NODELAY:
3410 set_opt = SCTP_PCB_FLAGS_NODELAY;
3411 break;
3412 case SCTP_AUTOCLOSE:
3413 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3414 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
3415 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3416 return (EINVAL);
3417 }
3418 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE;
3419 /*
3420 * The value is in ticks. Note this does not effect
3421 * old associations, only new ones.
3422 */
3423 inp->sctp_ep.auto_close_time = SEC_TO_TICKS(*mopt);
3424 break;
3425 }
3426 SCTP_INP_WLOCK(inp);
3427 if (*mopt != 0) {
3428 sctp_feature_on(inp, set_opt);
3429 } else {
3430 sctp_feature_off(inp, set_opt);
3431 }
3432 SCTP_INP_WUNLOCK(inp);
3433 break;
3434 case SCTP_REUSE_PORT:
3435 {
3436 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize);
3437 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) {
3438 /* Can't set it after we are bound */
3439 error = EINVAL;
3440 break;
3441 }
3442 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) {
3443 /* Can't do this for a 1-m socket */
3444 error = EINVAL;
3445 break;
3446 }
3447 if (optval)
3448 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE);
3449 else
3450 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE);
3451 break;
3452 }
3453 case SCTP_PARTIAL_DELIVERY_POINT:
3454 {
3455 uint32_t *value;
3456
3457 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
3458 if (*value > SCTP_SB_LIMIT_RCV(so)) {
3459 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3460 error = EINVAL;
3461 break;
3462 }
3463 inp->partial_delivery_point = *value;
3464 break;
3465 }
3466 case SCTP_FRAGMENT_INTERLEAVE:
3467 /* not yet until we re-write sctp_recvmsg() */
3468 {
3469 uint32_t *level;
3470
3471 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize);
3472 if (*level == SCTP_FRAG_LEVEL_2) {
3473 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3474 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3475 } else if (*level == SCTP_FRAG_LEVEL_1) {
3476 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3477 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3478 } else if (*level == SCTP_FRAG_LEVEL_0) {
3479 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE);
3480 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS);
3481
3482 } else {
3483 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3484 error = EINVAL;
3485 }
3486 break;
3487 }
3488 case SCTP_CMT_ON_OFF:
3489 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) {
3490 struct sctp_assoc_value *av;
3491
3492 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3493 if (av->assoc_value > SCTP_CMT_MAX) {
3494 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3495 error = EINVAL;
3496 break;
3497 }
3498 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3499 if (stcb) {
3500 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3501 SCTP_TCB_UNLOCK(stcb);
3502 } else {
3503 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3504 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3505 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3506 (av->assoc_id == SCTP_ALL_ASSOC)) {
3507 SCTP_INP_WLOCK(inp);
3508 inp->sctp_cmt_on_off = av->assoc_value;
3509 SCTP_INP_WUNLOCK(inp);
3510 }
3511 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3512 (av->assoc_id == SCTP_ALL_ASSOC)) {
3513 SCTP_INP_RLOCK(inp);
3514 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3515 SCTP_TCB_LOCK(stcb);
3516 stcb->asoc.sctp_cmt_on_off = av->assoc_value;
3517 SCTP_TCB_UNLOCK(stcb);
3518 }
3519 SCTP_INP_RUNLOCK(inp);
3520 }
3521 }
3522 } else {
3523 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
3524 error = ENOPROTOOPT;
3525 }
3526 break;
3527 case SCTP_PLUGGABLE_CC:
3528 {
3529 struct sctp_assoc_value *av;
3530 struct sctp_nets *net;
3531
3532 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3533 if ((av->assoc_value != SCTP_CC_RFC2581) &&
3534 (av->assoc_value != SCTP_CC_HSTCP) &&
3535 (av->assoc_value != SCTP_CC_HTCP) &&
3536 (av->assoc_value != SCTP_CC_RTCC)) {
3537 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3538 error = EINVAL;
3539 break;
3540 }
3541 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3542 if (stcb) {
3543 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3544 stcb->asoc.congestion_control_module = av->assoc_value;
3545 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3546 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3547 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3548 }
3549 }
3550 SCTP_TCB_UNLOCK(stcb);
3551 } else {
3552 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3553 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3554 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3555 (av->assoc_id == SCTP_ALL_ASSOC)) {
3556 SCTP_INP_WLOCK(inp);
3557 inp->sctp_ep.sctp_default_cc_module = av->assoc_value;
3558 SCTP_INP_WUNLOCK(inp);
3559 }
3560 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3561 (av->assoc_id == SCTP_ALL_ASSOC)) {
3562 SCTP_INP_RLOCK(inp);
3563 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3564 SCTP_TCB_LOCK(stcb);
3565 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value];
3566 stcb->asoc.congestion_control_module = av->assoc_value;
3567 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) {
3568 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
3569 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net);
3570 }
3571 }
3572 SCTP_TCB_UNLOCK(stcb);
3573 }
3574 SCTP_INP_RUNLOCK(inp);
3575 }
3576 }
3577 break;
3578 }
3579 case SCTP_CC_OPTION:
3580 {
3581 struct sctp_cc_option *cc_opt;
3582
3583 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize);
3584 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id);
3585 if (stcb == NULL) {
3586 if (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC) {
3587 SCTP_INP_RLOCK(inp);
3588 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3589 SCTP_TCB_LOCK(stcb);
3590 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) {
3591 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt);
3592 }
3593 SCTP_TCB_UNLOCK(stcb);
3594 }
3595 SCTP_INP_RUNLOCK(inp);
3596 } else {
3597 error = EINVAL;
3598 }
3599 } else {
3600 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) {
3601 error = ENOTSUP;
3602 } else {
3603 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1,
3604 cc_opt);
3605 }
3606 SCTP_TCB_UNLOCK(stcb);
3607 }
3608 break;
3609 }
3610 case SCTP_PLUGGABLE_SS:
3611 {
3612 struct sctp_assoc_value *av;
3613
3614 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3615 if ((av->assoc_value != SCTP_SS_DEFAULT) &&
3616 (av->assoc_value != SCTP_SS_ROUND_ROBIN) &&
3617 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) &&
3618 (av->assoc_value != SCTP_SS_PRIORITY) &&
3619 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) &&
3620 (av->assoc_value != SCTP_SS_FIRST_COME)) {
3621 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3622 error = EINVAL;
3623 break;
3624 }
3625 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3626 if (stcb) {
3627 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3628 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3629 stcb->asoc.stream_scheduling_module = av->assoc_value;
3630 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3631 SCTP_TCB_UNLOCK(stcb);
3632 } else {
3633 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3634 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3635 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3636 (av->assoc_id == SCTP_ALL_ASSOC)) {
3637 SCTP_INP_WLOCK(inp);
3638 inp->sctp_ep.sctp_default_ss_module = av->assoc_value;
3639 SCTP_INP_WUNLOCK(inp);
3640 }
3641 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3642 (av->assoc_id == SCTP_ALL_ASSOC)) {
3643 SCTP_INP_RLOCK(inp);
3644 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3645 SCTP_TCB_LOCK(stcb);
3646 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1);
3647 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value];
3648 stcb->asoc.stream_scheduling_module = av->assoc_value;
3649 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1);
3650 SCTP_TCB_UNLOCK(stcb);
3651 }
3652 SCTP_INP_RUNLOCK(inp);
3653 }
3654 }
3655 break;
3656 }
3657 case SCTP_SS_VALUE:
3658 {
3659 struct sctp_stream_value *av;
3660
3661 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize);
3662 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3663 if (stcb) {
3664 if ((av->stream_id >= stcb->asoc.streamoutcnt) ||
3665 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id],
3666 av->stream_value) < 0)) {
3667 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3668 error = EINVAL;
3669 }
3670 SCTP_TCB_UNLOCK(stcb);
3671 } else {
3672 if (av->assoc_id == SCTP_CURRENT_ASSOC) {
3673 SCTP_INP_RLOCK(inp);
3674 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3675 SCTP_TCB_LOCK(stcb);
3676 if (av->stream_id < stcb->asoc.streamoutcnt) {
3677 stcb->asoc.ss_functions.sctp_ss_set_value(stcb,
3678 &stcb->asoc,
3679 &stcb->asoc.strmout[av->stream_id],
3680 av->stream_value);
3681 }
3682 SCTP_TCB_UNLOCK(stcb);
3683 }
3684 SCTP_INP_RUNLOCK(inp);
3685
3686 } else {
3687 /*
3688 * Can't set stream value without
3689 * association
3690 */
3691 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3692 error = EINVAL;
3693 }
3694 }
3695 break;
3696 }
3697 case SCTP_CLR_STAT_LOG:
3698 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3699 error = EOPNOTSUPP;
3700 break;
3701 case SCTP_CONTEXT:
3702 {
3703 struct sctp_assoc_value *av;
3704
3705 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
3706 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
3707
3708 if (stcb) {
3709 stcb->asoc.context = av->assoc_value;
3710 SCTP_TCB_UNLOCK(stcb);
3711 } else {
3712 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3713 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3714 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
3715 (av->assoc_id == SCTP_ALL_ASSOC)) {
3716 SCTP_INP_WLOCK(inp);
3717 inp->sctp_context = av->assoc_value;
3718 SCTP_INP_WUNLOCK(inp);
3719 }
3720 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
3721 (av->assoc_id == SCTP_ALL_ASSOC)) {
3722 SCTP_INP_RLOCK(inp);
3723 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3724 SCTP_TCB_LOCK(stcb);
3725 stcb->asoc.context = av->assoc_value;
3726 SCTP_TCB_UNLOCK(stcb);
3727 }
3728 SCTP_INP_RUNLOCK(inp);
3729 }
3730 }
3731 break;
3732 }
3733 case SCTP_VRF_ID:
3734 {
3735 uint32_t *default_vrfid;
3736
3737 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize);
3738 if (*default_vrfid > SCTP_MAX_VRF_ID) {
3739 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3740 error = EINVAL;
3741 break;
3742 }
3743 inp->def_vrf_id = *default_vrfid;
3744 break;
3745 }
3746 case SCTP_DEL_VRF_ID:
3747 {
3748 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3749 error = EOPNOTSUPP;
3750 break;
3751 }
3752 case SCTP_ADD_VRF_ID:
3753 {
3754 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
3755 error = EOPNOTSUPP;
3756 break;
3757 }
3758 case SCTP_DELAYED_SACK:
3759 {
3760 struct sctp_sack_info *sack;
3761
3762 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize);
3763 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id);
3764 if (sack->sack_delay) {
3765 if (sack->sack_delay > SCTP_MAX_SACK_DELAY)
3766 sack->sack_delay = SCTP_MAX_SACK_DELAY;
3767 if (MSEC_TO_TICKS(sack->sack_delay) < 1) {
3768 sack->sack_delay = TICKS_TO_MSEC(1);
3769 }
3770 }
3771 if (stcb) {
3772 if (sack->sack_delay) {
3773 stcb->asoc.delayed_ack = sack->sack_delay;
3774 }
3775 if (sack->sack_freq) {
3776 stcb->asoc.sack_freq = sack->sack_freq;
3777 }
3778 SCTP_TCB_UNLOCK(stcb);
3779 } else {
3780 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3781 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3782 (sack->sack_assoc_id == SCTP_FUTURE_ASSOC) ||
3783 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3784 SCTP_INP_WLOCK(inp);
3785 if (sack->sack_delay) {
3786 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = MSEC_TO_TICKS(sack->sack_delay);
3787 }
3788 if (sack->sack_freq) {
3789 inp->sctp_ep.sctp_sack_freq = sack->sack_freq;
3790 }
3791 SCTP_INP_WUNLOCK(inp);
3792 }
3793 if ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) ||
3794 (sack->sack_assoc_id == SCTP_ALL_ASSOC)) {
3795 SCTP_INP_RLOCK(inp);
3796 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3797 SCTP_TCB_LOCK(stcb);
3798 if (sack->sack_delay) {
3799 stcb->asoc.delayed_ack = sack->sack_delay;
3800 }
3801 if (sack->sack_freq) {
3802 stcb->asoc.sack_freq = sack->sack_freq;
3803 }
3804 SCTP_TCB_UNLOCK(stcb);
3805 }
3806 SCTP_INP_RUNLOCK(inp);
3807 }
3808 }
3809 break;
3810 }
3811 case SCTP_AUTH_CHUNK:
3812 {
3813 struct sctp_authchunk *sauth;
3814
3815 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize);
3816
3817 SCTP_INP_WLOCK(inp);
3818 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) {
3819 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3820 error = EINVAL;
3821 }
3822 SCTP_INP_WUNLOCK(inp);
3823 break;
3824 }
3825 case SCTP_AUTH_KEY:
3826 {
3827 struct sctp_authkey *sca;
3828 struct sctp_keyhead *shared_keys;
3829 sctp_sharedkey_t *shared_key;
3830 sctp_key_t *key = NULL;
3831 size_t size;
3832
3833 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize);
3834 if (sca->sca_keylength == 0) {
3835 size = optsize - sizeof(struct sctp_authkey);
3836 } else {
3837 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) {
3838 size = sca->sca_keylength;
3839 } else {
3840 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3841 error = EINVAL;
3842 break;
3843 }
3844 }
3845 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id);
3846
3847 if (stcb) {
3848 shared_keys = &stcb->asoc.shared_keys;
3849 /* clear the cached keys for this key id */
3850 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3851 /*
3852 * create the new shared key and
3853 * insert/replace it
3854 */
3855 if (size > 0) {
3856 key = sctp_set_key(sca->sca_key, (uint32_t) size);
3857 if (key == NULL) {
3858 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3859 error = ENOMEM;
3860 SCTP_TCB_UNLOCK(stcb);
3861 break;
3862 }
3863 }
3864 shared_key = sctp_alloc_sharedkey();
3865 if (shared_key == NULL) {
3866 sctp_free_key(key);
3867 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3868 error = ENOMEM;
3869 SCTP_TCB_UNLOCK(stcb);
3870 break;
3871 }
3872 shared_key->key = key;
3873 shared_key->keyid = sca->sca_keynumber;
3874 error = sctp_insert_sharedkey(shared_keys, shared_key);
3875 SCTP_TCB_UNLOCK(stcb);
3876 } else {
3877 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
3878 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
3879 (sca->sca_assoc_id == SCTP_FUTURE_ASSOC) ||
3880 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3881 SCTP_INP_WLOCK(inp);
3882 shared_keys = &inp->sctp_ep.shared_keys;
3883 /*
3884 * clear the cached keys on all
3885 * assocs for this key id
3886 */
3887 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber);
3888 /*
3889 * create the new shared key and
3890 * insert/replace it
3891 */
3892 if (size > 0) {
3893 key = sctp_set_key(sca->sca_key, (uint32_t) size);
3894 if (key == NULL) {
3895 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3896 error = ENOMEM;
3897 SCTP_INP_WUNLOCK(inp);
3898 break;
3899 }
3900 }
3901 shared_key = sctp_alloc_sharedkey();
3902 if (shared_key == NULL) {
3903 sctp_free_key(key);
3904 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3905 error = ENOMEM;
3906 SCTP_INP_WUNLOCK(inp);
3907 break;
3908 }
3909 shared_key->key = key;
3910 shared_key->keyid = sca->sca_keynumber;
3911 error = sctp_insert_sharedkey(shared_keys, shared_key);
3912 SCTP_INP_WUNLOCK(inp);
3913 }
3914 if ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) ||
3915 (sca->sca_assoc_id == SCTP_ALL_ASSOC)) {
3916 SCTP_INP_RLOCK(inp);
3917 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
3918 SCTP_TCB_LOCK(stcb);
3919 shared_keys = &stcb->asoc.shared_keys;
3920 /*
3921 * clear the cached keys for
3922 * this key id
3923 */
3924 sctp_clear_cachedkeys(stcb, sca->sca_keynumber);
3925 /*
3926 * create the new shared key
3927 * and insert/replace it
3928 */
3929 if (size > 0) {
3930 key = sctp_set_key(sca->sca_key, (uint32_t) size);
3931 if (key == NULL) {
3932 SCTP_TCB_UNLOCK(stcb);
3933 continue;
3934 }
3935 }
3936 shared_key = sctp_alloc_sharedkey();
3937 if (shared_key == NULL) {
3938 sctp_free_key(key);
3939 SCTP_TCB_UNLOCK(stcb);
3940 continue;
3941 }
3942 shared_key->key = key;
3943 shared_key->keyid = sca->sca_keynumber;
3944 error = sctp_insert_sharedkey(shared_keys, shared_key);
3945 SCTP_TCB_UNLOCK(stcb);
3946 }
3947 SCTP_INP_RUNLOCK(inp);
3948 }
3949 }
3950 break;
3951 }
3952 case SCTP_HMAC_IDENT:
3953 {
3954 struct sctp_hmacalgo *shmac;
3955 sctp_hmaclist_t *hmaclist;
3956 uint16_t hmacid;
3957 uint32_t i;
3958
3959 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize);
3960 if (optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) {
3961 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3962 error = EINVAL;
3963 break;
3964 }
3965 hmaclist = sctp_alloc_hmaclist(shmac->shmac_number_of_idents);
3966 if (hmaclist == NULL) {
3967 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM);
3968 error = ENOMEM;
3969 break;
3970 }
3971 for (i = 0; i < shmac->shmac_number_of_idents; i++) {
3972 hmacid = shmac->shmac_idents[i];
3973 if (sctp_auth_add_hmacid(hmaclist, hmacid)) {
3974 /* invalid HMACs were found */ ;
3975 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3976 error = EINVAL;
3977 sctp_free_hmaclist(hmaclist);
3978 goto sctp_set_hmac_done;
3979 }
3980 }
3981 for (i = 0; i < hmaclist->num_algo; i++) {
3982 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) {
3983 /* already in list */
3984 break;
3985 }
3986 }
3987 if (i == hmaclist->num_algo) {
3988 /* not found in list */
3989 sctp_free_hmaclist(hmaclist);
3990 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
3991 error = EINVAL;
3992 break;
3993 }
3994 /* set it on the endpoint */
3995 SCTP_INP_WLOCK(inp);
3996 if (inp->sctp_ep.local_hmacs)
3997 sctp_free_hmaclist(inp->sctp_ep.local_hmacs);
3998 inp->sctp_ep.local_hmacs = hmaclist;
3999 SCTP_INP_WUNLOCK(inp);
4000 sctp_set_hmac_done:
4001 break;
4002 }
4003 case SCTP_AUTH_ACTIVE_KEY:
4004 {
4005 struct sctp_authkeyid *scact;
4006
4007 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize);
4008 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id);
4009
4010 /* set the active key on the right place */
4011 if (stcb) {
4012 /* set the active key on the assoc */
4013 if (sctp_auth_setactivekey(stcb,
4014 scact->scact_keynumber)) {
4015 SCTP_LTRACE_ERR_RET(inp, NULL, NULL,
4016 SCTP_FROM_SCTP_USRREQ,
4017 EINVAL);
4018 error = EINVAL;
4019 }
4020 SCTP_TCB_UNLOCK(stcb);
4021 } else {
4022 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4023 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4024 (scact->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4025 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4026 SCTP_INP_WLOCK(inp);
4027 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) {
4028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4029 error = EINVAL;
4030 }
4031 SCTP_INP_WUNLOCK(inp);
4032 }
4033 if ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4034 (scact->scact_assoc_id == SCTP_ALL_ASSOC)) {
4035 SCTP_INP_RLOCK(inp);
4036 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4037 SCTP_TCB_LOCK(stcb);
4038 sctp_auth_setactivekey(stcb, scact->scact_keynumber);
4039 SCTP_TCB_UNLOCK(stcb);
4040 }
4041 SCTP_INP_RUNLOCK(inp);
4042 }
4043 }
4044 break;
4045 }
4046 case SCTP_AUTH_DELETE_KEY:
4047 {
4048 struct sctp_authkeyid *scdel;
4049
4050 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize);
4051 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id);
4052
4053 /* delete the key from the right place */
4054 if (stcb) {
4055 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) {
4056 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4057 error = EINVAL;
4058 }
4059 SCTP_TCB_UNLOCK(stcb);
4060 } else {
4061 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4062 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4063 (scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4064 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4065 SCTP_INP_WLOCK(inp);
4066 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) {
4067 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4068 error = EINVAL;
4069 }
4070 SCTP_INP_WUNLOCK(inp);
4071 }
4072 if ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4073 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)) {
4074 SCTP_INP_RLOCK(inp);
4075 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4076 SCTP_TCB_LOCK(stcb);
4077 sctp_delete_sharedkey(stcb, scdel->scact_keynumber);
4078 SCTP_TCB_UNLOCK(stcb);
4079 }
4080 SCTP_INP_RUNLOCK(inp);
4081 }
4082 }
4083 break;
4084 }
4085 case SCTP_AUTH_DEACTIVATE_KEY:
4086 {
4087 struct sctp_authkeyid *keyid;
4088
4089 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize);
4090 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id);
4091
4092 /* deactivate the key from the right place */
4093 if (stcb) {
4094 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) {
4095 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4096 error = EINVAL;
4097 }
4098 SCTP_TCB_UNLOCK(stcb);
4099 } else {
4100 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4101 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4102 (keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) ||
4103 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4104 SCTP_INP_WLOCK(inp);
4105 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) {
4106 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4107 error = EINVAL;
4108 }
4109 SCTP_INP_WUNLOCK(inp);
4110 }
4111 if ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) ||
4112 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)) {
4113 SCTP_INP_RLOCK(inp);
4114 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4115 SCTP_TCB_LOCK(stcb);
4116 sctp_deact_sharedkey(stcb, keyid->scact_keynumber);
4117 SCTP_TCB_UNLOCK(stcb);
4118 }
4119 SCTP_INP_RUNLOCK(inp);
4120 }
4121 }
4122 break;
4123 }
4124 case SCTP_ENABLE_STREAM_RESET:
4125 {
4126 struct sctp_assoc_value *av;
4127
4128 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4129 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) {
4130 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4131 error = EINVAL;
4132 break;
4133 }
4134 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4135 if (stcb) {
4136 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4137 SCTP_TCB_UNLOCK(stcb);
4138 } else {
4139 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4140 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4141 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4142 (av->assoc_id == SCTP_ALL_ASSOC)) {
4143 SCTP_INP_WLOCK(inp);
4144 inp->local_strreset_support = (uint8_t) av->assoc_value;
4145 SCTP_INP_WUNLOCK(inp);
4146 }
4147 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4148 (av->assoc_id == SCTP_ALL_ASSOC)) {
4149 SCTP_INP_RLOCK(inp);
4150 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4151 SCTP_TCB_LOCK(stcb);
4152 stcb->asoc.local_strreset_support = (uint8_t) av->assoc_value;
4153 SCTP_TCB_UNLOCK(stcb);
4154 }
4155 SCTP_INP_RUNLOCK(inp);
4156 }
4157 }
4158 break;
4159 }
4160 case SCTP_RESET_STREAMS:
4161 {
4162 struct sctp_reset_streams *strrst;
4163 int i, send_out = 0;
4164 int send_in = 0;
4165
4166 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize);
4167 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id);
4168 if (stcb == NULL) {
4169 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4170 error = ENOENT;
4171 break;
4172 }
4173 if (stcb->asoc.peer_supports_strreset == 0) {
4174 /*
4175 * Peer does not support the chunk type.
4176 */
4177 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4178 error = EOPNOTSUPP;
4179 SCTP_TCB_UNLOCK(stcb);
4180 break;
4181 }
4182 if (stcb->asoc.stream_reset_outstanding) {
4183 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4184 error = EALREADY;
4185 SCTP_TCB_UNLOCK(stcb);
4186 break;
4187 }
4188 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) {
4189 send_in = 1;
4190 }
4191 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) {
4192 send_out = 1;
4193 }
4194 if ((send_in == 0) && (send_out == 0)) {
4195 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4196 error = EINVAL;
4197 SCTP_TCB_UNLOCK(stcb);
4198 break;
4199 }
4200 for (i = 0; i < strrst->srs_number_streams; i++) {
4201 if ((send_in) &&
4202 (strrst->srs_stream_list[i] > stcb->asoc.streamincnt)) {
4203 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4204 error = EINVAL;
4205 break;
4206 }
4207 if ((send_out) &&
4208 (strrst->srs_stream_list[i] > stcb->asoc.streamoutcnt)) {
4209 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4210 error = EINVAL;
4211 break;
4212 }
4213 }
4214 if (error) {
4215 SCTP_TCB_UNLOCK(stcb);
4216 break;
4217 }
4218 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4219 strrst->srs_stream_list,
4220 send_out, send_in, 0, 0, 0, 0, 0);
4221
4222 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4223 SCTP_TCB_UNLOCK(stcb);
4224 break;
4225 }
4226 case SCTP_ADD_STREAMS:
4227 {
4228 struct sctp_add_streams *stradd;
4229 uint8_t addstream = 0;
4230 uint16_t add_o_strmcnt = 0;
4231 uint16_t add_i_strmcnt = 0;
4232
4233 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4234 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4235 if (stcb == NULL) {
4236 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4237 error = ENOENT;
4238 break;
4239 }
4240 if (stcb->asoc.peer_supports_strreset == 0) {
4241 /*
4242 * Peer does not support the chunk type.
4243 */
4244 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4245 error = EOPNOTSUPP;
4246 SCTP_TCB_UNLOCK(stcb);
4247 break;
4248 }
4249 if (stcb->asoc.stream_reset_outstanding) {
4250 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4251 error = EALREADY;
4252 SCTP_TCB_UNLOCK(stcb);
4253 break;
4254 }
4255 if ((stradd->sas_outstrms == 0) &&
4256 (stradd->sas_instrms == 0)) {
4257 error = EINVAL;
4258 goto skip_stuff;
4259 }
4260 if (stradd->sas_outstrms) {
4261 addstream = 1;
4262 /* We allocate here */
4263 add_o_strmcnt = stradd->sas_outstrms;
4264 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4265 /* You can't have more than 64k */
4266 error = EINVAL;
4267 goto skip_stuff;
4268 }
4269 }
4270 if (stradd->sas_instrms) {
4271 int cnt;
4272
4273 addstream |= 2;
4274 /*
4275 * We allocate inside
4276 * sctp_send_str_reset_req()
4277 */
4278 add_i_strmcnt = stradd->sas_instrms;
4279 cnt = add_i_strmcnt;
4280 cnt += stcb->asoc.streamincnt;
4281 if (cnt > 0x0000ffff) {
4282 /* You can't have more than 64k */
4283 error = EINVAL;
4284 goto skip_stuff;
4285 }
4286 if (cnt > (int)stcb->asoc.max_inbound_streams) {
4287 /* More than you are allowed */
4288 error = EINVAL;
4289 goto skip_stuff;
4290 }
4291 }
4292 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4293 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4294 skip_stuff:
4295 SCTP_TCB_UNLOCK(stcb);
4296 break;
4297 }
4298 case SCTP_RESET_ASSOC:
4299 {
4300 uint32_t *value;
4301
4302 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4303 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t) * value);
4304 if (stcb == NULL) {
4305 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4306 error = ENOENT;
4307 break;
4308 }
4309 if (stcb->asoc.peer_supports_strreset == 0) {
4310 /*
4311 * Peer does not support the chunk type.
4312 */
4313 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4314 error = EOPNOTSUPP;
4315 SCTP_TCB_UNLOCK(stcb);
4316 break;
4317 }
4318 if (stcb->asoc.stream_reset_outstanding) {
4319 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4320 error = EALREADY;
4321 SCTP_TCB_UNLOCK(stcb);
4322 break;
4323 }
4324 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, 1, 0, 0, 0, 0);
4325 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4326 SCTP_TCB_UNLOCK(stcb);
4327 break;
4328 }
4329 case SCTP_CONNECT_X:
4330 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4331 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4332 error = EINVAL;
4333 break;
4334 }
4335 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4336 break;
4337 case SCTP_CONNECT_X_DELAYED:
4338 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4339 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4340 error = EINVAL;
4341 break;
4342 }
4343 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4344 break;
4345 case SCTP_CONNECT_X_COMPLETE:
4346 {
4347 struct sockaddr *sa;
4348 struct sctp_nets *net;
4349
4350 /* FIXME MT: check correct? */
4351 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4352
4353 /* find tcb */
4354 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4355 SCTP_INP_RLOCK(inp);
4356 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4357 if (stcb) {
4358 SCTP_TCB_LOCK(stcb);
4359 net = sctp_findnet(stcb, sa);
4360 }
4361 SCTP_INP_RUNLOCK(inp);
4362 } else {
4363 /*
4364 * We increment here since
4365 * sctp_findassociation_ep_addr() wil do a
4366 * decrement if it finds the stcb as long as
4367 * the locked tcb (last argument) is NOT a
4368 * TCB.. aka NULL.
4369 */
4370 SCTP_INP_INCR_REF(inp);
4371 stcb = sctp_findassociation_ep_addr(&inp, sa, &net, NULL, NULL);
4372 if (stcb == NULL) {
4373 SCTP_INP_DECR_REF(inp);
4374 }
4375 }
4376
4377 if (stcb == NULL) {
4378 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4379 error = ENOENT;
4380 break;
4381 }
4382 if (stcb->asoc.delayed_connection == 1) {
4383 stcb->asoc.delayed_connection = 0;
4384 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4385 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4386 stcb->asoc.primary_destination,
4387 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
4388 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4389 } else {
4390 /*
4391 * already expired or did not use delayed
4392 * connectx
4393 */
4394 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4395 error = EALREADY;
4396 }
4397 SCTP_TCB_UNLOCK(stcb);
4398 break;
4399 }
4400 case SCTP_MAX_BURST:
4401 {
4402 struct sctp_assoc_value *av;
4403
4404 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4405 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4406
4407 if (stcb) {
4408 stcb->asoc.max_burst = av->assoc_value;
4409 SCTP_TCB_UNLOCK(stcb);
4410 } else {
4411 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4412 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4413 (av->assoc_id == SCTP_FUTURE_ASSOC) ||
4414 (av->assoc_id == SCTP_ALL_ASSOC)) {
4415 SCTP_INP_WLOCK(inp);
4416 inp->sctp_ep.max_burst = av->assoc_value;
4417 SCTP_INP_WUNLOCK(inp);
4418 }
4419 if ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4420 (av->assoc_id == SCTP_ALL_ASSOC)) {
4421 SCTP_INP_RLOCK(inp);
4422 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4423 SCTP_TCB_LOCK(stcb);
4424 stcb->asoc.max_burst = av->assoc_value;
4425 SCTP_TCB_UNLOCK(stcb);
4426 }
4427 SCTP_INP_RUNLOCK(inp);
4428 }
4429 }
4430 break;
4431 }
4432 case SCTP_MAXSEG:
4433 {
4434 struct sctp_assoc_value *av;
4435 int ovh;
4436
4437 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4438 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4439
4440 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4441 ovh = SCTP_MED_OVERHEAD;
4442 } else {
4443 ovh = SCTP_MED_V4_OVERHEAD;
4444 }
4445 if (stcb) {
4446 if (av->assoc_value) {
4447 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh);
4448 } else {
4449 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4450 }
4451 SCTP_TCB_UNLOCK(stcb);
4452 } else {
4453 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4454 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4455 (av->assoc_id == SCTP_FUTURE_ASSOC)) {
4456 SCTP_INP_WLOCK(inp);
4457 /*
4458 * FIXME MT: I think this is not in
4459 * tune with the API ID
4460 */
4461 if (av->assoc_value) {
4462 inp->sctp_frag_point = (av->assoc_value + ovh);
4463 } else {
4464 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT;
4465 }
4466 SCTP_INP_WUNLOCK(inp);
4467 } else {
4468 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4469 error = EINVAL;
4470 }
4471 }
4472 break;
4473 }
4474 case SCTP_EVENTS:
4475 {
4476 struct sctp_event_subscribe *events;
4477
4478 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4479
4480 SCTP_INP_WLOCK(inp);
4481 if (events->sctp_data_io_event) {
4482 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4483 } else {
4484 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4485 }
4486
4487 if (events->sctp_association_event) {
4488 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4489 } else {
4490 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4491 }
4492
4493 if (events->sctp_address_event) {
4494 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4495 } else {
4496 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
4497 }
4498
4499 if (events->sctp_send_failure_event) {
4500 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4501 } else {
4502 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4503 }
4504
4505 if (events->sctp_peer_error_event) {
4506 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4507 } else {
4508 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
4509 }
4510
4511 if (events->sctp_shutdown_event) {
4512 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4513 } else {
4514 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4515 }
4516
4517 if (events->sctp_partial_delivery_event) {
4518 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4519 } else {
4520 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
4521 }
4522
4523 if (events->sctp_adaptation_layer_event) {
4524 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4525 } else {
4526 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4527 }
4528
4529 if (events->sctp_authentication_event) {
4530 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4531 } else {
4532 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
4533 }
4534
4535 if (events->sctp_sender_dry_event) {
4536 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
4537 } else {
4538 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
4539 }
4540
4541 if (events->sctp_stream_reset_event) {
4542 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4543 } else {
4544 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4545 }
4546 SCTP_INP_WUNLOCK(inp);
4547
4548 SCTP_INP_RLOCK(inp);
4549 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4550 SCTP_TCB_LOCK(stcb);
4551 if (events->sctp_association_event) {
4552 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4553 } else {
4554 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
4555 }
4556 if (events->sctp_address_event) {
4557 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4558 } else {
4559 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
4560 }
4561 if (events->sctp_send_failure_event) {
4562 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4563 } else {
4564 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
4565 }
4566 if (events->sctp_peer_error_event) {
4567 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4568 } else {
4569 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
4570 }
4571 if (events->sctp_shutdown_event) {
4572 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4573 } else {
4574 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
4575 }
4576 if (events->sctp_partial_delivery_event) {
4577 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4578 } else {
4579 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
4580 }
4581 if (events->sctp_adaptation_layer_event) {
4582 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4583 } else {
4584 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
4585 }
4586 if (events->sctp_authentication_event) {
4587 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4588 } else {
4589 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
4590 }
4591 if (events->sctp_sender_dry_event) {
4592 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4593 } else {
4594 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
4595 }
4596 if (events->sctp_stream_reset_event) {
4597 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4598 } else {
4599 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
4600 }
4601 SCTP_TCB_UNLOCK(stcb);
4602 }
4603 /*
4604 * Send up the sender dry event only for 1-to-1
4605 * style sockets.
4606 */
4607 if (events->sctp_sender_dry_event) {
4608 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4609 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
4610 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4611 if (stcb) {
4612 SCTP_TCB_LOCK(stcb);
4613 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
4614 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
4615 (stcb->asoc.stream_queue_cnt == 0)) {
4616 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
4617 }
4618 SCTP_TCB_UNLOCK(stcb);
4619 }
4620 }
4621 }
4622 SCTP_INP_RUNLOCK(inp);
4623 break;
4624 }
4625 case SCTP_ADAPTATION_LAYER:
4626 {
4627 struct sctp_setadaptation *adap_bits;
4628
4629 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
4630 SCTP_INP_WLOCK(inp);
4631 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
4632 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
4633 SCTP_INP_WUNLOCK(inp);
4634 break;
4635 }
4636 #ifdef SCTP_DEBUG
4637 case SCTP_SET_INITIAL_DBG_SEQ:
4638 {
4639 uint32_t *vvv;
4640
4641 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
4642 SCTP_INP_WLOCK(inp);
4643 inp->sctp_ep.initial_sequence_debug = *vvv;
4644 SCTP_INP_WUNLOCK(inp);
4645 break;
4646 }
4647 #endif
4648 case SCTP_DEFAULT_SEND_PARAM:
4649 {
4650 struct sctp_sndrcvinfo *s_info;
4651
4652 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
4653 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
4654
4655 if (stcb) {
4656 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4657 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4658 } else {
4659 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4660 error = EINVAL;
4661 }
4662 SCTP_TCB_UNLOCK(stcb);
4663 } else {
4664 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4665 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4666 (s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
4667 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4668 SCTP_INP_WLOCK(inp);
4669 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
4670 SCTP_INP_WUNLOCK(inp);
4671 }
4672 if ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
4673 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)) {
4674 SCTP_INP_RLOCK(inp);
4675 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4676 SCTP_TCB_LOCK(stcb);
4677 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
4678 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
4679 }
4680 SCTP_TCB_UNLOCK(stcb);
4681 }
4682 SCTP_INP_RUNLOCK(inp);
4683 }
4684 }
4685 break;
4686 }
4687 case SCTP_PEER_ADDR_PARAMS:
4688 {
4689 struct sctp_paddrparams *paddrp;
4690 struct sctp_nets *net;
4691
4692 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
4693 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
4694 net = NULL;
4695 if (stcb) {
4696 net = sctp_findnet(stcb, (struct sockaddr *)&paddrp->spp_address);
4697 } else {
4698 /*
4699 * We increment here since
4700 * sctp_findassociation_ep_addr() wil do a
4701 * decrement if it finds the stcb as long as
4702 * the locked tcb (last argument) is NOT a
4703 * TCB.. aka NULL.
4704 */
4705 SCTP_INP_INCR_REF(inp);
4706 stcb = sctp_findassociation_ep_addr(&inp,
4707 (struct sockaddr *)&paddrp->spp_address,
4708 &net, NULL, NULL);
4709 if (stcb == NULL) {
4710 SCTP_INP_DECR_REF(inp);
4711 }
4712 }
4713 if (stcb && (net == NULL)) {
4714 struct sockaddr *sa;
4715
4716 sa = (struct sockaddr *)&paddrp->spp_address;
4717 #ifdef INET
4718 if (sa->sa_family == AF_INET) {
4719
4720 struct sockaddr_in *sin;
4721
4722 sin = (struct sockaddr_in *)sa;
4723 if (sin->sin_addr.s_addr) {
4724 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4725 SCTP_TCB_UNLOCK(stcb);
4726 error = EINVAL;
4727 break;
4728 }
4729 } else
4730 #endif
4731 #ifdef INET6
4732 if (sa->sa_family == AF_INET6) {
4733 struct sockaddr_in6 *sin6;
4734
4735 sin6 = (struct sockaddr_in6 *)sa;
4736 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
4737 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4738 SCTP_TCB_UNLOCK(stcb);
4739 error = EINVAL;
4740 break;
4741 }
4742 } else
4743 #endif
4744 {
4745 error = EAFNOSUPPORT;
4746 SCTP_TCB_UNLOCK(stcb);
4747 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4748 break;
4749 }
4750 }
4751 /* sanity checks */
4752 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
4753 if (stcb)
4754 SCTP_TCB_UNLOCK(stcb);
4755 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4756 return (EINVAL);
4757 }
4758 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
4759 if (stcb)
4760 SCTP_TCB_UNLOCK(stcb);
4761 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4762 return (EINVAL);
4763 }
4764 if (stcb) {
4765 /************************TCB SPECIFIC SET ******************/
4766 /*
4767 * do we change the timer for HB, we run
4768 * only one?
4769 */
4770 int ovh = 0;
4771
4772 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
4773 ovh = SCTP_MED_OVERHEAD;
4774 } else {
4775 ovh = SCTP_MED_V4_OVERHEAD;
4776 }
4777
4778 /* network sets ? */
4779 if (net) {
4780 /************************NET SPECIFIC SET ******************/
4781 if (paddrp->spp_flags & SPP_HB_DISABLE) {
4782 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) &&
4783 !(net->dest_state & SCTP_ADDR_NOHB)) {
4784 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4785 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4786 }
4787 net->dest_state |= SCTP_ADDR_NOHB;
4788 }
4789 if (paddrp->spp_flags & SPP_HB_ENABLE) {
4790 if (paddrp->spp_hbinterval) {
4791 net->heart_beat_delay = paddrp->spp_hbinterval;
4792 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4793 net->heart_beat_delay = 0;
4794 }
4795 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4796 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4797 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4798 net->dest_state &= ~SCTP_ADDR_NOHB;
4799 }
4800 if (paddrp->spp_flags & SPP_HB_DEMAND) {
4801 /* on demand HB */
4802 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4803 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
4804 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4805 }
4806 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4807 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4808 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4809 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4810 }
4811 net->dest_state |= SCTP_ADDR_NO_PMTUD;
4812 net->mtu = paddrp->spp_pathmtu + ovh;
4813 if (net->mtu < stcb->asoc.smallest_mtu) {
4814 sctp_pathmtu_adjustment(stcb, net->mtu);
4815 }
4816 }
4817 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4818 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4819 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4820 }
4821 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4822 }
4823 if (paddrp->spp_pathmaxrxt) {
4824 if (net->dest_state & SCTP_ADDR_PF) {
4825 if (net->error_count > paddrp->spp_pathmaxrxt) {
4826 net->dest_state &= ~SCTP_ADDR_PF;
4827 }
4828 } else {
4829 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4830 (net->error_count > net->pf_threshold)) {
4831 net->dest_state |= SCTP_ADDR_PF;
4832 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4833 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4834 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4835 }
4836 }
4837 if (net->dest_state & SCTP_ADDR_REACHABLE) {
4838 if (net->error_count > paddrp->spp_pathmaxrxt) {
4839 net->dest_state &= ~SCTP_ADDR_REACHABLE;
4840 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
4841 }
4842 } else {
4843 if (net->error_count <= paddrp->spp_pathmaxrxt) {
4844 net->dest_state |= SCTP_ADDR_REACHABLE;
4845 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
4846 }
4847 }
4848 net->failure_threshold = paddrp->spp_pathmaxrxt;
4849 }
4850 if (paddrp->spp_flags & SPP_DSCP) {
4851 net->dscp = paddrp->spp_dscp & 0xfc;
4852 net->dscp |= 0x01;
4853 }
4854 #ifdef INET6
4855 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4856 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4857 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4858 net->flowlabel |= 0x80000000;
4859 }
4860 }
4861 #endif
4862 } else {
4863 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
4864 if (paddrp->spp_pathmaxrxt) {
4865 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
4866 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4867 if (net->dest_state & SCTP_ADDR_PF) {
4868 if (net->error_count > paddrp->spp_pathmaxrxt) {
4869 net->dest_state &= ~SCTP_ADDR_PF;
4870 }
4871 } else {
4872 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
4873 (net->error_count > net->pf_threshold)) {
4874 net->dest_state |= SCTP_ADDR_PF;
4875 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
4876 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
4877 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
4878 }
4879 }
4880 if (net->dest_state & SCTP_ADDR_REACHABLE) {
4881 if (net->error_count > paddrp->spp_pathmaxrxt) {
4882 net->dest_state &= ~SCTP_ADDR_REACHABLE;
4883 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
4884 }
4885 } else {
4886 if (net->error_count <= paddrp->spp_pathmaxrxt) {
4887 net->dest_state |= SCTP_ADDR_REACHABLE;
4888 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
4889 }
4890 }
4891 net->failure_threshold = paddrp->spp_pathmaxrxt;
4892 }
4893 }
4894 if (paddrp->spp_flags & SPP_HB_ENABLE) {
4895 if (paddrp->spp_hbinterval) {
4896 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
4897 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4898 stcb->asoc.heart_beat_delay = 0;
4899 }
4900 /* Turn back on the timer */
4901 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4902 if (paddrp->spp_hbinterval) {
4903 net->heart_beat_delay = paddrp->spp_hbinterval;
4904 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4905 net->heart_beat_delay = 0;
4906 }
4907 if (net->dest_state & SCTP_ADDR_NOHB) {
4908 net->dest_state &= ~SCTP_ADDR_NOHB;
4909 }
4910 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
4911 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4912 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
4913 }
4914 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4915 }
4916 if (paddrp->spp_flags & SPP_HB_DISABLE) {
4917 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4918 if (!(net->dest_state & SCTP_ADDR_NOHB)) {
4919 net->dest_state |= SCTP_ADDR_NOHB;
4920 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) {
4921 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4922 }
4923 }
4924 }
4925 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
4926 }
4927 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU)) {
4928 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4929 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4930 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
4931 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
4932 }
4933 net->dest_state |= SCTP_ADDR_NO_PMTUD;
4934 net->mtu = paddrp->spp_pathmtu + ovh;
4935 if (net->mtu < stcb->asoc.smallest_mtu) {
4936 sctp_pathmtu_adjustment(stcb, net->mtu);
4937 }
4938 }
4939 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4940 }
4941 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
4942 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4943 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
4944 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
4945 }
4946 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
4947 }
4948 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
4949 }
4950 if (paddrp->spp_flags & SPP_DSCP) {
4951 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4952 net->dscp = paddrp->spp_dscp & 0xfc;
4953 net->dscp |= 0x01;
4954 }
4955 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
4956 stcb->asoc.default_dscp |= 0x01;
4957 }
4958 #ifdef INET6
4959 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
4960 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
4961 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
4962 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4963 net->flowlabel |= 0x80000000;
4964 }
4965 }
4966 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
4967 stcb->asoc.default_flowlabel |= 0x80000000;
4968 }
4969 #endif
4970 }
4971 SCTP_TCB_UNLOCK(stcb);
4972 } else {
4973 /************************NO TCB, SET TO default stuff ******************/
4974 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4975 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4976 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC)) {
4977 SCTP_INP_WLOCK(inp);
4978 /*
4979 * For the TOS/FLOWLABEL stuff you
4980 * set it with the options on the
4981 * socket
4982 */
4983 if (paddrp->spp_pathmaxrxt) {
4984 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
4985 }
4986 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
4987 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4988 else if (paddrp->spp_hbinterval) {
4989 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
4990 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
4991 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4992 }
4993 if (paddrp->spp_flags & SPP_HB_ENABLE) {
4994 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
4995 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
4996 } else if (paddrp->spp_hbinterval) {
4997 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = MSEC_TO_TICKS(paddrp->spp_hbinterval);
4998 }
4999 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5000 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5001 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5002 }
5003 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5004 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5005 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5006 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5007 }
5008 if (paddrp->spp_flags & SPP_DSCP) {
5009 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5010 inp->sctp_ep.default_dscp |= 0x01;
5011 }
5012 #ifdef INET6
5013 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5014 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5015 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5016 inp->sctp_ep.default_flowlabel |= 0x80000000;
5017 }
5018 }
5019 #endif
5020 SCTP_INP_WUNLOCK(inp);
5021 } else {
5022 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5023 error = EINVAL;
5024 }
5025 }
5026 break;
5027 }
5028 case SCTP_RTOINFO:
5029 {
5030 struct sctp_rtoinfo *srto;
5031 uint32_t new_init, new_min, new_max;
5032
5033 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5034 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5035
5036 if (stcb) {
5037 if (srto->srto_initial)
5038 new_init = srto->srto_initial;
5039 else
5040 new_init = stcb->asoc.initial_rto;
5041 if (srto->srto_max)
5042 new_max = srto->srto_max;
5043 else
5044 new_max = stcb->asoc.maxrto;
5045 if (srto->srto_min)
5046 new_min = srto->srto_min;
5047 else
5048 new_min = stcb->asoc.minrto;
5049 if ((new_min <= new_init) && (new_init <= new_max)) {
5050 stcb->asoc.initial_rto = new_init;
5051 stcb->asoc.maxrto = new_max;
5052 stcb->asoc.minrto = new_min;
5053 } else {
5054 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5055 error = EINVAL;
5056 }
5057 SCTP_TCB_UNLOCK(stcb);
5058 } else {
5059 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5060 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5061 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC)) {
5062 SCTP_INP_WLOCK(inp);
5063 if (srto->srto_initial)
5064 new_init = srto->srto_initial;
5065 else
5066 new_init = inp->sctp_ep.initial_rto;
5067 if (srto->srto_max)
5068 new_max = srto->srto_max;
5069 else
5070 new_max = inp->sctp_ep.sctp_maxrto;
5071 if (srto->srto_min)
5072 new_min = srto->srto_min;
5073 else
5074 new_min = inp->sctp_ep.sctp_minrto;
5075 if ((new_min <= new_init) && (new_init <= new_max)) {
5076 inp->sctp_ep.initial_rto = new_init;
5077 inp->sctp_ep.sctp_maxrto = new_max;
5078 inp->sctp_ep.sctp_minrto = new_min;
5079 } else {
5080 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5081 error = EINVAL;
5082 }
5083 SCTP_INP_WUNLOCK(inp);
5084 } else {
5085 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5086 error = EINVAL;
5087 }
5088 }
5089 break;
5090 }
5091 case SCTP_ASSOCINFO:
5092 {
5093 struct sctp_assocparams *sasoc;
5094
5095 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5096 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5097 if (sasoc->sasoc_cookie_life) {
5098 /* boundary check the cookie life */
5099 if (sasoc->sasoc_cookie_life < 1000)
5100 sasoc->sasoc_cookie_life = 1000;
5101 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5102 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5103 }
5104 }
5105 if (stcb) {
5106 if (sasoc->sasoc_asocmaxrxt)
5107 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5108 if (sasoc->sasoc_cookie_life) {
5109 stcb->asoc.cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5110 }
5111 SCTP_TCB_UNLOCK(stcb);
5112 } else {
5113 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5114 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5115 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC)) {
5116 SCTP_INP_WLOCK(inp);
5117 if (sasoc->sasoc_asocmaxrxt)
5118 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5119 if (sasoc->sasoc_cookie_life) {
5120 inp->sctp_ep.def_cookie_life = MSEC_TO_TICKS(sasoc->sasoc_cookie_life);
5121 }
5122 SCTP_INP_WUNLOCK(inp);
5123 } else {
5124 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5125 error = EINVAL;
5126 }
5127 }
5128 break;
5129 }
5130 case SCTP_INITMSG:
5131 {
5132 struct sctp_initmsg *sinit;
5133
5134 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5135 SCTP_INP_WLOCK(inp);
5136 if (sinit->sinit_num_ostreams)
5137 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5138
5139 if (sinit->sinit_max_instreams)
5140 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5141
5142 if (sinit->sinit_max_attempts)
5143 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5144
5145 if (sinit->sinit_max_init_timeo)
5146 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5147 SCTP_INP_WUNLOCK(inp);
5148 break;
5149 }
5150 case SCTP_PRIMARY_ADDR:
5151 {
5152 struct sctp_setprim *spa;
5153 struct sctp_nets *net;
5154
5155 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5156 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5157
5158 net = NULL;
5159 if (stcb) {
5160 net = sctp_findnet(stcb, (struct sockaddr *)&spa->ssp_addr);
5161 } else {
5162 /*
5163 * We increment here since
5164 * sctp_findassociation_ep_addr() wil do a
5165 * decrement if it finds the stcb as long as
5166 * the locked tcb (last argument) is NOT a
5167 * TCB.. aka NULL.
5168 */
5169 SCTP_INP_INCR_REF(inp);
5170 stcb = sctp_findassociation_ep_addr(&inp,
5171 (struct sockaddr *)&spa->ssp_addr,
5172 &net, NULL, NULL);
5173 if (stcb == NULL) {
5174 SCTP_INP_DECR_REF(inp);
5175 }
5176 }
5177
5178 if ((stcb) && (net)) {
5179 if ((net != stcb->asoc.primary_destination) &&
5180 (!(net->dest_state & SCTP_ADDR_UNCONFIRMED))) {
5181 /* Ok we need to set it */
5182 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5183 if ((stcb->asoc.alternate) &&
5184 (!(net->dest_state & SCTP_ADDR_PF)) &&
5185 (net->dest_state & SCTP_ADDR_REACHABLE)) {
5186 sctp_free_remote_addr(stcb->asoc.alternate);
5187 stcb->asoc.alternate = NULL;
5188 }
5189 }
5190 }
5191 } else {
5192 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5193 error = EINVAL;
5194 }
5195 if (stcb) {
5196 SCTP_TCB_UNLOCK(stcb);
5197 }
5198 break;
5199 }
5200 case SCTP_SET_DYNAMIC_PRIMARY:
5201 {
5202 union sctp_sockstore *ss;
5203
5204 error = priv_check(curthread,
5205 PRIV_NETINET_RESERVEDPORT);
5206 if (error)
5207 break;
5208
5209 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5210 /* SUPER USER CHECK? */
5211 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5212 break;
5213 }
5214 case SCTP_SET_PEER_PRIMARY_ADDR:
5215 {
5216 struct sctp_setpeerprim *sspp;
5217
5218 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5219 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5220 if (stcb != NULL) {
5221 struct sctp_ifa *ifa;
5222
5223 ifa = sctp_find_ifa_by_addr((struct sockaddr *)&sspp->sspp_addr,
5224 stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5225 if (ifa == NULL) {
5226 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5227 error = EINVAL;
5228 goto out_of_it;
5229 }
5230 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5231 /*
5232 * Must validate the ifa found is in
5233 * our ep
5234 */
5235 struct sctp_laddr *laddr;
5236 int found = 0;
5237
5238 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5239 if (laddr->ifa == NULL) {
5240 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5241 __FUNCTION__);
5242 continue;
5243 }
5244 if (laddr->ifa == ifa) {
5245 found = 1;
5246 break;
5247 }
5248 }
5249 if (!found) {
5250 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5251 error = EINVAL;
5252 goto out_of_it;
5253 }
5254 } else {
5255 switch (sspp->sspp_addr.ss_family) {
5256 #ifdef INET
5257 case AF_INET:
5258 {
5259 struct sockaddr_in *sin;
5260
5261 sin = (struct sockaddr_in *)&sspp->sspp_addr;
5262 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5263 &sin->sin_addr) != 0) {
5264 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5265 error = EINVAL;
5266 goto out_of_it;
5267 }
5268 break;
5269 }
5270 #endif
5271 #ifdef INET6
5272 case AF_INET6:
5273 {
5274 struct sockaddr_in6 *sin6;
5275
5276 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5277 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5278 &sin6->sin6_addr) != 0) {
5279 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5280 error = EINVAL;
5281 goto out_of_it;
5282 }
5283 break;
5284 }
5285 #endif
5286 default:
5287 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5288 error = EINVAL;
5289 goto out_of_it;
5290 }
5291 }
5292 if (sctp_set_primary_ip_address_sa(stcb,
5293 (struct sockaddr *)&sspp->sspp_addr) != 0) {
5294 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5295 error = EINVAL;
5296 }
5297 out_of_it:
5298 SCTP_TCB_UNLOCK(stcb);
5299 } else {
5300 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5301 error = EINVAL;
5302 }
5303 break;
5304 }
5305 case SCTP_BINDX_ADD_ADDR:
5306 {
5307 struct sctp_getaddresses *addrs;
5308 struct thread *td;
5309
5310 td = (struct thread *)p;
5311 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses,
5312 optsize);
5313 #ifdef INET
5314 if (addrs->addr->sa_family == AF_INET) {
5315 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5316 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5317 error = EINVAL;
5318 break;
5319 }
5320 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5321 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5322 break;
5323 }
5324 } else
5325 #endif
5326 #ifdef INET6
5327 if (addrs->addr->sa_family == AF_INET6) {
5328 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5329 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5330 error = EINVAL;
5331 break;
5332 }
5333 if (td != NULL && (error = prison_local_ip6(td->td_ucred, &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5334 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5335 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5336 break;
5337 }
5338 } else
5339 #endif
5340 {
5341 error = EAFNOSUPPORT;
5342 break;
5343 }
5344 sctp_bindx_add_address(so, inp, addrs->addr,
5345 addrs->sget_assoc_id, vrf_id,
5346 &error, p);
5347 break;
5348 }
5349 case SCTP_BINDX_REM_ADDR:
5350 {
5351 struct sctp_getaddresses *addrs;
5352 struct thread *td;
5353
5354 td = (struct thread *)p;
5355
5356 SCTP_CHECK_AND_CAST(addrs, optval, struct sctp_getaddresses, optsize);
5357 #ifdef INET
5358 if (addrs->addr->sa_family == AF_INET) {
5359 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in)) {
5360 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5361 error = EINVAL;
5362 break;
5363 }
5364 if (td != NULL && (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)(addrs->addr))->sin_addr)))) {
5365 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5366 break;
5367 }
5368 } else
5369 #endif
5370 #ifdef INET6
5371 if (addrs->addr->sa_family == AF_INET6) {
5372 if (optsize < sizeof(struct sctp_getaddresses) - sizeof(struct sockaddr) + sizeof(struct sockaddr_in6)) {
5373 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5374 error = EINVAL;
5375 break;
5376 }
5377 if (td != NULL &&
5378 (error = prison_local_ip6(td->td_ucred,
5379 &(((struct sockaddr_in6 *)(addrs->addr))->sin6_addr),
5380 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5381 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5382 break;
5383 }
5384 } else
5385 #endif
5386 {
5387 error = EAFNOSUPPORT;
5388 break;
5389 }
5390 sctp_bindx_delete_address(inp, addrs->addr,
5391 addrs->sget_assoc_id, vrf_id,
5392 &error);
5393 break;
5394 }
5395 case SCTP_EVENT:
5396 {
5397 struct sctp_event *event;
5398 uint32_t event_type;
5399
5400 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
5401 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
5402 switch (event->se_type) {
5403 case SCTP_ASSOC_CHANGE:
5404 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
5405 break;
5406 case SCTP_PEER_ADDR_CHANGE:
5407 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
5408 break;
5409 case SCTP_REMOTE_ERROR:
5410 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
5411 break;
5412 case SCTP_SEND_FAILED:
5413 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
5414 break;
5415 case SCTP_SHUTDOWN_EVENT:
5416 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
5417 break;
5418 case SCTP_ADAPTATION_INDICATION:
5419 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
5420 break;
5421 case SCTP_PARTIAL_DELIVERY_EVENT:
5422 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
5423 break;
5424 case SCTP_AUTHENTICATION_EVENT:
5425 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
5426 break;
5427 case SCTP_STREAM_RESET_EVENT:
5428 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
5429 break;
5430 case SCTP_SENDER_DRY_EVENT:
5431 event_type = SCTP_PCB_FLAGS_DRYEVNT;
5432 break;
5433 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
5434 event_type = 0;
5435 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5436 error = ENOTSUP;
5437 break;
5438 case SCTP_ASSOC_RESET_EVENT:
5439 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
5440 break;
5441 case SCTP_STREAM_CHANGE_EVENT:
5442 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
5443 break;
5444 case SCTP_SEND_FAILED_EVENT:
5445 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
5446 break;
5447 default:
5448 event_type = 0;
5449 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5450 error = EINVAL;
5451 break;
5452 }
5453 if (event_type > 0) {
5454 if (stcb) {
5455 if (event->se_on) {
5456 sctp_stcb_feature_on(inp, stcb, event_type);
5457 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
5458 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5459 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5460 (stcb->asoc.stream_queue_cnt == 0)) {
5461 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5462 }
5463 }
5464 } else {
5465 sctp_stcb_feature_off(inp, stcb, event_type);
5466 }
5467 SCTP_TCB_UNLOCK(stcb);
5468 } else {
5469 /*
5470 * We don't want to send up a storm
5471 * of events, so return an error for
5472 * sender dry events
5473 */
5474 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
5475 ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) == 0) &&
5476 ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) == 0) &&
5477 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
5478 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
5479 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
5480 error = ENOTSUP;
5481 break;
5482 }
5483 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5484 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5485 (event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
5486 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5487 SCTP_INP_WLOCK(inp);
5488 if (event->se_on) {
5489 sctp_feature_on(inp, event_type);
5490 } else {
5491 sctp_feature_off(inp, event_type);
5492 }
5493 SCTP_INP_WUNLOCK(inp);
5494 }
5495 if ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
5496 (event->se_assoc_id == SCTP_ALL_ASSOC)) {
5497 SCTP_INP_RLOCK(inp);
5498 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5499 SCTP_TCB_LOCK(stcb);
5500 if (event->se_on) {
5501 sctp_stcb_feature_on(inp, stcb, event_type);
5502 } else {
5503 sctp_stcb_feature_off(inp, stcb, event_type);
5504 }
5505 SCTP_TCB_UNLOCK(stcb);
5506 }
5507 SCTP_INP_RUNLOCK(inp);
5508 }
5509 }
5510 }
5511 break;
5512 }
5513 case SCTP_RECVRCVINFO:
5514 {
5515 int *onoff;
5516
5517 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5518 SCTP_INP_WLOCK(inp);
5519 if (*onoff != 0) {
5520 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5521 } else {
5522 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
5523 }
5524 SCTP_INP_WUNLOCK(inp);
5525 break;
5526 }
5527 case SCTP_RECVNXTINFO:
5528 {
5529 int *onoff;
5530
5531 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
5532 SCTP_INP_WLOCK(inp);
5533 if (*onoff != 0) {
5534 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5535 } else {
5536 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
5537 }
5538 SCTP_INP_WUNLOCK(inp);
5539 break;
5540 }
5541 case SCTP_DEFAULT_SNDINFO:
5542 {
5543 struct sctp_sndinfo *info;
5544 uint16_t policy;
5545
5546 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
5547 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
5548
5549 if (stcb) {
5550 if (info->snd_sid < stcb->asoc.streamoutcnt) {
5551 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5552 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5553 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5554 stcb->asoc.def_send.sinfo_flags |= policy;
5555 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5556 stcb->asoc.def_send.sinfo_context = info->snd_context;
5557 } else {
5558 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5559 error = EINVAL;
5560 }
5561 SCTP_TCB_UNLOCK(stcb);
5562 } else {
5563 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5564 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5565 (info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
5566 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5567 SCTP_INP_WLOCK(inp);
5568 inp->def_send.sinfo_stream = info->snd_sid;
5569 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
5570 inp->def_send.sinfo_flags = info->snd_flags;
5571 inp->def_send.sinfo_flags |= policy;
5572 inp->def_send.sinfo_ppid = info->snd_ppid;
5573 inp->def_send.sinfo_context = info->snd_context;
5574 SCTP_INP_WUNLOCK(inp);
5575 }
5576 if ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
5577 (info->snd_assoc_id == SCTP_ALL_ASSOC)) {
5578 SCTP_INP_RLOCK(inp);
5579 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5580 SCTP_TCB_LOCK(stcb);
5581 if (info->snd_sid < stcb->asoc.streamoutcnt) {
5582 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
5583 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
5584 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
5585 stcb->asoc.def_send.sinfo_flags |= policy;
5586 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
5587 stcb->asoc.def_send.sinfo_context = info->snd_context;
5588 }
5589 SCTP_TCB_UNLOCK(stcb);
5590 }
5591 SCTP_INP_RUNLOCK(inp);
5592 }
5593 }
5594 break;
5595 }
5596 case SCTP_DEFAULT_PRINFO:
5597 {
5598 struct sctp_default_prinfo *info;
5599
5600 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
5601 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
5602
5603 if (PR_SCTP_INVALID_POLICY(info->pr_policy)) {
5604 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5605 error = EINVAL;
5606 break;
5607 }
5608 if (stcb) {
5609 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5610 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5611 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5612 SCTP_TCB_UNLOCK(stcb);
5613 } else {
5614 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5615 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5616 (info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
5617 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5618 SCTP_INP_WLOCK(inp);
5619 inp->def_send.sinfo_flags &= 0xfff0;
5620 inp->def_send.sinfo_flags |= info->pr_policy;
5621 inp->def_send.sinfo_timetolive = info->pr_value;
5622 SCTP_INP_WUNLOCK(inp);
5623 }
5624 if ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
5625 (info->pr_assoc_id == SCTP_ALL_ASSOC)) {
5626 SCTP_INP_RLOCK(inp);
5627 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5628 SCTP_TCB_LOCK(stcb);
5629 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
5630 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
5631 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
5632 SCTP_TCB_UNLOCK(stcb);
5633 }
5634 SCTP_INP_RUNLOCK(inp);
5635 }
5636 }
5637 break;
5638 }
5639 case SCTP_PEER_ADDR_THLDS:
5640 /* Applies to the specific association */
5641 {
5642 struct sctp_paddrthlds *thlds;
5643 struct sctp_nets *net;
5644
5645 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
5646 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
5647 net = NULL;
5648 if (stcb) {
5649 net = sctp_findnet(stcb, (struct sockaddr *)&thlds->spt_address);
5650 } else {
5651 /*
5652 * We increment here since
5653 * sctp_findassociation_ep_addr() wil do a
5654 * decrement if it finds the stcb as long as
5655 * the locked tcb (last argument) is NOT a
5656 * TCB.. aka NULL.
5657 */
5658 SCTP_INP_INCR_REF(inp);
5659 stcb = sctp_findassociation_ep_addr(&inp,
5660 (struct sockaddr *)&thlds->spt_address,
5661 &net, NULL, NULL);
5662 if (stcb == NULL) {
5663 SCTP_INP_DECR_REF(inp);
5664 }
5665 }
5666 if (stcb && (net == NULL)) {
5667 struct sockaddr *sa;
5668
5669 sa = (struct sockaddr *)&thlds->spt_address;
5670 #ifdef INET
5671 if (sa->sa_family == AF_INET) {
5672
5673 struct sockaddr_in *sin;
5674
5675 sin = (struct sockaddr_in *)sa;
5676 if (sin->sin_addr.s_addr) {
5677 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5678 SCTP_TCB_UNLOCK(stcb);
5679 error = EINVAL;
5680 break;
5681 }
5682 } else
5683 #endif
5684 #ifdef INET6
5685 if (sa->sa_family == AF_INET6) {
5686 struct sockaddr_in6 *sin6;
5687
5688 sin6 = (struct sockaddr_in6 *)sa;
5689 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5690 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5691 SCTP_TCB_UNLOCK(stcb);
5692 error = EINVAL;
5693 break;
5694 }
5695 } else
5696 #endif
5697 {
5698 error = EAFNOSUPPORT;
5699 SCTP_TCB_UNLOCK(stcb);
5700 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5701 break;
5702 }
5703 }
5704 if (stcb) {
5705 if (net) {
5706 if (net->dest_state & SCTP_ADDR_PF) {
5707 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5708 (net->failure_threshold <= thlds->spt_pathpfthld)) {
5709 net->dest_state &= ~SCTP_ADDR_PF;
5710 }
5711 } else {
5712 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5713 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5714 net->dest_state |= SCTP_ADDR_PF;
5715 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5716 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5717 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5718 }
5719 }
5720 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5721 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5722 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5723 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5724 }
5725 } else {
5726 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5727 net->dest_state |= SCTP_ADDR_REACHABLE;
5728 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5729 }
5730 }
5731 net->failure_threshold = thlds->spt_pathmaxrxt;
5732 net->pf_threshold = thlds->spt_pathpfthld;
5733 } else {
5734 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5735 if (net->dest_state & SCTP_ADDR_PF) {
5736 if ((net->failure_threshold > thlds->spt_pathmaxrxt) ||
5737 (net->failure_threshold <= thlds->spt_pathpfthld)) {
5738 net->dest_state &= ~SCTP_ADDR_PF;
5739 }
5740 } else {
5741 if ((net->failure_threshold > thlds->spt_pathpfthld) &&
5742 (net->failure_threshold <= thlds->spt_pathmaxrxt)) {
5743 net->dest_state |= SCTP_ADDR_PF;
5744 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5745 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net, SCTP_FROM_SCTP_TIMER + SCTP_LOC_3);
5746 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5747 }
5748 }
5749 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5750 if (net->failure_threshold > thlds->spt_pathmaxrxt) {
5751 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5752 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5753 }
5754 } else {
5755 if (net->failure_threshold <= thlds->spt_pathmaxrxt) {
5756 net->dest_state |= SCTP_ADDR_REACHABLE;
5757 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5758 }
5759 }
5760 net->failure_threshold = thlds->spt_pathmaxrxt;
5761 net->pf_threshold = thlds->spt_pathpfthld;
5762 }
5763 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
5764 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
5765 }
5766 } else {
5767 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5768 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5769 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC)) {
5770 SCTP_INP_WLOCK(inp);
5771 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
5772 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
5773 SCTP_INP_WUNLOCK(inp);
5774 } else {
5775 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5776 error = EINVAL;
5777 }
5778 }
5779 break;
5780 }
5781 case SCTP_REMOTE_UDP_ENCAPS_PORT:
5782 {
5783 struct sctp_udpencaps *encaps;
5784 struct sctp_nets *net;
5785
5786 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
5787 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
5788 if (stcb) {
5789 net = sctp_findnet(stcb, (struct sockaddr *)&encaps->sue_address);
5790 } else {
5791 /*
5792 * We increment here since
5793 * sctp_findassociation_ep_addr() wil do a
5794 * decrement if it finds the stcb as long as
5795 * the locked tcb (last argument) is NOT a
5796 * TCB.. aka NULL.
5797 */
5798 net = NULL;
5799 SCTP_INP_INCR_REF(inp);
5800 stcb = sctp_findassociation_ep_addr(&inp, (struct sockaddr *)&encaps->sue_address, &net, NULL, NULL);
5801 if (stcb == NULL) {
5802 SCTP_INP_DECR_REF(inp);
5803 }
5804 }
5805 if (stcb && (net == NULL)) {
5806 struct sockaddr *sa;
5807
5808 sa = (struct sockaddr *)&encaps->sue_address;
5809 #ifdef INET
5810 if (sa->sa_family == AF_INET) {
5811
5812 struct sockaddr_in *sin;
5813
5814 sin = (struct sockaddr_in *)sa;
5815 if (sin->sin_addr.s_addr) {
5816 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5817 SCTP_TCB_UNLOCK(stcb);
5818 error = EINVAL;
5819 break;
5820 }
5821 } else
5822 #endif
5823 #ifdef INET6
5824 if (sa->sa_family == AF_INET6) {
5825 struct sockaddr_in6 *sin6;
5826
5827 sin6 = (struct sockaddr_in6 *)sa;
5828 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5829 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5830 SCTP_TCB_UNLOCK(stcb);
5831 error = EINVAL;
5832 break;
5833 }
5834 } else
5835 #endif
5836 {
5837 error = EAFNOSUPPORT;
5838 SCTP_TCB_UNLOCK(stcb);
5839 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5840 break;
5841 }
5842 }
5843 if (stcb) {
5844 if (net) {
5845 net->port = encaps->sue_port;
5846 } else {
5847 stcb->asoc.port = encaps->sue_port;
5848 }
5849 SCTP_TCB_UNLOCK(stcb);
5850 } else {
5851 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5852 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5853 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC)) {
5854 SCTP_INP_WLOCK(inp);
5855 inp->sctp_ep.port = encaps->sue_port;
5856 SCTP_INP_WUNLOCK(inp);
5857 } else {
5858 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5859 error = EINVAL;
5860 }
5861 }
5862 break;
5863 }
5864 default:
5865 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
5866 error = ENOPROTOOPT;
5867 break;
5868 } /* end switch (opt) */
5869 return (error);
5870 }
5871
5872 int
sctp_ctloutput(struct socket * so,struct sockopt * sopt)5873 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
5874 {
5875 void *optval = NULL;
5876 size_t optsize = 0;
5877 void *p;
5878 int error = 0;
5879
5880 if (sopt->sopt_level != IPPROTO_SCTP) {
5881 /* wrong proto level... send back up to IP */
5882 #ifdef INET6
5883 if (INP_CHECK_SOCKAF(so, AF_INET6))
5884 error = ip6_ctloutput(so, sopt);
5885 #endif /* INET6 */
5886 #if defined(INET) && defined(INET6)
5887 else
5888 #endif
5889 #ifdef INET
5890 error = ip_ctloutput(so, sopt);
5891 #endif
5892 return (error);
5893 }
5894 optsize = sopt->sopt_valsize;
5895 if (optsize) {
5896 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
5897 if (optval == NULL) {
5898 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
5899 return (ENOBUFS);
5900 }
5901 error = sooptcopyin(sopt, optval, optsize, optsize);
5902 if (error) {
5903 SCTP_FREE(optval, SCTP_M_SOCKOPT);
5904 goto out;
5905 }
5906 }
5907 p = (void *)sopt->sopt_td;
5908 if (sopt->sopt_dir == SOPT_SET) {
5909 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
5910 } else if (sopt->sopt_dir == SOPT_GET) {
5911 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
5912 } else {
5913 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5914 error = EINVAL;
5915 }
5916 if ((error == 0) && (optval != NULL)) {
5917 error = sooptcopyout(sopt, optval, optsize);
5918 SCTP_FREE(optval, SCTP_M_SOCKOPT);
5919 } else if (optval != NULL) {
5920 SCTP_FREE(optval, SCTP_M_SOCKOPT);
5921 }
5922 out:
5923 return (error);
5924 }
5925
5926 #ifdef INET
5927 static int
sctp_connect(struct socket * so,struct sockaddr * addr,struct thread * p)5928 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
5929 {
5930 int error = 0;
5931 int create_lock_on = 0;
5932 uint32_t vrf_id;
5933 struct sctp_inpcb *inp;
5934 struct sctp_tcb *stcb = NULL;
5935
5936 inp = (struct sctp_inpcb *)so->so_pcb;
5937 if (inp == NULL) {
5938 /* I made the same as TCP since we are not setup? */
5939 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5940 return (ECONNRESET);
5941 }
5942 if (addr == NULL) {
5943 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5944 return EINVAL;
5945 }
5946 switch (addr->sa_family) {
5947 #ifdef INET6
5948 case AF_INET6:
5949 {
5950 struct sockaddr_in6 *sin6p;
5951
5952 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
5953 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5954 return (EINVAL);
5955 }
5956 sin6p = (struct sockaddr_in6 *)addr;
5957 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6p->sin6_addr)) != 0) {
5958 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5959 return (error);
5960 }
5961 break;
5962 }
5963 #endif
5964 #ifdef INET
5965 case AF_INET:
5966 {
5967 struct sockaddr_in *sinp;
5968
5969 if (addr->sa_len != sizeof(struct sockaddr_in)) {
5970 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5971 return (EINVAL);
5972 }
5973 sinp = (struct sockaddr_in *)addr;
5974 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sinp->sin_addr)) != 0) {
5975 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5976 return (error);
5977 }
5978 break;
5979 }
5980 #endif
5981 default:
5982 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
5983 return (EAFNOSUPPORT);
5984 }
5985 SCTP_INP_INCR_REF(inp);
5986 SCTP_ASOC_CREATE_LOCK(inp);
5987 create_lock_on = 1;
5988
5989
5990 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
5991 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
5992 /* Should I really unlock ? */
5993 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
5994 error = EFAULT;
5995 goto out_now;
5996 }
5997 #ifdef INET6
5998 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
5999 (addr->sa_family == AF_INET6)) {
6000 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6001 error = EINVAL;
6002 goto out_now;
6003 }
6004 #endif
6005 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) ==
6006 SCTP_PCB_FLAGS_UNBOUND) {
6007 /* Bind a ephemeral port */
6008 error = sctp_inpcb_bind(so, NULL, NULL, p);
6009 if (error) {
6010 goto out_now;
6011 }
6012 }
6013 /* Now do we connect? */
6014 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
6015 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
6016 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6017 error = EINVAL;
6018 goto out_now;
6019 }
6020 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6021 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6022 /* We are already connected AND the TCP model */
6023 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6024 error = EADDRINUSE;
6025 goto out_now;
6026 }
6027 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6028 SCTP_INP_RLOCK(inp);
6029 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6030 SCTP_INP_RUNLOCK(inp);
6031 } else {
6032 /*
6033 * We increment here since sctp_findassociation_ep_addr()
6034 * will do a decrement if it finds the stcb as long as the
6035 * locked tcb (last argument) is NOT a TCB.. aka NULL.
6036 */
6037 SCTP_INP_INCR_REF(inp);
6038 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
6039 if (stcb == NULL) {
6040 SCTP_INP_DECR_REF(inp);
6041 } else {
6042 SCTP_TCB_UNLOCK(stcb);
6043 }
6044 }
6045 if (stcb != NULL) {
6046 /* Already have or am bring up an association */
6047 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
6048 error = EALREADY;
6049 goto out_now;
6050 }
6051 vrf_id = inp->def_vrf_id;
6052 /* We are GOOD to go */
6053 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, p);
6054 if (stcb == NULL) {
6055 /* Gak! no memory */
6056 goto out_now;
6057 }
6058 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) {
6059 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED;
6060 /* Set the connected flag so we can queue data */
6061 soisconnecting(so);
6062 }
6063 SCTP_SET_STATE(&stcb->asoc, SCTP_STATE_COOKIE_WAIT);
6064 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
6065
6066 /* initialize authentication parameters for the assoc */
6067 sctp_initialize_auth_params(inp, stcb);
6068
6069 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
6070 SCTP_TCB_UNLOCK(stcb);
6071 out_now:
6072 if (create_lock_on) {
6073 SCTP_ASOC_CREATE_UNLOCK(inp);
6074 }
6075 SCTP_INP_DECR_REF(inp);
6076 return (error);
6077 }
6078
6079 #endif
6080
6081 int
sctp_listen(struct socket * so,int backlog,struct thread * p)6082 sctp_listen(struct socket *so, int backlog, struct thread *p)
6083 {
6084 /*
6085 * Note this module depends on the protocol processing being called
6086 * AFTER any socket level flags and backlog are applied to the
6087 * socket. The traditional way that the socket flags are applied is
6088 * AFTER protocol processing. We have made a change to the
6089 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
6090 * place if the socket API for SCTP is to work properly.
6091 */
6092
6093 int error = 0;
6094 struct sctp_inpcb *inp;
6095
6096 inp = (struct sctp_inpcb *)so->so_pcb;
6097 if (inp == NULL) {
6098 /* I made the same as TCP since we are not setup? */
6099 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6100 return (ECONNRESET);
6101 }
6102 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
6103 /* See if we have a listener */
6104 struct sctp_inpcb *tinp;
6105 union sctp_sockstore store;
6106
6107 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
6108 /* not bound all */
6109 struct sctp_laddr *laddr;
6110
6111 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6112 memcpy(&store, &laddr->ifa->address, sizeof(store));
6113 switch (store.sa.sa_family) {
6114 #ifdef INET
6115 case AF_INET:
6116 store.sin.sin_port = inp->sctp_lport;
6117 break;
6118 #endif
6119 #ifdef INET6
6120 case AF_INET6:
6121 store.sin6.sin6_port = inp->sctp_lport;
6122 break;
6123 #endif
6124 default:
6125 break;
6126 }
6127 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6128 if (tinp && (tinp != inp) &&
6129 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6130 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6131 (tinp->sctp_socket->so_qlimit)) {
6132 /*
6133 * we have a listener already and
6134 * its not this inp.
6135 */
6136 SCTP_INP_DECR_REF(tinp);
6137 return (EADDRINUSE);
6138 } else if (tinp) {
6139 SCTP_INP_DECR_REF(tinp);
6140 }
6141 }
6142 } else {
6143 /* Setup a local addr bound all */
6144 memset(&store, 0, sizeof(store));
6145 #ifdef INET6
6146 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
6147 store.sa.sa_family = AF_INET6;
6148 store.sa.sa_len = sizeof(struct sockaddr_in6);
6149 }
6150 #endif
6151 #ifdef INET
6152 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
6153 store.sa.sa_family = AF_INET;
6154 store.sa.sa_len = sizeof(struct sockaddr_in);
6155 }
6156 #endif
6157 switch (store.sa.sa_family) {
6158 #ifdef INET
6159 case AF_INET:
6160 store.sin.sin_port = inp->sctp_lport;
6161 break;
6162 #endif
6163 #ifdef INET6
6164 case AF_INET6:
6165 store.sin6.sin6_port = inp->sctp_lport;
6166 break;
6167 #endif
6168 default:
6169 break;
6170 }
6171 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
6172 if (tinp && (tinp != inp) &&
6173 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
6174 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
6175 (tinp->sctp_socket->so_qlimit)) {
6176 /*
6177 * we have a listener already and its not
6178 * this inp.
6179 */
6180 SCTP_INP_DECR_REF(tinp);
6181 return (EADDRINUSE);
6182 } else if (tinp) {
6183 SCTP_INP_DECR_REF(inp);
6184 }
6185 }
6186 }
6187 SCTP_INP_RLOCK(inp);
6188 #ifdef SCTP_LOCK_LOGGING
6189 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
6190 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
6191 }
6192 #endif
6193 SOCK_LOCK(so);
6194 error = solisten_proto_check(so);
6195 if (error) {
6196 SOCK_UNLOCK(so);
6197 SCTP_INP_RUNLOCK(inp);
6198 return (error);
6199 }
6200 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
6201 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
6202 /*
6203 * The unlucky case - We are in the tcp pool with this guy.
6204 * - Someone else is in the main inp slot. - We must move
6205 * this guy (the listener) to the main slot - We must then
6206 * move the guy that was listener to the TCP Pool.
6207 */
6208 if (sctp_swap_inpcb_for_listen(inp)) {
6209 goto in_use;
6210 }
6211 }
6212 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
6213 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
6214 /* We are already connected AND the TCP model */
6215 in_use:
6216 SCTP_INP_RUNLOCK(inp);
6217 SOCK_UNLOCK(so);
6218 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
6219 return (EADDRINUSE);
6220 }
6221 SCTP_INP_RUNLOCK(inp);
6222 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
6223 /* We must do a bind. */
6224 SOCK_UNLOCK(so);
6225 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) {
6226 /* bind error, probably perm */
6227 return (error);
6228 }
6229 SOCK_LOCK(so);
6230 }
6231 /* It appears for 7.0 and on, we must always call this. */
6232 solisten_proto(so, backlog);
6233 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6234 /* remove the ACCEPTCONN flag for one-to-many sockets */
6235 so->so_options &= ~SO_ACCEPTCONN;
6236 }
6237 if (backlog == 0) {
6238 /* turning off listen */
6239 so->so_options &= ~SO_ACCEPTCONN;
6240 }
6241 SOCK_UNLOCK(so);
6242 return (error);
6243 }
6244
6245 static int sctp_defered_wakeup_cnt = 0;
6246
6247 int
sctp_accept(struct socket * so,struct sockaddr ** addr)6248 sctp_accept(struct socket *so, struct sockaddr **addr)
6249 {
6250 struct sctp_tcb *stcb;
6251 struct sctp_inpcb *inp;
6252 union sctp_sockstore store;
6253
6254 #ifdef INET6
6255 int error;
6256
6257 #endif
6258 inp = (struct sctp_inpcb *)so->so_pcb;
6259
6260 if (inp == NULL) {
6261 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6262 return (ECONNRESET);
6263 }
6264 SCTP_INP_RLOCK(inp);
6265 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
6266 SCTP_INP_RUNLOCK(inp);
6267 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
6268 return (EOPNOTSUPP);
6269 }
6270 if (so->so_state & SS_ISDISCONNECTED) {
6271 SCTP_INP_RUNLOCK(inp);
6272 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
6273 return (ECONNABORTED);
6274 }
6275 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6276 if (stcb == NULL) {
6277 SCTP_INP_RUNLOCK(inp);
6278 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6279 return (ECONNRESET);
6280 }
6281 SCTP_TCB_LOCK(stcb);
6282 SCTP_INP_RUNLOCK(inp);
6283 store = stcb->asoc.primary_destination->ro._l_addr;
6284 stcb->asoc.state &= ~SCTP_STATE_IN_ACCEPT_QUEUE;
6285 SCTP_TCB_UNLOCK(stcb);
6286 switch (store.sa.sa_family) {
6287 #ifdef INET
6288 case AF_INET:
6289 {
6290 struct sockaddr_in *sin;
6291
6292 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6293 if (sin == NULL)
6294 return (ENOMEM);
6295 sin->sin_family = AF_INET;
6296 sin->sin_len = sizeof(*sin);
6297 sin->sin_port = store.sin.sin_port;
6298 sin->sin_addr = store.sin.sin_addr;
6299 *addr = (struct sockaddr *)sin;
6300 break;
6301 }
6302 #endif
6303 #ifdef INET6
6304 case AF_INET6:
6305 {
6306 struct sockaddr_in6 *sin6;
6307
6308 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6);
6309 if (sin6 == NULL)
6310 return (ENOMEM);
6311 sin6->sin6_family = AF_INET6;
6312 sin6->sin6_len = sizeof(*sin6);
6313 sin6->sin6_port = store.sin6.sin6_port;
6314 sin6->sin6_addr = store.sin6.sin6_addr;
6315 if ((error = sa6_recoverscope(sin6)) != 0) {
6316 SCTP_FREE_SONAME(sin6);
6317 return (error);
6318 }
6319 *addr = (struct sockaddr *)sin6;
6320 break;
6321 }
6322 #endif
6323 default:
6324 /* TSNH */
6325 break;
6326 }
6327 /* Wake any delayed sleep action */
6328 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
6329 SCTP_INP_WLOCK(inp);
6330 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
6331 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
6332 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
6333 SCTP_INP_WUNLOCK(inp);
6334 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
6335 if (sowriteable(inp->sctp_socket)) {
6336 sowwakeup_locked(inp->sctp_socket);
6337 } else {
6338 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
6339 }
6340 SCTP_INP_WLOCK(inp);
6341 }
6342 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
6343 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
6344 SCTP_INP_WUNLOCK(inp);
6345 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
6346 if (soreadable(inp->sctp_socket)) {
6347 sctp_defered_wakeup_cnt++;
6348 sorwakeup_locked(inp->sctp_socket);
6349 } else {
6350 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
6351 }
6352 SCTP_INP_WLOCK(inp);
6353 }
6354 SCTP_INP_WUNLOCK(inp);
6355 }
6356 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
6357 SCTP_TCB_LOCK(stcb);
6358 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, SCTP_FROM_SCTP_USRREQ + SCTP_LOC_7);
6359 }
6360 return (0);
6361 }
6362
6363 #ifdef INET
6364 int
sctp_ingetaddr(struct socket * so,struct sockaddr ** addr)6365 sctp_ingetaddr(struct socket *so, struct sockaddr **addr)
6366 {
6367 struct sockaddr_in *sin;
6368 uint32_t vrf_id;
6369 struct sctp_inpcb *inp;
6370 struct sctp_ifa *sctp_ifa;
6371
6372 /*
6373 * Do the malloc first in case it blocks.
6374 */
6375 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6376 if (sin == NULL)
6377 return (ENOMEM);
6378 sin->sin_family = AF_INET;
6379 sin->sin_len = sizeof(*sin);
6380 inp = (struct sctp_inpcb *)so->so_pcb;
6381 if (!inp) {
6382 SCTP_FREE_SONAME(sin);
6383 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6384 return (ECONNRESET);
6385 }
6386 SCTP_INP_RLOCK(inp);
6387 sin->sin_port = inp->sctp_lport;
6388 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
6389 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
6390 struct sctp_tcb *stcb;
6391 struct sockaddr_in *sin_a;
6392 struct sctp_nets *net;
6393 int fnd;
6394
6395 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6396 if (stcb == NULL) {
6397 goto notConn;
6398 }
6399 fnd = 0;
6400 sin_a = NULL;
6401 SCTP_TCB_LOCK(stcb);
6402 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6403 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6404 if (sin_a == NULL)
6405 /* this will make coverity happy */
6406 continue;
6407
6408 if (sin_a->sin_family == AF_INET) {
6409 fnd = 1;
6410 break;
6411 }
6412 }
6413 if ((!fnd) || (sin_a == NULL)) {
6414 /* punt */
6415 SCTP_TCB_UNLOCK(stcb);
6416 goto notConn;
6417 }
6418 vrf_id = inp->def_vrf_id;
6419 sctp_ifa = sctp_source_address_selection(inp,
6420 stcb,
6421 (sctp_route_t *) & net->ro,
6422 net, 0, vrf_id);
6423 if (sctp_ifa) {
6424 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
6425 sctp_free_ifa(sctp_ifa);
6426 }
6427 SCTP_TCB_UNLOCK(stcb);
6428 } else {
6429 /* For the bound all case you get back 0 */
6430 notConn:
6431 sin->sin_addr.s_addr = 0;
6432 }
6433
6434 } else {
6435 /* Take the first IPv4 address in the list */
6436 struct sctp_laddr *laddr;
6437 int fnd = 0;
6438
6439 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
6440 if (laddr->ifa->address.sa.sa_family == AF_INET) {
6441 struct sockaddr_in *sin_a;
6442
6443 sin_a = (struct sockaddr_in *)&laddr->ifa->address.sa;
6444 sin->sin_addr = sin_a->sin_addr;
6445 fnd = 1;
6446 break;
6447 }
6448 }
6449 if (!fnd) {
6450 SCTP_FREE_SONAME(sin);
6451 SCTP_INP_RUNLOCK(inp);
6452 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6453 return (ENOENT);
6454 }
6455 }
6456 SCTP_INP_RUNLOCK(inp);
6457 (*addr) = (struct sockaddr *)sin;
6458 return (0);
6459 }
6460
6461 int
sctp_peeraddr(struct socket * so,struct sockaddr ** addr)6462 sctp_peeraddr(struct socket *so, struct sockaddr **addr)
6463 {
6464 struct sockaddr_in *sin;
6465 int fnd;
6466 struct sockaddr_in *sin_a;
6467 struct sctp_inpcb *inp;
6468 struct sctp_tcb *stcb;
6469 struct sctp_nets *net;
6470
6471 /* Do the malloc first in case it blocks. */
6472 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin);
6473 if (sin == NULL)
6474 return (ENOMEM);
6475 sin->sin_family = AF_INET;
6476 sin->sin_len = sizeof(*sin);
6477
6478 inp = (struct sctp_inpcb *)so->so_pcb;
6479 if ((inp == NULL) ||
6480 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
6481 /* UDP type and listeners will drop out here */
6482 SCTP_FREE_SONAME(sin);
6483 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
6484 return (ENOTCONN);
6485 }
6486 SCTP_INP_RLOCK(inp);
6487 stcb = LIST_FIRST(&inp->sctp_asoc_list);
6488 if (stcb) {
6489 SCTP_TCB_LOCK(stcb);
6490 }
6491 SCTP_INP_RUNLOCK(inp);
6492 if (stcb == NULL) {
6493 SCTP_FREE_SONAME(sin);
6494 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6495 return (ECONNRESET);
6496 }
6497 fnd = 0;
6498 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6499 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
6500 if (sin_a->sin_family == AF_INET) {
6501 fnd = 1;
6502 sin->sin_port = stcb->rport;
6503 sin->sin_addr = sin_a->sin_addr;
6504 break;
6505 }
6506 }
6507 SCTP_TCB_UNLOCK(stcb);
6508 if (!fnd) {
6509 /* No IPv4 address */
6510 SCTP_FREE_SONAME(sin);
6511 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
6512 return (ENOENT);
6513 }
6514 (*addr) = (struct sockaddr *)sin;
6515 return (0);
6516 }
6517
6518 struct pr_usrreqs sctp_usrreqs = {
6519 .pru_abort = sctp_abort,
6520 .pru_accept = sctp_accept,
6521 .pru_attach = sctp_attach,
6522 .pru_bind = sctp_bind,
6523 .pru_connect = sctp_connect,
6524 .pru_control = in_control,
6525 .pru_close = sctp_close,
6526 .pru_detach = sctp_close,
6527 .pru_sopoll = sopoll_generic,
6528 .pru_flush = sctp_flush,
6529 .pru_disconnect = sctp_disconnect,
6530 .pru_listen = sctp_listen,
6531 .pru_peeraddr = sctp_peeraddr,
6532 .pru_send = sctp_sendm,
6533 .pru_shutdown = sctp_shutdown,
6534 .pru_sockaddr = sctp_ingetaddr,
6535 .pru_sosend = sctp_sosend,
6536 .pru_soreceive = sctp_soreceive
6537 };
6538
6539 #endif
6540