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