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