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