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