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