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