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 { 3081 int onoff; 3082 3083 if (*optsize < sizeof(int)) { 3084 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3085 error = EINVAL; 3086 } else { 3087 SCTP_INP_RLOCK(inp); 3088 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO); 3089 SCTP_INP_RUNLOCK(inp); 3090 } 3091 if (error == 0) { 3092 /* return the option value */ 3093 *(int *)optval = onoff; 3094 *optsize = sizeof(int); 3095 } 3096 break; 3097 } 3098 case SCTP_RECVNXTINFO: 3099 { 3100 int onoff; 3101 3102 if (*optsize < sizeof(int)) { 3103 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3104 error = EINVAL; 3105 } else { 3106 SCTP_INP_RLOCK(inp); 3107 onoff = sctp_is_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO); 3108 SCTP_INP_RUNLOCK(inp); 3109 } 3110 if (error == 0) { 3111 /* return the option value */ 3112 *(int *)optval = onoff; 3113 *optsize = sizeof(int); 3114 } 3115 break; 3116 } 3117 case SCTP_DEFAULT_SNDINFO: 3118 { 3119 struct sctp_sndinfo *info; 3120 3121 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, *optsize); 3122 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id); 3123 3124 if (stcb) { 3125 info->snd_sid = stcb->asoc.def_send.sinfo_stream; 3126 info->snd_flags = stcb->asoc.def_send.sinfo_flags; 3127 info->snd_flags &= 0xfff0; 3128 info->snd_ppid = stcb->asoc.def_send.sinfo_ppid; 3129 info->snd_context = stcb->asoc.def_send.sinfo_context; 3130 SCTP_TCB_UNLOCK(stcb); 3131 } else { 3132 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3133 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3134 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3135 (info->snd_assoc_id == SCTP_FUTURE_ASSOC))) { 3136 SCTP_INP_RLOCK(inp); 3137 info->snd_sid = inp->def_send.sinfo_stream; 3138 info->snd_flags = inp->def_send.sinfo_flags; 3139 info->snd_flags &= 0xfff0; 3140 info->snd_ppid = inp->def_send.sinfo_ppid; 3141 info->snd_context = inp->def_send.sinfo_context; 3142 SCTP_INP_RUNLOCK(inp); 3143 } else { 3144 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3145 error = EINVAL; 3146 } 3147 } 3148 if (error == 0) { 3149 *optsize = sizeof(struct sctp_sndinfo); 3150 } 3151 break; 3152 } 3153 case SCTP_DEFAULT_PRINFO: 3154 { 3155 struct sctp_default_prinfo *info; 3156 3157 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, *optsize); 3158 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id); 3159 3160 if (stcb) { 3161 info->pr_policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags); 3162 info->pr_value = stcb->asoc.def_send.sinfo_timetolive; 3163 SCTP_TCB_UNLOCK(stcb); 3164 } else { 3165 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3166 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3167 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3168 (info->pr_assoc_id == SCTP_FUTURE_ASSOC))) { 3169 SCTP_INP_RLOCK(inp); 3170 info->pr_policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags); 3171 info->pr_value = inp->def_send.sinfo_timetolive; 3172 SCTP_INP_RUNLOCK(inp); 3173 } else { 3174 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3175 error = EINVAL; 3176 } 3177 } 3178 if (error == 0) { 3179 *optsize = sizeof(struct sctp_default_prinfo); 3180 } 3181 break; 3182 } 3183 case SCTP_PEER_ADDR_THLDS: 3184 { 3185 struct sctp_paddrthlds *thlds; 3186 struct sctp_nets *net; 3187 struct sockaddr *addr; 3188 #if defined(INET) && defined(INET6) 3189 struct sockaddr_in sin_store; 3190 #endif 3191 3192 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, *optsize); 3193 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id); 3194 3195 #if defined(INET) && defined(INET6) 3196 if (thlds->spt_address.ss_family == AF_INET6) { 3197 struct sockaddr_in6 *sin6; 3198 3199 sin6 = (struct sockaddr_in6 *)&thlds->spt_address; 3200 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 3201 in6_sin6_2_sin(&sin_store, sin6); 3202 addr = (struct sockaddr *)&sin_store; 3203 } else { 3204 addr = (struct sockaddr *)&thlds->spt_address; 3205 } 3206 } else { 3207 addr = (struct sockaddr *)&thlds->spt_address; 3208 } 3209 #else 3210 addr = (struct sockaddr *)&thlds->spt_address; 3211 #endif 3212 if (stcb != NULL) { 3213 net = sctp_findnet(stcb, addr); 3214 } else { 3215 /* 3216 * We increment here since 3217 * sctp_findassociation_ep_addr() wil do a 3218 * decrement if it finds the stcb as long as 3219 * the locked tcb (last argument) is NOT a 3220 * TCB.. aka NULL. 3221 */ 3222 net = NULL; 3223 SCTP_INP_INCR_REF(inp); 3224 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL); 3225 if (stcb == NULL) { 3226 SCTP_INP_DECR_REF(inp); 3227 } 3228 } 3229 if ((stcb != NULL) && (net == NULL)) { 3230 #ifdef INET 3231 if (addr->sa_family == AF_INET) { 3232 struct sockaddr_in *sin; 3233 3234 sin = (struct sockaddr_in *)addr; 3235 if (sin->sin_addr.s_addr != INADDR_ANY) { 3236 error = EINVAL; 3237 SCTP_TCB_UNLOCK(stcb); 3238 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3239 break; 3240 } 3241 } else 3242 #endif 3243 #ifdef INET6 3244 if (addr->sa_family == AF_INET6) { 3245 struct sockaddr_in6 *sin6; 3246 3247 sin6 = (struct sockaddr_in6 *)addr; 3248 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 3249 error = EINVAL; 3250 SCTP_TCB_UNLOCK(stcb); 3251 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3252 break; 3253 } 3254 } else 3255 #endif 3256 { 3257 error = EAFNOSUPPORT; 3258 SCTP_TCB_UNLOCK(stcb); 3259 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3260 break; 3261 } 3262 } 3263 3264 if (stcb != NULL) { 3265 if (net != NULL) { 3266 thlds->spt_pathmaxrxt = net->failure_threshold; 3267 thlds->spt_pathpfthld = net->pf_threshold; 3268 thlds->spt_pathcpthld = 0xffff; 3269 } else { 3270 thlds->spt_pathmaxrxt = stcb->asoc.def_net_failure; 3271 thlds->spt_pathpfthld = stcb->asoc.def_net_pf_threshold; 3272 thlds->spt_pathcpthld = 0xffff; 3273 } 3274 thlds->spt_assoc_id = sctp_get_associd(stcb); 3275 SCTP_TCB_UNLOCK(stcb); 3276 } else { 3277 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3278 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3279 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3280 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) { 3281 /* Use endpoint defaults */ 3282 SCTP_INP_RLOCK(inp); 3283 thlds->spt_pathmaxrxt = inp->sctp_ep.def_net_failure; 3284 thlds->spt_pathpfthld = inp->sctp_ep.def_net_pf_threshold; 3285 thlds->spt_pathcpthld = 0xffff; 3286 SCTP_INP_RUNLOCK(inp); 3287 } else { 3288 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3289 error = EINVAL; 3290 } 3291 } 3292 if (error == 0) { 3293 *optsize = sizeof(struct sctp_paddrthlds); 3294 } 3295 break; 3296 } 3297 case SCTP_REMOTE_UDP_ENCAPS_PORT: 3298 { 3299 struct sctp_udpencaps *encaps; 3300 struct sctp_nets *net; 3301 struct sockaddr *addr; 3302 #if defined(INET) && defined(INET6) 3303 struct sockaddr_in sin_store; 3304 #endif 3305 3306 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, *optsize); 3307 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id); 3308 3309 #if defined(INET) && defined(INET6) 3310 if (encaps->sue_address.ss_family == AF_INET6) { 3311 struct sockaddr_in6 *sin6; 3312 3313 sin6 = (struct sockaddr_in6 *)&encaps->sue_address; 3314 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 3315 in6_sin6_2_sin(&sin_store, sin6); 3316 addr = (struct sockaddr *)&sin_store; 3317 } else { 3318 addr = (struct sockaddr *)&encaps->sue_address; 3319 } 3320 } else { 3321 addr = (struct sockaddr *)&encaps->sue_address; 3322 } 3323 #else 3324 addr = (struct sockaddr *)&encaps->sue_address; 3325 #endif 3326 if (stcb) { 3327 net = sctp_findnet(stcb, addr); 3328 } else { 3329 /* 3330 * We increment here since 3331 * sctp_findassociation_ep_addr() wil do a 3332 * decrement if it finds the stcb as long as 3333 * the locked tcb (last argument) is NOT a 3334 * TCB.. aka NULL. 3335 */ 3336 net = NULL; 3337 SCTP_INP_INCR_REF(inp); 3338 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL); 3339 if (stcb == NULL) { 3340 SCTP_INP_DECR_REF(inp); 3341 } 3342 } 3343 if ((stcb != NULL) && (net == NULL)) { 3344 #ifdef INET 3345 if (addr->sa_family == AF_INET) { 3346 struct sockaddr_in *sin; 3347 3348 sin = (struct sockaddr_in *)addr; 3349 if (sin->sin_addr.s_addr != INADDR_ANY) { 3350 error = EINVAL; 3351 SCTP_TCB_UNLOCK(stcb); 3352 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3353 break; 3354 } 3355 } else 3356 #endif 3357 #ifdef INET6 3358 if (addr->sa_family == AF_INET6) { 3359 struct sockaddr_in6 *sin6; 3360 3361 sin6 = (struct sockaddr_in6 *)addr; 3362 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 3363 error = EINVAL; 3364 SCTP_TCB_UNLOCK(stcb); 3365 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3366 break; 3367 } 3368 } else 3369 #endif 3370 { 3371 error = EAFNOSUPPORT; 3372 SCTP_TCB_UNLOCK(stcb); 3373 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 3374 break; 3375 } 3376 } 3377 3378 if (stcb != NULL) { 3379 if (net) { 3380 encaps->sue_port = net->port; 3381 } else { 3382 encaps->sue_port = stcb->asoc.port; 3383 } 3384 SCTP_TCB_UNLOCK(stcb); 3385 } else { 3386 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3387 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3388 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3389 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) { 3390 SCTP_INP_RLOCK(inp); 3391 encaps->sue_port = inp->sctp_ep.port; 3392 SCTP_INP_RUNLOCK(inp); 3393 } else { 3394 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3395 error = EINVAL; 3396 } 3397 } 3398 if (error == 0) { 3399 *optsize = sizeof(struct sctp_udpencaps); 3400 } 3401 break; 3402 } 3403 case SCTP_ECN_SUPPORTED: 3404 { 3405 struct sctp_assoc_value *av; 3406 3407 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3408 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3409 3410 if (stcb) { 3411 av->assoc_value = stcb->asoc.ecn_supported; 3412 SCTP_TCB_UNLOCK(stcb); 3413 } else { 3414 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3415 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3416 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3417 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3418 SCTP_INP_RLOCK(inp); 3419 av->assoc_value = inp->ecn_supported; 3420 SCTP_INP_RUNLOCK(inp); 3421 } else { 3422 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3423 error = EINVAL; 3424 } 3425 } 3426 if (error == 0) { 3427 *optsize = sizeof(struct sctp_assoc_value); 3428 } 3429 break; 3430 } 3431 case SCTP_PR_SUPPORTED: 3432 { 3433 struct sctp_assoc_value *av; 3434 3435 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3436 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3437 3438 if (stcb) { 3439 av->assoc_value = stcb->asoc.prsctp_supported; 3440 SCTP_TCB_UNLOCK(stcb); 3441 } else { 3442 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3443 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3444 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3445 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3446 SCTP_INP_RLOCK(inp); 3447 av->assoc_value = inp->prsctp_supported; 3448 SCTP_INP_RUNLOCK(inp); 3449 } else { 3450 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3451 error = EINVAL; 3452 } 3453 } 3454 if (error == 0) { 3455 *optsize = sizeof(struct sctp_assoc_value); 3456 } 3457 break; 3458 } 3459 case SCTP_AUTH_SUPPORTED: 3460 { 3461 struct sctp_assoc_value *av; 3462 3463 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3464 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3465 3466 if (stcb) { 3467 av->assoc_value = stcb->asoc.auth_supported; 3468 SCTP_TCB_UNLOCK(stcb); 3469 } else { 3470 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3471 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3472 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3473 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3474 SCTP_INP_RLOCK(inp); 3475 av->assoc_value = inp->auth_supported; 3476 SCTP_INP_RUNLOCK(inp); 3477 } else { 3478 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3479 error = EINVAL; 3480 } 3481 } 3482 if (error == 0) { 3483 *optsize = sizeof(struct sctp_assoc_value); 3484 } 3485 break; 3486 } 3487 case SCTP_ASCONF_SUPPORTED: 3488 { 3489 struct sctp_assoc_value *av; 3490 3491 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3492 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3493 3494 if (stcb) { 3495 av->assoc_value = stcb->asoc.asconf_supported; 3496 SCTP_TCB_UNLOCK(stcb); 3497 } else { 3498 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3499 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3500 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3501 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3502 SCTP_INP_RLOCK(inp); 3503 av->assoc_value = inp->asconf_supported; 3504 SCTP_INP_RUNLOCK(inp); 3505 } else { 3506 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3507 error = EINVAL; 3508 } 3509 } 3510 if (error == 0) { 3511 *optsize = sizeof(struct sctp_assoc_value); 3512 } 3513 break; 3514 } 3515 case SCTP_RECONFIG_SUPPORTED: 3516 { 3517 struct sctp_assoc_value *av; 3518 3519 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3520 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3521 3522 if (stcb) { 3523 av->assoc_value = stcb->asoc.reconfig_supported; 3524 SCTP_TCB_UNLOCK(stcb); 3525 } else { 3526 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3527 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3528 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3529 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3530 SCTP_INP_RLOCK(inp); 3531 av->assoc_value = inp->reconfig_supported; 3532 SCTP_INP_RUNLOCK(inp); 3533 } else { 3534 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3535 error = EINVAL; 3536 } 3537 } 3538 if (error == 0) { 3539 *optsize = sizeof(struct sctp_assoc_value); 3540 } 3541 break; 3542 } 3543 case SCTP_NRSACK_SUPPORTED: 3544 { 3545 struct sctp_assoc_value *av; 3546 3547 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3548 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3549 3550 if (stcb) { 3551 av->assoc_value = stcb->asoc.nrsack_supported; 3552 SCTP_TCB_UNLOCK(stcb); 3553 } else { 3554 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3555 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3556 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3557 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3558 SCTP_INP_RLOCK(inp); 3559 av->assoc_value = inp->nrsack_supported; 3560 SCTP_INP_RUNLOCK(inp); 3561 } else { 3562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3563 error = EINVAL; 3564 } 3565 } 3566 if (error == 0) { 3567 *optsize = sizeof(struct sctp_assoc_value); 3568 } 3569 break; 3570 } 3571 case SCTP_PKTDROP_SUPPORTED: 3572 { 3573 struct sctp_assoc_value *av; 3574 3575 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3576 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3577 3578 if (stcb) { 3579 av->assoc_value = stcb->asoc.pktdrop_supported; 3580 SCTP_TCB_UNLOCK(stcb); 3581 } else { 3582 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3583 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3584 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3585 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3586 SCTP_INP_RLOCK(inp); 3587 av->assoc_value = inp->pktdrop_supported; 3588 SCTP_INP_RUNLOCK(inp); 3589 } else { 3590 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3591 error = EINVAL; 3592 } 3593 } 3594 if (error == 0) { 3595 *optsize = sizeof(struct sctp_assoc_value); 3596 } 3597 break; 3598 } 3599 case SCTP_ENABLE_STREAM_RESET: 3600 { 3601 struct sctp_assoc_value *av; 3602 3603 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3604 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3605 3606 if (stcb) { 3607 av->assoc_value = (uint32_t)stcb->asoc.local_strreset_support; 3608 SCTP_TCB_UNLOCK(stcb); 3609 } else { 3610 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3611 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3612 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3613 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3614 SCTP_INP_RLOCK(inp); 3615 av->assoc_value = (uint32_t)inp->local_strreset_support; 3616 SCTP_INP_RUNLOCK(inp); 3617 } else { 3618 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3619 error = EINVAL; 3620 } 3621 } 3622 if (error == 0) { 3623 *optsize = sizeof(struct sctp_assoc_value); 3624 } 3625 break; 3626 } 3627 case SCTP_PR_STREAM_STATUS: 3628 { 3629 struct sctp_prstatus *sprstat; 3630 uint16_t sid; 3631 uint16_t policy; 3632 3633 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize); 3634 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id); 3635 3636 sid = sprstat->sprstat_sid; 3637 policy = sprstat->sprstat_policy; 3638 #if defined(SCTP_DETAILED_STR_STATS) 3639 if ((stcb != NULL) && 3640 (sid < stcb->asoc.streamoutcnt) && 3641 (policy != SCTP_PR_SCTP_NONE) && 3642 ((policy <= SCTP_PR_SCTP_MAX) || 3643 (policy == SCTP_PR_SCTP_ALL))) { 3644 if (policy == SCTP_PR_SCTP_ALL) { 3645 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0]; 3646 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0]; 3647 } else { 3648 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[policy]; 3649 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[policy]; 3650 } 3651 #else 3652 if ((stcb != NULL) && 3653 (sid < stcb->asoc.streamoutcnt) && 3654 (policy == SCTP_PR_SCTP_ALL)) { 3655 sprstat->sprstat_abandoned_unsent = stcb->asoc.strmout[sid].abandoned_unsent[0]; 3656 sprstat->sprstat_abandoned_sent = stcb->asoc.strmout[sid].abandoned_sent[0]; 3657 #endif 3658 } else { 3659 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3660 error = EINVAL; 3661 } 3662 if (stcb != NULL) { 3663 SCTP_TCB_UNLOCK(stcb); 3664 } 3665 if (error == 0) { 3666 *optsize = sizeof(struct sctp_prstatus); 3667 } 3668 break; 3669 } 3670 case SCTP_PR_ASSOC_STATUS: 3671 { 3672 struct sctp_prstatus *sprstat; 3673 uint16_t policy; 3674 3675 SCTP_CHECK_AND_CAST(sprstat, optval, struct sctp_prstatus, *optsize); 3676 SCTP_FIND_STCB(inp, stcb, sprstat->sprstat_assoc_id); 3677 3678 policy = sprstat->sprstat_policy; 3679 if ((stcb != NULL) && 3680 (policy != SCTP_PR_SCTP_NONE) && 3681 ((policy <= SCTP_PR_SCTP_MAX) || 3682 (policy == SCTP_PR_SCTP_ALL))) { 3683 if (policy == SCTP_PR_SCTP_ALL) { 3684 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[0]; 3685 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[0]; 3686 } else { 3687 sprstat->sprstat_abandoned_unsent = stcb->asoc.abandoned_unsent[policy]; 3688 sprstat->sprstat_abandoned_sent = stcb->asoc.abandoned_sent[policy]; 3689 } 3690 } else { 3691 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3692 error = EINVAL; 3693 } 3694 if (stcb != NULL) { 3695 SCTP_TCB_UNLOCK(stcb); 3696 } 3697 if (error == 0) { 3698 *optsize = sizeof(struct sctp_prstatus); 3699 } 3700 break; 3701 } 3702 case SCTP_MAX_CWND: 3703 { 3704 struct sctp_assoc_value *av; 3705 3706 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, *optsize); 3707 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3708 3709 if (stcb) { 3710 av->assoc_value = stcb->asoc.max_cwnd; 3711 SCTP_TCB_UNLOCK(stcb); 3712 } else { 3713 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3714 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3715 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3716 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3717 SCTP_INP_RLOCK(inp); 3718 av->assoc_value = inp->max_cwnd; 3719 SCTP_INP_RUNLOCK(inp); 3720 } else { 3721 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3722 error = EINVAL; 3723 } 3724 } 3725 if (error == 0) { 3726 *optsize = sizeof(struct sctp_assoc_value); 3727 } 3728 break; 3729 } 3730 default: 3731 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); 3732 error = ENOPROTOOPT; 3733 break; 3734 } /* end switch (sopt->sopt_name) */ 3735 if (error) { 3736 *optsize = 0; 3737 } 3738 return (error); 3739 } 3740 3741 static int 3742 sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize, 3743 void *p) 3744 { 3745 int error, set_opt; 3746 uint32_t *mopt; 3747 struct sctp_tcb *stcb = NULL; 3748 struct sctp_inpcb *inp = NULL; 3749 uint32_t vrf_id; 3750 3751 if (optval == NULL) { 3752 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3753 return (EINVAL); 3754 } 3755 inp = (struct sctp_inpcb *)so->so_pcb; 3756 if (inp == NULL) { 3757 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3758 return (EINVAL); 3759 } 3760 vrf_id = inp->def_vrf_id; 3761 3762 error = 0; 3763 switch (optname) { 3764 case SCTP_NODELAY: 3765 case SCTP_AUTOCLOSE: 3766 case SCTP_AUTO_ASCONF: 3767 case SCTP_EXPLICIT_EOR: 3768 case SCTP_DISABLE_FRAGMENTS: 3769 case SCTP_USE_EXT_RCVINFO: 3770 case SCTP_I_WANT_MAPPED_V4_ADDR: 3771 /* copy in the option value */ 3772 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize); 3773 set_opt = 0; 3774 if (error) 3775 break; 3776 switch (optname) { 3777 case SCTP_DISABLE_FRAGMENTS: 3778 set_opt = SCTP_PCB_FLAGS_NO_FRAGMENT; 3779 break; 3780 case SCTP_AUTO_ASCONF: 3781 /* 3782 * NOTE: we don't really support this flag 3783 */ 3784 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 3785 /* only valid for bound all sockets */ 3786 if ((SCTP_BASE_SYSCTL(sctp_auto_asconf) == 0) && 3787 (*mopt != 0)) { 3788 /* forbidden by admin */ 3789 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EPERM); 3790 return (EPERM); 3791 } 3792 set_opt = SCTP_PCB_FLAGS_AUTO_ASCONF; 3793 } else { 3794 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3795 return (EINVAL); 3796 } 3797 break; 3798 case SCTP_EXPLICIT_EOR: 3799 set_opt = SCTP_PCB_FLAGS_EXPLICIT_EOR; 3800 break; 3801 case SCTP_USE_EXT_RCVINFO: 3802 set_opt = SCTP_PCB_FLAGS_EXT_RCVINFO; 3803 break; 3804 case SCTP_I_WANT_MAPPED_V4_ADDR: 3805 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 3806 set_opt = SCTP_PCB_FLAGS_NEEDS_MAPPED_V4; 3807 } else { 3808 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3809 return (EINVAL); 3810 } 3811 break; 3812 case SCTP_NODELAY: 3813 set_opt = SCTP_PCB_FLAGS_NODELAY; 3814 break; 3815 case SCTP_AUTOCLOSE: 3816 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3817 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 3818 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3819 return (EINVAL); 3820 } 3821 set_opt = SCTP_PCB_FLAGS_AUTOCLOSE; 3822 /* 3823 * The value is in ticks. Note this does not effect 3824 * old associations, only new ones. 3825 */ 3826 inp->sctp_ep.auto_close_time = sctp_secs_to_ticks(*mopt); 3827 break; 3828 } 3829 SCTP_INP_WLOCK(inp); 3830 if (*mopt != 0) { 3831 sctp_feature_on(inp, set_opt); 3832 } else { 3833 sctp_feature_off(inp, set_opt); 3834 } 3835 SCTP_INP_WUNLOCK(inp); 3836 break; 3837 case SCTP_REUSE_PORT: 3838 { 3839 SCTP_CHECK_AND_CAST(mopt, optval, uint32_t, optsize); 3840 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 0) { 3841 /* Can't set it after we are bound */ 3842 error = EINVAL; 3843 break; 3844 } 3845 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE)) { 3846 /* Can't do this for a 1-m socket */ 3847 error = EINVAL; 3848 break; 3849 } 3850 if (optval) 3851 sctp_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE); 3852 else 3853 sctp_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE); 3854 break; 3855 } 3856 case SCTP_PARTIAL_DELIVERY_POINT: 3857 { 3858 uint32_t *value; 3859 3860 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize); 3861 if (*value > SCTP_SB_LIMIT_RCV(so)) { 3862 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3863 error = EINVAL; 3864 break; 3865 } 3866 inp->partial_delivery_point = *value; 3867 break; 3868 } 3869 case SCTP_FRAGMENT_INTERLEAVE: 3870 /* not yet until we re-write sctp_recvmsg() */ 3871 { 3872 uint32_t *level; 3873 3874 SCTP_CHECK_AND_CAST(level, optval, uint32_t, optsize); 3875 if (*level == SCTP_FRAG_LEVEL_2) { 3876 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 3877 sctp_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 3878 } else if (*level == SCTP_FRAG_LEVEL_1) { 3879 sctp_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 3880 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 3881 } else if (*level == SCTP_FRAG_LEVEL_0) { 3882 sctp_feature_off(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE); 3883 sctp_feature_off(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS); 3884 3885 } else { 3886 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3887 error = EINVAL; 3888 } 3889 break; 3890 } 3891 case SCTP_INTERLEAVING_SUPPORTED: 3892 { 3893 struct sctp_assoc_value *av; 3894 3895 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 3896 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3897 3898 if (stcb) { 3899 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3900 error = EINVAL; 3901 SCTP_TCB_UNLOCK(stcb); 3902 } else { 3903 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3904 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3905 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3906 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 3907 SCTP_INP_WLOCK(inp); 3908 if (av->assoc_value == 0) { 3909 inp->idata_supported = 0; 3910 } else { 3911 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_FRAG_INTERLEAVE)) && 3912 (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_INTERLEAVE_STRMS))) { 3913 inp->idata_supported = 1; 3914 } else { 3915 /* 3916 * Must have Frag 3917 * interleave and 3918 * stream interleave 3919 * on 3920 */ 3921 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3922 error = EINVAL; 3923 } 3924 } 3925 SCTP_INP_WUNLOCK(inp); 3926 } else { 3927 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3928 error = EINVAL; 3929 } 3930 } 3931 break; 3932 } 3933 case SCTP_CMT_ON_OFF: 3934 if (SCTP_BASE_SYSCTL(sctp_cmt_on_off)) { 3935 struct sctp_assoc_value *av; 3936 3937 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 3938 if (av->assoc_value > SCTP_CMT_MAX) { 3939 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3940 error = EINVAL; 3941 break; 3942 } 3943 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3944 if (stcb) { 3945 stcb->asoc.sctp_cmt_on_off = av->assoc_value; 3946 SCTP_TCB_UNLOCK(stcb); 3947 } else { 3948 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 3949 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 3950 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3951 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 3952 (av->assoc_id == SCTP_ALL_ASSOC)))) { 3953 SCTP_INP_WLOCK(inp); 3954 inp->sctp_cmt_on_off = av->assoc_value; 3955 SCTP_INP_WUNLOCK(inp); 3956 } 3957 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 3958 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 3959 (av->assoc_id == SCTP_ALL_ASSOC))) { 3960 SCTP_INP_RLOCK(inp); 3961 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 3962 SCTP_TCB_LOCK(stcb); 3963 stcb->asoc.sctp_cmt_on_off = av->assoc_value; 3964 SCTP_TCB_UNLOCK(stcb); 3965 } 3966 SCTP_INP_RUNLOCK(inp); 3967 } 3968 } 3969 } else { 3970 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); 3971 error = ENOPROTOOPT; 3972 } 3973 break; 3974 case SCTP_PLUGGABLE_CC: 3975 { 3976 struct sctp_assoc_value *av; 3977 struct sctp_nets *net; 3978 3979 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 3980 if ((av->assoc_value != SCTP_CC_RFC2581) && 3981 (av->assoc_value != SCTP_CC_HSTCP) && 3982 (av->assoc_value != SCTP_CC_HTCP) && 3983 (av->assoc_value != SCTP_CC_RTCC)) { 3984 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 3985 error = EINVAL; 3986 break; 3987 } 3988 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 3989 if (stcb) { 3990 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value]; 3991 stcb->asoc.congestion_control_module = av->assoc_value; 3992 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) { 3993 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 3994 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 3995 } 3996 } 3997 SCTP_TCB_UNLOCK(stcb); 3998 } else { 3999 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4000 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4001 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4002 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 4003 (av->assoc_id == SCTP_ALL_ASSOC)))) { 4004 SCTP_INP_WLOCK(inp); 4005 inp->sctp_ep.sctp_default_cc_module = av->assoc_value; 4006 SCTP_INP_WUNLOCK(inp); 4007 } 4008 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4009 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 4010 (av->assoc_id == SCTP_ALL_ASSOC))) { 4011 SCTP_INP_RLOCK(inp); 4012 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4013 SCTP_TCB_LOCK(stcb); 4014 stcb->asoc.cc_functions = sctp_cc_functions[av->assoc_value]; 4015 stcb->asoc.congestion_control_module = av->assoc_value; 4016 if (stcb->asoc.cc_functions.sctp_set_initial_cc_param != NULL) { 4017 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 4018 stcb->asoc.cc_functions.sctp_set_initial_cc_param(stcb, net); 4019 } 4020 } 4021 SCTP_TCB_UNLOCK(stcb); 4022 } 4023 SCTP_INP_RUNLOCK(inp); 4024 } 4025 } 4026 break; 4027 } 4028 case SCTP_CC_OPTION: 4029 { 4030 struct sctp_cc_option *cc_opt; 4031 4032 SCTP_CHECK_AND_CAST(cc_opt, optval, struct sctp_cc_option, optsize); 4033 SCTP_FIND_STCB(inp, stcb, cc_opt->aid_value.assoc_id); 4034 if (stcb == NULL) { 4035 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4036 (cc_opt->aid_value.assoc_id == SCTP_CURRENT_ASSOC)) { 4037 SCTP_INP_RLOCK(inp); 4038 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4039 SCTP_TCB_LOCK(stcb); 4040 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option) { 4041 (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, cc_opt); 4042 } 4043 SCTP_TCB_UNLOCK(stcb); 4044 } 4045 SCTP_INP_RUNLOCK(inp); 4046 } else { 4047 error = EINVAL; 4048 } 4049 } else { 4050 if (stcb->asoc.cc_functions.sctp_cwnd_socket_option == NULL) { 4051 error = ENOTSUP; 4052 } else { 4053 error = (*stcb->asoc.cc_functions.sctp_cwnd_socket_option) (stcb, 1, 4054 cc_opt); 4055 } 4056 SCTP_TCB_UNLOCK(stcb); 4057 } 4058 break; 4059 } 4060 case SCTP_PLUGGABLE_SS: 4061 { 4062 struct sctp_assoc_value *av; 4063 4064 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 4065 if ((av->assoc_value != SCTP_SS_DEFAULT) && 4066 (av->assoc_value != SCTP_SS_ROUND_ROBIN) && 4067 (av->assoc_value != SCTP_SS_ROUND_ROBIN_PACKET) && 4068 (av->assoc_value != SCTP_SS_PRIORITY) && 4069 (av->assoc_value != SCTP_SS_FAIR_BANDWITH) && 4070 (av->assoc_value != SCTP_SS_FIRST_COME)) { 4071 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4072 error = EINVAL; 4073 break; 4074 } 4075 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4076 if (stcb) { 4077 SCTP_TCB_SEND_LOCK(stcb); 4078 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1); 4079 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; 4080 stcb->asoc.stream_scheduling_module = av->assoc_value; 4081 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1); 4082 SCTP_TCB_SEND_UNLOCK(stcb); 4083 SCTP_TCB_UNLOCK(stcb); 4084 } else { 4085 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4086 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4087 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4088 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 4089 (av->assoc_id == SCTP_ALL_ASSOC)))) { 4090 SCTP_INP_WLOCK(inp); 4091 inp->sctp_ep.sctp_default_ss_module = av->assoc_value; 4092 SCTP_INP_WUNLOCK(inp); 4093 } 4094 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4095 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 4096 (av->assoc_id == SCTP_ALL_ASSOC))) { 4097 SCTP_INP_RLOCK(inp); 4098 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4099 SCTP_TCB_LOCK(stcb); 4100 SCTP_TCB_SEND_LOCK(stcb); 4101 stcb->asoc.ss_functions.sctp_ss_clear(stcb, &stcb->asoc, 1, 1); 4102 stcb->asoc.ss_functions = sctp_ss_functions[av->assoc_value]; 4103 stcb->asoc.stream_scheduling_module = av->assoc_value; 4104 stcb->asoc.ss_functions.sctp_ss_init(stcb, &stcb->asoc, 1); 4105 SCTP_TCB_SEND_UNLOCK(stcb); 4106 SCTP_TCB_UNLOCK(stcb); 4107 } 4108 SCTP_INP_RUNLOCK(inp); 4109 } 4110 } 4111 break; 4112 } 4113 case SCTP_SS_VALUE: 4114 { 4115 struct sctp_stream_value *av; 4116 4117 SCTP_CHECK_AND_CAST(av, optval, struct sctp_stream_value, optsize); 4118 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4119 if (stcb) { 4120 if ((av->stream_id >= stcb->asoc.streamoutcnt) || 4121 (stcb->asoc.ss_functions.sctp_ss_set_value(stcb, &stcb->asoc, &stcb->asoc.strmout[av->stream_id], 4122 av->stream_value) < 0)) { 4123 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4124 error = EINVAL; 4125 } 4126 SCTP_TCB_UNLOCK(stcb); 4127 } else { 4128 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4129 (av->assoc_id == SCTP_CURRENT_ASSOC)) { 4130 SCTP_INP_RLOCK(inp); 4131 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4132 SCTP_TCB_LOCK(stcb); 4133 if (av->stream_id < stcb->asoc.streamoutcnt) { 4134 stcb->asoc.ss_functions.sctp_ss_set_value(stcb, 4135 &stcb->asoc, 4136 &stcb->asoc.strmout[av->stream_id], 4137 av->stream_value); 4138 } 4139 SCTP_TCB_UNLOCK(stcb); 4140 } 4141 SCTP_INP_RUNLOCK(inp); 4142 } else { 4143 /* 4144 * Can't set stream value without 4145 * association 4146 */ 4147 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4148 error = EINVAL; 4149 } 4150 } 4151 break; 4152 } 4153 case SCTP_CLR_STAT_LOG: 4154 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4155 error = EOPNOTSUPP; 4156 break; 4157 case SCTP_CONTEXT: 4158 { 4159 struct sctp_assoc_value *av; 4160 4161 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 4162 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4163 4164 if (stcb) { 4165 stcb->asoc.context = av->assoc_value; 4166 SCTP_TCB_UNLOCK(stcb); 4167 } else { 4168 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4169 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4170 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4171 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 4172 (av->assoc_id == SCTP_ALL_ASSOC)))) { 4173 SCTP_INP_WLOCK(inp); 4174 inp->sctp_context = av->assoc_value; 4175 SCTP_INP_WUNLOCK(inp); 4176 } 4177 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4178 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 4179 (av->assoc_id == SCTP_ALL_ASSOC))) { 4180 SCTP_INP_RLOCK(inp); 4181 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4182 SCTP_TCB_LOCK(stcb); 4183 stcb->asoc.context = av->assoc_value; 4184 SCTP_TCB_UNLOCK(stcb); 4185 } 4186 SCTP_INP_RUNLOCK(inp); 4187 } 4188 } 4189 break; 4190 } 4191 case SCTP_VRF_ID: 4192 { 4193 uint32_t *default_vrfid; 4194 4195 SCTP_CHECK_AND_CAST(default_vrfid, optval, uint32_t, optsize); 4196 if (*default_vrfid > SCTP_MAX_VRF_ID) { 4197 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4198 error = EINVAL; 4199 break; 4200 } 4201 inp->def_vrf_id = *default_vrfid; 4202 break; 4203 } 4204 case SCTP_DEL_VRF_ID: 4205 { 4206 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4207 error = EOPNOTSUPP; 4208 break; 4209 } 4210 case SCTP_ADD_VRF_ID: 4211 { 4212 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4213 error = EOPNOTSUPP; 4214 break; 4215 } 4216 case SCTP_DELAYED_SACK: 4217 { 4218 struct sctp_sack_info *sack; 4219 4220 SCTP_CHECK_AND_CAST(sack, optval, struct sctp_sack_info, optsize); 4221 SCTP_FIND_STCB(inp, stcb, sack->sack_assoc_id); 4222 if (sack->sack_delay) { 4223 if (sack->sack_delay > SCTP_MAX_SACK_DELAY) { 4224 error = EINVAL; 4225 if (stcb != NULL) { 4226 SCTP_TCB_UNLOCK(stcb); 4227 } 4228 break; 4229 } 4230 } 4231 if (stcb) { 4232 if (sack->sack_delay) { 4233 stcb->asoc.delayed_ack = sack->sack_delay; 4234 } 4235 if (sack->sack_freq) { 4236 stcb->asoc.sack_freq = sack->sack_freq; 4237 } 4238 SCTP_TCB_UNLOCK(stcb); 4239 } else { 4240 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4241 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4242 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4243 ((sack->sack_assoc_id == SCTP_FUTURE_ASSOC) || 4244 (sack->sack_assoc_id == SCTP_ALL_ASSOC)))) { 4245 SCTP_INP_WLOCK(inp); 4246 if (sack->sack_delay) { 4247 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_RECV] = sctp_msecs_to_ticks(sack->sack_delay); 4248 } 4249 if (sack->sack_freq) { 4250 inp->sctp_ep.sctp_sack_freq = sack->sack_freq; 4251 } 4252 SCTP_INP_WUNLOCK(inp); 4253 } 4254 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4255 ((sack->sack_assoc_id == SCTP_CURRENT_ASSOC) || 4256 (sack->sack_assoc_id == SCTP_ALL_ASSOC))) { 4257 SCTP_INP_RLOCK(inp); 4258 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4259 SCTP_TCB_LOCK(stcb); 4260 if (sack->sack_delay) { 4261 stcb->asoc.delayed_ack = sack->sack_delay; 4262 } 4263 if (sack->sack_freq) { 4264 stcb->asoc.sack_freq = sack->sack_freq; 4265 } 4266 SCTP_TCB_UNLOCK(stcb); 4267 } 4268 SCTP_INP_RUNLOCK(inp); 4269 } 4270 } 4271 break; 4272 } 4273 case SCTP_AUTH_CHUNK: 4274 { 4275 struct sctp_authchunk *sauth; 4276 4277 SCTP_CHECK_AND_CAST(sauth, optval, struct sctp_authchunk, optsize); 4278 4279 SCTP_INP_WLOCK(inp); 4280 if (sctp_auth_add_chunk(sauth->sauth_chunk, inp->sctp_ep.local_auth_chunks)) { 4281 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4282 error = EINVAL; 4283 } else { 4284 inp->auth_supported = 1; 4285 } 4286 SCTP_INP_WUNLOCK(inp); 4287 break; 4288 } 4289 case SCTP_AUTH_KEY: 4290 { 4291 struct sctp_authkey *sca; 4292 struct sctp_keyhead *shared_keys; 4293 sctp_sharedkey_t *shared_key; 4294 sctp_key_t *key = NULL; 4295 size_t size; 4296 4297 SCTP_CHECK_AND_CAST(sca, optval, struct sctp_authkey, optsize); 4298 if (sca->sca_keylength == 0) { 4299 size = optsize - sizeof(struct sctp_authkey); 4300 } else { 4301 if (sca->sca_keylength + sizeof(struct sctp_authkey) <= optsize) { 4302 size = sca->sca_keylength; 4303 } else { 4304 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4305 error = EINVAL; 4306 break; 4307 } 4308 } 4309 SCTP_FIND_STCB(inp, stcb, sca->sca_assoc_id); 4310 4311 if (stcb) { 4312 shared_keys = &stcb->asoc.shared_keys; 4313 /* clear the cached keys for this key id */ 4314 sctp_clear_cachedkeys(stcb, sca->sca_keynumber); 4315 /* 4316 * create the new shared key and 4317 * insert/replace it 4318 */ 4319 if (size > 0) { 4320 key = sctp_set_key(sca->sca_key, (uint32_t)size); 4321 if (key == NULL) { 4322 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4323 error = ENOMEM; 4324 SCTP_TCB_UNLOCK(stcb); 4325 break; 4326 } 4327 } 4328 shared_key = sctp_alloc_sharedkey(); 4329 if (shared_key == NULL) { 4330 sctp_free_key(key); 4331 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4332 error = ENOMEM; 4333 SCTP_TCB_UNLOCK(stcb); 4334 break; 4335 } 4336 shared_key->key = key; 4337 shared_key->keyid = sca->sca_keynumber; 4338 error = sctp_insert_sharedkey(shared_keys, shared_key); 4339 SCTP_TCB_UNLOCK(stcb); 4340 } else { 4341 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4342 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4343 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4344 ((sca->sca_assoc_id == SCTP_FUTURE_ASSOC) || 4345 (sca->sca_assoc_id == SCTP_ALL_ASSOC)))) { 4346 SCTP_INP_WLOCK(inp); 4347 shared_keys = &inp->sctp_ep.shared_keys; 4348 /* 4349 * clear the cached keys on all 4350 * assocs for this key id 4351 */ 4352 sctp_clear_cachedkeys_ep(inp, sca->sca_keynumber); 4353 /* 4354 * create the new shared key and 4355 * insert/replace it 4356 */ 4357 if (size > 0) { 4358 key = sctp_set_key(sca->sca_key, (uint32_t)size); 4359 if (key == NULL) { 4360 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4361 error = ENOMEM; 4362 SCTP_INP_WUNLOCK(inp); 4363 break; 4364 } 4365 } 4366 shared_key = sctp_alloc_sharedkey(); 4367 if (shared_key == NULL) { 4368 sctp_free_key(key); 4369 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4370 error = ENOMEM; 4371 SCTP_INP_WUNLOCK(inp); 4372 break; 4373 } 4374 shared_key->key = key; 4375 shared_key->keyid = sca->sca_keynumber; 4376 error = sctp_insert_sharedkey(shared_keys, shared_key); 4377 SCTP_INP_WUNLOCK(inp); 4378 } 4379 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4380 ((sca->sca_assoc_id == SCTP_CURRENT_ASSOC) || 4381 (sca->sca_assoc_id == SCTP_ALL_ASSOC))) { 4382 SCTP_INP_RLOCK(inp); 4383 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4384 SCTP_TCB_LOCK(stcb); 4385 shared_keys = &stcb->asoc.shared_keys; 4386 /* 4387 * clear the cached keys for 4388 * this key id 4389 */ 4390 sctp_clear_cachedkeys(stcb, sca->sca_keynumber); 4391 /* 4392 * create the new shared key 4393 * and insert/replace it 4394 */ 4395 if (size > 0) { 4396 key = sctp_set_key(sca->sca_key, (uint32_t)size); 4397 if (key == NULL) { 4398 SCTP_TCB_UNLOCK(stcb); 4399 continue; 4400 } 4401 } 4402 shared_key = sctp_alloc_sharedkey(); 4403 if (shared_key == NULL) { 4404 sctp_free_key(key); 4405 SCTP_TCB_UNLOCK(stcb); 4406 continue; 4407 } 4408 shared_key->key = key; 4409 shared_key->keyid = sca->sca_keynumber; 4410 error = sctp_insert_sharedkey(shared_keys, shared_key); 4411 SCTP_TCB_UNLOCK(stcb); 4412 } 4413 SCTP_INP_RUNLOCK(inp); 4414 } 4415 } 4416 break; 4417 } 4418 case SCTP_HMAC_IDENT: 4419 { 4420 struct sctp_hmacalgo *shmac; 4421 sctp_hmaclist_t *hmaclist; 4422 uint16_t hmacid; 4423 uint32_t i; 4424 4425 SCTP_CHECK_AND_CAST(shmac, optval, struct sctp_hmacalgo, optsize); 4426 if ((optsize < sizeof(struct sctp_hmacalgo) + shmac->shmac_number_of_idents * sizeof(uint16_t)) || 4427 (shmac->shmac_number_of_idents > 0xffff)) { 4428 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4429 error = EINVAL; 4430 break; 4431 } 4432 4433 hmaclist = sctp_alloc_hmaclist((uint16_t)shmac->shmac_number_of_idents); 4434 if (hmaclist == NULL) { 4435 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4436 error = ENOMEM; 4437 break; 4438 } 4439 for (i = 0; i < shmac->shmac_number_of_idents; i++) { 4440 hmacid = shmac->shmac_idents[i]; 4441 if (sctp_auth_add_hmacid(hmaclist, hmacid)) { 4442 /* invalid HMACs were found */ ; 4443 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4444 error = EINVAL; 4445 sctp_free_hmaclist(hmaclist); 4446 goto sctp_set_hmac_done; 4447 } 4448 } 4449 for (i = 0; i < hmaclist->num_algo; i++) { 4450 if (hmaclist->hmac[i] == SCTP_AUTH_HMAC_ID_SHA1) { 4451 /* already in list */ 4452 break; 4453 } 4454 } 4455 if (i == hmaclist->num_algo) { 4456 /* not found in list */ 4457 sctp_free_hmaclist(hmaclist); 4458 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4459 error = EINVAL; 4460 break; 4461 } 4462 /* set it on the endpoint */ 4463 SCTP_INP_WLOCK(inp); 4464 if (inp->sctp_ep.local_hmacs) 4465 sctp_free_hmaclist(inp->sctp_ep.local_hmacs); 4466 inp->sctp_ep.local_hmacs = hmaclist; 4467 SCTP_INP_WUNLOCK(inp); 4468 sctp_set_hmac_done: 4469 break; 4470 } 4471 case SCTP_AUTH_ACTIVE_KEY: 4472 { 4473 struct sctp_authkeyid *scact; 4474 4475 SCTP_CHECK_AND_CAST(scact, optval, struct sctp_authkeyid, optsize); 4476 SCTP_FIND_STCB(inp, stcb, scact->scact_assoc_id); 4477 4478 /* set the active key on the right place */ 4479 if (stcb) { 4480 /* set the active key on the assoc */ 4481 if (sctp_auth_setactivekey(stcb, 4482 scact->scact_keynumber)) { 4483 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, 4484 SCTP_FROM_SCTP_USRREQ, 4485 EINVAL); 4486 error = EINVAL; 4487 } 4488 SCTP_TCB_UNLOCK(stcb); 4489 } else { 4490 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4491 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4492 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4493 ((scact->scact_assoc_id == SCTP_FUTURE_ASSOC) || 4494 (scact->scact_assoc_id == SCTP_ALL_ASSOC)))) { 4495 SCTP_INP_WLOCK(inp); 4496 if (sctp_auth_setactivekey_ep(inp, scact->scact_keynumber)) { 4497 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4498 error = EINVAL; 4499 } 4500 SCTP_INP_WUNLOCK(inp); 4501 } 4502 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4503 ((scact->scact_assoc_id == SCTP_CURRENT_ASSOC) || 4504 (scact->scact_assoc_id == SCTP_ALL_ASSOC))) { 4505 SCTP_INP_RLOCK(inp); 4506 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4507 SCTP_TCB_LOCK(stcb); 4508 sctp_auth_setactivekey(stcb, scact->scact_keynumber); 4509 SCTP_TCB_UNLOCK(stcb); 4510 } 4511 SCTP_INP_RUNLOCK(inp); 4512 } 4513 } 4514 break; 4515 } 4516 case SCTP_AUTH_DELETE_KEY: 4517 { 4518 struct sctp_authkeyid *scdel; 4519 4520 SCTP_CHECK_AND_CAST(scdel, optval, struct sctp_authkeyid, optsize); 4521 SCTP_FIND_STCB(inp, stcb, scdel->scact_assoc_id); 4522 4523 /* delete the key from the right place */ 4524 if (stcb) { 4525 if (sctp_delete_sharedkey(stcb, scdel->scact_keynumber)) { 4526 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4527 error = EINVAL; 4528 } 4529 SCTP_TCB_UNLOCK(stcb); 4530 } else { 4531 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4532 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4533 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4534 ((scdel->scact_assoc_id == SCTP_FUTURE_ASSOC) || 4535 (scdel->scact_assoc_id == SCTP_ALL_ASSOC)))) { 4536 SCTP_INP_WLOCK(inp); 4537 if (sctp_delete_sharedkey_ep(inp, scdel->scact_keynumber)) { 4538 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4539 error = EINVAL; 4540 } 4541 SCTP_INP_WUNLOCK(inp); 4542 } 4543 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4544 ((scdel->scact_assoc_id == SCTP_CURRENT_ASSOC) || 4545 (scdel->scact_assoc_id == SCTP_ALL_ASSOC))) { 4546 SCTP_INP_RLOCK(inp); 4547 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4548 SCTP_TCB_LOCK(stcb); 4549 sctp_delete_sharedkey(stcb, scdel->scact_keynumber); 4550 SCTP_TCB_UNLOCK(stcb); 4551 } 4552 SCTP_INP_RUNLOCK(inp); 4553 } 4554 } 4555 break; 4556 } 4557 case SCTP_AUTH_DEACTIVATE_KEY: 4558 { 4559 struct sctp_authkeyid *keyid; 4560 4561 SCTP_CHECK_AND_CAST(keyid, optval, struct sctp_authkeyid, optsize); 4562 SCTP_FIND_STCB(inp, stcb, keyid->scact_assoc_id); 4563 4564 /* deactivate the key from the right place */ 4565 if (stcb) { 4566 if (sctp_deact_sharedkey(stcb, keyid->scact_keynumber)) { 4567 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4568 error = EINVAL; 4569 } 4570 SCTP_TCB_UNLOCK(stcb); 4571 } else { 4572 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4573 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4574 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4575 ((keyid->scact_assoc_id == SCTP_FUTURE_ASSOC) || 4576 (keyid->scact_assoc_id == SCTP_ALL_ASSOC)))) { 4577 SCTP_INP_WLOCK(inp); 4578 if (sctp_deact_sharedkey_ep(inp, keyid->scact_keynumber)) { 4579 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4580 error = EINVAL; 4581 } 4582 SCTP_INP_WUNLOCK(inp); 4583 } 4584 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4585 ((keyid->scact_assoc_id == SCTP_CURRENT_ASSOC) || 4586 (keyid->scact_assoc_id == SCTP_ALL_ASSOC))) { 4587 SCTP_INP_RLOCK(inp); 4588 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4589 SCTP_TCB_LOCK(stcb); 4590 sctp_deact_sharedkey(stcb, keyid->scact_keynumber); 4591 SCTP_TCB_UNLOCK(stcb); 4592 } 4593 SCTP_INP_RUNLOCK(inp); 4594 } 4595 } 4596 break; 4597 } 4598 case SCTP_ENABLE_STREAM_RESET: 4599 { 4600 struct sctp_assoc_value *av; 4601 4602 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 4603 if (av->assoc_value & (~SCTP_ENABLE_VALUE_MASK)) { 4604 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4605 error = EINVAL; 4606 break; 4607 } 4608 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4609 if (stcb) { 4610 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value; 4611 SCTP_TCB_UNLOCK(stcb); 4612 } else { 4613 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4614 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4615 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4616 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 4617 (av->assoc_id == SCTP_ALL_ASSOC)))) { 4618 SCTP_INP_WLOCK(inp); 4619 inp->local_strreset_support = (uint8_t)av->assoc_value; 4620 SCTP_INP_WUNLOCK(inp); 4621 } 4622 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4623 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 4624 (av->assoc_id == SCTP_ALL_ASSOC))) { 4625 SCTP_INP_RLOCK(inp); 4626 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4627 SCTP_TCB_LOCK(stcb); 4628 stcb->asoc.local_strreset_support = (uint8_t)av->assoc_value; 4629 SCTP_TCB_UNLOCK(stcb); 4630 } 4631 SCTP_INP_RUNLOCK(inp); 4632 } 4633 } 4634 break; 4635 } 4636 case SCTP_RESET_STREAMS: 4637 { 4638 struct sctp_reset_streams *strrst; 4639 int i, send_out = 0; 4640 int send_in = 0; 4641 4642 SCTP_CHECK_AND_CAST(strrst, optval, struct sctp_reset_streams, optsize); 4643 SCTP_FIND_STCB(inp, stcb, strrst->srs_assoc_id); 4644 if (stcb == NULL) { 4645 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 4646 error = ENOENT; 4647 break; 4648 } 4649 if (stcb->asoc.reconfig_supported == 0) { 4650 /* 4651 * Peer does not support the chunk type. 4652 */ 4653 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4654 error = EOPNOTSUPP; 4655 SCTP_TCB_UNLOCK(stcb); 4656 break; 4657 } 4658 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { 4659 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4660 error = EINVAL; 4661 SCTP_TCB_UNLOCK(stcb); 4662 break; 4663 } 4664 if (sizeof(struct sctp_reset_streams) + 4665 strrst->srs_number_streams * sizeof(uint16_t) > optsize) { 4666 error = EINVAL; 4667 SCTP_TCB_UNLOCK(stcb); 4668 break; 4669 } 4670 if (strrst->srs_flags & SCTP_STREAM_RESET_INCOMING) { 4671 send_in = 1; 4672 if (stcb->asoc.stream_reset_outstanding) { 4673 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); 4674 error = EALREADY; 4675 SCTP_TCB_UNLOCK(stcb); 4676 break; 4677 } 4678 } 4679 if (strrst->srs_flags & SCTP_STREAM_RESET_OUTGOING) { 4680 send_out = 1; 4681 } 4682 if ((strrst->srs_number_streams > SCTP_MAX_STREAMS_AT_ONCE_RESET) && send_in) { 4683 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOMEM); 4684 error = ENOMEM; 4685 SCTP_TCB_UNLOCK(stcb); 4686 break; 4687 } 4688 if ((send_in == 0) && (send_out == 0)) { 4689 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4690 error = EINVAL; 4691 SCTP_TCB_UNLOCK(stcb); 4692 break; 4693 } 4694 for (i = 0; i < strrst->srs_number_streams; i++) { 4695 if ((send_in) && 4696 (strrst->srs_stream_list[i] >= stcb->asoc.streamincnt)) { 4697 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4698 error = EINVAL; 4699 break; 4700 } 4701 if ((send_out) && 4702 (strrst->srs_stream_list[i] >= stcb->asoc.streamoutcnt)) { 4703 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4704 error = EINVAL; 4705 break; 4706 } 4707 } 4708 if (error) { 4709 SCTP_TCB_UNLOCK(stcb); 4710 break; 4711 } 4712 if (send_out) { 4713 int cnt; 4714 uint16_t strm; 4715 4716 if (strrst->srs_number_streams) { 4717 for (i = 0, cnt = 0; i < strrst->srs_number_streams; i++) { 4718 strm = strrst->srs_stream_list[i]; 4719 if (stcb->asoc.strmout[strm].state == SCTP_STREAM_OPEN) { 4720 stcb->asoc.strmout[strm].state = SCTP_STREAM_RESET_PENDING; 4721 cnt++; 4722 } 4723 } 4724 } else { 4725 /* Its all */ 4726 for (i = 0, cnt = 0; i < stcb->asoc.streamoutcnt; i++) { 4727 if (stcb->asoc.strmout[i].state == SCTP_STREAM_OPEN) { 4728 stcb->asoc.strmout[i].state = SCTP_STREAM_RESET_PENDING; 4729 cnt++; 4730 } 4731 } 4732 } 4733 } 4734 if (send_in) { 4735 error = sctp_send_str_reset_req(stcb, strrst->srs_number_streams, 4736 strrst->srs_stream_list, 4737 send_in, 0, 0, 0, 0, 0); 4738 } else { 4739 error = sctp_send_stream_reset_out_if_possible(stcb, SCTP_SO_LOCKED); 4740 } 4741 if (error == 0) { 4742 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); 4743 } else { 4744 /* 4745 * For outgoing streams don't report any 4746 * problems in sending the request to the 4747 * application. XXX: Double check resetting 4748 * incoming streams. 4749 */ 4750 error = 0; 4751 } 4752 SCTP_TCB_UNLOCK(stcb); 4753 break; 4754 } 4755 case SCTP_ADD_STREAMS: 4756 { 4757 struct sctp_add_streams *stradd; 4758 uint8_t addstream = 0; 4759 uint16_t add_o_strmcnt = 0; 4760 uint16_t add_i_strmcnt = 0; 4761 4762 SCTP_CHECK_AND_CAST(stradd, optval, struct sctp_add_streams, optsize); 4763 SCTP_FIND_STCB(inp, stcb, stradd->sas_assoc_id); 4764 if (stcb == NULL) { 4765 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 4766 error = ENOENT; 4767 break; 4768 } 4769 if (stcb->asoc.reconfig_supported == 0) { 4770 /* 4771 * Peer does not support the chunk type. 4772 */ 4773 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4774 error = EOPNOTSUPP; 4775 SCTP_TCB_UNLOCK(stcb); 4776 break; 4777 } 4778 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { 4779 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4780 error = EINVAL; 4781 SCTP_TCB_UNLOCK(stcb); 4782 break; 4783 } 4784 if (stcb->asoc.stream_reset_outstanding) { 4785 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); 4786 error = EALREADY; 4787 SCTP_TCB_UNLOCK(stcb); 4788 break; 4789 } 4790 if ((stradd->sas_outstrms == 0) && 4791 (stradd->sas_instrms == 0)) { 4792 error = EINVAL; 4793 goto skip_stuff; 4794 } 4795 if (stradd->sas_outstrms) { 4796 addstream = 1; 4797 /* We allocate here */ 4798 add_o_strmcnt = stradd->sas_outstrms; 4799 if ((((int)add_o_strmcnt) + ((int)stcb->asoc.streamoutcnt)) > 0x0000ffff) { 4800 /* You can't have more than 64k */ 4801 error = EINVAL; 4802 goto skip_stuff; 4803 } 4804 } 4805 if (stradd->sas_instrms) { 4806 int cnt; 4807 4808 addstream |= 2; 4809 /* 4810 * We allocate inside 4811 * sctp_send_str_reset_req() 4812 */ 4813 add_i_strmcnt = stradd->sas_instrms; 4814 cnt = add_i_strmcnt; 4815 cnt += stcb->asoc.streamincnt; 4816 if (cnt > 0x0000ffff) { 4817 /* You can't have more than 64k */ 4818 error = EINVAL; 4819 goto skip_stuff; 4820 } 4821 if (cnt > (int)stcb->asoc.max_inbound_streams) { 4822 /* More than you are allowed */ 4823 error = EINVAL; 4824 goto skip_stuff; 4825 } 4826 } 4827 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 0, addstream, add_o_strmcnt, add_i_strmcnt, 0); 4828 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); 4829 skip_stuff: 4830 SCTP_TCB_UNLOCK(stcb); 4831 break; 4832 } 4833 case SCTP_RESET_ASSOC: 4834 { 4835 int i; 4836 uint32_t *value; 4837 4838 SCTP_CHECK_AND_CAST(value, optval, uint32_t, optsize); 4839 SCTP_FIND_STCB(inp, stcb, (sctp_assoc_t)*value); 4840 if (stcb == NULL) { 4841 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 4842 error = ENOENT; 4843 break; 4844 } 4845 if (stcb->asoc.reconfig_supported == 0) { 4846 /* 4847 * Peer does not support the chunk type. 4848 */ 4849 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 4850 error = EOPNOTSUPP; 4851 SCTP_TCB_UNLOCK(stcb); 4852 break; 4853 } 4854 if (SCTP_GET_STATE(stcb) != SCTP_STATE_OPEN) { 4855 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4856 error = EINVAL; 4857 SCTP_TCB_UNLOCK(stcb); 4858 break; 4859 } 4860 if (stcb->asoc.stream_reset_outstanding) { 4861 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); 4862 error = EALREADY; 4863 SCTP_TCB_UNLOCK(stcb); 4864 break; 4865 } 4866 /* 4867 * Is there any data pending in the send or sent 4868 * queues? 4869 */ 4870 if (!TAILQ_EMPTY(&stcb->asoc.send_queue) || 4871 !TAILQ_EMPTY(&stcb->asoc.sent_queue)) { 4872 busy_out: 4873 error = EBUSY; 4874 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 4875 SCTP_TCB_UNLOCK(stcb); 4876 break; 4877 } 4878 /* Do any streams have data queued? */ 4879 for (i = 0; i < stcb->asoc.streamoutcnt; i++) { 4880 if (!TAILQ_EMPTY(&stcb->asoc.strmout[i].outqueue)) { 4881 goto busy_out; 4882 } 4883 } 4884 error = sctp_send_str_reset_req(stcb, 0, NULL, 0, 1, 0, 0, 0, 0); 4885 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_STRRST_REQ, SCTP_SO_LOCKED); 4886 SCTP_TCB_UNLOCK(stcb); 4887 break; 4888 } 4889 case SCTP_CONNECT_X: 4890 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) { 4891 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4892 error = EINVAL; 4893 break; 4894 } 4895 error = sctp_do_connect_x(so, inp, optval, optsize, p, 0); 4896 break; 4897 case SCTP_CONNECT_X_DELAYED: 4898 if (optsize < (sizeof(int) + sizeof(struct sockaddr_in))) { 4899 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 4900 error = EINVAL; 4901 break; 4902 } 4903 error = sctp_do_connect_x(so, inp, optval, optsize, p, 1); 4904 break; 4905 case SCTP_CONNECT_X_COMPLETE: 4906 { 4907 struct sockaddr *sa; 4908 4909 /* FIXME MT: check correct? */ 4910 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize); 4911 4912 /* find tcb */ 4913 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { 4914 SCTP_INP_RLOCK(inp); 4915 stcb = LIST_FIRST(&inp->sctp_asoc_list); 4916 if (stcb) { 4917 SCTP_TCB_LOCK(stcb); 4918 } 4919 SCTP_INP_RUNLOCK(inp); 4920 } else { 4921 /* 4922 * We increment here since 4923 * sctp_findassociation_ep_addr() wil do a 4924 * decrement if it finds the stcb as long as 4925 * the locked tcb (last argument) is NOT a 4926 * TCB.. aka NULL. 4927 */ 4928 SCTP_INP_INCR_REF(inp); 4929 stcb = sctp_findassociation_ep_addr(&inp, sa, NULL, NULL, NULL); 4930 if (stcb == NULL) { 4931 SCTP_INP_DECR_REF(inp); 4932 } 4933 } 4934 4935 if (stcb == NULL) { 4936 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 4937 error = ENOENT; 4938 break; 4939 } 4940 if (stcb->asoc.delayed_connection == 1) { 4941 stcb->asoc.delayed_connection = 0; 4942 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 4943 sctp_timer_stop(SCTP_TIMER_TYPE_INIT, inp, stcb, 4944 stcb->asoc.primary_destination, 4945 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_8); 4946 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED); 4947 } else { 4948 /* 4949 * already expired or did not use delayed 4950 * connectx 4951 */ 4952 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); 4953 error = EALREADY; 4954 } 4955 SCTP_TCB_UNLOCK(stcb); 4956 break; 4957 } 4958 case SCTP_MAX_BURST: 4959 { 4960 struct sctp_assoc_value *av; 4961 4962 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 4963 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4964 4965 if (stcb) { 4966 stcb->asoc.max_burst = av->assoc_value; 4967 SCTP_TCB_UNLOCK(stcb); 4968 } else { 4969 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 4970 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 4971 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4972 ((av->assoc_id == SCTP_FUTURE_ASSOC) || 4973 (av->assoc_id == SCTP_ALL_ASSOC)))) { 4974 SCTP_INP_WLOCK(inp); 4975 inp->sctp_ep.max_burst = av->assoc_value; 4976 SCTP_INP_WUNLOCK(inp); 4977 } 4978 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 4979 ((av->assoc_id == SCTP_CURRENT_ASSOC) || 4980 (av->assoc_id == SCTP_ALL_ASSOC))) { 4981 SCTP_INP_RLOCK(inp); 4982 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 4983 SCTP_TCB_LOCK(stcb); 4984 stcb->asoc.max_burst = av->assoc_value; 4985 SCTP_TCB_UNLOCK(stcb); 4986 } 4987 SCTP_INP_RUNLOCK(inp); 4988 } 4989 } 4990 break; 4991 } 4992 case SCTP_MAXSEG: 4993 { 4994 struct sctp_assoc_value *av; 4995 int ovh; 4996 4997 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 4998 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 4999 5000 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 5001 ovh = SCTP_MED_OVERHEAD; 5002 } else { 5003 ovh = SCTP_MED_V4_OVERHEAD; 5004 } 5005 if (stcb) { 5006 if (av->assoc_value) { 5007 stcb->asoc.sctp_frag_point = (av->assoc_value + ovh); 5008 } else { 5009 stcb->asoc.sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; 5010 } 5011 SCTP_TCB_UNLOCK(stcb); 5012 } else { 5013 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5014 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 5015 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5016 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 5017 SCTP_INP_WLOCK(inp); 5018 /* 5019 * FIXME MT: I think this is not in 5020 * tune with the API ID 5021 */ 5022 if (av->assoc_value) { 5023 inp->sctp_frag_point = (av->assoc_value + ovh); 5024 } else { 5025 inp->sctp_frag_point = SCTP_DEFAULT_MAXSEGMENT; 5026 } 5027 SCTP_INP_WUNLOCK(inp); 5028 } else { 5029 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5030 error = EINVAL; 5031 } 5032 } 5033 break; 5034 } 5035 case SCTP_EVENTS: 5036 { 5037 struct sctp_event_subscribe *events; 5038 5039 SCTP_CHECK_AND_CAST(events, optval, struct sctp_event_subscribe, optsize); 5040 5041 SCTP_INP_WLOCK(inp); 5042 if (events->sctp_data_io_event) { 5043 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT); 5044 } else { 5045 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVDATAIOEVNT); 5046 } 5047 5048 if (events->sctp_association_event) { 5049 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT); 5050 } else { 5051 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVASSOCEVNT); 5052 } 5053 5054 if (events->sctp_address_event) { 5055 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPADDREVNT); 5056 } else { 5057 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPADDREVNT); 5058 } 5059 5060 if (events->sctp_send_failure_event) { 5061 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT); 5062 } else { 5063 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSENDFAILEVNT); 5064 } 5065 5066 if (events->sctp_peer_error_event) { 5067 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVPEERERR); 5068 } else { 5069 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVPEERERR); 5070 } 5071 5072 if (events->sctp_shutdown_event) { 5073 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT); 5074 } else { 5075 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT); 5076 } 5077 5078 if (events->sctp_partial_delivery_event) { 5079 sctp_feature_on(inp, SCTP_PCB_FLAGS_PDAPIEVNT); 5080 } else { 5081 sctp_feature_off(inp, SCTP_PCB_FLAGS_PDAPIEVNT); 5082 } 5083 5084 if (events->sctp_adaptation_layer_event) { 5085 sctp_feature_on(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT); 5086 } else { 5087 sctp_feature_off(inp, SCTP_PCB_FLAGS_ADAPTATIONEVNT); 5088 } 5089 5090 if (events->sctp_authentication_event) { 5091 sctp_feature_on(inp, SCTP_PCB_FLAGS_AUTHEVNT); 5092 } else { 5093 sctp_feature_off(inp, SCTP_PCB_FLAGS_AUTHEVNT); 5094 } 5095 5096 if (events->sctp_sender_dry_event) { 5097 sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT); 5098 } else { 5099 sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT); 5100 } 5101 5102 if (events->sctp_stream_reset_event) { 5103 sctp_feature_on(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT); 5104 } else { 5105 sctp_feature_off(inp, SCTP_PCB_FLAGS_STREAM_RESETEVNT); 5106 } 5107 SCTP_INP_WUNLOCK(inp); 5108 5109 SCTP_INP_RLOCK(inp); 5110 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 5111 SCTP_TCB_LOCK(stcb); 5112 if (events->sctp_association_event) { 5113 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT); 5114 } else { 5115 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVASSOCEVNT); 5116 } 5117 if (events->sctp_address_event) { 5118 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT); 5119 } else { 5120 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPADDREVNT); 5121 } 5122 if (events->sctp_send_failure_event) { 5123 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT); 5124 } else { 5125 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSENDFAILEVNT); 5126 } 5127 if (events->sctp_peer_error_event) { 5128 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR); 5129 } else { 5130 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVPEERERR); 5131 } 5132 if (events->sctp_shutdown_event) { 5133 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT); 5134 } else { 5135 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT); 5136 } 5137 if (events->sctp_partial_delivery_event) { 5138 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT); 5139 } else { 5140 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_PDAPIEVNT); 5141 } 5142 if (events->sctp_adaptation_layer_event) { 5143 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT); 5144 } else { 5145 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_ADAPTATIONEVNT); 5146 } 5147 if (events->sctp_authentication_event) { 5148 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT); 5149 } else { 5150 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_AUTHEVNT); 5151 } 5152 if (events->sctp_sender_dry_event) { 5153 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT); 5154 } else { 5155 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DRYEVNT); 5156 } 5157 if (events->sctp_stream_reset_event) { 5158 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT); 5159 } else { 5160 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_STREAM_RESETEVNT); 5161 } 5162 SCTP_TCB_UNLOCK(stcb); 5163 } 5164 /* 5165 * Send up the sender dry event only for 1-to-1 5166 * style sockets. 5167 */ 5168 if (events->sctp_sender_dry_event) { 5169 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5170 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 5171 stcb = LIST_FIRST(&inp->sctp_asoc_list); 5172 if (stcb) { 5173 SCTP_TCB_LOCK(stcb); 5174 if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 5175 TAILQ_EMPTY(&stcb->asoc.sent_queue) && 5176 (stcb->asoc.stream_queue_cnt == 0)) { 5177 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED); 5178 } 5179 SCTP_TCB_UNLOCK(stcb); 5180 } 5181 } 5182 } 5183 SCTP_INP_RUNLOCK(inp); 5184 break; 5185 } 5186 case SCTP_ADAPTATION_LAYER: 5187 { 5188 struct sctp_setadaptation *adap_bits; 5189 5190 SCTP_CHECK_AND_CAST(adap_bits, optval, struct sctp_setadaptation, optsize); 5191 SCTP_INP_WLOCK(inp); 5192 inp->sctp_ep.adaptation_layer_indicator = adap_bits->ssb_adaptation_ind; 5193 inp->sctp_ep.adaptation_layer_indicator_provided = 1; 5194 SCTP_INP_WUNLOCK(inp); 5195 break; 5196 } 5197 #ifdef SCTP_DEBUG 5198 case SCTP_SET_INITIAL_DBG_SEQ: 5199 { 5200 uint32_t *vvv; 5201 5202 SCTP_CHECK_AND_CAST(vvv, optval, uint32_t, optsize); 5203 SCTP_INP_WLOCK(inp); 5204 inp->sctp_ep.initial_sequence_debug = *vvv; 5205 SCTP_INP_WUNLOCK(inp); 5206 break; 5207 } 5208 #endif 5209 case SCTP_DEFAULT_SEND_PARAM: 5210 { 5211 struct sctp_sndrcvinfo *s_info; 5212 5213 SCTP_CHECK_AND_CAST(s_info, optval, struct sctp_sndrcvinfo, optsize); 5214 SCTP_FIND_STCB(inp, stcb, s_info->sinfo_assoc_id); 5215 5216 if (stcb) { 5217 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) { 5218 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send))); 5219 } else { 5220 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5221 error = EINVAL; 5222 } 5223 SCTP_TCB_UNLOCK(stcb); 5224 } else { 5225 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5226 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 5227 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5228 ((s_info->sinfo_assoc_id == SCTP_FUTURE_ASSOC) || 5229 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC)))) { 5230 SCTP_INP_WLOCK(inp); 5231 memcpy(&inp->def_send, s_info, min(optsize, sizeof(inp->def_send))); 5232 SCTP_INP_WUNLOCK(inp); 5233 } 5234 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5235 ((s_info->sinfo_assoc_id == SCTP_CURRENT_ASSOC) || 5236 (s_info->sinfo_assoc_id == SCTP_ALL_ASSOC))) { 5237 SCTP_INP_RLOCK(inp); 5238 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 5239 SCTP_TCB_LOCK(stcb); 5240 if (s_info->sinfo_stream < stcb->asoc.streamoutcnt) { 5241 memcpy(&stcb->asoc.def_send, s_info, min(optsize, sizeof(stcb->asoc.def_send))); 5242 } 5243 SCTP_TCB_UNLOCK(stcb); 5244 } 5245 SCTP_INP_RUNLOCK(inp); 5246 } 5247 } 5248 break; 5249 } 5250 case SCTP_PEER_ADDR_PARAMS: 5251 { 5252 struct sctp_paddrparams *paddrp; 5253 struct sctp_nets *net; 5254 struct sockaddr *addr; 5255 #if defined(INET) && defined(INET6) 5256 struct sockaddr_in sin_store; 5257 #endif 5258 5259 SCTP_CHECK_AND_CAST(paddrp, optval, struct sctp_paddrparams, optsize); 5260 SCTP_FIND_STCB(inp, stcb, paddrp->spp_assoc_id); 5261 5262 #if defined(INET) && defined(INET6) 5263 if (paddrp->spp_address.ss_family == AF_INET6) { 5264 struct sockaddr_in6 *sin6; 5265 5266 sin6 = (struct sockaddr_in6 *)&paddrp->spp_address; 5267 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 5268 in6_sin6_2_sin(&sin_store, sin6); 5269 addr = (struct sockaddr *)&sin_store; 5270 } else { 5271 addr = (struct sockaddr *)&paddrp->spp_address; 5272 } 5273 } else { 5274 addr = (struct sockaddr *)&paddrp->spp_address; 5275 } 5276 #else 5277 addr = (struct sockaddr *)&paddrp->spp_address; 5278 #endif 5279 if (stcb != NULL) { 5280 net = sctp_findnet(stcb, addr); 5281 } else { 5282 /* 5283 * We increment here since 5284 * sctp_findassociation_ep_addr() wil do a 5285 * decrement if it finds the stcb as long as 5286 * the locked tcb (last argument) is NOT a 5287 * TCB.. aka NULL. 5288 */ 5289 net = NULL; 5290 SCTP_INP_INCR_REF(inp); 5291 stcb = sctp_findassociation_ep_addr(&inp, addr, 5292 &net, NULL, NULL); 5293 if (stcb == NULL) { 5294 SCTP_INP_DECR_REF(inp); 5295 } 5296 } 5297 if ((stcb != NULL) && (net == NULL)) { 5298 #ifdef INET 5299 if (addr->sa_family == AF_INET) { 5300 struct sockaddr_in *sin; 5301 5302 sin = (struct sockaddr_in *)addr; 5303 if (sin->sin_addr.s_addr != INADDR_ANY) { 5304 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5305 SCTP_TCB_UNLOCK(stcb); 5306 error = EINVAL; 5307 break; 5308 } 5309 } else 5310 #endif 5311 #ifdef INET6 5312 if (addr->sa_family == AF_INET6) { 5313 struct sockaddr_in6 *sin6; 5314 5315 sin6 = (struct sockaddr_in6 *)addr; 5316 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 5317 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5318 SCTP_TCB_UNLOCK(stcb); 5319 error = EINVAL; 5320 break; 5321 } 5322 } else 5323 #endif 5324 { 5325 error = EAFNOSUPPORT; 5326 SCTP_TCB_UNLOCK(stcb); 5327 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 5328 break; 5329 } 5330 } 5331 /* sanity checks */ 5332 if ((paddrp->spp_flags & SPP_HB_ENABLE) && (paddrp->spp_flags & SPP_HB_DISABLE)) { 5333 if (stcb) 5334 SCTP_TCB_UNLOCK(stcb); 5335 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5336 return (EINVAL); 5337 } 5338 5339 if ((paddrp->spp_flags & SPP_PMTUD_ENABLE) && (paddrp->spp_flags & SPP_PMTUD_DISABLE)) { 5340 if (stcb) 5341 SCTP_TCB_UNLOCK(stcb); 5342 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5343 return (EINVAL); 5344 } 5345 if ((paddrp->spp_flags & SPP_PMTUD_DISABLE) && 5346 ((paddrp->spp_pathmtu < SCTP_SMALLEST_PMTU) || 5347 (paddrp->spp_pathmtu > SCTP_LARGEST_PMTU))) { 5348 if (stcb) 5349 SCTP_TCB_UNLOCK(stcb); 5350 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5351 return (EINVAL); 5352 } 5353 5354 if (stcb != NULL) { 5355 /************************TCB SPECIFIC SET ******************/ 5356 if (net != NULL) { 5357 /************************NET SPECIFIC SET ******************/ 5358 if (paddrp->spp_flags & SPP_HB_DISABLE) { 5359 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED) && 5360 !(net->dest_state & SCTP_ADDR_NOHB)) { 5361 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, 5362 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_9); 5363 } 5364 net->dest_state |= SCTP_ADDR_NOHB; 5365 } 5366 if (paddrp->spp_flags & SPP_HB_ENABLE) { 5367 if (paddrp->spp_hbinterval) { 5368 net->heart_beat_delay = paddrp->spp_hbinterval; 5369 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) { 5370 net->heart_beat_delay = 0; 5371 } 5372 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, 5373 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_10); 5374 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 5375 net->dest_state &= ~SCTP_ADDR_NOHB; 5376 } 5377 if (paddrp->spp_flags & SPP_HB_DEMAND) { 5378 if (SCTP_GET_STATE(stcb) == SCTP_STATE_OPEN) { 5379 sctp_send_hb(stcb, net, SCTP_SO_LOCKED); 5380 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED); 5381 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 5382 } 5383 } 5384 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) { 5385 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { 5386 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, 5387 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_11); 5388 } 5389 net->dest_state |= SCTP_ADDR_NO_PMTUD; 5390 net->mtu = paddrp->spp_pathmtu; 5391 switch (net->ro._l_addr.sa.sa_family) { 5392 #ifdef INET 5393 case AF_INET: 5394 net->mtu += SCTP_MIN_V4_OVERHEAD; 5395 break; 5396 #endif 5397 #ifdef INET6 5398 case AF_INET6: 5399 net->mtu += SCTP_MIN_OVERHEAD; 5400 break; 5401 #endif 5402 default: 5403 break; 5404 } 5405 if (net->mtu < stcb->asoc.smallest_mtu) { 5406 sctp_pathmtu_adjustment(stcb, net->mtu); 5407 } 5408 } 5409 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { 5410 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { 5411 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 5412 } 5413 net->dest_state &= ~SCTP_ADDR_NO_PMTUD; 5414 } 5415 if (paddrp->spp_pathmaxrxt) { 5416 if (net->dest_state & SCTP_ADDR_PF) { 5417 if (net->error_count > paddrp->spp_pathmaxrxt) { 5418 net->dest_state &= ~SCTP_ADDR_PF; 5419 } 5420 } else { 5421 if ((net->error_count <= paddrp->spp_pathmaxrxt) && 5422 (net->error_count > net->pf_threshold)) { 5423 net->dest_state |= SCTP_ADDR_PF; 5424 sctp_send_hb(stcb, net, SCTP_SO_LOCKED); 5425 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 5426 stcb->sctp_ep, stcb, net, 5427 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_12); 5428 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 5429 } 5430 } 5431 if (net->dest_state & SCTP_ADDR_REACHABLE) { 5432 if (net->error_count > paddrp->spp_pathmaxrxt) { 5433 net->dest_state &= ~SCTP_ADDR_REACHABLE; 5434 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); 5435 } 5436 } else { 5437 if (net->error_count <= paddrp->spp_pathmaxrxt) { 5438 net->dest_state |= SCTP_ADDR_REACHABLE; 5439 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED); 5440 } 5441 } 5442 net->failure_threshold = paddrp->spp_pathmaxrxt; 5443 } 5444 if (paddrp->spp_flags & SPP_DSCP) { 5445 net->dscp = paddrp->spp_dscp & 0xfc; 5446 net->dscp |= 0x01; 5447 } 5448 #ifdef INET6 5449 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) { 5450 if (net->ro._l_addr.sa.sa_family == AF_INET6) { 5451 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff; 5452 net->flowlabel |= 0x80000000; 5453 } 5454 } 5455 #endif 5456 } else { 5457 /************************ASSOC ONLY -- NO NET SPECIFIC SET ******************/ 5458 if (paddrp->spp_pathmaxrxt != 0) { 5459 stcb->asoc.def_net_failure = paddrp->spp_pathmaxrxt; 5460 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5461 if (net->dest_state & SCTP_ADDR_PF) { 5462 if (net->error_count > paddrp->spp_pathmaxrxt) { 5463 net->dest_state &= ~SCTP_ADDR_PF; 5464 } 5465 } else { 5466 if ((net->error_count <= paddrp->spp_pathmaxrxt) && 5467 (net->error_count > net->pf_threshold)) { 5468 net->dest_state |= SCTP_ADDR_PF; 5469 sctp_send_hb(stcb, net, SCTP_SO_LOCKED); 5470 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 5471 stcb->sctp_ep, stcb, net, 5472 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_13); 5473 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 5474 } 5475 } 5476 if (net->dest_state & SCTP_ADDR_REACHABLE) { 5477 if (net->error_count > paddrp->spp_pathmaxrxt) { 5478 net->dest_state &= ~SCTP_ADDR_REACHABLE; 5479 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); 5480 } 5481 } else { 5482 if (net->error_count <= paddrp->spp_pathmaxrxt) { 5483 net->dest_state |= SCTP_ADDR_REACHABLE; 5484 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED); 5485 } 5486 } 5487 net->failure_threshold = paddrp->spp_pathmaxrxt; 5488 } 5489 } 5490 5491 if (paddrp->spp_flags & SPP_HB_ENABLE) { 5492 if (paddrp->spp_hbinterval != 0) { 5493 stcb->asoc.heart_beat_delay = paddrp->spp_hbinterval; 5494 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) { 5495 stcb->asoc.heart_beat_delay = 0; 5496 } 5497 /* Turn back on the timer */ 5498 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5499 if (paddrp->spp_hbinterval != 0) { 5500 net->heart_beat_delay = paddrp->spp_hbinterval; 5501 } else if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) { 5502 net->heart_beat_delay = 0; 5503 } 5504 if (net->dest_state & SCTP_ADDR_NOHB) { 5505 net->dest_state &= ~SCTP_ADDR_NOHB; 5506 } 5507 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net, 5508 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_14); 5509 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, inp, stcb, net); 5510 } 5511 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); 5512 } 5513 if (paddrp->spp_flags & SPP_HB_DISABLE) { 5514 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5515 if (!(net->dest_state & SCTP_ADDR_NOHB)) { 5516 net->dest_state |= SCTP_ADDR_NOHB; 5517 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { 5518 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 5519 inp, stcb, net, 5520 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_15); 5521 } 5522 } 5523 } 5524 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); 5525 } 5526 if (paddrp->spp_flags & SPP_PMTUD_DISABLE) { 5527 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5528 if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { 5529 sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net, 5530 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_16); 5531 } 5532 net->dest_state |= SCTP_ADDR_NO_PMTUD; 5533 net->mtu = paddrp->spp_pathmtu; 5534 switch (net->ro._l_addr.sa.sa_family) { 5535 #ifdef INET 5536 case AF_INET: 5537 net->mtu += SCTP_MIN_V4_OVERHEAD; 5538 break; 5539 #endif 5540 #ifdef INET6 5541 case AF_INET6: 5542 net->mtu += SCTP_MIN_OVERHEAD; 5543 break; 5544 #endif 5545 default: 5546 break; 5547 } 5548 if (net->mtu < stcb->asoc.smallest_mtu) { 5549 sctp_pathmtu_adjustment(stcb, net->mtu); 5550 } 5551 } 5552 stcb->asoc.default_mtu = paddrp->spp_pathmtu; 5553 sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); 5554 } 5555 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { 5556 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5557 if (!SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) { 5558 sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net); 5559 } 5560 net->dest_state &= ~SCTP_ADDR_NO_PMTUD; 5561 } 5562 stcb->asoc.default_mtu = 0; 5563 sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD); 5564 } 5565 if (paddrp->spp_flags & SPP_DSCP) { 5566 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5567 net->dscp = paddrp->spp_dscp & 0xfc; 5568 net->dscp |= 0x01; 5569 } 5570 stcb->asoc.default_dscp = paddrp->spp_dscp & 0xfc; 5571 stcb->asoc.default_dscp |= 0x01; 5572 } 5573 #ifdef INET6 5574 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) { 5575 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 5576 if (net->ro._l_addr.sa.sa_family == AF_INET6) { 5577 net->flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff; 5578 net->flowlabel |= 0x80000000; 5579 } 5580 } 5581 stcb->asoc.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff; 5582 stcb->asoc.default_flowlabel |= 0x80000000; 5583 } 5584 #endif 5585 } 5586 SCTP_TCB_UNLOCK(stcb); 5587 } else { 5588 /************************NO TCB, SET TO default stuff ******************/ 5589 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5590 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 5591 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5592 (paddrp->spp_assoc_id == SCTP_FUTURE_ASSOC))) { 5593 SCTP_INP_WLOCK(inp); 5594 /* 5595 * For the TOS/FLOWLABEL stuff you 5596 * set it with the options on the 5597 * socket 5598 */ 5599 if (paddrp->spp_pathmaxrxt != 0) { 5600 inp->sctp_ep.def_net_failure = paddrp->spp_pathmaxrxt; 5601 } 5602 5603 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) 5604 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0; 5605 else if (paddrp->spp_hbinterval != 0) { 5606 if (paddrp->spp_hbinterval > SCTP_MAX_HB_INTERVAL) 5607 paddrp->spp_hbinterval = SCTP_MAX_HB_INTERVAL; 5608 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval); 5609 } 5610 5611 if (paddrp->spp_flags & SPP_HB_ENABLE) { 5612 if (paddrp->spp_flags & SPP_HB_TIME_IS_ZERO) { 5613 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = 0; 5614 } else if (paddrp->spp_hbinterval) { 5615 inp->sctp_ep.sctp_timeoutticks[SCTP_TIMER_HEARTBEAT] = sctp_msecs_to_ticks(paddrp->spp_hbinterval); 5616 } 5617 sctp_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); 5618 } else if (paddrp->spp_flags & SPP_HB_DISABLE) { 5619 sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT); 5620 } 5621 if (paddrp->spp_flags & SPP_PMTUD_ENABLE) { 5622 inp->sctp_ep.default_mtu = 0; 5623 sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD); 5624 } else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) { 5625 inp->sctp_ep.default_mtu = paddrp->spp_pathmtu; 5626 sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD); 5627 } 5628 if (paddrp->spp_flags & SPP_DSCP) { 5629 inp->sctp_ep.default_dscp = paddrp->spp_dscp & 0xfc; 5630 inp->sctp_ep.default_dscp |= 0x01; 5631 } 5632 #ifdef INET6 5633 if (paddrp->spp_flags & SPP_IPV6_FLOWLABEL) { 5634 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 5635 inp->sctp_ep.default_flowlabel = paddrp->spp_ipv6_flowlabel & 0x000fffff; 5636 inp->sctp_ep.default_flowlabel |= 0x80000000; 5637 } 5638 } 5639 #endif 5640 SCTP_INP_WUNLOCK(inp); 5641 } else { 5642 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5643 error = EINVAL; 5644 } 5645 } 5646 break; 5647 } 5648 case SCTP_RTOINFO: 5649 { 5650 struct sctp_rtoinfo *srto; 5651 uint32_t new_init, new_min, new_max; 5652 5653 SCTP_CHECK_AND_CAST(srto, optval, struct sctp_rtoinfo, optsize); 5654 SCTP_FIND_STCB(inp, stcb, srto->srto_assoc_id); 5655 5656 if (stcb) { 5657 if (srto->srto_initial) 5658 new_init = srto->srto_initial; 5659 else 5660 new_init = stcb->asoc.initial_rto; 5661 if (srto->srto_max) 5662 new_max = srto->srto_max; 5663 else 5664 new_max = stcb->asoc.maxrto; 5665 if (srto->srto_min) 5666 new_min = srto->srto_min; 5667 else 5668 new_min = stcb->asoc.minrto; 5669 if ((new_min <= new_init) && (new_init <= new_max)) { 5670 stcb->asoc.initial_rto = new_init; 5671 stcb->asoc.maxrto = new_max; 5672 stcb->asoc.minrto = new_min; 5673 } else { 5674 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5675 error = EINVAL; 5676 } 5677 SCTP_TCB_UNLOCK(stcb); 5678 } else { 5679 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5680 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 5681 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5682 (srto->srto_assoc_id == SCTP_FUTURE_ASSOC))) { 5683 SCTP_INP_WLOCK(inp); 5684 if (srto->srto_initial) 5685 new_init = srto->srto_initial; 5686 else 5687 new_init = inp->sctp_ep.initial_rto; 5688 if (srto->srto_max) 5689 new_max = srto->srto_max; 5690 else 5691 new_max = inp->sctp_ep.sctp_maxrto; 5692 if (srto->srto_min) 5693 new_min = srto->srto_min; 5694 else 5695 new_min = inp->sctp_ep.sctp_minrto; 5696 if ((new_min <= new_init) && (new_init <= new_max)) { 5697 inp->sctp_ep.initial_rto = new_init; 5698 inp->sctp_ep.sctp_maxrto = new_max; 5699 inp->sctp_ep.sctp_minrto = new_min; 5700 } else { 5701 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5702 error = EINVAL; 5703 } 5704 SCTP_INP_WUNLOCK(inp); 5705 } else { 5706 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5707 error = EINVAL; 5708 } 5709 } 5710 break; 5711 } 5712 case SCTP_ASSOCINFO: 5713 { 5714 struct sctp_assocparams *sasoc; 5715 5716 SCTP_CHECK_AND_CAST(sasoc, optval, struct sctp_assocparams, optsize); 5717 SCTP_FIND_STCB(inp, stcb, sasoc->sasoc_assoc_id); 5718 if (sasoc->sasoc_cookie_life) { 5719 /* boundary check the cookie life */ 5720 if (sasoc->sasoc_cookie_life < 1000) 5721 sasoc->sasoc_cookie_life = 1000; 5722 if (sasoc->sasoc_cookie_life > SCTP_MAX_COOKIE_LIFE) { 5723 sasoc->sasoc_cookie_life = SCTP_MAX_COOKIE_LIFE; 5724 } 5725 } 5726 if (stcb) { 5727 if (sasoc->sasoc_asocmaxrxt) 5728 stcb->asoc.max_send_times = sasoc->sasoc_asocmaxrxt; 5729 if (sasoc->sasoc_cookie_life) { 5730 stcb->asoc.cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life); 5731 } 5732 SCTP_TCB_UNLOCK(stcb); 5733 } else { 5734 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 5735 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 5736 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 5737 (sasoc->sasoc_assoc_id == SCTP_FUTURE_ASSOC))) { 5738 SCTP_INP_WLOCK(inp); 5739 if (sasoc->sasoc_asocmaxrxt) 5740 inp->sctp_ep.max_send_times = sasoc->sasoc_asocmaxrxt; 5741 if (sasoc->sasoc_cookie_life) { 5742 inp->sctp_ep.def_cookie_life = sctp_msecs_to_ticks(sasoc->sasoc_cookie_life); 5743 } 5744 SCTP_INP_WUNLOCK(inp); 5745 } else { 5746 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5747 error = EINVAL; 5748 } 5749 } 5750 break; 5751 } 5752 case SCTP_INITMSG: 5753 { 5754 struct sctp_initmsg *sinit; 5755 5756 SCTP_CHECK_AND_CAST(sinit, optval, struct sctp_initmsg, optsize); 5757 SCTP_INP_WLOCK(inp); 5758 if (sinit->sinit_num_ostreams) 5759 inp->sctp_ep.pre_open_stream_count = sinit->sinit_num_ostreams; 5760 5761 if (sinit->sinit_max_instreams) 5762 inp->sctp_ep.max_open_streams_intome = sinit->sinit_max_instreams; 5763 5764 if (sinit->sinit_max_attempts) 5765 inp->sctp_ep.max_init_times = sinit->sinit_max_attempts; 5766 5767 if (sinit->sinit_max_init_timeo) 5768 inp->sctp_ep.initial_init_rto_max = sinit->sinit_max_init_timeo; 5769 SCTP_INP_WUNLOCK(inp); 5770 break; 5771 } 5772 case SCTP_PRIMARY_ADDR: 5773 { 5774 struct sctp_setprim *spa; 5775 struct sctp_nets *net; 5776 struct sockaddr *addr; 5777 #if defined(INET) && defined(INET6) 5778 struct sockaddr_in sin_store; 5779 #endif 5780 5781 SCTP_CHECK_AND_CAST(spa, optval, struct sctp_setprim, optsize); 5782 SCTP_FIND_STCB(inp, stcb, spa->ssp_assoc_id); 5783 5784 #if defined(INET) && defined(INET6) 5785 if (spa->ssp_addr.ss_family == AF_INET6) { 5786 struct sockaddr_in6 *sin6; 5787 5788 sin6 = (struct sockaddr_in6 *)&spa->ssp_addr; 5789 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 5790 in6_sin6_2_sin(&sin_store, sin6); 5791 addr = (struct sockaddr *)&sin_store; 5792 } else { 5793 addr = (struct sockaddr *)&spa->ssp_addr; 5794 } 5795 } else { 5796 addr = (struct sockaddr *)&spa->ssp_addr; 5797 } 5798 #else 5799 addr = (struct sockaddr *)&spa->ssp_addr; 5800 #endif 5801 if (stcb != NULL) { 5802 net = sctp_findnet(stcb, addr); 5803 } else { 5804 /* 5805 * We increment here since 5806 * sctp_findassociation_ep_addr() wil do a 5807 * decrement if it finds the stcb as long as 5808 * the locked tcb (last argument) is NOT a 5809 * TCB.. aka NULL. 5810 */ 5811 net = NULL; 5812 SCTP_INP_INCR_REF(inp); 5813 stcb = sctp_findassociation_ep_addr(&inp, addr, 5814 &net, NULL, NULL); 5815 if (stcb == NULL) { 5816 SCTP_INP_DECR_REF(inp); 5817 } 5818 } 5819 5820 if ((stcb != NULL) && (net != NULL)) { 5821 if (net != stcb->asoc.primary_destination) { 5822 if (!(net->dest_state & SCTP_ADDR_UNCONFIRMED)) { 5823 /* Ok we need to set it */ 5824 if (sctp_set_primary_addr(stcb, (struct sockaddr *)NULL, net) == 0) { 5825 if ((stcb->asoc.alternate) && 5826 (!(net->dest_state & SCTP_ADDR_PF)) && 5827 (net->dest_state & SCTP_ADDR_REACHABLE)) { 5828 sctp_free_remote_addr(stcb->asoc.alternate); 5829 stcb->asoc.alternate = NULL; 5830 } 5831 } else { 5832 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5833 error = EINVAL; 5834 } 5835 } else { 5836 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5837 error = EINVAL; 5838 } 5839 } 5840 } else { 5841 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5842 error = EINVAL; 5843 } 5844 if (stcb != NULL) { 5845 SCTP_TCB_UNLOCK(stcb); 5846 } 5847 break; 5848 } 5849 case SCTP_SET_DYNAMIC_PRIMARY: 5850 { 5851 union sctp_sockstore *ss; 5852 5853 error = priv_check(curthread, 5854 PRIV_NETINET_RESERVEDPORT); 5855 if (error) 5856 break; 5857 5858 SCTP_CHECK_AND_CAST(ss, optval, union sctp_sockstore, optsize); 5859 /* SUPER USER CHECK? */ 5860 error = sctp_dynamic_set_primary(&ss->sa, vrf_id); 5861 break; 5862 } 5863 case SCTP_SET_PEER_PRIMARY_ADDR: 5864 { 5865 struct sctp_setpeerprim *sspp; 5866 struct sockaddr *addr; 5867 #if defined(INET) && defined(INET6) 5868 struct sockaddr_in sin_store; 5869 #endif 5870 5871 SCTP_CHECK_AND_CAST(sspp, optval, struct sctp_setpeerprim, optsize); 5872 SCTP_FIND_STCB(inp, stcb, sspp->sspp_assoc_id); 5873 if (stcb != NULL) { 5874 struct sctp_ifa *ifa; 5875 5876 #if defined(INET) && defined(INET6) 5877 if (sspp->sspp_addr.ss_family == AF_INET6) { 5878 struct sockaddr_in6 *sin6; 5879 5880 sin6 = (struct sockaddr_in6 *)&sspp->sspp_addr; 5881 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 5882 in6_sin6_2_sin(&sin_store, sin6); 5883 addr = (struct sockaddr *)&sin_store; 5884 } else { 5885 addr = (struct sockaddr *)&sspp->sspp_addr; 5886 } 5887 } else { 5888 addr = (struct sockaddr *)&sspp->sspp_addr; 5889 } 5890 #else 5891 addr = (struct sockaddr *)&sspp->sspp_addr; 5892 #endif 5893 ifa = sctp_find_ifa_by_addr(addr, stcb->asoc.vrf_id, SCTP_ADDR_NOT_LOCKED); 5894 if (ifa == NULL) { 5895 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5896 error = EINVAL; 5897 goto out_of_it; 5898 } 5899 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 5900 /* 5901 * Must validate the ifa found is in 5902 * our ep 5903 */ 5904 struct sctp_laddr *laddr; 5905 int found = 0; 5906 5907 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 5908 if (laddr->ifa == NULL) { 5909 SCTPDBG(SCTP_DEBUG_OUTPUT1, "%s: NULL ifa\n", 5910 __func__); 5911 continue; 5912 } 5913 if ((sctp_is_addr_restricted(stcb, laddr->ifa)) && 5914 (!sctp_is_addr_pending(stcb, laddr->ifa))) { 5915 continue; 5916 } 5917 if (laddr->ifa == ifa) { 5918 found = 1; 5919 break; 5920 } 5921 } 5922 if (!found) { 5923 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5924 error = EINVAL; 5925 goto out_of_it; 5926 } 5927 } else { 5928 switch (addr->sa_family) { 5929 #ifdef INET 5930 case AF_INET: 5931 { 5932 struct sockaddr_in *sin; 5933 5934 sin = (struct sockaddr_in *)addr; 5935 if (prison_check_ip4(inp->ip_inp.inp.inp_cred, 5936 &sin->sin_addr) != 0) { 5937 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5938 error = EINVAL; 5939 goto out_of_it; 5940 } 5941 break; 5942 } 5943 #endif 5944 #ifdef INET6 5945 case AF_INET6: 5946 { 5947 struct sockaddr_in6 *sin6; 5948 5949 sin6 = (struct sockaddr_in6 *)addr; 5950 if (prison_check_ip6(inp->ip_inp.inp.inp_cred, 5951 &sin6->sin6_addr) != 0) { 5952 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5953 error = EINVAL; 5954 goto out_of_it; 5955 } 5956 break; 5957 } 5958 #endif 5959 default: 5960 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5961 error = EINVAL; 5962 goto out_of_it; 5963 } 5964 } 5965 if (sctp_set_primary_ip_address_sa(stcb, addr) != 0) { 5966 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5967 error = EINVAL; 5968 } 5969 sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_SOCKOPT, SCTP_SO_LOCKED); 5970 out_of_it: 5971 SCTP_TCB_UNLOCK(stcb); 5972 } else { 5973 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5974 error = EINVAL; 5975 } 5976 break; 5977 } 5978 case SCTP_BINDX_ADD_ADDR: 5979 { 5980 struct sockaddr *sa; 5981 struct thread *td; 5982 5983 td = (struct thread *)p; 5984 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize); 5985 #ifdef INET 5986 if (sa->sa_family == AF_INET) { 5987 if (optsize < sizeof(struct sockaddr_in)) { 5988 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 5989 error = EINVAL; 5990 break; 5991 } 5992 if (td != NULL && 5993 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) { 5994 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); 5995 break; 5996 } 5997 } else 5998 #endif 5999 #ifdef INET6 6000 if (sa->sa_family == AF_INET6) { 6001 if (optsize < sizeof(struct sockaddr_in6)) { 6002 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6003 error = EINVAL; 6004 break; 6005 } 6006 if (td != NULL && 6007 (error = prison_local_ip6(td->td_ucred, 6008 &(((struct sockaddr_in6 *)sa)->sin6_addr), 6009 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) { 6010 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); 6011 break; 6012 } 6013 } else 6014 #endif 6015 { 6016 error = EAFNOSUPPORT; 6017 break; 6018 } 6019 sctp_bindx_add_address(so, inp, sa, vrf_id, &error, p); 6020 break; 6021 } 6022 case SCTP_BINDX_REM_ADDR: 6023 { 6024 struct sockaddr *sa; 6025 struct thread *td; 6026 6027 td = (struct thread *)p; 6028 6029 SCTP_CHECK_AND_CAST(sa, optval, struct sockaddr, optsize); 6030 #ifdef INET 6031 if (sa->sa_family == AF_INET) { 6032 if (optsize < sizeof(struct sockaddr_in)) { 6033 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6034 error = EINVAL; 6035 break; 6036 } 6037 if (td != NULL && 6038 (error = prison_local_ip4(td->td_ucred, &(((struct sockaddr_in *)sa)->sin_addr)))) { 6039 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); 6040 break; 6041 } 6042 } else 6043 #endif 6044 #ifdef INET6 6045 if (sa->sa_family == AF_INET6) { 6046 if (optsize < sizeof(struct sockaddr_in6)) { 6047 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6048 error = EINVAL; 6049 break; 6050 } 6051 if (td != NULL && 6052 (error = prison_local_ip6(td->td_ucred, 6053 &(((struct sockaddr_in6 *)sa)->sin6_addr), 6054 (SCTP_IPV6_V6ONLY(inp) != 0))) != 0) { 6055 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, error); 6056 break; 6057 } 6058 } else 6059 #endif 6060 { 6061 error = EAFNOSUPPORT; 6062 break; 6063 } 6064 sctp_bindx_delete_address(inp, sa, vrf_id, &error); 6065 break; 6066 } 6067 case SCTP_EVENT: 6068 { 6069 struct sctp_event *event; 6070 uint32_t event_type; 6071 6072 SCTP_CHECK_AND_CAST(event, optval, struct sctp_event, optsize); 6073 SCTP_FIND_STCB(inp, stcb, event->se_assoc_id); 6074 switch (event->se_type) { 6075 case SCTP_ASSOC_CHANGE: 6076 event_type = SCTP_PCB_FLAGS_RECVASSOCEVNT; 6077 break; 6078 case SCTP_PEER_ADDR_CHANGE: 6079 event_type = SCTP_PCB_FLAGS_RECVPADDREVNT; 6080 break; 6081 case SCTP_REMOTE_ERROR: 6082 event_type = SCTP_PCB_FLAGS_RECVPEERERR; 6083 break; 6084 case SCTP_SEND_FAILED: 6085 event_type = SCTP_PCB_FLAGS_RECVSENDFAILEVNT; 6086 break; 6087 case SCTP_SHUTDOWN_EVENT: 6088 event_type = SCTP_PCB_FLAGS_RECVSHUTDOWNEVNT; 6089 break; 6090 case SCTP_ADAPTATION_INDICATION: 6091 event_type = SCTP_PCB_FLAGS_ADAPTATIONEVNT; 6092 break; 6093 case SCTP_PARTIAL_DELIVERY_EVENT: 6094 event_type = SCTP_PCB_FLAGS_PDAPIEVNT; 6095 break; 6096 case SCTP_AUTHENTICATION_EVENT: 6097 event_type = SCTP_PCB_FLAGS_AUTHEVNT; 6098 break; 6099 case SCTP_STREAM_RESET_EVENT: 6100 event_type = SCTP_PCB_FLAGS_STREAM_RESETEVNT; 6101 break; 6102 case SCTP_SENDER_DRY_EVENT: 6103 event_type = SCTP_PCB_FLAGS_DRYEVNT; 6104 break; 6105 case SCTP_NOTIFICATIONS_STOPPED_EVENT: 6106 event_type = 0; 6107 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP); 6108 error = ENOTSUP; 6109 break; 6110 case SCTP_ASSOC_RESET_EVENT: 6111 event_type = SCTP_PCB_FLAGS_ASSOC_RESETEVNT; 6112 break; 6113 case SCTP_STREAM_CHANGE_EVENT: 6114 event_type = SCTP_PCB_FLAGS_STREAM_CHANGEEVNT; 6115 break; 6116 case SCTP_SEND_FAILED_EVENT: 6117 event_type = SCTP_PCB_FLAGS_RECVNSENDFAILEVNT; 6118 break; 6119 default: 6120 event_type = 0; 6121 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6122 error = EINVAL; 6123 break; 6124 } 6125 if (event_type > 0) { 6126 if (stcb) { 6127 if (event->se_on) { 6128 sctp_stcb_feature_on(inp, stcb, event_type); 6129 if (event_type == SCTP_PCB_FLAGS_DRYEVNT) { 6130 if (TAILQ_EMPTY(&stcb->asoc.send_queue) && 6131 TAILQ_EMPTY(&stcb->asoc.sent_queue) && 6132 (stcb->asoc.stream_queue_cnt == 0)) { 6133 sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED); 6134 } 6135 } 6136 } else { 6137 sctp_stcb_feature_off(inp, stcb, event_type); 6138 } 6139 SCTP_TCB_UNLOCK(stcb); 6140 } else { 6141 /* 6142 * We don't want to send up a storm 6143 * of events, so return an error for 6144 * sender dry events 6145 */ 6146 if ((event_type == SCTP_PCB_FLAGS_DRYEVNT) && 6147 (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6148 ((event->se_assoc_id == SCTP_ALL_ASSOC) || 6149 (event->se_assoc_id == SCTP_CURRENT_ASSOC))) { 6150 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTSUP); 6151 error = ENOTSUP; 6152 break; 6153 } 6154 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6155 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6156 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6157 ((event->se_assoc_id == SCTP_FUTURE_ASSOC) || 6158 (event->se_assoc_id == SCTP_ALL_ASSOC)))) { 6159 SCTP_INP_WLOCK(inp); 6160 if (event->se_on) { 6161 sctp_feature_on(inp, event_type); 6162 } else { 6163 sctp_feature_off(inp, event_type); 6164 } 6165 SCTP_INP_WUNLOCK(inp); 6166 } 6167 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6168 ((event->se_assoc_id == SCTP_CURRENT_ASSOC) || 6169 (event->se_assoc_id == SCTP_ALL_ASSOC))) { 6170 SCTP_INP_RLOCK(inp); 6171 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 6172 SCTP_TCB_LOCK(stcb); 6173 if (event->se_on) { 6174 sctp_stcb_feature_on(inp, stcb, event_type); 6175 } else { 6176 sctp_stcb_feature_off(inp, stcb, event_type); 6177 } 6178 SCTP_TCB_UNLOCK(stcb); 6179 } 6180 SCTP_INP_RUNLOCK(inp); 6181 } 6182 } 6183 } else { 6184 if (stcb) { 6185 SCTP_TCB_UNLOCK(stcb); 6186 } 6187 } 6188 break; 6189 } 6190 case SCTP_RECVRCVINFO: 6191 { 6192 int *onoff; 6193 6194 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize); 6195 SCTP_INP_WLOCK(inp); 6196 if (*onoff != 0) { 6197 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVRCVINFO); 6198 } else { 6199 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVRCVINFO); 6200 } 6201 SCTP_INP_WUNLOCK(inp); 6202 break; 6203 } 6204 case SCTP_RECVNXTINFO: 6205 { 6206 int *onoff; 6207 6208 SCTP_CHECK_AND_CAST(onoff, optval, int, optsize); 6209 SCTP_INP_WLOCK(inp); 6210 if (*onoff != 0) { 6211 sctp_feature_on(inp, SCTP_PCB_FLAGS_RECVNXTINFO); 6212 } else { 6213 sctp_feature_off(inp, SCTP_PCB_FLAGS_RECVNXTINFO); 6214 } 6215 SCTP_INP_WUNLOCK(inp); 6216 break; 6217 } 6218 case SCTP_DEFAULT_SNDINFO: 6219 { 6220 struct sctp_sndinfo *info; 6221 uint16_t policy; 6222 6223 SCTP_CHECK_AND_CAST(info, optval, struct sctp_sndinfo, optsize); 6224 SCTP_FIND_STCB(inp, stcb, info->snd_assoc_id); 6225 6226 if (stcb) { 6227 if (info->snd_sid < stcb->asoc.streamoutcnt) { 6228 stcb->asoc.def_send.sinfo_stream = info->snd_sid; 6229 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags); 6230 stcb->asoc.def_send.sinfo_flags = info->snd_flags; 6231 stcb->asoc.def_send.sinfo_flags |= policy; 6232 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid; 6233 stcb->asoc.def_send.sinfo_context = info->snd_context; 6234 } else { 6235 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6236 error = EINVAL; 6237 } 6238 SCTP_TCB_UNLOCK(stcb); 6239 } else { 6240 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6241 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6242 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6243 ((info->snd_assoc_id == SCTP_FUTURE_ASSOC) || 6244 (info->snd_assoc_id == SCTP_ALL_ASSOC)))) { 6245 SCTP_INP_WLOCK(inp); 6246 inp->def_send.sinfo_stream = info->snd_sid; 6247 policy = PR_SCTP_POLICY(inp->def_send.sinfo_flags); 6248 inp->def_send.sinfo_flags = info->snd_flags; 6249 inp->def_send.sinfo_flags |= policy; 6250 inp->def_send.sinfo_ppid = info->snd_ppid; 6251 inp->def_send.sinfo_context = info->snd_context; 6252 SCTP_INP_WUNLOCK(inp); 6253 } 6254 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6255 ((info->snd_assoc_id == SCTP_CURRENT_ASSOC) || 6256 (info->snd_assoc_id == SCTP_ALL_ASSOC))) { 6257 SCTP_INP_RLOCK(inp); 6258 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 6259 SCTP_TCB_LOCK(stcb); 6260 if (info->snd_sid < stcb->asoc.streamoutcnt) { 6261 stcb->asoc.def_send.sinfo_stream = info->snd_sid; 6262 policy = PR_SCTP_POLICY(stcb->asoc.def_send.sinfo_flags); 6263 stcb->asoc.def_send.sinfo_flags = info->snd_flags; 6264 stcb->asoc.def_send.sinfo_flags |= policy; 6265 stcb->asoc.def_send.sinfo_ppid = info->snd_ppid; 6266 stcb->asoc.def_send.sinfo_context = info->snd_context; 6267 } 6268 SCTP_TCB_UNLOCK(stcb); 6269 } 6270 SCTP_INP_RUNLOCK(inp); 6271 } 6272 } 6273 break; 6274 } 6275 case SCTP_DEFAULT_PRINFO: 6276 { 6277 struct sctp_default_prinfo *info; 6278 6279 SCTP_CHECK_AND_CAST(info, optval, struct sctp_default_prinfo, optsize); 6280 SCTP_FIND_STCB(inp, stcb, info->pr_assoc_id); 6281 6282 if (info->pr_policy > SCTP_PR_SCTP_MAX) { 6283 if (stcb) { 6284 SCTP_TCB_UNLOCK(stcb); 6285 } 6286 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6287 error = EINVAL; 6288 break; 6289 } 6290 if (stcb) { 6291 stcb->asoc.def_send.sinfo_flags &= 0xfff0; 6292 stcb->asoc.def_send.sinfo_flags |= info->pr_policy; 6293 stcb->asoc.def_send.sinfo_timetolive = info->pr_value; 6294 SCTP_TCB_UNLOCK(stcb); 6295 } else { 6296 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6297 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6298 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6299 ((info->pr_assoc_id == SCTP_FUTURE_ASSOC) || 6300 (info->pr_assoc_id == SCTP_ALL_ASSOC)))) { 6301 SCTP_INP_WLOCK(inp); 6302 inp->def_send.sinfo_flags &= 0xfff0; 6303 inp->def_send.sinfo_flags |= info->pr_policy; 6304 inp->def_send.sinfo_timetolive = info->pr_value; 6305 SCTP_INP_WUNLOCK(inp); 6306 } 6307 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6308 ((info->pr_assoc_id == SCTP_CURRENT_ASSOC) || 6309 (info->pr_assoc_id == SCTP_ALL_ASSOC))) { 6310 SCTP_INP_RLOCK(inp); 6311 LIST_FOREACH(stcb, &inp->sctp_asoc_list, sctp_tcblist) { 6312 SCTP_TCB_LOCK(stcb); 6313 stcb->asoc.def_send.sinfo_flags &= 0xfff0; 6314 stcb->asoc.def_send.sinfo_flags |= info->pr_policy; 6315 stcb->asoc.def_send.sinfo_timetolive = info->pr_value; 6316 SCTP_TCB_UNLOCK(stcb); 6317 } 6318 SCTP_INP_RUNLOCK(inp); 6319 } 6320 } 6321 break; 6322 } 6323 case SCTP_PEER_ADDR_THLDS: 6324 /* Applies to the specific association */ 6325 { 6326 struct sctp_paddrthlds *thlds; 6327 struct sctp_nets *net; 6328 struct sockaddr *addr; 6329 #if defined(INET) && defined(INET6) 6330 struct sockaddr_in sin_store; 6331 #endif 6332 6333 SCTP_CHECK_AND_CAST(thlds, optval, struct sctp_paddrthlds, optsize); 6334 SCTP_FIND_STCB(inp, stcb, thlds->spt_assoc_id); 6335 6336 #if defined(INET) && defined(INET6) 6337 if (thlds->spt_address.ss_family == AF_INET6) { 6338 struct sockaddr_in6 *sin6; 6339 6340 sin6 = (struct sockaddr_in6 *)&thlds->spt_address; 6341 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6342 in6_sin6_2_sin(&sin_store, sin6); 6343 addr = (struct sockaddr *)&sin_store; 6344 } else { 6345 addr = (struct sockaddr *)&thlds->spt_address; 6346 } 6347 } else { 6348 addr = (struct sockaddr *)&thlds->spt_address; 6349 } 6350 #else 6351 addr = (struct sockaddr *)&thlds->spt_address; 6352 #endif 6353 if (stcb != NULL) { 6354 net = sctp_findnet(stcb, addr); 6355 } else { 6356 /* 6357 * We increment here since 6358 * sctp_findassociation_ep_addr() wil do a 6359 * decrement if it finds the stcb as long as 6360 * the locked tcb (last argument) is NOT a 6361 * TCB.. aka NULL. 6362 */ 6363 net = NULL; 6364 SCTP_INP_INCR_REF(inp); 6365 stcb = sctp_findassociation_ep_addr(&inp, addr, 6366 &net, NULL, NULL); 6367 if (stcb == NULL) { 6368 SCTP_INP_DECR_REF(inp); 6369 } 6370 } 6371 if ((stcb != NULL) && (net == NULL)) { 6372 #ifdef INET 6373 if (addr->sa_family == AF_INET) { 6374 struct sockaddr_in *sin; 6375 6376 sin = (struct sockaddr_in *)addr; 6377 if (sin->sin_addr.s_addr != INADDR_ANY) { 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 #ifdef INET6 6386 if (addr->sa_family == AF_INET6) { 6387 struct sockaddr_in6 *sin6; 6388 6389 sin6 = (struct sockaddr_in6 *)addr; 6390 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 6391 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6392 SCTP_TCB_UNLOCK(stcb); 6393 error = EINVAL; 6394 break; 6395 } 6396 } else 6397 #endif 6398 { 6399 error = EAFNOSUPPORT; 6400 SCTP_TCB_UNLOCK(stcb); 6401 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 6402 break; 6403 } 6404 } 6405 if (thlds->spt_pathcpthld != 0xffff) { 6406 if (stcb != NULL) { 6407 SCTP_TCB_UNLOCK(stcb); 6408 } 6409 error = EINVAL; 6410 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 6411 break; 6412 } 6413 if (stcb != NULL) { 6414 if (net != NULL) { 6415 net->failure_threshold = thlds->spt_pathmaxrxt; 6416 net->pf_threshold = thlds->spt_pathpfthld; 6417 if (net->dest_state & SCTP_ADDR_PF) { 6418 if ((net->error_count > net->failure_threshold) || 6419 (net->error_count <= net->pf_threshold)) { 6420 net->dest_state &= ~SCTP_ADDR_PF; 6421 } 6422 } else { 6423 if ((net->error_count > net->pf_threshold) && 6424 (net->error_count <= net->failure_threshold)) { 6425 net->dest_state |= SCTP_ADDR_PF; 6426 sctp_send_hb(stcb, net, SCTP_SO_LOCKED); 6427 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 6428 stcb->sctp_ep, stcb, net, 6429 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_17); 6430 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 6431 } 6432 } 6433 if (net->dest_state & SCTP_ADDR_REACHABLE) { 6434 if (net->error_count > net->failure_threshold) { 6435 net->dest_state &= ~SCTP_ADDR_REACHABLE; 6436 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); 6437 } 6438 } else { 6439 if (net->error_count <= net->failure_threshold) { 6440 net->dest_state |= SCTP_ADDR_REACHABLE; 6441 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED); 6442 } 6443 } 6444 } else { 6445 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 6446 net->failure_threshold = thlds->spt_pathmaxrxt; 6447 net->pf_threshold = thlds->spt_pathpfthld; 6448 if (net->dest_state & SCTP_ADDR_PF) { 6449 if ((net->error_count > net->failure_threshold) || 6450 (net->error_count <= net->pf_threshold)) { 6451 net->dest_state &= ~SCTP_ADDR_PF; 6452 } 6453 } else { 6454 if ((net->error_count > net->pf_threshold) && 6455 (net->error_count <= net->failure_threshold)) { 6456 net->dest_state |= SCTP_ADDR_PF; 6457 sctp_send_hb(stcb, net, SCTP_SO_LOCKED); 6458 sctp_timer_stop(SCTP_TIMER_TYPE_HEARTBEAT, 6459 stcb->sctp_ep, stcb, net, 6460 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_18); 6461 sctp_timer_start(SCTP_TIMER_TYPE_HEARTBEAT, stcb->sctp_ep, stcb, net); 6462 } 6463 } 6464 if (net->dest_state & SCTP_ADDR_REACHABLE) { 6465 if (net->error_count > net->failure_threshold) { 6466 net->dest_state &= ~SCTP_ADDR_REACHABLE; 6467 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_DOWN, stcb, 0, net, SCTP_SO_LOCKED); 6468 } 6469 } else { 6470 if (net->error_count <= net->failure_threshold) { 6471 net->dest_state |= SCTP_ADDR_REACHABLE; 6472 sctp_ulp_notify(SCTP_NOTIFY_INTERFACE_UP, stcb, 0, net, SCTP_SO_LOCKED); 6473 } 6474 } 6475 } 6476 stcb->asoc.def_net_failure = thlds->spt_pathmaxrxt; 6477 stcb->asoc.def_net_pf_threshold = thlds->spt_pathpfthld; 6478 } 6479 SCTP_TCB_UNLOCK(stcb); 6480 } else { 6481 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6482 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6483 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6484 (thlds->spt_assoc_id == SCTP_FUTURE_ASSOC))) { 6485 SCTP_INP_WLOCK(inp); 6486 inp->sctp_ep.def_net_failure = thlds->spt_pathmaxrxt; 6487 inp->sctp_ep.def_net_pf_threshold = thlds->spt_pathpfthld; 6488 SCTP_INP_WUNLOCK(inp); 6489 } else { 6490 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6491 error = EINVAL; 6492 } 6493 } 6494 break; 6495 } 6496 case SCTP_REMOTE_UDP_ENCAPS_PORT: 6497 { 6498 struct sctp_udpencaps *encaps; 6499 struct sctp_nets *net; 6500 struct sockaddr *addr; 6501 #if defined(INET) && defined(INET6) 6502 struct sockaddr_in sin_store; 6503 #endif 6504 6505 SCTP_CHECK_AND_CAST(encaps, optval, struct sctp_udpencaps, optsize); 6506 SCTP_FIND_STCB(inp, stcb, encaps->sue_assoc_id); 6507 6508 #if defined(INET) && defined(INET6) 6509 if (encaps->sue_address.ss_family == AF_INET6) { 6510 struct sockaddr_in6 *sin6; 6511 6512 sin6 = (struct sockaddr_in6 *)&encaps->sue_address; 6513 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) { 6514 in6_sin6_2_sin(&sin_store, sin6); 6515 addr = (struct sockaddr *)&sin_store; 6516 } else { 6517 addr = (struct sockaddr *)&encaps->sue_address; 6518 } 6519 } else { 6520 addr = (struct sockaddr *)&encaps->sue_address; 6521 } 6522 #else 6523 addr = (struct sockaddr *)&encaps->sue_address; 6524 #endif 6525 if (stcb != NULL) { 6526 net = sctp_findnet(stcb, addr); 6527 } else { 6528 /* 6529 * We increment here since 6530 * sctp_findassociation_ep_addr() wil do a 6531 * decrement if it finds the stcb as long as 6532 * the locked tcb (last argument) is NOT a 6533 * TCB.. aka NULL. 6534 */ 6535 net = NULL; 6536 SCTP_INP_INCR_REF(inp); 6537 stcb = sctp_findassociation_ep_addr(&inp, addr, &net, NULL, NULL); 6538 if (stcb == NULL) { 6539 SCTP_INP_DECR_REF(inp); 6540 } 6541 } 6542 if ((stcb != NULL) && (net == NULL)) { 6543 #ifdef INET 6544 if (addr->sa_family == AF_INET) { 6545 struct sockaddr_in *sin; 6546 6547 sin = (struct sockaddr_in *)addr; 6548 if (sin->sin_addr.s_addr != INADDR_ANY) { 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 #ifdef INET6 6557 if (addr->sa_family == AF_INET6) { 6558 struct sockaddr_in6 *sin6; 6559 6560 sin6 = (struct sockaddr_in6 *)addr; 6561 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 6562 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6563 SCTP_TCB_UNLOCK(stcb); 6564 error = EINVAL; 6565 break; 6566 } 6567 } else 6568 #endif 6569 { 6570 error = EAFNOSUPPORT; 6571 SCTP_TCB_UNLOCK(stcb); 6572 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 6573 break; 6574 } 6575 } 6576 6577 if (stcb != NULL) { 6578 if (net != NULL) { 6579 net->port = encaps->sue_port; 6580 } else { 6581 stcb->asoc.port = encaps->sue_port; 6582 } 6583 SCTP_TCB_UNLOCK(stcb); 6584 } else { 6585 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6586 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6587 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6588 (encaps->sue_assoc_id == SCTP_FUTURE_ASSOC))) { 6589 SCTP_INP_WLOCK(inp); 6590 inp->sctp_ep.port = encaps->sue_port; 6591 SCTP_INP_WUNLOCK(inp); 6592 } else { 6593 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6594 error = EINVAL; 6595 } 6596 } 6597 break; 6598 } 6599 case SCTP_ECN_SUPPORTED: 6600 { 6601 struct sctp_assoc_value *av; 6602 6603 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6604 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6605 6606 if (stcb) { 6607 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6608 error = EINVAL; 6609 SCTP_TCB_UNLOCK(stcb); 6610 } else { 6611 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6612 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6613 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6614 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6615 SCTP_INP_WLOCK(inp); 6616 if (av->assoc_value == 0) { 6617 inp->ecn_supported = 0; 6618 } else { 6619 inp->ecn_supported = 1; 6620 } 6621 SCTP_INP_WUNLOCK(inp); 6622 } else { 6623 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6624 error = EINVAL; 6625 } 6626 } 6627 break; 6628 } 6629 case SCTP_PR_SUPPORTED: 6630 { 6631 struct sctp_assoc_value *av; 6632 6633 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6634 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6635 6636 if (stcb) { 6637 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6638 error = EINVAL; 6639 SCTP_TCB_UNLOCK(stcb); 6640 } else { 6641 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6642 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6643 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6644 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6645 SCTP_INP_WLOCK(inp); 6646 if (av->assoc_value == 0) { 6647 inp->prsctp_supported = 0; 6648 } else { 6649 inp->prsctp_supported = 1; 6650 } 6651 SCTP_INP_WUNLOCK(inp); 6652 } else { 6653 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6654 error = EINVAL; 6655 } 6656 } 6657 break; 6658 } 6659 case SCTP_AUTH_SUPPORTED: 6660 { 6661 struct sctp_assoc_value *av; 6662 6663 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6664 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6665 6666 if (stcb) { 6667 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6668 error = EINVAL; 6669 SCTP_TCB_UNLOCK(stcb); 6670 } else { 6671 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6672 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6673 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6674 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6675 if ((av->assoc_value == 0) && 6676 (inp->asconf_supported == 1)) { 6677 /* 6678 * AUTH is required for 6679 * ASCONF 6680 */ 6681 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6682 error = EINVAL; 6683 } else { 6684 SCTP_INP_WLOCK(inp); 6685 if (av->assoc_value == 0) { 6686 inp->auth_supported = 0; 6687 } else { 6688 inp->auth_supported = 1; 6689 } 6690 SCTP_INP_WUNLOCK(inp); 6691 } 6692 } else { 6693 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6694 error = EINVAL; 6695 } 6696 } 6697 break; 6698 } 6699 case SCTP_ASCONF_SUPPORTED: 6700 { 6701 struct sctp_assoc_value *av; 6702 6703 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6704 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6705 6706 if (stcb) { 6707 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6708 error = EINVAL; 6709 SCTP_TCB_UNLOCK(stcb); 6710 } else { 6711 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6712 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6713 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6714 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6715 if ((av->assoc_value != 0) && 6716 (inp->auth_supported == 0)) { 6717 /* 6718 * AUTH is required for 6719 * ASCONF 6720 */ 6721 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6722 error = EINVAL; 6723 } else { 6724 SCTP_INP_WLOCK(inp); 6725 if (av->assoc_value == 0) { 6726 inp->asconf_supported = 0; 6727 sctp_auth_delete_chunk(SCTP_ASCONF, 6728 inp->sctp_ep.local_auth_chunks); 6729 sctp_auth_delete_chunk(SCTP_ASCONF_ACK, 6730 inp->sctp_ep.local_auth_chunks); 6731 } else { 6732 inp->asconf_supported = 1; 6733 sctp_auth_add_chunk(SCTP_ASCONF, 6734 inp->sctp_ep.local_auth_chunks); 6735 sctp_auth_add_chunk(SCTP_ASCONF_ACK, 6736 inp->sctp_ep.local_auth_chunks); 6737 } 6738 SCTP_INP_WUNLOCK(inp); 6739 } 6740 } else { 6741 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6742 error = EINVAL; 6743 } 6744 } 6745 break; 6746 } 6747 case SCTP_RECONFIG_SUPPORTED: 6748 { 6749 struct sctp_assoc_value *av; 6750 6751 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6752 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6753 6754 if (stcb) { 6755 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6756 error = EINVAL; 6757 SCTP_TCB_UNLOCK(stcb); 6758 } else { 6759 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6760 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6761 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6762 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6763 SCTP_INP_WLOCK(inp); 6764 if (av->assoc_value == 0) { 6765 inp->reconfig_supported = 0; 6766 } else { 6767 inp->reconfig_supported = 1; 6768 } 6769 SCTP_INP_WUNLOCK(inp); 6770 } else { 6771 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6772 error = EINVAL; 6773 } 6774 } 6775 break; 6776 } 6777 case SCTP_NRSACK_SUPPORTED: 6778 { 6779 struct sctp_assoc_value *av; 6780 6781 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6782 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6783 6784 if (stcb) { 6785 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6786 error = EINVAL; 6787 SCTP_TCB_UNLOCK(stcb); 6788 } else { 6789 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6790 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6791 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6792 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6793 SCTP_INP_WLOCK(inp); 6794 if (av->assoc_value == 0) { 6795 inp->nrsack_supported = 0; 6796 } else { 6797 inp->nrsack_supported = 1; 6798 } 6799 SCTP_INP_WUNLOCK(inp); 6800 } else { 6801 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6802 error = EINVAL; 6803 } 6804 } 6805 break; 6806 } 6807 case SCTP_PKTDROP_SUPPORTED: 6808 { 6809 struct sctp_assoc_value *av; 6810 6811 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6812 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6813 6814 if (stcb) { 6815 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6816 error = EINVAL; 6817 SCTP_TCB_UNLOCK(stcb); 6818 } else { 6819 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6820 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6821 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6822 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6823 SCTP_INP_WLOCK(inp); 6824 if (av->assoc_value == 0) { 6825 inp->pktdrop_supported = 0; 6826 } else { 6827 inp->pktdrop_supported = 1; 6828 } 6829 SCTP_INP_WUNLOCK(inp); 6830 } else { 6831 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6832 error = EINVAL; 6833 } 6834 } 6835 break; 6836 } 6837 case SCTP_MAX_CWND: 6838 { 6839 struct sctp_assoc_value *av; 6840 struct sctp_nets *net; 6841 6842 SCTP_CHECK_AND_CAST(av, optval, struct sctp_assoc_value, optsize); 6843 SCTP_FIND_STCB(inp, stcb, av->assoc_id); 6844 6845 if (stcb) { 6846 stcb->asoc.max_cwnd = av->assoc_value; 6847 if (stcb->asoc.max_cwnd > 0) { 6848 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 6849 if ((net->cwnd > stcb->asoc.max_cwnd) && 6850 (net->cwnd > (net->mtu - sizeof(struct sctphdr)))) { 6851 net->cwnd = stcb->asoc.max_cwnd; 6852 if (net->cwnd < (net->mtu - sizeof(struct sctphdr))) { 6853 net->cwnd = net->mtu - sizeof(struct sctphdr); 6854 } 6855 } 6856 } 6857 } 6858 SCTP_TCB_UNLOCK(stcb); 6859 } else { 6860 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) || 6861 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) || 6862 ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) && 6863 (av->assoc_id == SCTP_FUTURE_ASSOC))) { 6864 SCTP_INP_WLOCK(inp); 6865 inp->max_cwnd = av->assoc_value; 6866 SCTP_INP_WUNLOCK(inp); 6867 } else { 6868 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6869 error = EINVAL; 6870 } 6871 } 6872 break; 6873 } 6874 default: 6875 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOPROTOOPT); 6876 error = ENOPROTOOPT; 6877 break; 6878 } /* end switch (opt) */ 6879 return (error); 6880 } 6881 6882 int 6883 sctp_ctloutput(struct socket *so, struct sockopt *sopt) 6884 { 6885 struct epoch_tracker et; 6886 struct sctp_inpcb *inp; 6887 void *optval = NULL; 6888 void *p; 6889 size_t optsize = 0; 6890 int error = 0; 6891 6892 if ((sopt->sopt_level == SOL_SOCKET) && 6893 (sopt->sopt_name == SO_SETFIB)) { 6894 inp = (struct sctp_inpcb *)so->so_pcb; 6895 if (inp == NULL) { 6896 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS); 6897 return (EINVAL); 6898 } 6899 SCTP_INP_WLOCK(inp); 6900 inp->fibnum = so->so_fibnum; 6901 SCTP_INP_WUNLOCK(inp); 6902 return (0); 6903 } 6904 if (sopt->sopt_level != IPPROTO_SCTP) { 6905 /* wrong proto level... send back up to IP */ 6906 #ifdef INET6 6907 if (INP_CHECK_SOCKAF(so, AF_INET6)) 6908 error = ip6_ctloutput(so, sopt); 6909 #endif /* INET6 */ 6910 #if defined(INET) && defined(INET6) 6911 else 6912 #endif 6913 #ifdef INET 6914 error = ip_ctloutput(so, sopt); 6915 #endif 6916 return (error); 6917 } 6918 optsize = sopt->sopt_valsize; 6919 if (optsize > SCTP_SOCKET_OPTION_LIMIT) { 6920 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS); 6921 return (ENOBUFS); 6922 } 6923 if (optsize) { 6924 SCTP_MALLOC(optval, void *, optsize, SCTP_M_SOCKOPT); 6925 if (optval == NULL) { 6926 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOBUFS); 6927 return (ENOBUFS); 6928 } 6929 error = sooptcopyin(sopt, optval, optsize, optsize); 6930 if (error) { 6931 SCTP_FREE(optval, SCTP_M_SOCKOPT); 6932 goto out; 6933 } 6934 } 6935 p = (void *)sopt->sopt_td; 6936 if (sopt->sopt_dir == SOPT_SET) { 6937 NET_EPOCH_ENTER(et); 6938 error = sctp_setopt(so, sopt->sopt_name, optval, optsize, p); 6939 NET_EPOCH_EXIT(et); 6940 } else if (sopt->sopt_dir == SOPT_GET) { 6941 error = sctp_getopt(so, sopt->sopt_name, optval, &optsize, p); 6942 } else { 6943 SCTP_LTRACE_ERR_RET(so->so_pcb, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6944 error = EINVAL; 6945 } 6946 if ((error == 0) && (optval != NULL)) { 6947 error = sooptcopyout(sopt, optval, optsize); 6948 SCTP_FREE(optval, SCTP_M_SOCKOPT); 6949 } else if (optval != NULL) { 6950 SCTP_FREE(optval, SCTP_M_SOCKOPT); 6951 } 6952 out: 6953 return (error); 6954 } 6955 6956 #ifdef INET 6957 static int 6958 sctp_connect(struct socket *so, struct sockaddr *addr, struct thread *p) 6959 { 6960 struct epoch_tracker et; 6961 int error = 0; 6962 int create_lock_on = 0; 6963 uint32_t vrf_id; 6964 struct sctp_inpcb *inp; 6965 struct sctp_tcb *stcb = NULL; 6966 6967 inp = (struct sctp_inpcb *)so->so_pcb; 6968 if (inp == NULL) { 6969 /* I made the same as TCP since we are not setup? */ 6970 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6971 return (ECONNRESET); 6972 } 6973 if (addr == NULL) { 6974 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6975 return EINVAL; 6976 } 6977 6978 switch (addr->sa_family) { 6979 #ifdef INET6 6980 case AF_INET6: 6981 { 6982 struct sockaddr_in6 *sin6; 6983 6984 if (addr->sa_len != sizeof(struct sockaddr_in6)) { 6985 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 6986 return (EINVAL); 6987 } 6988 sin6 = (struct sockaddr_in6 *)addr; 6989 if (p != NULL && (error = prison_remote_ip6(p->td_ucred, &sin6->sin6_addr)) != 0) { 6990 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 6991 return (error); 6992 } 6993 break; 6994 } 6995 #endif 6996 #ifdef INET 6997 case AF_INET: 6998 { 6999 struct sockaddr_in *sin; 7000 7001 if (addr->sa_len != sizeof(struct sockaddr_in)) { 7002 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7003 return (EINVAL); 7004 } 7005 sin = (struct sockaddr_in *)addr; 7006 if (p != NULL && (error = prison_remote_ip4(p->td_ucred, &sin->sin_addr)) != 0) { 7007 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, error); 7008 return (error); 7009 } 7010 break; 7011 } 7012 #endif 7013 default: 7014 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EAFNOSUPPORT); 7015 return (EAFNOSUPPORT); 7016 } 7017 SCTP_INP_INCR_REF(inp); 7018 SCTP_ASOC_CREATE_LOCK(inp); 7019 create_lock_on = 1; 7020 NET_EPOCH_ENTER(et); 7021 7022 if ((inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) || 7023 (inp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE)) { 7024 /* Should I really unlock ? */ 7025 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EFAULT); 7026 error = EFAULT; 7027 goto out_now; 7028 } 7029 #ifdef INET6 7030 if (((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) && 7031 (addr->sa_family == AF_INET6)) { 7032 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7033 error = EINVAL; 7034 goto out_now; 7035 } 7036 #endif 7037 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) == 7038 SCTP_PCB_FLAGS_UNBOUND) { 7039 /* Bind a ephemeral port */ 7040 error = sctp_inpcb_bind(so, NULL, NULL, p); 7041 if (error) { 7042 goto out_now; 7043 } 7044 } 7045 /* Now do we connect? */ 7046 if ((inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL) && 7047 (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_PORTREUSE))) { 7048 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7049 error = EINVAL; 7050 goto out_now; 7051 } 7052 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 7053 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) { 7054 /* We are already connected AND the TCP model */ 7055 SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE); 7056 error = EADDRINUSE; 7057 goto out_now; 7058 } 7059 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { 7060 SCTP_INP_RLOCK(inp); 7061 stcb = LIST_FIRST(&inp->sctp_asoc_list); 7062 SCTP_INP_RUNLOCK(inp); 7063 } else { 7064 /* 7065 * We increment here since sctp_findassociation_ep_addr() 7066 * will do a decrement if it finds the stcb as long as the 7067 * locked tcb (last argument) is NOT a TCB.. aka NULL. 7068 */ 7069 SCTP_INP_INCR_REF(inp); 7070 stcb = sctp_findassociation_ep_addr(&inp, addr, NULL, NULL, NULL); 7071 if (stcb == NULL) { 7072 SCTP_INP_DECR_REF(inp); 7073 } else { 7074 SCTP_TCB_UNLOCK(stcb); 7075 } 7076 } 7077 if (stcb != NULL) { 7078 /* Already have or am bring up an association */ 7079 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EALREADY); 7080 error = EALREADY; 7081 goto out_now; 7082 } 7083 7084 vrf_id = inp->def_vrf_id; 7085 /* We are GOOD to go */ 7086 stcb = sctp_aloc_assoc(inp, addr, &error, 0, vrf_id, 7087 inp->sctp_ep.pre_open_stream_count, 7088 inp->sctp_ep.port, p, 7089 SCTP_INITIALIZE_AUTH_PARAMS); 7090 if (stcb == NULL) { 7091 /* Gak! no memory */ 7092 goto out_now; 7093 } 7094 if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) { 7095 stcb->sctp_ep->sctp_flags |= SCTP_PCB_FLAGS_CONNECTED; 7096 /* Set the connected flag so we can queue data */ 7097 soisconnecting(so); 7098 } 7099 SCTP_SET_STATE(stcb, SCTP_STATE_COOKIE_WAIT); 7100 (void)SCTP_GETTIME_TIMEVAL(&stcb->asoc.time_entered); 7101 7102 sctp_send_initiate(inp, stcb, SCTP_SO_LOCKED); 7103 SCTP_TCB_UNLOCK(stcb); 7104 out_now: 7105 NET_EPOCH_EXIT(et); 7106 if (create_lock_on) { 7107 SCTP_ASOC_CREATE_UNLOCK(inp); 7108 } 7109 SCTP_INP_DECR_REF(inp); 7110 return (error); 7111 } 7112 #endif 7113 7114 int 7115 sctp_listen(struct socket *so, int backlog, struct thread *p) 7116 { 7117 /* 7118 * Note this module depends on the protocol processing being called 7119 * AFTER any socket level flags and backlog are applied to the 7120 * socket. The traditional way that the socket flags are applied is 7121 * AFTER protocol processing. We have made a change to the 7122 * sys/kern/uipc_socket.c module to reverse this but this MUST be in 7123 * place if the socket API for SCTP is to work properly. 7124 */ 7125 7126 int error = 0; 7127 struct sctp_inpcb *inp; 7128 7129 inp = (struct sctp_inpcb *)so->so_pcb; 7130 if (inp == NULL) { 7131 /* I made the same as TCP since we are not setup? */ 7132 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7133 return (ECONNRESET); 7134 } 7135 if (sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) { 7136 /* See if we have a listener */ 7137 struct sctp_inpcb *tinp; 7138 union sctp_sockstore store; 7139 7140 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) == 0) { 7141 /* not bound all */ 7142 struct sctp_laddr *laddr; 7143 7144 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 7145 memcpy(&store, &laddr->ifa->address, sizeof(store)); 7146 switch (store.sa.sa_family) { 7147 #ifdef INET 7148 case AF_INET: 7149 store.sin.sin_port = inp->sctp_lport; 7150 break; 7151 #endif 7152 #ifdef INET6 7153 case AF_INET6: 7154 store.sin6.sin6_port = inp->sctp_lport; 7155 break; 7156 #endif 7157 default: 7158 break; 7159 } 7160 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id); 7161 if (tinp && (tinp != inp) && 7162 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && 7163 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && 7164 (SCTP_IS_LISTENING(tinp))) { 7165 /* 7166 * we have a listener already and 7167 * its not this inp. 7168 */ 7169 SCTP_INP_DECR_REF(tinp); 7170 return (EADDRINUSE); 7171 } else if (tinp) { 7172 SCTP_INP_DECR_REF(tinp); 7173 } 7174 } 7175 } else { 7176 /* Setup a local addr bound all */ 7177 memset(&store, 0, sizeof(store)); 7178 #ifdef INET6 7179 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) { 7180 store.sa.sa_family = AF_INET6; 7181 store.sa.sa_len = sizeof(struct sockaddr_in6); 7182 } 7183 #endif 7184 #ifdef INET 7185 if ((inp->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) == 0) { 7186 store.sa.sa_family = AF_INET; 7187 store.sa.sa_len = sizeof(struct sockaddr_in); 7188 } 7189 #endif 7190 switch (store.sa.sa_family) { 7191 #ifdef INET 7192 case AF_INET: 7193 store.sin.sin_port = inp->sctp_lport; 7194 break; 7195 #endif 7196 #ifdef INET6 7197 case AF_INET6: 7198 store.sin6.sin6_port = inp->sctp_lport; 7199 break; 7200 #endif 7201 default: 7202 break; 7203 } 7204 tinp = sctp_pcb_findep(&store.sa, 0, 0, inp->def_vrf_id); 7205 if (tinp && (tinp != inp) && 7206 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_ALLGONE) == 0) && 7207 ((tinp->sctp_flags & SCTP_PCB_FLAGS_SOCKET_GONE) == 0) && 7208 (SCTP_IS_LISTENING(tinp))) { 7209 /* 7210 * we have a listener already and its not 7211 * this inp. 7212 */ 7213 SCTP_INP_DECR_REF(tinp); 7214 return (EADDRINUSE); 7215 } else if (tinp) { 7216 SCTP_INP_DECR_REF(tinp); 7217 } 7218 } 7219 } 7220 SCTP_INP_RLOCK(inp); 7221 #ifdef SCTP_LOCK_LOGGING 7222 if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LOCK_LOGGING_ENABLE) { 7223 sctp_log_lock(inp, (struct sctp_tcb *)NULL, SCTP_LOG_LOCK_SOCK); 7224 } 7225 #endif 7226 SOCK_LOCK(so); 7227 error = solisten_proto_check(so); 7228 SOCK_UNLOCK(so); 7229 if (error) { 7230 SCTP_INP_RUNLOCK(inp); 7231 return (error); 7232 } 7233 if ((sctp_is_feature_on(inp, SCTP_PCB_FLAGS_PORTREUSE)) && 7234 (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) { 7235 /* 7236 * The unlucky case - We are in the tcp pool with this guy. 7237 * - Someone else is in the main inp slot. - We must move 7238 * this guy (the listener) to the main slot - We must then 7239 * move the guy that was listener to the TCP Pool. 7240 */ 7241 if (sctp_swap_inpcb_for_listen(inp)) { 7242 SCTP_INP_RUNLOCK(inp); 7243 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE); 7244 return (EADDRINUSE); 7245 } 7246 } 7247 7248 if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) && 7249 (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED)) { 7250 /* We are already connected AND the TCP model */ 7251 SCTP_INP_RUNLOCK(inp); 7252 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EADDRINUSE); 7253 return (EADDRINUSE); 7254 } 7255 SCTP_INP_RUNLOCK(inp); 7256 if (inp->sctp_flags & SCTP_PCB_FLAGS_UNBOUND) { 7257 /* We must do a bind. */ 7258 if ((error = sctp_inpcb_bind(so, NULL, NULL, p))) { 7259 /* bind error, probably perm */ 7260 return (error); 7261 } 7262 } 7263 SCTP_INP_WLOCK(inp); 7264 if ((inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) == 0) { 7265 SOCK_LOCK(so); 7266 solisten_proto(so, backlog); 7267 SOCK_UNLOCK(so); 7268 } 7269 if (backlog > 0) { 7270 inp->sctp_flags |= SCTP_PCB_FLAGS_ACCEPTING; 7271 } else { 7272 inp->sctp_flags &= ~SCTP_PCB_FLAGS_ACCEPTING; 7273 } 7274 SCTP_INP_WUNLOCK(inp); 7275 return (error); 7276 } 7277 7278 static int sctp_defered_wakeup_cnt = 0; 7279 7280 int 7281 sctp_accept(struct socket *so, struct sockaddr **addr) 7282 { 7283 struct sctp_tcb *stcb; 7284 struct sctp_inpcb *inp; 7285 union sctp_sockstore store; 7286 #ifdef INET6 7287 int error; 7288 #endif 7289 inp = (struct sctp_inpcb *)so->so_pcb; 7290 7291 if (inp == NULL) { 7292 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7293 return (ECONNRESET); 7294 } 7295 SCTP_INP_WLOCK(inp); 7296 if (inp->sctp_flags & SCTP_PCB_FLAGS_UDPTYPE) { 7297 SCTP_INP_WUNLOCK(inp); 7298 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EOPNOTSUPP); 7299 return (EOPNOTSUPP); 7300 } 7301 if (so->so_state & SS_ISDISCONNECTED) { 7302 SCTP_INP_WUNLOCK(inp); 7303 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ECONNABORTED); 7304 return (ECONNABORTED); 7305 } 7306 stcb = LIST_FIRST(&inp->sctp_asoc_list); 7307 if (stcb == NULL) { 7308 SCTP_INP_WUNLOCK(inp); 7309 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7310 return (ECONNRESET); 7311 } 7312 SCTP_TCB_LOCK(stcb); 7313 store = stcb->asoc.primary_destination->ro._l_addr; 7314 SCTP_CLEAR_SUBSTATE(stcb, SCTP_STATE_IN_ACCEPT_QUEUE); 7315 /* Wake any delayed sleep action */ 7316 if (inp->sctp_flags & SCTP_PCB_FLAGS_DONT_WAKE) { 7317 inp->sctp_flags &= ~SCTP_PCB_FLAGS_DONT_WAKE; 7318 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEOUTPUT) { 7319 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEOUTPUT; 7320 SOCKBUF_LOCK(&inp->sctp_socket->so_snd); 7321 if (sowriteable(inp->sctp_socket)) { 7322 sowwakeup_locked(inp->sctp_socket); 7323 } else { 7324 SOCKBUF_UNLOCK(&inp->sctp_socket->so_snd); 7325 } 7326 } 7327 if (inp->sctp_flags & SCTP_PCB_FLAGS_WAKEINPUT) { 7328 inp->sctp_flags &= ~SCTP_PCB_FLAGS_WAKEINPUT; 7329 SOCKBUF_LOCK(&inp->sctp_socket->so_rcv); 7330 if (soreadable(inp->sctp_socket)) { 7331 sctp_defered_wakeup_cnt++; 7332 sorwakeup_locked(inp->sctp_socket); 7333 } else { 7334 SOCKBUF_UNLOCK(&inp->sctp_socket->so_rcv); 7335 } 7336 } 7337 } 7338 SCTP_INP_WUNLOCK(inp); 7339 if (stcb->asoc.state & SCTP_STATE_ABOUT_TO_BE_FREED) { 7340 sctp_free_assoc(inp, stcb, SCTP_NORMAL_PROC, 7341 SCTP_FROM_SCTP_USRREQ + SCTP_LOC_19); 7342 } else { 7343 SCTP_TCB_UNLOCK(stcb); 7344 } 7345 switch (store.sa.sa_family) { 7346 #ifdef INET 7347 case AF_INET: 7348 { 7349 struct sockaddr_in *sin; 7350 7351 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); 7352 if (sin == NULL) 7353 return (ENOMEM); 7354 sin->sin_family = AF_INET; 7355 sin->sin_len = sizeof(*sin); 7356 sin->sin_port = store.sin.sin_port; 7357 sin->sin_addr = store.sin.sin_addr; 7358 *addr = (struct sockaddr *)sin; 7359 break; 7360 } 7361 #endif 7362 #ifdef INET6 7363 case AF_INET6: 7364 { 7365 struct sockaddr_in6 *sin6; 7366 7367 SCTP_MALLOC_SONAME(sin6, struct sockaddr_in6 *, sizeof *sin6); 7368 if (sin6 == NULL) 7369 return (ENOMEM); 7370 sin6->sin6_family = AF_INET6; 7371 sin6->sin6_len = sizeof(*sin6); 7372 sin6->sin6_port = store.sin6.sin6_port; 7373 sin6->sin6_addr = store.sin6.sin6_addr; 7374 if ((error = sa6_recoverscope(sin6)) != 0) { 7375 SCTP_FREE_SONAME(sin6); 7376 return (error); 7377 } 7378 *addr = (struct sockaddr *)sin6; 7379 break; 7380 } 7381 #endif 7382 default: 7383 /* TSNH */ 7384 break; 7385 } 7386 return (0); 7387 } 7388 7389 #ifdef INET 7390 int 7391 sctp_ingetaddr(struct socket *so, struct sockaddr **addr) 7392 { 7393 struct sockaddr_in *sin; 7394 uint32_t vrf_id; 7395 struct sctp_inpcb *inp; 7396 struct sctp_ifa *sctp_ifa; 7397 7398 /* 7399 * Do the malloc first in case it blocks. 7400 */ 7401 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); 7402 if (sin == NULL) 7403 return (ENOMEM); 7404 sin->sin_family = AF_INET; 7405 sin->sin_len = sizeof(*sin); 7406 inp = (struct sctp_inpcb *)so->so_pcb; 7407 if (!inp) { 7408 SCTP_FREE_SONAME(sin); 7409 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7410 return (ECONNRESET); 7411 } 7412 SCTP_INP_RLOCK(inp); 7413 sin->sin_port = inp->sctp_lport; 7414 if (inp->sctp_flags & SCTP_PCB_FLAGS_BOUNDALL) { 7415 if (inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) { 7416 struct sctp_tcb *stcb; 7417 struct sockaddr_in *sin_a; 7418 struct sctp_nets *net; 7419 int fnd; 7420 7421 stcb = LIST_FIRST(&inp->sctp_asoc_list); 7422 if (stcb == NULL) { 7423 goto notConn; 7424 } 7425 fnd = 0; 7426 sin_a = NULL; 7427 SCTP_TCB_LOCK(stcb); 7428 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 7429 sin_a = (struct sockaddr_in *)&net->ro._l_addr; 7430 if (sin_a == NULL) 7431 /* this will make coverity happy */ 7432 continue; 7433 7434 if (sin_a->sin_family == AF_INET) { 7435 fnd = 1; 7436 break; 7437 } 7438 } 7439 if ((!fnd) || (sin_a == NULL)) { 7440 /* punt */ 7441 SCTP_TCB_UNLOCK(stcb); 7442 goto notConn; 7443 } 7444 7445 vrf_id = inp->def_vrf_id; 7446 sctp_ifa = sctp_source_address_selection(inp, 7447 stcb, 7448 (sctp_route_t *)&net->ro, 7449 net, 0, vrf_id); 7450 if (sctp_ifa) { 7451 sin->sin_addr = sctp_ifa->address.sin.sin_addr; 7452 sctp_free_ifa(sctp_ifa); 7453 } 7454 SCTP_TCB_UNLOCK(stcb); 7455 } else { 7456 /* For the bound all case you get back 0 */ 7457 notConn: 7458 sin->sin_addr.s_addr = 0; 7459 } 7460 7461 } else { 7462 /* Take the first IPv4 address in the list */ 7463 struct sctp_laddr *laddr; 7464 int fnd = 0; 7465 7466 LIST_FOREACH(laddr, &inp->sctp_addr_list, sctp_nxt_addr) { 7467 if (laddr->ifa->address.sa.sa_family == AF_INET) { 7468 struct sockaddr_in *sin_a; 7469 7470 sin_a = &laddr->ifa->address.sin; 7471 sin->sin_addr = sin_a->sin_addr; 7472 fnd = 1; 7473 break; 7474 } 7475 } 7476 if (!fnd) { 7477 SCTP_FREE_SONAME(sin); 7478 SCTP_INP_RUNLOCK(inp); 7479 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 7480 return (ENOENT); 7481 } 7482 } 7483 SCTP_INP_RUNLOCK(inp); 7484 (*addr) = (struct sockaddr *)sin; 7485 return (0); 7486 } 7487 7488 int 7489 sctp_peeraddr(struct socket *so, struct sockaddr **addr) 7490 { 7491 struct sockaddr_in *sin; 7492 int fnd; 7493 struct sockaddr_in *sin_a; 7494 struct sctp_inpcb *inp; 7495 struct sctp_tcb *stcb; 7496 struct sctp_nets *net; 7497 7498 /* Do the malloc first in case it blocks. */ 7499 SCTP_MALLOC_SONAME(sin, struct sockaddr_in *, sizeof *sin); 7500 if (sin == NULL) 7501 return (ENOMEM); 7502 sin->sin_family = AF_INET; 7503 sin->sin_len = sizeof(*sin); 7504 7505 inp = (struct sctp_inpcb *)so->so_pcb; 7506 if ((inp == NULL) || 7507 ((inp->sctp_flags & SCTP_PCB_FLAGS_CONNECTED) == 0)) { 7508 /* UDP type and listeners will drop out here */ 7509 SCTP_FREE_SONAME(sin); 7510 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOTCONN); 7511 return (ENOTCONN); 7512 } 7513 SCTP_INP_RLOCK(inp); 7514 stcb = LIST_FIRST(&inp->sctp_asoc_list); 7515 if (stcb) { 7516 SCTP_TCB_LOCK(stcb); 7517 } 7518 SCTP_INP_RUNLOCK(inp); 7519 if (stcb == NULL) { 7520 SCTP_FREE_SONAME(sin); 7521 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, EINVAL); 7522 return (ECONNRESET); 7523 } 7524 fnd = 0; 7525 TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) { 7526 sin_a = (struct sockaddr_in *)&net->ro._l_addr; 7527 if (sin_a->sin_family == AF_INET) { 7528 fnd = 1; 7529 sin->sin_port = stcb->rport; 7530 sin->sin_addr = sin_a->sin_addr; 7531 break; 7532 } 7533 } 7534 SCTP_TCB_UNLOCK(stcb); 7535 if (!fnd) { 7536 /* No IPv4 address */ 7537 SCTP_FREE_SONAME(sin); 7538 SCTP_LTRACE_ERR_RET(inp, NULL, NULL, SCTP_FROM_SCTP_USRREQ, ENOENT); 7539 return (ENOENT); 7540 } 7541 (*addr) = (struct sockaddr *)sin; 7542 return (0); 7543 } 7544 7545 struct pr_usrreqs sctp_usrreqs = { 7546 .pru_abort = sctp_abort, 7547 .pru_accept = sctp_accept, 7548 .pru_attach = sctp_attach, 7549 .pru_bind = sctp_bind, 7550 .pru_connect = sctp_connect, 7551 .pru_control = in_control, 7552 .pru_close = sctp_close, 7553 .pru_detach = sctp_close, 7554 .pru_sopoll = sopoll_generic, 7555 .pru_flush = sctp_flush, 7556 .pru_disconnect = sctp_disconnect, 7557 .pru_listen = sctp_listen, 7558 .pru_peeraddr = sctp_peeraddr, 7559 .pru_send = sctp_sendm, 7560 .pru_shutdown = sctp_shutdown, 7561 .pru_sockaddr = sctp_ingetaddr, 7562 .pru_sosend = sctp_sosend, 7563 .pru_soreceive = sctp_soreceive 7564 }; 7565 #endif 7566