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