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