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