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