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