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