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