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