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