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 int cnt;
4687 uint16_t strm;
4688
4689 if (strrst->srs_number_streams) {
4690 for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) {
4691 strm = strrst->srs_stream_list[i];
4692 if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) {
4693 stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING;
4694 cnt++;
4695 }
4696 }
4697 } else {
4698 /* Its all */
4699 for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) {
4700 if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) {
4701 stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING;
4702 cnt++;
4703 }
4704 }
4705 }
4706 }
4707 if (send_in) {
4708 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams,
4709 strrst->srs_stream_list,
4710 send_in, 0, 0, 0, 0, 0);
4711 } else {
4712 error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED);
4713 }
4714 if (error == 0) {
4715 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4716 } else {
4717 /*
4718 * For outgoing streams don't report any
4719 * problems in sending the request to the
4720 * application. XXX: Double check resetting
4721 * incoming streams.
4722 */
4723 error = 0;
4724 }
4725 SCTP_TCB_UNLOCK(stcb);
4726 break;
4727 }
4728 case SCTP_ADD_STREAMS:
4729 {
4730 struct sctp_add_streams *stradd;
4731 uint8_t addstream = 0;
4732 uint16_t add_o_strmcnt = 0;
4733 uint16_t add_i_strmcnt = 0;
4734
4735 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize);
4736 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id);
4737 if (stcb == NULL) {
4738 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4739 error = ENOENT;
4740 break;
4741 }
4742 if (stcb->asoc.reconfig_supported == 0) {
4743 /*
4744 * Peer does not support the chunk type.
4745 */
4746 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4747 error = EOPNOTSUPP;
4748 SCTP_TCB_UNLOCK(stcb);
4749 break;
4750 }
4751 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
4752 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4753 error = EINVAL;
4754 SCTP_TCB_UNLOCK(stcb);
4755 break;
4756 }
4757 if (stcb->asoc.stream_reset_outstanding) {
4758 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4759 error = EALREADY;
4760 SCTP_TCB_UNLOCK(stcb);
4761 break;
4762 }
4763 if ((stradd->sas_outstrms == 0) &&
4764 (stradd->sas_instrms == 0)) {
4765 error = EINVAL;
4766 goto skip_stuff;
4767 }
4768 if (stradd->sas_outstrms) {
4769 addstream = 1;
4770 /* We allocate here */
4771 add_o_strmcnt = stradd->sas_outstrms;
4772 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) {
4773 /* You can't have more than 64k */
4774 error = EINVAL;
4775 goto skip_stuff;
4776 }
4777 }
4778 if (stradd->sas_instrms) {
4779 int cnt;
4780
4781 addstream |= 2;
4782 /*
4783 * We allocate inside
4784 * sctp_send_str_reset_req()
4785 */
4786 add_i_strmcnt = stradd->sas_instrms;
4787 cnt = add_i_strmcnt;
4788 cnt += stcb->asoc.streamincnt;
4789 if (cnt > 0x0000ffff) {
4790 /* You can't have more than 64k */
4791 error = EINVAL;
4792 goto skip_stuff;
4793 }
4794 if (cnt > (int)stcb->asoc.max_inbound_streams) {
4795 /* More than you are allowed */
4796 error = EINVAL;
4797 goto skip_stuff;
4798 }
4799 }
4800 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0);
4801 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4802 skip_stuff:
4803 SCTP_TCB_UNLOCK(stcb);
4804 break;
4805 }
4806 case SCTP_RESET_ASSOC:
4807 {
4808 int i;
4809 uint32_t *value;
4810
4811 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
4812 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t)*value);
4813 if (stcb == NULL) {
4814 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4815 error = ENOENT;
4816 break;
4817 }
4818 if (stcb->asoc.reconfig_supported == 0) {
4819 /*
4820 * Peer does not support the chunk type.
4821 */
4822 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
4823 error = EOPNOTSUPP;
4824 SCTP_TCB_UNLOCK(stcb);
4825 break;
4826 }
4827 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) {
4828 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4829 error = EINVAL;
4830 SCTP_TCB_UNLOCK(stcb);
4831 break;
4832 }
4833 if (stcb->asoc.stream_reset_outstanding) {
4834 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4835 error = EALREADY;
4836 SCTP_TCB_UNLOCK(stcb);
4837 break;
4838 }
4839 /*
4840 * Is there any data pending in the send or sent
4841 * queues?
4842 */
4843 if (!TAILQ_EMPTY(&stcb->asoc.send_queue) ||
4844 !TAILQ_EMPTY(&stcb->asoc.sent_queue)) {
4845 busy_out:
4846 error = EBUSY;
4847 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
4848 SCTP_TCB_UNLOCK(stcb);
4849 break;
4850 }
4851 /* Do any streams have data queued? */
4852 for (i = 0; i < stcb->asoc.streamoutcnt; i++) {
4853 if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) {
4854 goto busy_out;
4855 }
4856 }
4857 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0);
4858 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED);
4859 SCTP_TCB_UNLOCK(stcb);
4860 break;
4861 }
4862 case SCTP_CONNECT_X:
4863 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4864 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4865 error = EINVAL;
4866 break;
4867 }
4868 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0);
4869 break;
4870 case SCTP_CONNECT_X_DELAYED:
4871 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) {
4872 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4873 error = EINVAL;
4874 break;
4875 }
4876 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1);
4877 break;
4878 case SCTP_CONNECT_X_COMPLETE:
4879 {
4880 struct sockaddr *sa;
4881
4882 /* FIXME MT: check correct? */
4883 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
4884
4885 /* find tcb */
4886 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
4887 SCTP_INP_RLOCK(inp);
4888 stcb = LIST_FIRST(&inp->sctp_asoc_list);
4889 if (stcb) {
4890 SCTP_TCB_LOCK(stcb);
4891 }
4892 SCTP_INP_RUNLOCK(inp);
4893 } else {
4894 /*
4895 * We increment here since
4896 * sctp_findassociation_ep_addr() wil do a
4897 * decrement if it finds the stcb as long as
4898 * the locked tcb (last argument) is NOT a
4899 * TCB.. aka NULL.
4900 */
4901 SCTP_INP_INCR_REF(inp);
4902 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL);
4903 if (stcb == NULL) {
4904 SCTP_INP_DECR_REF(inp);
4905 }
4906 }
4907
4908 if (stcb == NULL) {
4909 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
4910 error = ENOENT;
4911 break;
4912 }
4913 if (stcb->asoc.delayed_connection == 1) {
4914 stcb->asoc.delayed_connection = 0;
4915 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
4916 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb,
4917 stcb->asoc.primary_destination,
4918 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8);
4919 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
4920 } else {
4921 /*
4922 * already expired or did not use delayed
4923 * connectx
4924 */
4925 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
4926 error = EALREADY;
4927 }
4928 SCTP_TCB_UNLOCK(stcb);
4929 break;
4930 }
4931 case SCTP_MAX_BURST:
4932 {
4933 struct sctp_assoc_value *av;
4934
4935 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4936 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4937
4938 if (stcb) {
4939 stcb->asoc.max_burst = av->assoc_value;
4940 SCTP_TCB_UNLOCK(stcb);
4941 } else {
4942 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4943 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4944 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4945 ((av->assoc_id == SCTP_FUTURE_ASSOC) ||
4946 (av->assoc_id == SCTP_ALL_ASSOC)))) {
4947 SCTP_INP_WLOCK(inp);
4948 inp->sctp_ep.max_burst = av->assoc_value;
4949 SCTP_INP_WUNLOCK(inp);
4950 }
4951 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4952 ((av->assoc_id == SCTP_CURRENT_ASSOC) ||
4953 (av->assoc_id == SCTP_ALL_ASSOC))) {
4954 SCTP_INP_RLOCK(inp);
4955 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
4956 SCTP_TCB_LOCK(stcb);
4957 stcb->asoc.max_burst = av->assoc_value;
4958 SCTP_TCB_UNLOCK(stcb);
4959 }
4960 SCTP_INP_RUNLOCK(inp);
4961 }
4962 }
4963 break;
4964 }
4965 case SCTP_MAXSEG:
4966 {
4967 struct sctp_assoc_value *av;
4968
4969 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
4970 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
4971
4972 if (stcb) {
4973 stcb->asoc.sctp_frag_point = av->assoc_value;
4974 SCTP_TCB_UNLOCK(stcb);
4975 } else {
4976 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
4977 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
4978 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
4979 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
4980 SCTP_INP_WLOCK(inp);
4981 inp->sctp_frag_point = av->assoc_value;
4982 SCTP_INP_WUNLOCK(inp);
4983 } else {
4984 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
4985 error = EINVAL;
4986 }
4987 }
4988 break;
4989 }
4990 case SCTP_EVENTS:
4991 {
4992 struct sctp_event_subscribe *events;
4993
4994 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize);
4995
4996 SCTP_INP_WLOCK(inp);
4997 if (events->sctp_data_io_event) {
4998 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
4999 } else {
5000 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT);
5001 }
5002
5003 if (events->sctp_association_event) {
5004 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5005 } else {
5006 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5007 }
5008
5009 if (events->sctp_address_event) {
5010 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5011 } else {
5012 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT);
5013 }
5014
5015 if (events->sctp_send_failure_event) {
5016 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5017 } else {
5018 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5019 }
5020
5021 if (events->sctp_peer_error_event) {
5022 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5023 } else {
5024 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR);
5025 }
5026
5027 if (events->sctp_shutdown_event) {
5028 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5029 } else {
5030 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5031 }
5032
5033 if (events->sctp_partial_delivery_event) {
5034 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5035 } else {
5036 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT);
5037 }
5038
5039 if (events->sctp_adaptation_layer_event) {
5040 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5041 } else {
5042 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5043 }
5044
5045 if (events->sctp_authentication_event) {
5046 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5047 } else {
5048 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT);
5049 }
5050
5051 if (events->sctp_sender_dry_event) {
5052 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
5053 } else {
5054 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
5055 }
5056
5057 if (events->sctp_stream_reset_event) {
5058 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5059 } else {
5060 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5061 }
5062
5063 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5064 SCTP_TCB_LOCK(stcb);
5065 if (events->sctp_association_event) {
5066 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5067 } else {
5068 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT);
5069 }
5070 if (events->sctp_address_event) {
5071 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5072 } else {
5073 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT);
5074 }
5075 if (events->sctp_send_failure_event) {
5076 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5077 } else {
5078 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT);
5079 }
5080 if (events->sctp_peer_error_event) {
5081 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5082 } else {
5083 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR);
5084 }
5085 if (events->sctp_shutdown_event) {
5086 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5087 } else {
5088 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT);
5089 }
5090 if (events->sctp_partial_delivery_event) {
5091 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5092 } else {
5093 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT);
5094 }
5095 if (events->sctp_adaptation_layer_event) {
5096 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5097 } else {
5098 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT);
5099 }
5100 if (events->sctp_authentication_event) {
5101 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5102 } else {
5103 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT);
5104 }
5105 if (events->sctp_sender_dry_event) {
5106 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5107 } else {
5108 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT);
5109 }
5110 if (events->sctp_stream_reset_event) {
5111 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5112 } else {
5113 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT);
5114 }
5115 SCTP_TCB_UNLOCK(stcb);
5116 }
5117 /*
5118 * Send up the sender dry event only for 1-to-1
5119 * style sockets.
5120 */
5121 if (events->sctp_sender_dry_event) {
5122 if (((inp->sctp_flags & (SCTP_PCB_FLAGS_TCPTYPE | SCTP_PCB_FLAGS_IN_TCPPOOL)) != 0) &&
5123 !SCTP_IS_LISTENING(inp)) {
5124 stcb = LIST_FIRST(&inp->sctp_asoc_list);
5125 if (stcb != NULL) {
5126 SCTP_TCB_LOCK(stcb);
5127 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
5128 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
5129 (stcb->asoc.stream_queue_cnt == 0)) {
5130 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
5131 }
5132 SCTP_TCB_UNLOCK(stcb);
5133 }
5134 }
5135 }
5136 SCTP_INP_WUNLOCK(inp);
5137 break;
5138 }
5139 case SCTP_ADAPTATION_LAYER:
5140 {
5141 struct sctp_setadaptation *adap_bits;
5142
5143 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize);
5144 SCTP_INP_WLOCK(inp);
5145 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind;
5146 inp->sctp_ep.adaptation_layer_indicator_provided = 1;
5147 SCTP_INP_WUNLOCK(inp);
5148 break;
5149 }
5150 #ifdef SCTP_DEBUG
5151 case SCTP_SET_INITIAL_DBG_SEQ:
5152 {
5153 uint32_t *vvv;
5154
5155 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize);
5156 SCTP_INP_WLOCK(inp);
5157 inp->sctp_ep.initial_sequence_debug = *vvv;
5158 SCTP_INP_WUNLOCK(inp);
5159 break;
5160 }
5161 #endif
5162 case SCTP_DEFAULT_SEND_PARAM:
5163 {
5164 struct sctp_sndrcvinfo *s_info;
5165
5166 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize);
5167 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id);
5168
5169 if (stcb) {
5170 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5171 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5172 } else {
5173 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5174 error = EINVAL;
5175 }
5176 SCTP_TCB_UNLOCK(stcb);
5177 } else {
5178 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5179 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5180 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5181 ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) ||
5182 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)))) {
5183 SCTP_INP_WLOCK(inp);
5184 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send)));
5185 SCTP_INP_WUNLOCK(inp);
5186 }
5187 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5188 ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) ||
5189 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC))) {
5190 SCTP_INP_RLOCK(inp);
5191 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
5192 SCTP_TCB_LOCK(stcb);
5193 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) {
5194 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send)));
5195 }
5196 SCTP_TCB_UNLOCK(stcb);
5197 }
5198 SCTP_INP_RUNLOCK(inp);
5199 }
5200 }
5201 break;
5202 }
5203 case SCTP_PEER_ADDR_PARAMS:
5204 {
5205 struct sctp_paddrparams *paddrp;
5206 struct sctp_nets *net;
5207 struct sockaddr *addr;
5208 #if defined(INET) && defined(INET6)
5209 struct sockaddr_in sin_store;
5210 #endif
5211
5212 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize);
5213 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id);
5214
5215 #if defined(INET) && defined(INET6)
5216 if (paddrp->spp_address.ss_family == AF_INET6) {
5217 struct sockaddr_in6 *sin6;
5218
5219 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address;
5220 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5221 in6_sin6_2_sin(&sin_store, sin6);
5222 addr = (struct sockaddr *)&sin_store;
5223 } else {
5224 addr = (struct sockaddr *)&paddrp->spp_address;
5225 }
5226 } else {
5227 addr = (struct sockaddr *)&paddrp->spp_address;
5228 }
5229 #else
5230 addr = (struct sockaddr *)&paddrp->spp_address;
5231 #endif
5232 if (stcb != NULL) {
5233 net = sctp_findnet(stcb, addr);
5234 } else {
5235 /*
5236 * We increment here since
5237 * sctp_findassociation_ep_addr() wil do a
5238 * decrement if it finds the stcb as long as
5239 * the locked tcb (last argument) is NOT a
5240 * TCB.. aka NULL.
5241 */
5242 net = NULL;
5243 SCTP_INP_INCR_REF(inp);
5244 stcb = sctp_findassociation_ep_addr(&inp, addr,
5245 &net, NULL, NULL);
5246 if (stcb == NULL) {
5247 SCTP_INP_DECR_REF(inp);
5248 }
5249 }
5250 if ((stcb != NULL) && (net == NULL)) {
5251 #ifdef INET
5252 if (addr->sa_family == AF_INET) {
5253 struct sockaddr_in *sin;
5254
5255 sin = (struct sockaddr_in *)addr;
5256 if (sin->sin_addr.s_addr != INADDR_ANY) {
5257 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5258 SCTP_TCB_UNLOCK(stcb);
5259 error = EINVAL;
5260 break;
5261 }
5262 } else
5263 #endif
5264 #ifdef INET6
5265 if (addr->sa_family == AF_INET6) {
5266 struct sockaddr_in6 *sin6;
5267
5268 sin6 = (struct sockaddr_in6 *)addr;
5269 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
5270 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5271 SCTP_TCB_UNLOCK(stcb);
5272 error = EINVAL;
5273 break;
5274 }
5275 } else
5276 #endif
5277 {
5278 error = EAFNOSUPPORT;
5279 SCTP_TCB_UNLOCK(stcb);
5280 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
5281 break;
5282 }
5283 }
5284 /* sanity checks */
5285 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) {
5286 if (stcb)
5287 SCTP_TCB_UNLOCK(stcb);
5288 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5289 return (EINVAL);
5290 }
5291
5292 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) {
5293 if (stcb)
5294 SCTP_TCB_UNLOCK(stcb);
5295 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5296 return (EINVAL);
5297 }
5298 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) &&
5299 (paddrp->spp_pathmtu > 0) &&
5300 ((paddrp->spp_pathmtu < SCTP_SMALLEST_PMTU) ||
5301 (paddrp->spp_pathmtu > SCTP_LARGEST_PMTU))) {
5302 if (stcb)
5303 SCTP_TCB_UNLOCK(stcb);
5304 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5305 return (EINVAL);
5306 }
5307
5308 if (stcb != NULL) {
5309 /************************TCB SPECIFIC SET ******************/
5310 if (net != NULL) {
5311 /************************NET SPECIFIC SET ******************/
5312 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5313 if (((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) &&
5314 ((net->dest_state & SCTP_ADDR_NOHB) == 0)) {
5315 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5316 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9);
5317 }
5318 net->dest_state |= SCTP_ADDR_NOHB;
5319 }
5320 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5321 if (paddrp->spp_hbinterval) {
5322 net->heart_beat_delay = paddrp->spp_hbinterval;
5323 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5324 net->heart_beat_delay = 0;
5325 }
5326 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5327 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10);
5328 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5329 net->dest_state &= ~SCTP_ADDR_NOHB;
5330 }
5331 if (paddrp->spp_flags & SPP_HB_DEMAND) {
5332 if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) {
5333 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5334 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5335 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5336 }
5337 }
5338 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5339 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5340 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5341 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11);
5342 }
5343 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5344 if (paddrp->spp_pathmtu > 0) {
5345 net->mtu = paddrp->spp_pathmtu;
5346 switch (net->ro._l_addr.sa.sa_family) {
5347 #ifdef INET
5348 case AF_INET:
5349 net->mtu += SCTP_MIN_V4_OVERHEAD;
5350 break;
5351 #endif
5352 #ifdef INET6
5353 case AF_INET6:
5354 net->mtu += SCTP_MIN_OVERHEAD;
5355 break;
5356 #endif
5357 default:
5358 break;
5359 }
5360 if (net->mtu < stcb->asoc.smallest_mtu) {
5361 sctp_pathmtu_adjustment(stcb, net->mtu, true);
5362 }
5363 }
5364 }
5365 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5366 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5367 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5368 }
5369 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5370 }
5371 if (paddrp->spp_pathmaxrxt > 0) {
5372 if (net->dest_state & SCTP_ADDR_PF) {
5373 if (net->error_count > paddrp->spp_pathmaxrxt) {
5374 net->dest_state &= ~SCTP_ADDR_PF;
5375 }
5376 } else {
5377 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5378 (net->error_count > net->pf_threshold)) {
5379 net->dest_state |= SCTP_ADDR_PF;
5380 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5381 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5382 stcb->sctp_ep, stcb, net,
5383 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12);
5384 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5385 }
5386 }
5387 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5388 if (net->error_count > paddrp->spp_pathmaxrxt) {
5389 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5390 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5391 }
5392 } else {
5393 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5394 net->dest_state |= SCTP_ADDR_REACHABLE;
5395 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5396 }
5397 }
5398 net->failure_threshold = paddrp->spp_pathmaxrxt;
5399 }
5400 if (paddrp->spp_flags & SPP_DSCP) {
5401 net->dscp = paddrp->spp_dscp & 0xfc;
5402 net->dscp |= 0x01;
5403 }
5404 #ifdef INET6
5405 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5406 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5407 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5408 net->flowlabel |= 0x80000000;
5409 }
5410 }
5411 #endif
5412 } else {
5413 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/
5414 if (paddrp->spp_pathmaxrxt > 0) {
5415 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt;
5416 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5417 if (net->dest_state & SCTP_ADDR_PF) {
5418 if (net->error_count > paddrp->spp_pathmaxrxt) {
5419 net->dest_state &= ~SCTP_ADDR_PF;
5420 }
5421 } else {
5422 if ((net->error_count <= paddrp->spp_pathmaxrxt) &&
5423 (net->error_count > net->pf_threshold)) {
5424 net->dest_state |= SCTP_ADDR_PF;
5425 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
5426 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5427 stcb->sctp_ep, stcb, net,
5428 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13);
5429 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
5430 }
5431 }
5432 if (net->dest_state & SCTP_ADDR_REACHABLE) {
5433 if (net->error_count > paddrp->spp_pathmaxrxt) {
5434 net->dest_state &= ~SCTP_ADDR_REACHABLE;
5435 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
5436 }
5437 } else {
5438 if (net->error_count <= paddrp->spp_pathmaxrxt) {
5439 net->dest_state |= SCTP_ADDR_REACHABLE;
5440 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
5441 }
5442 }
5443 net->failure_threshold = paddrp->spp_pathmaxrxt;
5444 }
5445 }
5446 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5447 if (paddrp->spp_hbinterval != 0) {
5448 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval;
5449 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5450 stcb->asoc.heart_beat_delay = 0;
5451 }
5452 /* Turn back on the timer */
5453 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5454 if (paddrp->spp_hbinterval != 0) {
5455 net->heart_beat_delay = paddrp->spp_hbinterval;
5456 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5457 net->heart_beat_delay = 0;
5458 }
5459 if (net->dest_state & SCTP_ADDR_NOHB) {
5460 net->dest_state &= ~SCTP_ADDR_NOHB;
5461 }
5462 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net,
5463 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14);
5464 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net);
5465 }
5466 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5467 }
5468 if (paddrp->spp_flags & SPP_HB_DISABLE) {
5469 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5470 if ((net->dest_state & SCTP_ADDR_NOHB) == 0) {
5471 net->dest_state |= SCTP_ADDR_NOHB;
5472 if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
5473 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
5474 inp, stcb, net,
5475 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15);
5476 }
5477 }
5478 }
5479 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5480 }
5481 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5482 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5483 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5484 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
5485 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16);
5486 }
5487 net->dest_state |= SCTP_ADDR_NO_PMTUD;
5488 if (paddrp->spp_pathmtu > 0) {
5489 net->mtu = paddrp->spp_pathmtu;
5490 switch (net->ro._l_addr.sa.sa_family) {
5491 #ifdef INET
5492 case AF_INET:
5493 net->mtu += SCTP_MIN_V4_OVERHEAD;
5494 break;
5495 #endif
5496 #ifdef INET6
5497 case AF_INET6:
5498 net->mtu += SCTP_MIN_OVERHEAD;
5499 break;
5500 #endif
5501 default:
5502 break;
5503 }
5504 if (net->mtu < stcb->asoc.smallest_mtu) {
5505 sctp_pathmtu_adjustment(stcb, net->mtu, true);
5506 }
5507 }
5508 }
5509 if (paddrp->spp_pathmtu > 0) {
5510 stcb->asoc.default_mtu = paddrp->spp_pathmtu;
5511 }
5512 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5513 }
5514 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5515 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5516 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
5517 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net);
5518 }
5519 net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
5520 }
5521 stcb->asoc.default_mtu = 0;
5522 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5523 }
5524 if (paddrp->spp_flags & SPP_DSCP) {
5525 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5526 net->dscp = paddrp->spp_dscp & 0xfc;
5527 net->dscp |= 0x01;
5528 }
5529 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc;
5530 stcb->asoc.default_dscp |= 0x01;
5531 }
5532 #ifdef INET6
5533 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5534 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
5535 if (net->ro._l_addr.sa.sa_family == AF_INET6) {
5536 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5537 net->flowlabel |= 0x80000000;
5538 }
5539 }
5540 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5541 stcb->asoc.default_flowlabel |= 0x80000000;
5542 }
5543 #endif
5544 }
5545 SCTP_TCB_UNLOCK(stcb);
5546 } else {
5547 /************************NO TCB, SET TO default stuff ******************/
5548 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5549 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5550 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5551 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) {
5552 SCTP_INP_WLOCK(inp);
5553 /*
5554 * For the TOS/FLOWLABEL stuff you
5555 * set it with the options on the
5556 * socket
5557 */
5558 if (paddrp->spp_pathmaxrxt > 0) {
5559 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt;
5560 }
5561
5562 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO)
5563 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5564 else if (paddrp->spp_hbinterval != 0) {
5565 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL)
5566 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL;
5567 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
5568 }
5569
5570 if (paddrp->spp_flags & SPP_HB_ENABLE) {
5571 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) {
5572 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0;
5573 } else if (paddrp->spp_hbinterval) {
5574 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval);
5575 }
5576 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5577 } else if (paddrp->spp_flags & SPP_HB_DISABLE) {
5578 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
5579 }
5580 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
5581 inp->sctp_ep.default_mtu = 0;
5582 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5583 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
5584 if (paddrp->spp_pathmtu > 0) {
5585 inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
5586 }
5587 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
5588 }
5589 if (paddrp->spp_flags & SPP_DSCP) {
5590 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc;
5591 inp->sctp_ep.default_dscp |= 0x01;
5592 }
5593 #ifdef INET6
5594 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) {
5595 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
5596 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff;
5597 inp->sctp_ep.default_flowlabel |= 0x80000000;
5598 }
5599 }
5600 #endif
5601 SCTP_INP_WUNLOCK(inp);
5602 } else {
5603 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5604 error = EINVAL;
5605 }
5606 }
5607 break;
5608 }
5609 case SCTP_RTOINFO:
5610 {
5611 struct sctp_rtoinfo *srto;
5612 uint32_t new_init, new_min, new_max;
5613
5614 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize);
5615 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id);
5616
5617 if (stcb) {
5618 if (srto->srto_initial)
5619 new_init = srto->srto_initial;
5620 else
5621 new_init = stcb->asoc.initial_rto;
5622 if (srto->srto_max)
5623 new_max = srto->srto_max;
5624 else
5625 new_max = stcb->asoc.maxrto;
5626 if (srto->srto_min)
5627 new_min = srto->srto_min;
5628 else
5629 new_min = stcb->asoc.minrto;
5630 if ((new_min <= new_init) && (new_init <= new_max)) {
5631 stcb->asoc.initial_rto = new_init;
5632 stcb->asoc.maxrto = new_max;
5633 stcb->asoc.minrto = new_min;
5634 } else {
5635 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5636 error = EINVAL;
5637 }
5638 SCTP_TCB_UNLOCK(stcb);
5639 } else {
5640 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5641 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5642 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5643 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) {
5644 SCTP_INP_WLOCK(inp);
5645 if (srto->srto_initial)
5646 new_init = srto->srto_initial;
5647 else
5648 new_init = inp->sctp_ep.initial_rto;
5649 if (srto->srto_max)
5650 new_max = srto->srto_max;
5651 else
5652 new_max = inp->sctp_ep.sctp_maxrto;
5653 if (srto->srto_min)
5654 new_min = srto->srto_min;
5655 else
5656 new_min = inp->sctp_ep.sctp_minrto;
5657 if ((new_min <= new_init) && (new_init <= new_max)) {
5658 inp->sctp_ep.initial_rto = new_init;
5659 inp->sctp_ep.sctp_maxrto = new_max;
5660 inp->sctp_ep.sctp_minrto = new_min;
5661 } else {
5662 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5663 error = EINVAL;
5664 }
5665 SCTP_INP_WUNLOCK(inp);
5666 } else {
5667 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5668 error = EINVAL;
5669 }
5670 }
5671 break;
5672 }
5673 case SCTP_ASSOCINFO:
5674 {
5675 struct sctp_assocparams *sasoc;
5676
5677 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize);
5678 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id);
5679 if (sasoc->sasoc_cookie_life > 0) {
5680 /* boundary check the cookie life */
5681 if (sasoc->sasoc_cookie_life < SCTP_MIN_COOKIE_LIFE) {
5682 sasoc->sasoc_cookie_life = SCTP_MIN_COOKIE_LIFE;
5683 }
5684 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) {
5685 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE;
5686 }
5687 }
5688 if (stcb) {
5689 if (sasoc->sasoc_asocmaxrxt > 0) {
5690 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt;
5691 }
5692 if (sasoc->sasoc_cookie_life > 0) {
5693 stcb->asoc.cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
5694 }
5695 SCTP_TCB_UNLOCK(stcb);
5696 } else {
5697 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
5698 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
5699 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
5700 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) {
5701 SCTP_INP_WLOCK(inp);
5702 if (sasoc->sasoc_asocmaxrxt > 0) {
5703 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt;
5704 }
5705 if (sasoc->sasoc_cookie_life > 0) {
5706 inp->sctp_ep.def_cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life);
5707 }
5708 SCTP_INP_WUNLOCK(inp);
5709 } else {
5710 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5711 error = EINVAL;
5712 }
5713 }
5714 break;
5715 }
5716 case SCTP_INITMSG:
5717 {
5718 struct sctp_initmsg *sinit;
5719
5720 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize);
5721 SCTP_INP_WLOCK(inp);
5722 if (sinit->sinit_num_ostreams)
5723 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams;
5724
5725 if (sinit->sinit_max_instreams)
5726 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams;
5727
5728 if (sinit->sinit_max_attempts)
5729 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts;
5730
5731 if (sinit->sinit_max_init_timeo)
5732 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo;
5733 SCTP_INP_WUNLOCK(inp);
5734 break;
5735 }
5736 case SCTP_PRIMARY_ADDR:
5737 {
5738 struct sctp_setprim *spa;
5739 struct sctp_nets *net;
5740 struct sockaddr *addr;
5741 #if defined(INET) && defined(INET6)
5742 struct sockaddr_in sin_store;
5743 #endif
5744
5745 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize);
5746 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id);
5747
5748 #if defined(INET) && defined(INET6)
5749 if (spa->ssp_addr.ss_family == AF_INET6) {
5750 struct sockaddr_in6 *sin6;
5751
5752 sin6 = (struct sockaddr_in6 *)&spa->ssp_addr;
5753 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5754 in6_sin6_2_sin(&sin_store, sin6);
5755 addr = (struct sockaddr *)&sin_store;
5756 } else {
5757 addr = (struct sockaddr *)&spa->ssp_addr;
5758 }
5759 } else {
5760 addr = (struct sockaddr *)&spa->ssp_addr;
5761 }
5762 #else
5763 addr = (struct sockaddr *)&spa->ssp_addr;
5764 #endif
5765 if (stcb != NULL) {
5766 net = sctp_findnet(stcb, addr);
5767 } else {
5768 /*
5769 * We increment here since
5770 * sctp_findassociation_ep_addr() wil do a
5771 * decrement if it finds the stcb as long as
5772 * the locked tcb (last argument) is NOT a
5773 * TCB.. aka NULL.
5774 */
5775 net = NULL;
5776 SCTP_INP_INCR_REF(inp);
5777 stcb = sctp_findassociation_ep_addr(&inp, addr,
5778 &net, NULL, NULL);
5779 if (stcb == NULL) {
5780 SCTP_INP_DECR_REF(inp);
5781 }
5782 }
5783
5784 if ((stcb != NULL) && (net != NULL)) {
5785 if (net != stcb->asoc.primary_destination) {
5786 if ((net->dest_state & SCTP_ADDR_UNCONFIRMED) == 0) {
5787 /* Ok we need to set it */
5788 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) {
5789 if ((stcb->asoc.alternate) &&
5790 ((net->dest_state & SCTP_ADDR_PF) == 0) &&
5791 (net->dest_state & SCTP_ADDR_REACHABLE)) {
5792 sctp_free_remote_addr(stcb->asoc.alternate);
5793 stcb->asoc.alternate = NULL;
5794 }
5795 } else {
5796 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5797 error = EINVAL;
5798 }
5799 } else {
5800 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5801 error = EINVAL;
5802 }
5803 }
5804 } else {
5805 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5806 error = EINVAL;
5807 }
5808 if (stcb != NULL) {
5809 SCTP_TCB_UNLOCK(stcb);
5810 }
5811 break;
5812 }
5813 case SCTP_SET_DYNAMIC_PRIMARY:
5814 {
5815 union sctp_sockstore *ss;
5816
5817 error = priv_check(curthread,
5818 PRIV_NETINET_RESERVEDPORT);
5819 if (error)
5820 break;
5821
5822 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize);
5823 /* SUPER USER CHECK? */
5824 error = sctp_dynamic_set_primary(&ss->sa, vrf_id);
5825 break;
5826 }
5827 case SCTP_SET_PEER_PRIMARY_ADDR:
5828 {
5829 struct sctp_setpeerprim *sspp;
5830 struct sockaddr *addr;
5831 #if defined(INET) && defined(INET6)
5832 struct sockaddr_in sin_store;
5833 #endif
5834
5835 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize);
5836 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id);
5837 if (stcb != NULL) {
5838 struct sctp_ifa *ifa;
5839
5840 #if defined(INET) && defined(INET6)
5841 if (sspp->sspp_addr.ss_family == AF_INET6) {
5842 struct sockaddr_in6 *sin6;
5843
5844 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr;
5845 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
5846 in6_sin6_2_sin(&sin_store, sin6);
5847 addr = (struct sockaddr *)&sin_store;
5848 } else {
5849 addr = (struct sockaddr *)&sspp->sspp_addr;
5850 }
5851 } else {
5852 addr = (struct sockaddr *)&sspp->sspp_addr;
5853 }
5854 #else
5855 addr = (struct sockaddr *)&sspp->sspp_addr;
5856 #endif
5857 ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED);
5858 if (ifa == NULL) {
5859 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5860 error = EINVAL;
5861 goto out_of_it;
5862 }
5863 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
5864 /*
5865 * Must validate the ifa found is in
5866 * our ep
5867 */
5868 struct sctp_laddr *laddr;
5869 int found = 0;
5870
5871 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
5872 if (laddr->ifa == NULL) {
5873 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n",
5874 __func__);
5875 continue;
5876 }
5877 if ((sctp_is_addr_restricted(stcb, laddr->ifa)) &&
5878 (!sctp_is_addr_pending(stcb, laddr->ifa))) {
5879 continue;
5880 }
5881 if (laddr->ifa == ifa) {
5882 found = 1;
5883 break;
5884 }
5885 }
5886 if (!found) {
5887 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5888 error = EINVAL;
5889 goto out_of_it;
5890 }
5891 } else {
5892 switch (addr->sa_family) {
5893 #ifdef INET
5894 case AF_INET:
5895 {
5896 struct sockaddr_in *sin;
5897
5898 sin = (struct sockaddr_in *)addr;
5899 if (prison_check_ip4(inp->ip_inp.inp.inp_cred,
5900 &sin->sin_addr) != 0) {
5901 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5902 error = EINVAL;
5903 goto out_of_it;
5904 }
5905 break;
5906 }
5907 #endif
5908 #ifdef INET6
5909 case AF_INET6:
5910 {
5911 struct sockaddr_in6 *sin6;
5912
5913 sin6 = (struct sockaddr_in6 *)addr;
5914 if (prison_check_ip6(inp->ip_inp.inp.inp_cred,
5915 &sin6->sin6_addr) != 0) {
5916 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5917 error = EINVAL;
5918 goto out_of_it;
5919 }
5920 break;
5921 }
5922 #endif
5923 default:
5924 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5925 error = EINVAL;
5926 goto out_of_it;
5927 }
5928 }
5929 if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) {
5930 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5931 error = EINVAL;
5932 }
5933 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED);
5934 out_of_it:
5935 SCTP_TCB_UNLOCK(stcb);
5936 } else {
5937 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5938 error = EINVAL;
5939 }
5940 break;
5941 }
5942 case SCTP_BINDX_ADD_ADDR:
5943 {
5944 struct sockaddr *sa;
5945 struct thread *td;
5946
5947 td = (struct thread *)p;
5948 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5949 #ifdef INET
5950 if (sa->sa_family == AF_INET) {
5951 if (optsize < sizeof(struct sockaddr_in)) {
5952 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5953 error = EINVAL;
5954 break;
5955 }
5956 if (td != NULL &&
5957 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
5958 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5959 break;
5960 }
5961 } else
5962 #endif
5963 #ifdef INET6
5964 if (sa->sa_family == AF_INET6) {
5965 if (optsize < sizeof(struct sockaddr_in6)) {
5966 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5967 error = EINVAL;
5968 break;
5969 }
5970 if (td != NULL &&
5971 (error = prison_local_ip6(td->td_ucred,
5972 &(((struct sockaddr_in6 *)sa)->sin6_addr),
5973 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
5974 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
5975 break;
5976 }
5977 } else
5978 #endif
5979 {
5980 error = EAFNOSUPPORT;
5981 break;
5982 }
5983 sctp_bindx_add_address(so, inp, sa, vrf_id, &error, p);
5984 break;
5985 }
5986 case SCTP_BINDX_REM_ADDR:
5987 {
5988 struct sockaddr *sa;
5989 struct thread *td;
5990
5991 td = (struct thread *)p;
5992
5993 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize);
5994 #ifdef INET
5995 if (sa->sa_family == AF_INET) {
5996 if (optsize < sizeof(struct sockaddr_in)) {
5997 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
5998 error = EINVAL;
5999 break;
6000 }
6001 if (td != NULL &&
6002 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) {
6003 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6004 break;
6005 }
6006 } else
6007 #endif
6008 #ifdef INET6
6009 if (sa->sa_family == AF_INET6) {
6010 if (optsize < sizeof(struct sockaddr_in6)) {
6011 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6012 error = EINVAL;
6013 break;
6014 }
6015 if (td != NULL &&
6016 (error = prison_local_ip6(td->td_ucred,
6017 &(((struct sockaddr_in6 *)sa)->sin6_addr),
6018 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) {
6019 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error);
6020 break;
6021 }
6022 } else
6023 #endif
6024 {
6025 error = EAFNOSUPPORT;
6026 break;
6027 }
6028 sctp_bindx_delete_address(inp, sa, vrf_id, &error);
6029 break;
6030 }
6031 case SCTP_EVENT:
6032 {
6033 struct sctp_event *event;
6034 uint32_t event_type;
6035
6036 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize);
6037 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id);
6038 switch (event->se_type) {
6039 case SCTP_ASSOC_CHANGE:
6040 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT;
6041 break;
6042 case SCTP_PEER_ADDR_CHANGE:
6043 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT;
6044 break;
6045 case SCTP_REMOTE_ERROR:
6046 event_type = SCTP_PCB_FLAGS_RECVPEERERR;
6047 break;
6048 case SCTP_SEND_FAILED:
6049 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT;
6050 break;
6051 case SCTP_SHUTDOWN_EVENT:
6052 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT;
6053 break;
6054 case SCTP_ADAPTATION_INDICATION:
6055 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT;
6056 break;
6057 case SCTP_PARTIAL_DELIVERY_EVENT:
6058 event_type = SCTP_PCB_FLAGS_PDAPIEVNT;
6059 break;
6060 case SCTP_AUTHENTICATION_EVENT:
6061 event_type = SCTP_PCB_FLAGS_AUTHEVNT;
6062 break;
6063 case SCTP_STREAM_RESET_EVENT:
6064 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT;
6065 break;
6066 case SCTP_SENDER_DRY_EVENT:
6067 event_type = SCTP_PCB_FLAGS_DRYEVNT;
6068 break;
6069 case SCTP_NOTIFICATIONS_STOPPED_EVENT:
6070 event_type = 0;
6071 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6072 error = ENOTSUP;
6073 break;
6074 case SCTP_ASSOC_RESET_EVENT:
6075 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT;
6076 break;
6077 case SCTP_STREAM_CHANGE_EVENT:
6078 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT;
6079 break;
6080 case SCTP_SEND_FAILED_EVENT:
6081 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT;
6082 break;
6083 default:
6084 event_type = 0;
6085 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6086 error = EINVAL;
6087 break;
6088 }
6089 if (event_type > 0) {
6090 if (stcb) {
6091 if (event->se_on) {
6092 sctp_stcb_feature_on(inp, stcb, event_type);
6093 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) {
6094 if (TAILQ_EMPTY(&stcb->asoc.send_queue) &&
6095 TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
6096 (stcb->asoc.stream_queue_cnt == 0)) {
6097 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
6098 }
6099 }
6100 } else {
6101 sctp_stcb_feature_off(inp, stcb, event_type);
6102 }
6103 SCTP_TCB_UNLOCK(stcb);
6104 } else {
6105 /*
6106 * We don't want to send up a storm
6107 * of events, so return an error for
6108 * sender dry events
6109 */
6110 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) &&
6111 (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6112 ((event->se_assoc_id == SCTP_ALL_ASSOC) ||
6113 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) {
6114 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP);
6115 error = ENOTSUP;
6116 break;
6117 }
6118 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6119 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6120 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6121 ((event->se_assoc_id == SCTP_FUTURE_ASSOC) ||
6122 (event->se_assoc_id == SCTP_ALL_ASSOC)))) {
6123 SCTP_INP_WLOCK(inp);
6124 if (event->se_on) {
6125 sctp_feature_on(inp, event_type);
6126 } else {
6127 sctp_feature_off(inp, event_type);
6128 }
6129 SCTP_INP_WUNLOCK(inp);
6130 }
6131 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6132 ((event->se_assoc_id == SCTP_CURRENT_ASSOC) ||
6133 (event->se_assoc_id == SCTP_ALL_ASSOC))) {
6134 SCTP_INP_RLOCK(inp);
6135 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6136 SCTP_TCB_LOCK(stcb);
6137 if (event->se_on) {
6138 sctp_stcb_feature_on(inp, stcb, event_type);
6139 } else {
6140 sctp_stcb_feature_off(inp, stcb, event_type);
6141 }
6142 SCTP_TCB_UNLOCK(stcb);
6143 }
6144 SCTP_INP_RUNLOCK(inp);
6145 }
6146 }
6147 } else {
6148 if (stcb) {
6149 SCTP_TCB_UNLOCK(stcb);
6150 }
6151 }
6152 break;
6153 }
6154 case SCTP_RECVRCVINFO:
6155 {
6156 int *onoff;
6157
6158 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6159 SCTP_INP_WLOCK(inp);
6160 if (*onoff != 0) {
6161 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6162 } else {
6163 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO);
6164 }
6165 SCTP_INP_WUNLOCK(inp);
6166 break;
6167 }
6168 case SCTP_RECVNXTINFO:
6169 {
6170 int *onoff;
6171
6172 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize);
6173 SCTP_INP_WLOCK(inp);
6174 if (*onoff != 0) {
6175 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6176 } else {
6177 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO);
6178 }
6179 SCTP_INP_WUNLOCK(inp);
6180 break;
6181 }
6182 case SCTP_DEFAULT_SNDINFO:
6183 {
6184 struct sctp_sndinfo *info;
6185 uint16_t policy;
6186
6187 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize);
6188 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id);
6189
6190 if (stcb) {
6191 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6192 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6193 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6194 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6195 stcb->asoc.def_send.sinfo_flags |= policy;
6196 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6197 stcb->asoc.def_send.sinfo_context = info->snd_context;
6198 } else {
6199 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6200 error = EINVAL;
6201 }
6202 SCTP_TCB_UNLOCK(stcb);
6203 } else {
6204 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6205 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6206 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6207 ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) ||
6208 (info->snd_assoc_id == SCTP_ALL_ASSOC)))) {
6209 SCTP_INP_WLOCK(inp);
6210 inp->def_send.sinfo_stream = info->snd_sid;
6211 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags);
6212 inp->def_send.sinfo_flags = info->snd_flags;
6213 inp->def_send.sinfo_flags |= policy;
6214 inp->def_send.sinfo_ppid = info->snd_ppid;
6215 inp->def_send.sinfo_context = info->snd_context;
6216 SCTP_INP_WUNLOCK(inp);
6217 }
6218 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6219 ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) ||
6220 (info->snd_assoc_id == SCTP_ALL_ASSOC))) {
6221 SCTP_INP_RLOCK(inp);
6222 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6223 SCTP_TCB_LOCK(stcb);
6224 if (info->snd_sid < stcb->asoc.streamoutcnt) {
6225 stcb->asoc.def_send.sinfo_stream = info->snd_sid;
6226 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags);
6227 stcb->asoc.def_send.sinfo_flags = info->snd_flags;
6228 stcb->asoc.def_send.sinfo_flags |= policy;
6229 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid;
6230 stcb->asoc.def_send.sinfo_context = info->snd_context;
6231 }
6232 SCTP_TCB_UNLOCK(stcb);
6233 }
6234 SCTP_INP_RUNLOCK(inp);
6235 }
6236 }
6237 break;
6238 }
6239 case SCTP_DEFAULT_PRINFO:
6240 {
6241 struct sctp_default_prinfo *info;
6242
6243 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize);
6244 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id);
6245
6246 if (info->pr_policy > SCTP_PR_SCTP_MAX) {
6247 if (stcb) {
6248 SCTP_TCB_UNLOCK(stcb);
6249 }
6250 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6251 error = EINVAL;
6252 break;
6253 }
6254 if (stcb) {
6255 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6256 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6257 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6258 SCTP_TCB_UNLOCK(stcb);
6259 } else {
6260 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6261 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6262 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6263 ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) ||
6264 (info->pr_assoc_id == SCTP_ALL_ASSOC)))) {
6265 SCTP_INP_WLOCK(inp);
6266 inp->def_send.sinfo_flags &= 0xfff0;
6267 inp->def_send.sinfo_flags |= info->pr_policy;
6268 inp->def_send.sinfo_timetolive = info->pr_value;
6269 SCTP_INP_WUNLOCK(inp);
6270 }
6271 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6272 ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) ||
6273 (info->pr_assoc_id == SCTP_ALL_ASSOC))) {
6274 SCTP_INP_RLOCK(inp);
6275 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) {
6276 SCTP_TCB_LOCK(stcb);
6277 stcb->asoc.def_send.sinfo_flags &= 0xfff0;
6278 stcb->asoc.def_send.sinfo_flags |= info->pr_policy;
6279 stcb->asoc.def_send.sinfo_timetolive = info->pr_value;
6280 SCTP_TCB_UNLOCK(stcb);
6281 }
6282 SCTP_INP_RUNLOCK(inp);
6283 }
6284 }
6285 break;
6286 }
6287 case SCTP_PEER_ADDR_THLDS:
6288 /* Applies to the specific association */
6289 {
6290 struct sctp_paddrthlds *thlds;
6291 struct sctp_nets *net;
6292 struct sockaddr *addr;
6293 #if defined(INET) && defined(INET6)
6294 struct sockaddr_in sin_store;
6295 #endif
6296
6297 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize);
6298 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id);
6299
6300 #if defined(INET) && defined(INET6)
6301 if (thlds->spt_address.ss_family == AF_INET6) {
6302 struct sockaddr_in6 *sin6;
6303
6304 sin6 = (struct sockaddr_in6 *)&thlds->spt_address;
6305 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6306 in6_sin6_2_sin(&sin_store, sin6);
6307 addr = (struct sockaddr *)&sin_store;
6308 } else {
6309 addr = (struct sockaddr *)&thlds->spt_address;
6310 }
6311 } else {
6312 addr = (struct sockaddr *)&thlds->spt_address;
6313 }
6314 #else
6315 addr = (struct sockaddr *)&thlds->spt_address;
6316 #endif
6317 if (stcb != NULL) {
6318 net = sctp_findnet(stcb, addr);
6319 } else {
6320 /*
6321 * We increment here since
6322 * sctp_findassociation_ep_addr() wil do a
6323 * decrement if it finds the stcb as long as
6324 * the locked tcb (last argument) is NOT a
6325 * TCB.. aka NULL.
6326 */
6327 net = NULL;
6328 SCTP_INP_INCR_REF(inp);
6329 stcb = sctp_findassociation_ep_addr(&inp, addr,
6330 &net, NULL, NULL);
6331 if (stcb == NULL) {
6332 SCTP_INP_DECR_REF(inp);
6333 }
6334 }
6335 if ((stcb != NULL) && (net == NULL)) {
6336 #ifdef INET
6337 if (addr->sa_family == AF_INET) {
6338 struct sockaddr_in *sin;
6339
6340 sin = (struct sockaddr_in *)addr;
6341 if (sin->sin_addr.s_addr != INADDR_ANY) {
6342 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6343 SCTP_TCB_UNLOCK(stcb);
6344 error = EINVAL;
6345 break;
6346 }
6347 } else
6348 #endif
6349 #ifdef INET6
6350 if (addr->sa_family == AF_INET6) {
6351 struct sockaddr_in6 *sin6;
6352
6353 sin6 = (struct sockaddr_in6 *)addr;
6354 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6355 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6356 SCTP_TCB_UNLOCK(stcb);
6357 error = EINVAL;
6358 break;
6359 }
6360 } else
6361 #endif
6362 {
6363 error = EAFNOSUPPORT;
6364 SCTP_TCB_UNLOCK(stcb);
6365 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6366 break;
6367 }
6368 }
6369 if (thlds->spt_pathcpthld != 0xffff) {
6370 if (stcb != NULL) {
6371 SCTP_TCB_UNLOCK(stcb);
6372 }
6373 error = EINVAL;
6374 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6375 break;
6376 }
6377 if (stcb != NULL) {
6378 if (net != NULL) {
6379 net->failure_threshold = thlds->spt_pathmaxrxt;
6380 net->pf_threshold = thlds->spt_pathpfthld;
6381 if (net->dest_state & SCTP_ADDR_PF) {
6382 if ((net->error_count > net->failure_threshold) ||
6383 (net->error_count <= net->pf_threshold)) {
6384 net->dest_state &= ~SCTP_ADDR_PF;
6385 }
6386 } else {
6387 if ((net->error_count > net->pf_threshold) &&
6388 (net->error_count <= net->failure_threshold)) {
6389 net->dest_state |= SCTP_ADDR_PF;
6390 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6391 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6392 stcb->sctp_ep, stcb, net,
6393 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17);
6394 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6395 }
6396 }
6397 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6398 if (net->error_count > net->failure_threshold) {
6399 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6400 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6401 }
6402 } else {
6403 if (net->error_count <= net->failure_threshold) {
6404 net->dest_state |= SCTP_ADDR_REACHABLE;
6405 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6406 }
6407 }
6408 } else {
6409 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6410 net->failure_threshold = thlds->spt_pathmaxrxt;
6411 net->pf_threshold = thlds->spt_pathpfthld;
6412 if (net->dest_state & SCTP_ADDR_PF) {
6413 if ((net->error_count > net->failure_threshold) ||
6414 (net->error_count <= net->pf_threshold)) {
6415 net->dest_state &= ~SCTP_ADDR_PF;
6416 }
6417 } else {
6418 if ((net->error_count > net->pf_threshold) &&
6419 (net->error_count <= net->failure_threshold)) {
6420 net->dest_state |= SCTP_ADDR_PF;
6421 sctp_send_hb(stcb, net, SCTP_SO_LOCKED);
6422 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT,
6423 stcb->sctp_ep, stcb, net,
6424 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18);
6425 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net);
6426 }
6427 }
6428 if (net->dest_state & SCTP_ADDR_REACHABLE) {
6429 if (net->error_count > net->failure_threshold) {
6430 net->dest_state &= ~SCTP_ADDR_REACHABLE;
6431 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED);
6432 }
6433 } else {
6434 if (net->error_count <= net->failure_threshold) {
6435 net->dest_state |= SCTP_ADDR_REACHABLE;
6436 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED);
6437 }
6438 }
6439 }
6440 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt;
6441 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld;
6442 }
6443 SCTP_TCB_UNLOCK(stcb);
6444 } else {
6445 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6446 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6447 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6448 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) {
6449 SCTP_INP_WLOCK(inp);
6450 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt;
6451 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld;
6452 SCTP_INP_WUNLOCK(inp);
6453 } else {
6454 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6455 error = EINVAL;
6456 }
6457 }
6458 break;
6459 }
6460 case SCTP_REMOTE_UDP_ENCAPS_PORT:
6461 {
6462 struct sctp_udpencaps *encaps;
6463 struct sctp_nets *net;
6464 struct sockaddr *addr;
6465 #if defined(INET) && defined(INET6)
6466 struct sockaddr_in sin_store;
6467 #endif
6468
6469 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize);
6470 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id);
6471
6472 #if defined(INET) && defined(INET6)
6473 if (encaps->sue_address.ss_family == AF_INET6) {
6474 struct sockaddr_in6 *sin6;
6475
6476 sin6 = (struct sockaddr_in6 *)&encaps->sue_address;
6477 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
6478 in6_sin6_2_sin(&sin_store, sin6);
6479 addr = (struct sockaddr *)&sin_store;
6480 } else {
6481 addr = (struct sockaddr *)&encaps->sue_address;
6482 }
6483 } else {
6484 addr = (struct sockaddr *)&encaps->sue_address;
6485 }
6486 #else
6487 addr = (struct sockaddr *)&encaps->sue_address;
6488 #endif
6489 if (stcb != NULL) {
6490 net = sctp_findnet(stcb, addr);
6491 } else {
6492 /*
6493 * We increment here since
6494 * sctp_findassociation_ep_addr() wil do a
6495 * decrement if it finds the stcb as long as
6496 * the locked tcb (last argument) is NOT a
6497 * TCB.. aka NULL.
6498 */
6499 net = NULL;
6500 SCTP_INP_INCR_REF(inp);
6501 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL);
6502 if (stcb == NULL) {
6503 SCTP_INP_DECR_REF(inp);
6504 }
6505 }
6506 if ((stcb != NULL) && (net == NULL)) {
6507 #ifdef INET
6508 if (addr->sa_family == AF_INET) {
6509 struct sockaddr_in *sin;
6510
6511 sin = (struct sockaddr_in *)addr;
6512 if (sin->sin_addr.s_addr != INADDR_ANY) {
6513 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6514 SCTP_TCB_UNLOCK(stcb);
6515 error = EINVAL;
6516 break;
6517 }
6518 } else
6519 #endif
6520 #ifdef INET6
6521 if (addr->sa_family == AF_INET6) {
6522 struct sockaddr_in6 *sin6;
6523
6524 sin6 = (struct sockaddr_in6 *)addr;
6525 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) {
6526 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6527 SCTP_TCB_UNLOCK(stcb);
6528 error = EINVAL;
6529 break;
6530 }
6531 } else
6532 #endif
6533 {
6534 error = EAFNOSUPPORT;
6535 SCTP_TCB_UNLOCK(stcb);
6536 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6537 break;
6538 }
6539 }
6540
6541 if (stcb != NULL) {
6542 if (net != NULL) {
6543 net->port = encaps->sue_port;
6544 } else {
6545 stcb->asoc.port = encaps->sue_port;
6546 }
6547 SCTP_TCB_UNLOCK(stcb);
6548 } else {
6549 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6550 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6551 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6552 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) {
6553 SCTP_INP_WLOCK(inp);
6554 inp->sctp_ep.port = encaps->sue_port;
6555 SCTP_INP_WUNLOCK(inp);
6556 } else {
6557 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6558 error = EINVAL;
6559 }
6560 }
6561 break;
6562 }
6563 case SCTP_ECN_SUPPORTED:
6564 {
6565 struct sctp_assoc_value *av;
6566
6567 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6568 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6569
6570 if (stcb) {
6571 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6572 error = EINVAL;
6573 SCTP_TCB_UNLOCK(stcb);
6574 } else {
6575 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6576 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6577 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6578 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6579 SCTP_INP_WLOCK(inp);
6580 if (av->assoc_value == 0) {
6581 inp->ecn_supported = 0;
6582 } else {
6583 inp->ecn_supported = 1;
6584 }
6585 SCTP_INP_WUNLOCK(inp);
6586 } else {
6587 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6588 error = EINVAL;
6589 }
6590 }
6591 break;
6592 }
6593 case SCTP_PR_SUPPORTED:
6594 {
6595 struct sctp_assoc_value *av;
6596
6597 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6598 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6599
6600 if (stcb) {
6601 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6602 error = EINVAL;
6603 SCTP_TCB_UNLOCK(stcb);
6604 } else {
6605 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6606 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6607 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6608 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6609 SCTP_INP_WLOCK(inp);
6610 if (av->assoc_value == 0) {
6611 inp->prsctp_supported = 0;
6612 } else {
6613 inp->prsctp_supported = 1;
6614 }
6615 SCTP_INP_WUNLOCK(inp);
6616 } else {
6617 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6618 error = EINVAL;
6619 }
6620 }
6621 break;
6622 }
6623 case SCTP_AUTH_SUPPORTED:
6624 {
6625 struct sctp_assoc_value *av;
6626
6627 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6628 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6629
6630 if (stcb) {
6631 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6632 error = EINVAL;
6633 SCTP_TCB_UNLOCK(stcb);
6634 } else {
6635 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6636 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6637 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6638 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6639 if ((av->assoc_value == 0) &&
6640 (inp->asconf_supported == 1)) {
6641 /*
6642 * AUTH is required for
6643 * ASCONF
6644 */
6645 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6646 error = EINVAL;
6647 } else {
6648 SCTP_INP_WLOCK(inp);
6649 if (av->assoc_value == 0) {
6650 inp->auth_supported = 0;
6651 } else {
6652 inp->auth_supported = 1;
6653 }
6654 SCTP_INP_WUNLOCK(inp);
6655 }
6656 } else {
6657 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6658 error = EINVAL;
6659 }
6660 }
6661 break;
6662 }
6663 case SCTP_ASCONF_SUPPORTED:
6664 {
6665 struct sctp_assoc_value *av;
6666
6667 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6668 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6669
6670 if (stcb) {
6671 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6672 error = EINVAL;
6673 SCTP_TCB_UNLOCK(stcb);
6674 } else {
6675 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6676 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6677 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6678 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6679 if ((av->assoc_value != 0) &&
6680 (inp->auth_supported == 0)) {
6681 /*
6682 * AUTH is required for
6683 * ASCONF
6684 */
6685 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6686 error = EINVAL;
6687 } else {
6688 SCTP_INP_WLOCK(inp);
6689 if (av->assoc_value == 0) {
6690 inp->asconf_supported = 0;
6691 sctp_auth_delete_chunk(SCTP_ASCONF,
6692 inp->sctp_ep.local_auth_chunks);
6693 sctp_auth_delete_chunk(SCTP_ASCONF_ACK,
6694 inp->sctp_ep.local_auth_chunks);
6695 } else {
6696 inp->asconf_supported = 1;
6697 sctp_auth_add_chunk(SCTP_ASCONF,
6698 inp->sctp_ep.local_auth_chunks);
6699 sctp_auth_add_chunk(SCTP_ASCONF_ACK,
6700 inp->sctp_ep.local_auth_chunks);
6701 }
6702 SCTP_INP_WUNLOCK(inp);
6703 }
6704 } else {
6705 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6706 error = EINVAL;
6707 }
6708 }
6709 break;
6710 }
6711 case SCTP_RECONFIG_SUPPORTED:
6712 {
6713 struct sctp_assoc_value *av;
6714
6715 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6716 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6717
6718 if (stcb) {
6719 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6720 error = EINVAL;
6721 SCTP_TCB_UNLOCK(stcb);
6722 } else {
6723 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6724 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6725 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6726 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6727 SCTP_INP_WLOCK(inp);
6728 if (av->assoc_value == 0) {
6729 inp->reconfig_supported = 0;
6730 } else {
6731 inp->reconfig_supported = 1;
6732 }
6733 SCTP_INP_WUNLOCK(inp);
6734 } else {
6735 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6736 error = EINVAL;
6737 }
6738 }
6739 break;
6740 }
6741 case SCTP_NRSACK_SUPPORTED:
6742 {
6743 struct sctp_assoc_value *av;
6744
6745 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6746 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6747
6748 if (stcb) {
6749 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6750 error = EINVAL;
6751 SCTP_TCB_UNLOCK(stcb);
6752 } else {
6753 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6754 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6755 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6756 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6757 SCTP_INP_WLOCK(inp);
6758 if (av->assoc_value == 0) {
6759 inp->nrsack_supported = 0;
6760 } else {
6761 inp->nrsack_supported = 1;
6762 }
6763 SCTP_INP_WUNLOCK(inp);
6764 } else {
6765 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6766 error = EINVAL;
6767 }
6768 }
6769 break;
6770 }
6771 case SCTP_PKTDROP_SUPPORTED:
6772 {
6773 struct sctp_assoc_value *av;
6774
6775 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6776 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6777
6778 if (stcb) {
6779 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6780 error = EINVAL;
6781 SCTP_TCB_UNLOCK(stcb);
6782 } else {
6783 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6784 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6785 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6786 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6787 SCTP_INP_WLOCK(inp);
6788 if (av->assoc_value == 0) {
6789 inp->pktdrop_supported = 0;
6790 } else {
6791 inp->pktdrop_supported = 1;
6792 }
6793 SCTP_INP_WUNLOCK(inp);
6794 } else {
6795 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6796 error = EINVAL;
6797 }
6798 }
6799 break;
6800 }
6801 case SCTP_MAX_CWND:
6802 {
6803 struct sctp_assoc_value *av;
6804 struct sctp_nets *net;
6805
6806 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize);
6807 SCTP_FIND_STCB(inp, stcb, av->assoc_id);
6808
6809 if (stcb) {
6810 stcb->asoc.max_cwnd = av->assoc_value;
6811 if (stcb->asoc.max_cwnd > 0) {
6812 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
6813 if ((net->cwnd > stcb->asoc.max_cwnd) &&
6814 (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) {
6815 net->cwnd = stcb->asoc.max_cwnd;
6816 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) {
6817 net->cwnd = net->mtu - sizeof(struct sctphdr);
6818 }
6819 }
6820 }
6821 }
6822 SCTP_TCB_UNLOCK(stcb);
6823 } else {
6824 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
6825 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) ||
6826 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) &&
6827 (av->assoc_id == SCTP_FUTURE_ASSOC))) {
6828 SCTP_INP_WLOCK(inp);
6829 inp->max_cwnd = av->assoc_value;
6830 SCTP_INP_WUNLOCK(inp);
6831 } else {
6832 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6833 error = EINVAL;
6834 }
6835 }
6836 break;
6837 }
6838 case SCTP_ACCEPT_ZERO_CHECKSUM:
6839 {
6840 uint32_t *value;
6841
6842 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize);
6843 if ((*value == SCTP_EDMID_NONE) ||
6844 (*value == SCTP_EDMID_LOWER_LAYER_DTLS)) {
6845 SCTP_INP_WLOCK(inp);
6846 inp->rcv_edmid = *value;
6847 SCTP_INP_WUNLOCK(inp);
6848 } else {
6849 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6850 error = EINVAL;
6851 }
6852 break;
6853 }
6854
6855 default:
6856 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT);
6857 error = ENOPROTOOPT;
6858 break;
6859 } /* end switch (opt) */
6860 return (error);
6861 }
6862
6863 int
6864 sctp_ctloutput(struct socket *so, struct sockopt *sopt)
6865 {
6866 struct epoch_tracker et;
6867 struct sctp_inpcb *inp;
6868 void *optval = NULL;
6869 void *p;
6870 size_t optsize = 0;
6871 int error = 0;
6872
6873 if ((sopt->sopt_level == SOL_SOCKET) &&
6874 (sopt->sopt_name == SO_SETFIB)) {
6875 inp = (struct sctp_inpcb *)so->so_pcb;
6876 if (inp == NULL) {
6877 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6878 return (EINVAL);
6879 }
6880 SCTP_INP_WLOCK(inp);
6881 inp->fibnum = so->so_fibnum;
6882 SCTP_INP_WUNLOCK(inp);
6883 return (0);
6884 }
6885 if (sopt->sopt_level != IPPROTO_SCTP) {
6886 /* wrong proto level... send back up to IP */
6887 #ifdef INET6
6888 if (INP_CHECK_SOCKAF(so, AF_INET6))
6889 error = ip6_ctloutput(so, sopt);
6890 #endif /* INET6 */
6891 #if defined(INET) && defined(INET6)
6892 else
6893 #endif
6894 #ifdef INET
6895 error = ip_ctloutput(so, sopt);
6896 #endif
6897 return (error);
6898 }
6899 optsize = sopt->sopt_valsize;
6900 if (optsize > SCTP_SOCKET_OPTION_LIMIT) {
6901 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6902 return (ENOBUFS);
6903 }
6904 if (optsize) {
6905 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT);
6906 if (optval == NULL) {
6907 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS);
6908 return (ENOBUFS);
6909 }
6910 error = sooptcopyin(sopt, optval, optsize, optsize);
6911 if (error) {
6912 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6913 goto out;
6914 }
6915 }
6916 p = (void *)sopt->sopt_td;
6917 if (sopt->sopt_dir == SOPT_SET) {
6918 NET_EPOCH_ENTER(et);
6919 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p);
6920 NET_EPOCH_EXIT(et);
6921 } else if (sopt->sopt_dir == SOPT_GET) {
6922 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p);
6923 } else {
6924 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6925 error = EINVAL;
6926 }
6927 if ((error == 0) && (optval != NULL)) {
6928 error = sooptcopyout(sopt, optval, optsize);
6929 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6930 } else if (optval != NULL) {
6931 SCTP_FREE(optval, SCTP_M_SOCKOPT);
6932 }
6933 out:
6934 return (error);
6935 }
6936
6937 #ifdef INET
6938 static int
6939 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p)
6940 {
6941 struct epoch_tracker et;
6942 int error = 0;
6943 int create_lock_on = 0;
6944 uint32_t vrf_id;
6945 struct sctp_inpcb *inp;
6946 struct sctp_tcb *stcb = NULL;
6947
6948 inp = (struct sctp_inpcb *)so->so_pcb;
6949 if (inp == NULL) {
6950 /* I made the same as TCP since we are not setup? */
6951 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6952 return (ECONNRESET);
6953 }
6954 if (addr == NULL) {
6955 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6956 return EINVAL;
6957 }
6958
6959 switch (addr->sa_family) {
6960 #ifdef INET6
6961 case AF_INET6:
6962 {
6963 struct sockaddr_in6 *sin6;
6964
6965 if (addr->sa_len != sizeof(struct sockaddr_in6)) {
6966 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6967 return (EINVAL);
6968 }
6969 sin6 = (struct sockaddr_in6 *)addr;
6970 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6->sin6_addr)) != 0) {
6971 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6972 return (error);
6973 }
6974 break;
6975 }
6976 #endif
6977 #ifdef INET
6978 case AF_INET:
6979 {
6980 struct sockaddr_in *sin;
6981
6982 if (addr->sa_len != sizeof(struct sockaddr_in)) {
6983 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
6984 return (EINVAL);
6985 }
6986 sin = (struct sockaddr_in *)addr;
6987 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sin->sin_addr)) != 0) {
6988 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
6989 return (error);
6990 }
6991 break;
6992 }
6993 #endif
6994 default:
6995 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT);
6996 return (EAFNOSUPPORT);
6997 }
6998 SCTP_INP_INCR_REF(inp);
6999 SCTP_ASOC_CREATE_LOCK(inp);
7000 create_lock_on = 1;
7001 NET_EPOCH_ENTER(et);
7002
7003 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) ||
7004 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) {
7005 /* Should I really unlock ? */
7006 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT);
7007 error = EFAULT;
7008 goto out_now;
7009 }
7010 #ifdef INET6
7011 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) &&
7012 (addr->sa_family == AF_INET6)) {
7013 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7014 error = EINVAL;
7015 goto out_now;
7016 }
7017 #endif
7018 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7019 /* Bind a ephemeral port */
7020 error = sctp_inpcb_bind(so, NULL, NULL, p);
7021 if (error) {
7022 goto out_now;
7023 }
7024 }
7025 /* Now do we connect? */
7026 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) &&
7027 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) {
7028 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7029 error = EINVAL;
7030 goto out_now;
7031 }
7032 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7033 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7034 /* We are already connected AND the TCP model */
7035 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE);
7036 error = EADDRINUSE;
7037 goto out_now;
7038 }
7039 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7040 SCTP_INP_RLOCK(inp);
7041 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7042 SCTP_INP_RUNLOCK(inp);
7043 } else {
7044 /*
7045 * We increment here since sctp_findassociation_ep_addr()
7046 * will do a decrement if it finds the stcb as long as the
7047 * locked tcb (last argument) is NOT a TCB.. aka NULL.
7048 */
7049 SCTP_INP_INCR_REF(inp);
7050 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL);
7051 if (stcb == NULL) {
7052 SCTP_INP_DECR_REF(inp);
7053 } else {
7054 SCTP_TCB_UNLOCK(stcb);
7055 }
7056 }
7057 if (stcb != NULL) {
7058 /* Already have or am bring up an association */
7059 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY);
7060 error = EALREADY;
7061 goto out_now;
7062 }
7063
7064 vrf_id = inp->def_vrf_id;
7065 /* We are GOOD to go */
7066 stcb = sctp_aloc_assoc_connected(inp, addr, &error, 0, 0, vrf_id,
7067 inp->sctp_ep.pre_open_stream_count,
7068 inp->sctp_ep.port, p,
7069 SCTP_INITIALIZE_AUTH_PARAMS);
7070 if (stcb == NULL) {
7071 /* Gak! no memory */
7072 goto out_now;
7073 }
7074 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT);
7075 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered);
7076
7077 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED);
7078 SCTP_TCB_UNLOCK(stcb);
7079 out_now:
7080 NET_EPOCH_EXIT(et);
7081 if (create_lock_on) {
7082 SCTP_ASOC_CREATE_UNLOCK(inp);
7083 }
7084 SCTP_INP_DECR_REF(inp);
7085 return (error);
7086 }
7087 #endif
7088
7089 int
7090 sctp_listen(struct socket *so, int backlog, struct thread *p)
7091 {
7092 /*
7093 * Note this module depends on the protocol processing being called
7094 * AFTER any socket level flags and backlog are applied to the
7095 * socket. The traditional way that the socket flags are applied is
7096 * AFTER protocol processing. We have made a change to the
7097 * sys/kern/uipc_socket.c module to reverse this but this MUST be in
7098 * place if the socket API for SCTP is to work properly.
7099 */
7100
7101 int error = 0;
7102 struct sctp_inpcb *inp;
7103
7104 inp = (struct sctp_inpcb *)so->so_pcb;
7105 if (inp == NULL) {
7106 /* I made the same as TCP since we are not setup? */
7107 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7108 return (ECONNRESET);
7109 }
7110 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) {
7111 /* See if we have a listener */
7112 struct sctp_inpcb *tinp;
7113 union sctp_sockstore store;
7114
7115 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) {
7116 /* not bound all */
7117 struct sctp_laddr *laddr;
7118
7119 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7120 memcpy(&store, &laddr->ifa->address, sizeof(store));
7121 switch (store.sa.sa_family) {
7122 #ifdef INET
7123 case AF_INET:
7124 store.sin.sin_port = inp->sctp_lport;
7125 break;
7126 #endif
7127 #ifdef INET6
7128 case AF_INET6:
7129 store.sin6.sin6_port = inp->sctp_lport;
7130 break;
7131 #endif
7132 default:
7133 break;
7134 }
7135 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7136 if (tinp && (tinp != inp) &&
7137 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7138 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7139 (SCTP_IS_LISTENING(tinp))) {
7140 /*
7141 * we have a listener already and
7142 * its not this inp.
7143 */
7144 SCTP_INP_DECR_REF(tinp);
7145 return (EADDRINUSE);
7146 } else if (tinp) {
7147 SCTP_INP_DECR_REF(tinp);
7148 }
7149 }
7150 } else {
7151 /* Setup a local addr bound all */
7152 memset(&store, 0, sizeof(store));
7153 #ifdef INET6
7154 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
7155 store.sa.sa_family = AF_INET6;
7156 store.sa.sa_len = sizeof(struct sockaddr_in6);
7157 }
7158 #endif
7159 #ifdef INET
7160 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) {
7161 store.sa.sa_family = AF_INET;
7162 store.sa.sa_len = sizeof(struct sockaddr_in);
7163 }
7164 #endif
7165 switch (store.sa.sa_family) {
7166 #ifdef INET
7167 case AF_INET:
7168 store.sin.sin_port = inp->sctp_lport;
7169 break;
7170 #endif
7171 #ifdef INET6
7172 case AF_INET6:
7173 store.sin6.sin6_port = inp->sctp_lport;
7174 break;
7175 #endif
7176 default:
7177 break;
7178 }
7179 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id);
7180 if (tinp && (tinp != inp) &&
7181 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) &&
7182 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) &&
7183 (SCTP_IS_LISTENING(tinp))) {
7184 /*
7185 * we have a listener already and its not
7186 * this inp.
7187 */
7188 SCTP_INP_DECR_REF(tinp);
7189 return (EADDRINUSE);
7190 } else if (tinp) {
7191 SCTP_INP_DECR_REF(tinp);
7192 }
7193 }
7194 }
7195 SCTP_INP_INFO_WLOCK();
7196 SCTP_INP_WLOCK(inp);
7197 #ifdef SCTP_LOCK_LOGGING
7198 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) {
7199 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK);
7200 }
7201 #endif
7202 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) &&
7203 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
7204 /*
7205 * The unlucky case - We are in the tcp pool with this guy.
7206 * - Someone else is in the main inp slot. - We must move
7207 * this guy (the listener) to the main slot - We must then
7208 * move the guy that was listener to the TCP Pool.
7209 */
7210 if (sctp_swap_inpcb_for_listen(inp)) {
7211 error = EADDRINUSE;
7212 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7213 goto out;
7214 }
7215 }
7216 SOCK_LOCK(so);
7217 error = solisten_proto_check(so);
7218 if (error) {
7219 SOCK_UNLOCK(so);
7220 goto out;
7221 }
7222 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7223 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) {
7224 SOCK_UNLOCK(so);
7225 solisten_proto_abort(so);
7226 error = EADDRINUSE;
7227 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7228 goto out;
7229 }
7230 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) &&
7231 ((inp->sctp_flags & SCTP_PCB_FLAGS_WAS_CONNECTED) ||
7232 (inp->sctp_flags & SCTP_PCB_FLAGS_WAS_ABORTED))) {
7233 SOCK_UNLOCK(so);
7234 solisten_proto_abort(so);
7235 error = EINVAL;
7236 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error);
7237 goto out;
7238 }
7239 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) {
7240 if ((error = sctp_inpcb_bind_locked(inp, NULL, NULL, p))) {
7241 SOCK_UNLOCK(so);
7242 solisten_proto_abort(so);
7243 /* bind error, probably perm */
7244 goto out;
7245 }
7246 }
7247 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) {
7248 solisten_proto(so, backlog);
7249 SOCK_UNLOCK(so);
7250 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
7251 } else {
7252 solisten_proto_abort(so);
7253 SOCK_UNLOCK(so);
7254 if (backlog > 0) {
7255 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING;
7256 } else {
7257 inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING;
7258 }
7259 }
7260 out:
7261 SCTP_INP_WUNLOCK(inp);
7262 SCTP_INP_INFO_WUNLOCK();
7263 return (error);
7264 }
7265
7266 static int sctp_defered_wakeup_cnt = 0;
7267
7268 int
7269 sctp_accept(struct socket *so, struct sockaddr *sa)
7270 {
7271 struct sctp_tcb *stcb;
7272 struct sctp_inpcb *inp;
7273 union sctp_sockstore store;
7274 #ifdef INET6
7275 int error;
7276 #endif
7277 inp = (struct sctp_inpcb *)so->so_pcb;
7278
7279 if (inp == NULL) {
7280 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7281 return (ECONNRESET);
7282 }
7283 SCTP_INP_WLOCK(inp);
7284 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) {
7285 SCTP_INP_WUNLOCK(inp);
7286 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP);
7287 return (EOPNOTSUPP);
7288 }
7289 if (so->so_state & SS_ISDISCONNECTED) {
7290 SCTP_INP_WUNLOCK(inp);
7291 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED);
7292 return (ECONNABORTED);
7293 }
7294 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7295 if (stcb == NULL) {
7296 SCTP_INP_WUNLOCK(inp);
7297 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7298 return (ECONNRESET);
7299 }
7300 SCTP_TCB_LOCK(stcb);
7301 store = stcb->asoc.primary_destination->ro._l_addr;
7302 SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE);
7303 /* Wake any delayed sleep action */
7304 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) {
7305 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE;
7306 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) {
7307 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT;
7308 SOCKBUF_LOCK(&inp->sctp_socket->so_snd);
7309 if (sowriteable(inp->sctp_socket)) {
7310 sowwakeup_locked(inp->sctp_socket);
7311 } else {
7312 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd);
7313 }
7314 }
7315 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) {
7316 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT;
7317 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv);
7318 if (soreadable(inp->sctp_socket)) {
7319 sctp_defered_wakeup_cnt++;
7320 sorwakeup_locked(inp->sctp_socket);
7321 } else {
7322 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv);
7323 }
7324 }
7325 }
7326 SCTP_INP_WUNLOCK(inp);
7327 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) {
7328 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC,
7329 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19);
7330 } else {
7331 SCTP_TCB_UNLOCK(stcb);
7332 }
7333 switch (store.sa.sa_family) {
7334 #ifdef INET
7335 case AF_INET:
7336 *(struct sockaddr_in *)sa = (struct sockaddr_in ){
7337 .sin_family = AF_INET,
7338 .sin_len = sizeof(struct sockaddr_in),
7339 .sin_port = store.sin.sin_port,
7340 .sin_addr = store.sin.sin_addr,
7341 };
7342 break;
7343 #endif
7344 #ifdef INET6
7345 case AF_INET6:
7346 *(struct sockaddr_in6 *)sa = (struct sockaddr_in6 ){
7347 .sin6_family = AF_INET6,
7348 .sin6_len = sizeof(struct sockaddr_in6),
7349 .sin6_port = store.sin6.sin6_port,
7350 .sin6_addr = store.sin6.sin6_addr,
7351 };
7352 if ((error = sa6_recoverscope((struct sockaddr_in6 *)sa)) != 0)
7353 return (error);
7354 break;
7355 #endif
7356 default:
7357 /* TSNH */
7358 break;
7359 }
7360 return (0);
7361 }
7362
7363 #ifdef INET
7364 int
7365 sctp_ingetaddr(struct socket *so, struct sockaddr *sa)
7366 {
7367 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
7368 uint32_t vrf_id;
7369 struct sctp_inpcb *inp;
7370 struct sctp_ifa *sctp_ifa;
7371
7372 *sin = (struct sockaddr_in ){
7373 .sin_len = sizeof(struct sockaddr_in),
7374 .sin_family = AF_INET,
7375 };
7376
7377 inp = (struct sctp_inpcb *)so->so_pcb;
7378 if (!inp) {
7379 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7380 return (ECONNRESET);
7381 }
7382 SCTP_INP_RLOCK(inp);
7383 sin->sin_port = inp->sctp_lport;
7384 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) {
7385 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) {
7386 struct sctp_tcb *stcb;
7387 struct sockaddr_in *sin_a;
7388 struct sctp_nets *net;
7389 int fnd;
7390
7391 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7392 if (stcb == NULL) {
7393 goto notConn;
7394 }
7395 fnd = 0;
7396 sin_a = NULL;
7397 SCTP_TCB_LOCK(stcb);
7398 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7399 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7400 if (sin_a == NULL)
7401 /* this will make coverity happy */
7402 continue;
7403
7404 if (sin_a->sin_family == AF_INET) {
7405 fnd = 1;
7406 break;
7407 }
7408 }
7409 if ((!fnd) || (sin_a == NULL)) {
7410 /* punt */
7411 SCTP_TCB_UNLOCK(stcb);
7412 goto notConn;
7413 }
7414
7415 vrf_id = inp->def_vrf_id;
7416 sctp_ifa = sctp_source_address_selection(inp,
7417 stcb,
7418 (sctp_route_t *)&net->ro,
7419 net, 0, vrf_id);
7420 if (sctp_ifa) {
7421 sin->sin_addr = sctp_ifa->address.sin.sin_addr;
7422 sctp_free_ifa(sctp_ifa);
7423 }
7424 SCTP_TCB_UNLOCK(stcb);
7425 } else {
7426 /* For the bound all case you get back 0 */
7427 notConn:
7428 sin->sin_addr.s_addr = 0;
7429 }
7430
7431 } else {
7432 /* Take the first IPv4 address in the list */
7433 struct sctp_laddr *laddr;
7434 int fnd = 0;
7435
7436 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) {
7437 if (laddr->ifa->address.sa.sa_family == AF_INET) {
7438 struct sockaddr_in *sin_a;
7439
7440 sin_a = &laddr->ifa->address.sin;
7441 sin->sin_addr = sin_a->sin_addr;
7442 fnd = 1;
7443 break;
7444 }
7445 }
7446 if (!fnd) {
7447 SCTP_INP_RUNLOCK(inp);
7448 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7449 return (ENOENT);
7450 }
7451 }
7452 SCTP_INP_RUNLOCK(inp);
7453
7454 return (0);
7455 }
7456
7457 int
7458 sctp_peeraddr(struct socket *so, struct sockaddr *sa)
7459 {
7460 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
7461 int fnd;
7462 struct sockaddr_in *sin_a;
7463 struct sctp_inpcb *inp;
7464 struct sctp_tcb *stcb;
7465 struct sctp_nets *net;
7466
7467 *sin = (struct sockaddr_in ){
7468 .sin_len = sizeof(struct sockaddr_in),
7469 .sin_family = AF_INET,
7470 };
7471
7472 inp = (struct sctp_inpcb *)so->so_pcb;
7473 if ((inp == NULL) ||
7474 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) {
7475 /* UDP type and listeners will drop out here */
7476 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN);
7477 return (ENOTCONN);
7478 }
7479 SCTP_INP_RLOCK(inp);
7480 stcb = LIST_FIRST(&inp->sctp_asoc_list);
7481 if (stcb) {
7482 SCTP_TCB_LOCK(stcb);
7483 }
7484 SCTP_INP_RUNLOCK(inp);
7485 if (stcb == NULL) {
7486 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL);
7487 return (ECONNRESET);
7488 }
7489 fnd = 0;
7490 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
7491 sin_a = (struct sockaddr_in *)&net->ro._l_addr;
7492 if (sin_a->sin_family == AF_INET) {
7493 fnd = 1;
7494 sin->sin_port = stcb->rport;
7495 sin->sin_addr = sin_a->sin_addr;
7496 break;
7497 }
7498 }
7499 SCTP_TCB_UNLOCK(stcb);
7500 if (!fnd) {
7501 /* No IPv4 address */
7502 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT);
7503 return (ENOENT);
7504 }
7505
7506 return (0);
7507 }
7508
7509 #define SCTP_PROTOSW \
7510 .pr_protocol = IPPROTO_SCTP, \
7511 .pr_ctloutput = sctp_ctloutput, \
7512 .pr_abort = sctp_abort, \
7513 .pr_accept = sctp_accept, \
7514 .pr_attach = sctp_attach, \
7515 .pr_bind = sctp_bind, \
7516 .pr_connect = sctp_connect, \
7517 .pr_control = in_control, \
7518 .pr_close = sctp_close, \
7519 .pr_detach = sctp_close, \
7520 .pr_disconnect = sctp_disconnect, \
7521 .pr_listen = sctp_listen, \
7522 .pr_peeraddr = sctp_peeraddr, \
7523 .pr_send = sctp_sendm, \
7524 .pr_shutdown = sctp_shutdown, \
7525 .pr_sockaddr = sctp_ingetaddr, \
7526 .pr_sosend = sctp_sosend, \
7527 .pr_soreceive = sctp_soreceive \
7528
7529 struct protosw sctp_seqpacket_protosw = {
7530 .pr_type = SOCK_SEQPACKET,
7531 .pr_flags = PR_WANTRCVD,
7532 SCTP_PROTOSW
7533 };
7534
7535 struct protosw sctp_stream_protosw = {
7536 .pr_type = SOCK_STREAM,
7537 .pr_flags = PR_CONNREQUIRED | PR_WANTRCVD,
7538 SCTP_PROTOSW
7539 };
7540 #endif
7541