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