tcp_usrreq.c revision 185344
155682Smarkm/*- 272445Sassar * Copyright (c) 1982, 1986, 1988, 1993 355682Smarkm * The Regents of the University of California. 455682Smarkm * Copyright (c) 2006-2007 Robert N. M. Watson 555682Smarkm * All rights reserved. 655682Smarkm * 755682Smarkm * Redistribution and use in source and binary forms, with or without 855682Smarkm * modification, are permitted provided that the following conditions 955682Smarkm * are met: 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1355682Smarkm * notice, this list of conditions and the following disclaimer in the 1455682Smarkm * documentation and/or other materials provided with the distribution. 1555682Smarkm * 4. Neither the name of the University nor the names of its contributors 1655682Smarkm * may be used to endorse or promote products derived from this software 1755682Smarkm * without specific prior written permission. 1855682Smarkm * 1955682Smarkm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2055682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2155682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2255682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2355682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2455682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2555682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2655682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2755682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2855682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2955682Smarkm * SUCH DAMAGE. 3055682Smarkm * 3155682Smarkm * From: @(#)tcp_usrreq.c 8.2 (Berkeley) 1/3/94 3255682Smarkm */ 3355682Smarkm 3490926Snectar#include <sys/cdefs.h> 3555682Smarkm__FBSDID("$FreeBSD: head/sys/netinet/tcp_usrreq.c 185344 2008-11-26 20:52:26Z bz $"); 3655682Smarkm 3755682Smarkm#include "opt_ddb.h" 3855682Smarkm#include "opt_inet.h" 3972445Sassar#include "opt_inet6.h" 4072445Sassar#include "opt_tcpdebug.h" 4172445Sassar 4272445Sassar#include <sys/param.h> 4372445Sassar#include <sys/systm.h> 4472445Sassar#include <sys/malloc.h> 4572445Sassar#include <sys/kernel.h> 4672445Sassar#include <sys/sysctl.h> 4755682Smarkm#include <sys/mbuf.h> 4855682Smarkm#ifdef INET6 4955682Smarkm#include <sys/domain.h> 5055682Smarkm#endif /* INET6 */ 5155682Smarkm#include <sys/socket.h> 5255682Smarkm#include <sys/socketvar.h> 5355682Smarkm#include <sys/protosw.h> 5455682Smarkm#include <sys/proc.h> 5555682Smarkm#include <sys/jail.h> 5655682Smarkm#include <sys/vimage.h> 5755682Smarkm 5855682Smarkm#ifdef DDB 5955682Smarkm#include <ddb/ddb.h> 6055682Smarkm#endif 6155682Smarkm 6255682Smarkm#include <net/if.h> 6355682Smarkm#include <net/route.h> 6455682Smarkm 6555682Smarkm#include <netinet/in.h> 6655682Smarkm#include <netinet/in_systm.h> 6755682Smarkm#ifdef INET6 6855682Smarkm#include <netinet/ip6.h> 6955682Smarkm#endif 7055682Smarkm#include <netinet/in_pcb.h> 7155682Smarkm#ifdef INET6 7255682Smarkm#include <netinet6/in6_pcb.h> 7355682Smarkm#endif 7455682Smarkm#include <netinet/in_var.h> 7555682Smarkm#include <netinet/ip_var.h> 7655682Smarkm#ifdef INET6 7755682Smarkm#include <netinet6/ip6_var.h> 7855682Smarkm#include <netinet6/scope6_var.h> 7955682Smarkm#endif 8055682Smarkm#include <netinet/tcp.h> 8155682Smarkm#include <netinet/tcp_fsm.h> 8255682Smarkm#include <netinet/tcp_seq.h> 8355682Smarkm#include <netinet/tcp_timer.h> 8455682Smarkm#include <netinet/tcp_var.h> 8555682Smarkm#include <netinet/tcpip.h> 8655682Smarkm#ifdef TCPDEBUG 8755682Smarkm#include <netinet/tcp_debug.h> 8855682Smarkm#endif 8955682Smarkm#include <netinet/tcp_offload.h> 9055682Smarkm 9155682Smarkm/* 9255682Smarkm * TCP protocol interface to socket abstraction. 9355682Smarkm */ 9455682Smarkmstatic int tcp_attach(struct socket *); 9555682Smarkmstatic int tcp_connect(struct tcpcb *, struct sockaddr *, 9655682Smarkm struct thread *td); 9755682Smarkm#ifdef INET6 9855682Smarkmstatic int tcp6_connect(struct tcpcb *, struct sockaddr *, 9955682Smarkm struct thread *td); 10055682Smarkm#endif /* INET6 */ 10155682Smarkmstatic void tcp_disconnect(struct tcpcb *); 10255682Smarkmstatic void tcp_usrclosed(struct tcpcb *); 10355682Smarkmstatic void tcp_fill_info(struct tcpcb *, struct tcp_info *); 10455682Smarkm 10555682Smarkm#ifdef TCPDEBUG 10655682Smarkm#define TCPDEBUG0 int ostate = 0 10755682Smarkm#define TCPDEBUG1() ostate = tp ? tp->t_state : 0 10855682Smarkm#define TCPDEBUG2(req) if (tp && (so->so_options & SO_DEBUG)) \ 10955682Smarkm tcp_trace(TA_USER, ostate, tp, 0, 0, req) 11055682Smarkm#else 11155682Smarkm#define TCPDEBUG0 11255682Smarkm#define TCPDEBUG1() 11355682Smarkm#define TCPDEBUG2(req) 11455682Smarkm#endif 11557416Smarkm 11657416Smarkm/* 11757416Smarkm * TCP attaches to socket via pru_attach(), reserving space, 11857416Smarkm * and an internet control block. 11955682Smarkm */ 12055682Smarkmstatic int 12155682Smarkmtcp_usr_attach(struct socket *so, int proto, struct thread *td) 12255682Smarkm{ 12355682Smarkm struct inpcb *inp; 12455682Smarkm struct tcpcb *tp = NULL; 12555682Smarkm int error; 12655682Smarkm TCPDEBUG0; 12772445Sassar 12872445Sassar inp = sotoinpcb(so); 12972445Sassar KASSERT(inp == NULL, ("tcp_usr_attach: inp != NULL")); 13072445Sassar TCPDEBUG1(); 13172445Sassar 13272445Sassar error = tcp_attach(so); 13372445Sassar if (error) 13472445Sassar goto out; 13555682Smarkm 13655682Smarkm if ((so->so_options & SO_LINGER) && so->so_linger == 0) 13755682Smarkm so->so_linger = TCP_LINGERTIME; 13855682Smarkm 13955682Smarkm inp = sotoinpcb(so); 14072445Sassar tp = intotcpcb(inp); 14155682Smarkmout: 14255682Smarkm TCPDEBUG2(PRU_ATTACH); 14355682Smarkm return error; 14455682Smarkm} 14555682Smarkm 14655682Smarkm/* 14755682Smarkm * tcp_detach is called when the socket layer loses its final reference 14855682Smarkm * to the socket, be it a file descriptor reference, a reference from TCP, 14955682Smarkm * etc. At this point, there is only one case in which we will keep around 15055682Smarkm * inpcb state: time wait. 15155682Smarkm * 15255682Smarkm * This function can probably be re-absorbed back into tcp_usr_detach() now 15355682Smarkm * that there is a single detach path. 15455682Smarkm */ 15555682Smarkmstatic void 15655682Smarkmtcp_detach(struct socket *so, struct inpcb *inp) 15755682Smarkm{ 15855682Smarkm struct tcpcb *tp; 15955682Smarkm#ifdef INET6 16055682Smarkm int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != 0; 16155682Smarkm#endif 16255682Smarkm#ifdef INVARIANTS 16355682Smarkm INIT_VNET_INET(so->so_vnet); 16455682Smarkm#endif 16555682Smarkm 16655682Smarkm INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 16755682Smarkm INP_WLOCK_ASSERT(inp); 16855682Smarkm 16955682Smarkm KASSERT(so->so_pcb == inp, ("tcp_detach: so_pcb != inp")); 17055682Smarkm KASSERT(inp->inp_socket == so, ("tcp_detach: inp_socket != so")); 17155682Smarkm 17255682Smarkm tp = intotcpcb(inp); 17355682Smarkm 17455682Smarkm if (inp->inp_vflag & INP_TIMEWAIT) { 17555682Smarkm /* 17655682Smarkm * There are two cases to handle: one in which the time wait 17755682Smarkm * state is being discarded (INP_DROPPED), and one in which 17855682Smarkm * this connection will remain in timewait. In the former, 17955682Smarkm * it is time to discard all state (except tcptw, which has 18055682Smarkm * already been discarded by the timewait close code, which 18155682Smarkm * should be further up the call stack somewhere). In the 18255682Smarkm * latter case, we detach from the socket, but leave the pcb 18355682Smarkm * present until timewait ends. 18455682Smarkm * 18555682Smarkm * XXXRW: Would it be cleaner to free the tcptw here? 18655682Smarkm */ 18755682Smarkm if (inp->inp_vflag & INP_DROPPED) { 18855682Smarkm KASSERT(tp == NULL, ("tcp_detach: INP_TIMEWAIT && " 18955682Smarkm "INP_DROPPED && tp != NULL")); 19055682Smarkm in_pcbdetach(inp); 19155682Smarkm#ifdef INET6 19255682Smarkm if (isipv6) 19355682Smarkm in6_pcbfree(inp); 19455682Smarkm else 19555682Smarkm#endif 19655682Smarkm in_pcbfree(inp); 19755682Smarkm } else { 19855682Smarkm in_pcbdetach(inp); 19955682Smarkm INP_WUNLOCK(inp); 20055682Smarkm } 20155682Smarkm } else { 20255682Smarkm /* 20355682Smarkm * If the connection is not in timewait, we consider two 20455682Smarkm * two conditions: one in which no further processing is 20555682Smarkm * necessary (dropped || embryonic), and one in which TCP is 20655682Smarkm * not yet done, but no longer requires the socket, so the 20755682Smarkm * pcb will persist for the time being. 20855682Smarkm * 20955682Smarkm * XXXRW: Does the second case still occur? 21055682Smarkm */ 21155682Smarkm if (inp->inp_vflag & INP_DROPPED || 21255682Smarkm tp->t_state < TCPS_SYN_SENT) { 21355682Smarkm tcp_discardcb(tp); 21455682Smarkm in_pcbdetach(inp); 21555682Smarkm#ifdef INET6 21655682Smarkm if (isipv6) 21755682Smarkm in6_pcbfree(inp); 21855682Smarkm else 21955682Smarkm#endif 22055682Smarkm in_pcbfree(inp); 22155682Smarkm } else { 22255682Smarkm in_pcbdetach(inp); 22355682Smarkm } 22455682Smarkm } 22555682Smarkm} 22655682Smarkm 22755682Smarkm/* 22855682Smarkm * pru_detach() detaches the TCP protocol from the socket. 22955682Smarkm * If the protocol state is non-embryonic, then can't 23055682Smarkm * do this directly: have to initiate a pru_disconnect(), 23155682Smarkm * which may finish later; embryonic TCB's can just 23255682Smarkm * be discarded here. 23355682Smarkm */ 23455682Smarkmstatic void 23555682Smarkmtcp_usr_detach(struct socket *so) 23655682Smarkm{ 23755682Smarkm INIT_VNET_INET(so->so_vnet); 23855682Smarkm struct inpcb *inp; 23955682Smarkm 24055682Smarkm inp = sotoinpcb(so); 24155682Smarkm KASSERT(inp != NULL, ("tcp_usr_detach: inp == NULL")); 24255682Smarkm INP_INFO_WLOCK(&V_tcbinfo); 24355682Smarkm INP_WLOCK(inp); 24455682Smarkm KASSERT(inp->inp_socket != NULL, 24555682Smarkm ("tcp_usr_detach: inp_socket == NULL")); 24655682Smarkm tcp_detach(so, inp); 24755682Smarkm INP_INFO_WUNLOCK(&V_tcbinfo); 24855682Smarkm} 24955682Smarkm 25055682Smarkm/* 25155682Smarkm * Give the socket an address. 25272445Sassar */ 25372445Sassarstatic int 25455682Smarkmtcp_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 25555682Smarkm{ 25672445Sassar INIT_VNET_INET(so->so_vnet); 25755682Smarkm int error = 0; 25855682Smarkm struct inpcb *inp; 25955682Smarkm struct tcpcb *tp = NULL; 26055682Smarkm struct sockaddr_in *sinp; 26155682Smarkm 26255682Smarkm sinp = (struct sockaddr_in *)nam; 26355682Smarkm if (nam->sa_len != sizeof (*sinp)) 26455682Smarkm return (EINVAL); 26572445Sassar /* 26655682Smarkm * Must check for multicast addresses and disallow binding 26790926Snectar * to them. 26890926Snectar */ 26990926Snectar if (sinp->sin_family == AF_INET && 27055682Smarkm IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) 27155682Smarkm return (EAFNOSUPPORT); 27255682Smarkm 27355682Smarkm TCPDEBUG0; 27455682Smarkm INP_INFO_WLOCK(&V_tcbinfo); 27590926Snectar inp = sotoinpcb(so); 27690926Snectar KASSERT(inp != NULL, ("tcp_usr_bind: inp == NULL")); 27790926Snectar INP_WLOCK(inp); 27890926Snectar if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 27990926Snectar error = EINVAL; 28055682Smarkm goto out; 28172445Sassar } 28272445Sassar tp = intotcpcb(inp); 28372445Sassar TCPDEBUG1(); 28455682Smarkm error = in_pcbbind(inp, nam, td->td_ucred); 28555682Smarkmout: 28655682Smarkm TCPDEBUG2(PRU_BIND); 28755682Smarkm INP_WUNLOCK(inp); 28855682Smarkm INP_INFO_WUNLOCK(&V_tcbinfo); 28955682Smarkm 29055682Smarkm return (error); 29155682Smarkm} 29255682Smarkm 29355682Smarkm#ifdef INET6 29455682Smarkmstatic int 29555682Smarkmtcp6_usr_bind(struct socket *so, struct sockaddr *nam, struct thread *td) 29655682Smarkm{ 29755682Smarkm INIT_VNET_INET(so->so_vnet); 29855682Smarkm int error = 0; 29955682Smarkm struct inpcb *inp; 30055682Smarkm struct tcpcb *tp = NULL; 30155682Smarkm struct sockaddr_in6 *sin6p; 30255682Smarkm 30355682Smarkm sin6p = (struct sockaddr_in6 *)nam; 30455682Smarkm if (nam->sa_len != sizeof (*sin6p)) 30590926Snectar return (EINVAL); 30690926Snectar /* 30790926Snectar * Must check for multicast addresses and disallow binding 30855682Smarkm * to them. 30955682Smarkm */ 31055682Smarkm if (sin6p->sin6_family == AF_INET6 && 31155682Smarkm IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) 31255682Smarkm return (EAFNOSUPPORT); 31355682Smarkm 31455682Smarkm TCPDEBUG0; 31555682Smarkm INP_INFO_WLOCK(&V_tcbinfo); 31657416Smarkm inp = sotoinpcb(so); 31757416Smarkm KASSERT(inp != NULL, ("tcp6_usr_bind: inp == NULL")); 31857416Smarkm INP_WLOCK(inp); 31957416Smarkm if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 32057416Smarkm error = EINVAL; 32157416Smarkm goto out; 32272445Sassar } 32372445Sassar tp = intotcpcb(inp); 32472445Sassar TCPDEBUG1(); 32557419Smarkm inp->inp_vflag &= ~INP_IPV4; 32672445Sassar inp->inp_vflag |= INP_IPV6; 32772445Sassar if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) { 32872445Sassar if (IN6_IS_ADDR_UNSPECIFIED(&sin6p->sin6_addr)) 32972445Sassar inp->inp_vflag |= INP_IPV4; 33072445Sassar else if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { 33172445Sassar struct sockaddr_in sin; 33272445Sassar 33372445Sassar in6_sin6_2_sin(&sin, sin6p); 33472445Sassar inp->inp_vflag |= INP_IPV4; 33572445Sassar inp->inp_vflag &= ~INP_IPV6; 33672445Sassar error = in_pcbbind(inp, (struct sockaddr *)&sin, 33755682Smarkm td->td_ucred); 338 goto out; 339 } 340 } 341 error = in6_pcbbind(inp, nam, td->td_ucred); 342out: 343 TCPDEBUG2(PRU_BIND); 344 INP_WUNLOCK(inp); 345 INP_INFO_WUNLOCK(&V_tcbinfo); 346 return (error); 347} 348#endif /* INET6 */ 349 350/* 351 * Prepare to accept connections. 352 */ 353static int 354tcp_usr_listen(struct socket *so, int backlog, struct thread *td) 355{ 356 INIT_VNET_INET(so->so_vnet); 357 int error = 0; 358 struct inpcb *inp; 359 struct tcpcb *tp = NULL; 360 361 TCPDEBUG0; 362 INP_INFO_WLOCK(&V_tcbinfo); 363 inp = sotoinpcb(so); 364 KASSERT(inp != NULL, ("tcp_usr_listen: inp == NULL")); 365 INP_WLOCK(inp); 366 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 367 error = EINVAL; 368 goto out; 369 } 370 tp = intotcpcb(inp); 371 TCPDEBUG1(); 372 SOCK_LOCK(so); 373 error = solisten_proto_check(so); 374 if (error == 0 && inp->inp_lport == 0) 375 error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); 376 if (error == 0) { 377 tp->t_state = TCPS_LISTEN; 378 solisten_proto(so, backlog); 379 tcp_offload_listen_open(tp); 380 } 381 SOCK_UNLOCK(so); 382 383out: 384 TCPDEBUG2(PRU_LISTEN); 385 INP_WUNLOCK(inp); 386 INP_INFO_WUNLOCK(&V_tcbinfo); 387 return (error); 388} 389 390#ifdef INET6 391static int 392tcp6_usr_listen(struct socket *so, int backlog, struct thread *td) 393{ 394 INIT_VNET_INET(so->so_vnet); 395 int error = 0; 396 struct inpcb *inp; 397 struct tcpcb *tp = NULL; 398 399 TCPDEBUG0; 400 INP_INFO_WLOCK(&V_tcbinfo); 401 inp = sotoinpcb(so); 402 KASSERT(inp != NULL, ("tcp6_usr_listen: inp == NULL")); 403 INP_WLOCK(inp); 404 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 405 error = EINVAL; 406 goto out; 407 } 408 tp = intotcpcb(inp); 409 TCPDEBUG1(); 410 SOCK_LOCK(so); 411 error = solisten_proto_check(so); 412 if (error == 0 && inp->inp_lport == 0) { 413 inp->inp_vflag &= ~INP_IPV4; 414 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) == 0) 415 inp->inp_vflag |= INP_IPV4; 416 error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); 417 } 418 if (error == 0) { 419 tp->t_state = TCPS_LISTEN; 420 solisten_proto(so, backlog); 421 } 422 SOCK_UNLOCK(so); 423 424out: 425 TCPDEBUG2(PRU_LISTEN); 426 INP_WUNLOCK(inp); 427 INP_INFO_WUNLOCK(&V_tcbinfo); 428 return (error); 429} 430#endif /* INET6 */ 431 432/* 433 * Initiate connection to peer. 434 * Create a template for use in transmissions on this connection. 435 * Enter SYN_SENT state, and mark socket as connecting. 436 * Start keep-alive timer, and seed output sequence space. 437 * Send initial segment on connection. 438 */ 439static int 440tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 441{ 442 INIT_VNET_INET(so->so_vnet); 443 int error = 0; 444 struct inpcb *inp; 445 struct tcpcb *tp = NULL; 446 struct sockaddr_in *sinp; 447 448 sinp = (struct sockaddr_in *)nam; 449 if (nam->sa_len != sizeof (*sinp)) 450 return (EINVAL); 451 /* 452 * Must disallow TCP ``connections'' to multicast addresses. 453 */ 454 if (sinp->sin_family == AF_INET 455 && IN_MULTICAST(ntohl(sinp->sin_addr.s_addr))) 456 return (EAFNOSUPPORT); 457 if (jailed(td->td_ucred)) 458 prison_remote_ip(td->td_ucred, 0, &sinp->sin_addr.s_addr); 459 460 TCPDEBUG0; 461 INP_INFO_WLOCK(&V_tcbinfo); 462 inp = sotoinpcb(so); 463 KASSERT(inp != NULL, ("tcp_usr_connect: inp == NULL")); 464 INP_WLOCK(inp); 465 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 466 error = EINVAL; 467 goto out; 468 } 469 tp = intotcpcb(inp); 470 TCPDEBUG1(); 471 if ((error = tcp_connect(tp, nam, td)) != 0) 472 goto out; 473 error = tcp_output_connect(so, nam); 474out: 475 TCPDEBUG2(PRU_CONNECT); 476 INP_WUNLOCK(inp); 477 INP_INFO_WUNLOCK(&V_tcbinfo); 478 return (error); 479} 480 481#ifdef INET6 482static int 483tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td) 484{ 485 INIT_VNET_INET(so->so_vnet); 486 int error = 0; 487 struct inpcb *inp; 488 struct tcpcb *tp = NULL; 489 struct sockaddr_in6 *sin6p; 490 491 TCPDEBUG0; 492 493 sin6p = (struct sockaddr_in6 *)nam; 494 if (nam->sa_len != sizeof (*sin6p)) 495 return (EINVAL); 496 /* 497 * Must disallow TCP ``connections'' to multicast addresses. 498 */ 499 if (sin6p->sin6_family == AF_INET6 500 && IN6_IS_ADDR_MULTICAST(&sin6p->sin6_addr)) 501 return (EAFNOSUPPORT); 502 503 INP_INFO_WLOCK(&V_tcbinfo); 504 inp = sotoinpcb(so); 505 KASSERT(inp != NULL, ("tcp6_usr_connect: inp == NULL")); 506 INP_WLOCK(inp); 507 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 508 error = EINVAL; 509 goto out; 510 } 511 tp = intotcpcb(inp); 512 TCPDEBUG1(); 513 if (IN6_IS_ADDR_V4MAPPED(&sin6p->sin6_addr)) { 514 struct sockaddr_in sin; 515 516 if ((inp->inp_flags & IN6P_IPV6_V6ONLY) != 0) { 517 error = EINVAL; 518 goto out; 519 } 520 521 in6_sin6_2_sin(&sin, sin6p); 522 inp->inp_vflag |= INP_IPV4; 523 inp->inp_vflag &= ~INP_IPV6; 524 if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0) 525 goto out; 526 error = tcp_output_connect(so, nam); 527 goto out; 528 } 529 inp->inp_vflag &= ~INP_IPV4; 530 inp->inp_vflag |= INP_IPV6; 531 inp->inp_inc.inc_isipv6 = 1; 532 if ((error = tcp6_connect(tp, nam, td)) != 0) 533 goto out; 534 error = tcp_output_connect(so, nam); 535 536out: 537 TCPDEBUG2(PRU_CONNECT); 538 INP_WUNLOCK(inp); 539 INP_INFO_WUNLOCK(&V_tcbinfo); 540 return (error); 541} 542#endif /* INET6 */ 543 544/* 545 * Initiate disconnect from peer. 546 * If connection never passed embryonic stage, just drop; 547 * else if don't need to let data drain, then can just drop anyways, 548 * else have to begin TCP shutdown process: mark socket disconnecting, 549 * drain unread data, state switch to reflect user close, and 550 * send segment (e.g. FIN) to peer. Socket will be really disconnected 551 * when peer sends FIN and acks ours. 552 * 553 * SHOULD IMPLEMENT LATER PRU_CONNECT VIA REALLOC TCPCB. 554 */ 555static int 556tcp_usr_disconnect(struct socket *so) 557{ 558 INIT_VNET_INET(so->so_vnet); 559 struct inpcb *inp; 560 struct tcpcb *tp = NULL; 561 int error = 0; 562 563 TCPDEBUG0; 564 INP_INFO_WLOCK(&V_tcbinfo); 565 inp = sotoinpcb(so); 566 KASSERT(inp != NULL, ("tcp_usr_disconnect: inp == NULL")); 567 INP_WLOCK(inp); 568 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 569 error = ECONNRESET; 570 goto out; 571 } 572 tp = intotcpcb(inp); 573 TCPDEBUG1(); 574 tcp_disconnect(tp); 575out: 576 TCPDEBUG2(PRU_DISCONNECT); 577 INP_WUNLOCK(inp); 578 INP_INFO_WUNLOCK(&V_tcbinfo); 579 return (error); 580} 581 582/* 583 * Accept a connection. Essentially all the work is 584 * done at higher levels; just return the address 585 * of the peer, storing through addr. 586 */ 587static int 588tcp_usr_accept(struct socket *so, struct sockaddr **nam) 589{ 590 INIT_VNET_INET(so->so_vnet); 591 int error = 0; 592 struct inpcb *inp = NULL; 593 struct tcpcb *tp = NULL; 594 struct in_addr addr; 595 in_port_t port = 0; 596 TCPDEBUG0; 597 598 if (so->so_state & SS_ISDISCONNECTED) 599 return (ECONNABORTED); 600 601 inp = sotoinpcb(so); 602 KASSERT(inp != NULL, ("tcp_usr_accept: inp == NULL")); 603 INP_INFO_RLOCK(&V_tcbinfo); 604 INP_WLOCK(inp); 605 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 606 error = ECONNABORTED; 607 goto out; 608 } 609 tp = intotcpcb(inp); 610 TCPDEBUG1(); 611 612 /* 613 * We inline in_getpeeraddr and COMMON_END here, so that we can 614 * copy the data of interest and defer the malloc until after we 615 * release the lock. 616 */ 617 port = inp->inp_fport; 618 addr = inp->inp_faddr; 619 620out: 621 TCPDEBUG2(PRU_ACCEPT); 622 INP_WUNLOCK(inp); 623 INP_INFO_RUNLOCK(&V_tcbinfo); 624 if (error == 0) 625 *nam = in_sockaddr(port, &addr); 626 return error; 627} 628 629#ifdef INET6 630static int 631tcp6_usr_accept(struct socket *so, struct sockaddr **nam) 632{ 633 struct inpcb *inp = NULL; 634 int error = 0; 635 struct tcpcb *tp = NULL; 636 struct in_addr addr; 637 struct in6_addr addr6; 638 in_port_t port = 0; 639 int v4 = 0; 640 TCPDEBUG0; 641 642 if (so->so_state & SS_ISDISCONNECTED) 643 return (ECONNABORTED); 644 645 inp = sotoinpcb(so); 646 KASSERT(inp != NULL, ("tcp6_usr_accept: inp == NULL")); 647 INP_WLOCK(inp); 648 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 649 error = ECONNABORTED; 650 goto out; 651 } 652 tp = intotcpcb(inp); 653 TCPDEBUG1(); 654 655 /* 656 * We inline in6_mapped_peeraddr and COMMON_END here, so that we can 657 * copy the data of interest and defer the malloc until after we 658 * release the lock. 659 */ 660 if (inp->inp_vflag & INP_IPV4) { 661 v4 = 1; 662 port = inp->inp_fport; 663 addr = inp->inp_faddr; 664 } else { 665 port = inp->inp_fport; 666 addr6 = inp->in6p_faddr; 667 } 668 669out: 670 TCPDEBUG2(PRU_ACCEPT); 671 INP_WUNLOCK(inp); 672 if (error == 0) { 673 if (v4) 674 *nam = in6_v4mapsin6_sockaddr(port, &addr); 675 else 676 *nam = in6_sockaddr(port, &addr6); 677 } 678 return error; 679} 680#endif /* INET6 */ 681 682/* 683 * Mark the connection as being incapable of further output. 684 */ 685static int 686tcp_usr_shutdown(struct socket *so) 687{ 688 INIT_VNET_INET(so->so_vnet); 689 int error = 0; 690 struct inpcb *inp; 691 struct tcpcb *tp = NULL; 692 693 TCPDEBUG0; 694 INP_INFO_WLOCK(&V_tcbinfo); 695 inp = sotoinpcb(so); 696 KASSERT(inp != NULL, ("inp == NULL")); 697 INP_WLOCK(inp); 698 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 699 error = ECONNRESET; 700 goto out; 701 } 702 tp = intotcpcb(inp); 703 TCPDEBUG1(); 704 socantsendmore(so); 705 tcp_usrclosed(tp); 706 error = tcp_output_disconnect(tp); 707 708out: 709 TCPDEBUG2(PRU_SHUTDOWN); 710 INP_WUNLOCK(inp); 711 INP_INFO_WUNLOCK(&V_tcbinfo); 712 713 return (error); 714} 715 716/* 717 * After a receive, possibly send window update to peer. 718 */ 719static int 720tcp_usr_rcvd(struct socket *so, int flags) 721{ 722 struct inpcb *inp; 723 struct tcpcb *tp = NULL; 724 int error = 0; 725 726 TCPDEBUG0; 727 inp = sotoinpcb(so); 728 KASSERT(inp != NULL, ("tcp_usr_rcvd: inp == NULL")); 729 INP_WLOCK(inp); 730 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 731 error = ECONNRESET; 732 goto out; 733 } 734 tp = intotcpcb(inp); 735 TCPDEBUG1(); 736 tcp_output_rcvd(tp); 737 738out: 739 TCPDEBUG2(PRU_RCVD); 740 INP_WUNLOCK(inp); 741 return (error); 742} 743 744/* 745 * Do a send by putting data in output queue and updating urgent 746 * marker if URG set. Possibly send more data. Unlike the other 747 * pru_*() routines, the mbuf chains are our responsibility. We 748 * must either enqueue them or free them. The other pru_* routines 749 * generally are caller-frees. 750 */ 751static int 752tcp_usr_send(struct socket *so, int flags, struct mbuf *m, 753 struct sockaddr *nam, struct mbuf *control, struct thread *td) 754{ 755 INIT_VNET_INET(so->so_vnet); 756 int error = 0; 757 struct inpcb *inp; 758 struct tcpcb *tp = NULL; 759 int headlocked = 0; 760#ifdef INET6 761 int isipv6; 762#endif 763 TCPDEBUG0; 764 765 /* 766 * We require the pcbinfo lock in two cases: 767 * 768 * (1) An implied connect is taking place, which can result in 769 * binding IPs and ports and hence modification of the pcb hash 770 * chains. 771 * 772 * (2) PRUS_EOF is set, resulting in explicit close on the send. 773 */ 774 if ((nam != NULL) || (flags & PRUS_EOF)) { 775 INP_INFO_WLOCK(&V_tcbinfo); 776 headlocked = 1; 777 } 778 inp = sotoinpcb(so); 779 KASSERT(inp != NULL, ("tcp_usr_send: inp == NULL")); 780 INP_WLOCK(inp); 781 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 782 if (control) 783 m_freem(control); 784 if (m) 785 m_freem(m); 786 error = ECONNRESET; 787 goto out; 788 } 789#ifdef INET6 790 isipv6 = nam && nam->sa_family == AF_INET6; 791#endif /* INET6 */ 792 tp = intotcpcb(inp); 793 TCPDEBUG1(); 794 if (control) { 795 /* TCP doesn't do control messages (rights, creds, etc) */ 796 if (control->m_len) { 797 m_freem(control); 798 if (m) 799 m_freem(m); 800 error = EINVAL; 801 goto out; 802 } 803 m_freem(control); /* empty control, just free it */ 804 } 805 if (!(flags & PRUS_OOB)) { 806 sbappendstream(&so->so_snd, m); 807 if (nam && tp->t_state < TCPS_SYN_SENT) { 808 /* 809 * Do implied connect if not yet connected, 810 * initialize window to default value, and 811 * initialize maxseg/maxopd using peer's cached 812 * MSS. 813 */ 814 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 815#ifdef INET6 816 if (isipv6) 817 error = tcp6_connect(tp, nam, td); 818 else 819#endif /* INET6 */ 820 error = tcp_connect(tp, nam, td); 821 if (error) 822 goto out; 823 tp->snd_wnd = TTCP_CLIENT_SND_WND; 824 tcp_mss(tp, -1); 825 } 826 if (flags & PRUS_EOF) { 827 /* 828 * Close the send side of the connection after 829 * the data is sent. 830 */ 831 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 832 socantsendmore(so); 833 tcp_usrclosed(tp); 834 } 835 if (headlocked) { 836 INP_INFO_WUNLOCK(&V_tcbinfo); 837 headlocked = 0; 838 } 839 if (tp != NULL) { 840 if (flags & PRUS_MORETOCOME) 841 tp->t_flags |= TF_MORETOCOME; 842 error = tcp_output_send(tp); 843 if (flags & PRUS_MORETOCOME) 844 tp->t_flags &= ~TF_MORETOCOME; 845 } 846 } else { 847 /* 848 * XXXRW: PRUS_EOF not implemented with PRUS_OOB? 849 */ 850 SOCKBUF_LOCK(&so->so_snd); 851 if (sbspace(&so->so_snd) < -512) { 852 SOCKBUF_UNLOCK(&so->so_snd); 853 m_freem(m); 854 error = ENOBUFS; 855 goto out; 856 } 857 /* 858 * According to RFC961 (Assigned Protocols), 859 * the urgent pointer points to the last octet 860 * of urgent data. We continue, however, 861 * to consider it to indicate the first octet 862 * of data past the urgent section. 863 * Otherwise, snd_up should be one lower. 864 */ 865 sbappendstream_locked(&so->so_snd, m); 866 SOCKBUF_UNLOCK(&so->so_snd); 867 if (nam && tp->t_state < TCPS_SYN_SENT) { 868 /* 869 * Do implied connect if not yet connected, 870 * initialize window to default value, and 871 * initialize maxseg/maxopd using peer's cached 872 * MSS. 873 */ 874 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 875#ifdef INET6 876 if (isipv6) 877 error = tcp6_connect(tp, nam, td); 878 else 879#endif /* INET6 */ 880 error = tcp_connect(tp, nam, td); 881 if (error) 882 goto out; 883 tp->snd_wnd = TTCP_CLIENT_SND_WND; 884 tcp_mss(tp, -1); 885 INP_INFO_WUNLOCK(&V_tcbinfo); 886 headlocked = 0; 887 } else if (nam) { 888 INP_INFO_WUNLOCK(&V_tcbinfo); 889 headlocked = 0; 890 } 891 tp->snd_up = tp->snd_una + so->so_snd.sb_cc; 892 tp->t_flags |= TF_FORCEDATA; 893 error = tcp_output_send(tp); 894 tp->t_flags &= ~TF_FORCEDATA; 895 } 896out: 897 TCPDEBUG2((flags & PRUS_OOB) ? PRU_SENDOOB : 898 ((flags & PRUS_EOF) ? PRU_SEND_EOF : PRU_SEND)); 899 INP_WUNLOCK(inp); 900 if (headlocked) 901 INP_INFO_WUNLOCK(&V_tcbinfo); 902 return (error); 903} 904 905/* 906 * Abort the TCP. Drop the connection abruptly. 907 */ 908static void 909tcp_usr_abort(struct socket *so) 910{ 911 INIT_VNET_INET(so->so_vnet); 912 struct inpcb *inp; 913 struct tcpcb *tp = NULL; 914 TCPDEBUG0; 915 916 inp = sotoinpcb(so); 917 KASSERT(inp != NULL, ("tcp_usr_abort: inp == NULL")); 918 919 INP_INFO_WLOCK(&V_tcbinfo); 920 INP_WLOCK(inp); 921 KASSERT(inp->inp_socket != NULL, 922 ("tcp_usr_abort: inp_socket == NULL")); 923 924 /* 925 * If we still have full TCP state, and we're not dropped, drop. 926 */ 927 if (!(inp->inp_vflag & INP_TIMEWAIT) && 928 !(inp->inp_vflag & INP_DROPPED)) { 929 tp = intotcpcb(inp); 930 TCPDEBUG1(); 931 tcp_drop(tp, ECONNABORTED); 932 TCPDEBUG2(PRU_ABORT); 933 } 934 if (!(inp->inp_vflag & INP_DROPPED)) { 935 SOCK_LOCK(so); 936 so->so_state |= SS_PROTOREF; 937 SOCK_UNLOCK(so); 938 inp->inp_vflag |= INP_SOCKREF; 939 } 940 INP_WUNLOCK(inp); 941 INP_INFO_WUNLOCK(&V_tcbinfo); 942} 943 944/* 945 * TCP socket is closed. Start friendly disconnect. 946 */ 947static void 948tcp_usr_close(struct socket *so) 949{ 950 INIT_VNET_INET(so->so_vnet); 951 struct inpcb *inp; 952 struct tcpcb *tp = NULL; 953 TCPDEBUG0; 954 955 inp = sotoinpcb(so); 956 KASSERT(inp != NULL, ("tcp_usr_close: inp == NULL")); 957 958 INP_INFO_WLOCK(&V_tcbinfo); 959 INP_WLOCK(inp); 960 KASSERT(inp->inp_socket != NULL, 961 ("tcp_usr_close: inp_socket == NULL")); 962 963 /* 964 * If we still have full TCP state, and we're not dropped, initiate 965 * a disconnect. 966 */ 967 if (!(inp->inp_vflag & INP_TIMEWAIT) && 968 !(inp->inp_vflag & INP_DROPPED)) { 969 tp = intotcpcb(inp); 970 TCPDEBUG1(); 971 tcp_disconnect(tp); 972 TCPDEBUG2(PRU_CLOSE); 973 } 974 if (!(inp->inp_vflag & INP_DROPPED)) { 975 SOCK_LOCK(so); 976 so->so_state |= SS_PROTOREF; 977 SOCK_UNLOCK(so); 978 inp->inp_vflag |= INP_SOCKREF; 979 } 980 INP_WUNLOCK(inp); 981 INP_INFO_WUNLOCK(&V_tcbinfo); 982} 983 984/* 985 * Receive out-of-band data. 986 */ 987static int 988tcp_usr_rcvoob(struct socket *so, struct mbuf *m, int flags) 989{ 990 int error = 0; 991 struct inpcb *inp; 992 struct tcpcb *tp = NULL; 993 994 TCPDEBUG0; 995 inp = sotoinpcb(so); 996 KASSERT(inp != NULL, ("tcp_usr_rcvoob: inp == NULL")); 997 INP_WLOCK(inp); 998 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 999 error = ECONNRESET; 1000 goto out; 1001 } 1002 tp = intotcpcb(inp); 1003 TCPDEBUG1(); 1004 if ((so->so_oobmark == 0 && 1005 (so->so_rcv.sb_state & SBS_RCVATMARK) == 0) || 1006 so->so_options & SO_OOBINLINE || 1007 tp->t_oobflags & TCPOOB_HADDATA) { 1008 error = EINVAL; 1009 goto out; 1010 } 1011 if ((tp->t_oobflags & TCPOOB_HAVEDATA) == 0) { 1012 error = EWOULDBLOCK; 1013 goto out; 1014 } 1015 m->m_len = 1; 1016 *mtod(m, caddr_t) = tp->t_iobc; 1017 if ((flags & MSG_PEEK) == 0) 1018 tp->t_oobflags ^= (TCPOOB_HAVEDATA | TCPOOB_HADDATA); 1019 1020out: 1021 TCPDEBUG2(PRU_RCVOOB); 1022 INP_WUNLOCK(inp); 1023 return (error); 1024} 1025 1026struct pr_usrreqs tcp_usrreqs = { 1027 .pru_abort = tcp_usr_abort, 1028 .pru_accept = tcp_usr_accept, 1029 .pru_attach = tcp_usr_attach, 1030 .pru_bind = tcp_usr_bind, 1031 .pru_connect = tcp_usr_connect, 1032 .pru_control = in_control, 1033 .pru_detach = tcp_usr_detach, 1034 .pru_disconnect = tcp_usr_disconnect, 1035 .pru_listen = tcp_usr_listen, 1036 .pru_peeraddr = in_getpeeraddr, 1037 .pru_rcvd = tcp_usr_rcvd, 1038 .pru_rcvoob = tcp_usr_rcvoob, 1039 .pru_send = tcp_usr_send, 1040 .pru_shutdown = tcp_usr_shutdown, 1041 .pru_sockaddr = in_getsockaddr, 1042 .pru_sosetlabel = in_pcbsosetlabel, 1043 .pru_close = tcp_usr_close, 1044}; 1045 1046#ifdef INET6 1047struct pr_usrreqs tcp6_usrreqs = { 1048 .pru_abort = tcp_usr_abort, 1049 .pru_accept = tcp6_usr_accept, 1050 .pru_attach = tcp_usr_attach, 1051 .pru_bind = tcp6_usr_bind, 1052 .pru_connect = tcp6_usr_connect, 1053 .pru_control = in6_control, 1054 .pru_detach = tcp_usr_detach, 1055 .pru_disconnect = tcp_usr_disconnect, 1056 .pru_listen = tcp6_usr_listen, 1057 .pru_peeraddr = in6_mapped_peeraddr, 1058 .pru_rcvd = tcp_usr_rcvd, 1059 .pru_rcvoob = tcp_usr_rcvoob, 1060 .pru_send = tcp_usr_send, 1061 .pru_shutdown = tcp_usr_shutdown, 1062 .pru_sockaddr = in6_mapped_sockaddr, 1063 .pru_sosetlabel = in_pcbsosetlabel, 1064 .pru_close = tcp_usr_close, 1065}; 1066#endif /* INET6 */ 1067 1068/* 1069 * Common subroutine to open a TCP connection to remote host specified 1070 * by struct sockaddr_in in mbuf *nam. Call in_pcbbind to assign a local 1071 * port number if needed. Call in_pcbconnect_setup to do the routing and 1072 * to choose a local host address (interface). If there is an existing 1073 * incarnation of the same connection in TIME-WAIT state and if the remote 1074 * host was sending CC options and if the connection duration was < MSL, then 1075 * truncate the previous TIME-WAIT state and proceed. 1076 * Initialize connection parameters and enter SYN-SENT state. 1077 */ 1078static int 1079tcp_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) 1080{ 1081 struct inpcb *inp = tp->t_inpcb, *oinp; 1082 struct socket *so = inp->inp_socket; 1083 INIT_VNET_INET(so->so_vnet); 1084 struct in_addr laddr; 1085 u_short lport; 1086 int error; 1087 1088 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 1089 INP_WLOCK_ASSERT(inp); 1090 1091 if (inp->inp_lport == 0) { 1092 error = in_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); 1093 if (error) 1094 return error; 1095 } 1096 1097 /* 1098 * Cannot simply call in_pcbconnect, because there might be an 1099 * earlier incarnation of this same connection still in 1100 * TIME_WAIT state, creating an ADDRINUSE error. 1101 */ 1102 laddr = inp->inp_laddr; 1103 lport = inp->inp_lport; 1104 error = in_pcbconnect_setup(inp, nam, &laddr.s_addr, &lport, 1105 &inp->inp_faddr.s_addr, &inp->inp_fport, &oinp, td->td_ucred); 1106 if (error && oinp == NULL) 1107 return error; 1108 if (oinp) 1109 return EADDRINUSE; 1110 inp->inp_laddr = laddr; 1111 in_pcbrehash(inp); 1112 1113 /* 1114 * Compute window scaling to request: 1115 * Scale to fit into sweet spot. See tcp_syncache.c. 1116 * XXX: This should move to tcp_output(). 1117 */ 1118 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 1119 (TCP_MAXWIN << tp->request_r_scale) < sb_max) 1120 tp->request_r_scale++; 1121 1122 soisconnecting(so); 1123 V_tcpstat.tcps_connattempt++; 1124 tp->t_state = TCPS_SYN_SENT; 1125 tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); 1126 tp->iss = tcp_new_isn(tp); 1127 tp->t_bw_rtseq = tp->iss; 1128 tcp_sendseqinit(tp); 1129 1130 return 0; 1131} 1132 1133#ifdef INET6 1134static int 1135tcp6_connect(struct tcpcb *tp, struct sockaddr *nam, struct thread *td) 1136{ 1137 struct inpcb *inp = tp->t_inpcb, *oinp; 1138 struct socket *so = inp->inp_socket; 1139 INIT_VNET_INET(so->so_vnet); 1140 struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)nam; 1141 struct in6_addr *addr6; 1142 int error; 1143 1144 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 1145 INP_WLOCK_ASSERT(inp); 1146 1147 if (inp->inp_lport == 0) { 1148 error = in6_pcbbind(inp, (struct sockaddr *)0, td->td_ucred); 1149 if (error) 1150 return error; 1151 } 1152 1153 /* 1154 * Cannot simply call in_pcbconnect, because there might be an 1155 * earlier incarnation of this same connection still in 1156 * TIME_WAIT state, creating an ADDRINUSE error. 1157 * in6_pcbladdr() also handles scope zone IDs. 1158 */ 1159 error = in6_pcbladdr(inp, nam, &addr6); 1160 if (error) 1161 return error; 1162 oinp = in6_pcblookup_hash(inp->inp_pcbinfo, 1163 &sin6->sin6_addr, sin6->sin6_port, 1164 IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr) 1165 ? addr6 1166 : &inp->in6p_laddr, 1167 inp->inp_lport, 0, NULL); 1168 if (oinp) 1169 return EADDRINUSE; 1170 if (IN6_IS_ADDR_UNSPECIFIED(&inp->in6p_laddr)) 1171 inp->in6p_laddr = *addr6; 1172 inp->in6p_faddr = sin6->sin6_addr; 1173 inp->inp_fport = sin6->sin6_port; 1174 /* update flowinfo - draft-itojun-ipv6-flowlabel-api-00 */ 1175 inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK; 1176 if (inp->in6p_flags & IN6P_AUTOFLOWLABEL) 1177 inp->in6p_flowinfo |= 1178 (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK); 1179 in_pcbrehash(inp); 1180 1181 /* Compute window scaling to request. */ 1182 while (tp->request_r_scale < TCP_MAX_WINSHIFT && 1183 (TCP_MAXWIN << tp->request_r_scale) < so->so_rcv.sb_hiwat) 1184 tp->request_r_scale++; 1185 1186 soisconnecting(so); 1187 V_tcpstat.tcps_connattempt++; 1188 tp->t_state = TCPS_SYN_SENT; 1189 tcp_timer_activate(tp, TT_KEEP, tcp_keepinit); 1190 tp->iss = tcp_new_isn(tp); 1191 tp->t_bw_rtseq = tp->iss; 1192 tcp_sendseqinit(tp); 1193 1194 return 0; 1195} 1196#endif /* INET6 */ 1197 1198/* 1199 * Export TCP internal state information via a struct tcp_info, based on the 1200 * Linux 2.6 API. Not ABI compatible as our constants are mapped differently 1201 * (TCP state machine, etc). We export all information using FreeBSD-native 1202 * constants -- for example, the numeric values for tcpi_state will differ 1203 * from Linux. 1204 */ 1205static void 1206tcp_fill_info(struct tcpcb *tp, struct tcp_info *ti) 1207{ 1208 1209 INP_WLOCK_ASSERT(tp->t_inpcb); 1210 bzero(ti, sizeof(*ti)); 1211 1212 ti->tcpi_state = tp->t_state; 1213 if ((tp->t_flags & TF_REQ_TSTMP) && (tp->t_flags & TF_RCVD_TSTMP)) 1214 ti->tcpi_options |= TCPI_OPT_TIMESTAMPS; 1215 if (tp->t_flags & TF_SACK_PERMIT) 1216 ti->tcpi_options |= TCPI_OPT_SACK; 1217 if ((tp->t_flags & TF_REQ_SCALE) && (tp->t_flags & TF_RCVD_SCALE)) { 1218 ti->tcpi_options |= TCPI_OPT_WSCALE; 1219 ti->tcpi_snd_wscale = tp->snd_scale; 1220 ti->tcpi_rcv_wscale = tp->rcv_scale; 1221 } 1222 1223 ti->tcpi_rtt = ((u_int64_t)tp->t_srtt * tick) >> TCP_RTT_SHIFT; 1224 ti->tcpi_rttvar = ((u_int64_t)tp->t_rttvar * tick) >> TCP_RTTVAR_SHIFT; 1225 1226 ti->tcpi_snd_ssthresh = tp->snd_ssthresh; 1227 ti->tcpi_snd_cwnd = tp->snd_cwnd; 1228 1229 /* 1230 * FreeBSD-specific extension fields for tcp_info. 1231 */ 1232 ti->tcpi_rcv_space = tp->rcv_wnd; 1233 ti->tcpi_rcv_nxt = tp->rcv_nxt; 1234 ti->tcpi_snd_wnd = tp->snd_wnd; 1235 ti->tcpi_snd_bwnd = tp->snd_bwnd; 1236 ti->tcpi_snd_nxt = tp->snd_nxt; 1237 ti->__tcpi_snd_mss = tp->t_maxseg; 1238 ti->__tcpi_rcv_mss = tp->t_maxseg; 1239 if (tp->t_flags & TF_TOE) 1240 ti->tcpi_options |= TCPI_OPT_TOE; 1241} 1242 1243/* 1244 * tcp_ctloutput() must drop the inpcb lock before performing copyin on 1245 * socket option arguments. When it re-acquires the lock after the copy, it 1246 * has to revalidate that the connection is still valid for the socket 1247 * option. 1248 */ 1249#define INP_WLOCK_RECHECK(inp) do { \ 1250 INP_WLOCK(inp); \ 1251 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { \ 1252 INP_WUNLOCK(inp); \ 1253 return (ECONNRESET); \ 1254 } \ 1255 tp = intotcpcb(inp); \ 1256} while(0) 1257 1258int 1259tcp_ctloutput(struct socket *so, struct sockopt *sopt) 1260{ 1261 INIT_VNET_INET(so->so_vnet); 1262 int error, opt, optval; 1263 struct inpcb *inp; 1264 struct tcpcb *tp; 1265 struct tcp_info ti; 1266 1267 error = 0; 1268 inp = sotoinpcb(so); 1269 KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL")); 1270 INP_WLOCK(inp); 1271 if (sopt->sopt_level != IPPROTO_TCP) { 1272#ifdef INET6 1273 if (INP_CHECK_SOCKAF(so, AF_INET6)) { 1274 INP_WUNLOCK(inp); 1275 error = ip6_ctloutput(so, sopt); 1276 } else { 1277#endif /* INET6 */ 1278 INP_WUNLOCK(inp); 1279 error = ip_ctloutput(so, sopt); 1280#ifdef INET6 1281 } 1282#endif 1283 return (error); 1284 } 1285 if (inp->inp_vflag & (INP_TIMEWAIT | INP_DROPPED)) { 1286 INP_WUNLOCK(inp); 1287 return (ECONNRESET); 1288 } 1289 1290 switch (sopt->sopt_dir) { 1291 case SOPT_SET: 1292 switch (sopt->sopt_name) { 1293#ifdef TCP_SIGNATURE 1294 case TCP_MD5SIG: 1295 INP_WUNLOCK(inp); 1296 error = sooptcopyin(sopt, &optval, sizeof optval, 1297 sizeof optval); 1298 if (error) 1299 return (error); 1300 1301 INP_WLOCK_RECHECK(inp); 1302 if (optval > 0) 1303 tp->t_flags |= TF_SIGNATURE; 1304 else 1305 tp->t_flags &= ~TF_SIGNATURE; 1306 INP_WUNLOCK(inp); 1307 break; 1308#endif /* TCP_SIGNATURE */ 1309 case TCP_NODELAY: 1310 case TCP_NOOPT: 1311 INP_WUNLOCK(inp); 1312 error = sooptcopyin(sopt, &optval, sizeof optval, 1313 sizeof optval); 1314 if (error) 1315 return (error); 1316 1317 INP_WLOCK_RECHECK(inp); 1318 switch (sopt->sopt_name) { 1319 case TCP_NODELAY: 1320 opt = TF_NODELAY; 1321 break; 1322 case TCP_NOOPT: 1323 opt = TF_NOOPT; 1324 break; 1325 default: 1326 opt = 0; /* dead code to fool gcc */ 1327 break; 1328 } 1329 1330 if (optval) 1331 tp->t_flags |= opt; 1332 else 1333 tp->t_flags &= ~opt; 1334 INP_WUNLOCK(inp); 1335 break; 1336 1337 case TCP_NOPUSH: 1338 INP_WUNLOCK(inp); 1339 error = sooptcopyin(sopt, &optval, sizeof optval, 1340 sizeof optval); 1341 if (error) 1342 return (error); 1343 1344 INP_WLOCK_RECHECK(inp); 1345 if (optval) 1346 tp->t_flags |= TF_NOPUSH; 1347 else { 1348 tp->t_flags &= ~TF_NOPUSH; 1349 error = tcp_output(tp); 1350 } 1351 INP_WUNLOCK(inp); 1352 break; 1353 1354 case TCP_MAXSEG: 1355 INP_WUNLOCK(inp); 1356 error = sooptcopyin(sopt, &optval, sizeof optval, 1357 sizeof optval); 1358 if (error) 1359 return (error); 1360 1361 INP_WLOCK_RECHECK(inp); 1362 if (optval > 0 && optval <= tp->t_maxseg && 1363 optval + 40 >= V_tcp_minmss) 1364 tp->t_maxseg = optval; 1365 else 1366 error = EINVAL; 1367 INP_WUNLOCK(inp); 1368 break; 1369 1370 case TCP_INFO: 1371 INP_WUNLOCK(inp); 1372 error = EINVAL; 1373 break; 1374 1375 default: 1376 INP_WUNLOCK(inp); 1377 error = ENOPROTOOPT; 1378 break; 1379 } 1380 break; 1381 1382 case SOPT_GET: 1383 tp = intotcpcb(inp); 1384 switch (sopt->sopt_name) { 1385#ifdef TCP_SIGNATURE 1386 case TCP_MD5SIG: 1387 optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0; 1388 INP_WUNLOCK(inp); 1389 error = sooptcopyout(sopt, &optval, sizeof optval); 1390 break; 1391#endif 1392 1393 case TCP_NODELAY: 1394 optval = tp->t_flags & TF_NODELAY; 1395 INP_WUNLOCK(inp); 1396 error = sooptcopyout(sopt, &optval, sizeof optval); 1397 break; 1398 case TCP_MAXSEG: 1399 optval = tp->t_maxseg; 1400 INP_WUNLOCK(inp); 1401 error = sooptcopyout(sopt, &optval, sizeof optval); 1402 break; 1403 case TCP_NOOPT: 1404 optval = tp->t_flags & TF_NOOPT; 1405 INP_WUNLOCK(inp); 1406 error = sooptcopyout(sopt, &optval, sizeof optval); 1407 break; 1408 case TCP_NOPUSH: 1409 optval = tp->t_flags & TF_NOPUSH; 1410 INP_WUNLOCK(inp); 1411 error = sooptcopyout(sopt, &optval, sizeof optval); 1412 break; 1413 case TCP_INFO: 1414 tcp_fill_info(tp, &ti); 1415 INP_WUNLOCK(inp); 1416 error = sooptcopyout(sopt, &ti, sizeof ti); 1417 break; 1418 default: 1419 INP_WUNLOCK(inp); 1420 error = ENOPROTOOPT; 1421 break; 1422 } 1423 break; 1424 } 1425 return (error); 1426} 1427#undef INP_WLOCK_RECHECK 1428 1429/* 1430 * tcp_sendspace and tcp_recvspace are the default send and receive window 1431 * sizes, respectively. These are obsolescent (this information should 1432 * be set by the route). 1433 */ 1434u_long tcp_sendspace = 1024*32; 1435SYSCTL_ULONG(_net_inet_tcp, TCPCTL_SENDSPACE, sendspace, CTLFLAG_RW, 1436 &tcp_sendspace , 0, "Maximum outgoing TCP datagram size"); 1437u_long tcp_recvspace = 1024*64; 1438SYSCTL_ULONG(_net_inet_tcp, TCPCTL_RECVSPACE, recvspace, CTLFLAG_RW, 1439 &tcp_recvspace , 0, "Maximum incoming TCP datagram size"); 1440 1441/* 1442 * Attach TCP protocol to socket, allocating 1443 * internet protocol control block, tcp control block, 1444 * bufer space, and entering LISTEN state if to accept connections. 1445 */ 1446static int 1447tcp_attach(struct socket *so) 1448{ 1449 INIT_VNET_INET(so->so_vnet); 1450 struct tcpcb *tp; 1451 struct inpcb *inp; 1452 int error; 1453#ifdef INET6 1454 int isipv6 = INP_CHECK_SOCKAF(so, AF_INET6) != 0; 1455#endif 1456 1457 if (so->so_snd.sb_hiwat == 0 || so->so_rcv.sb_hiwat == 0) { 1458 error = soreserve(so, tcp_sendspace, tcp_recvspace); 1459 if (error) 1460 return (error); 1461 } 1462 so->so_rcv.sb_flags |= SB_AUTOSIZE; 1463 so->so_snd.sb_flags |= SB_AUTOSIZE; 1464 INP_INFO_WLOCK(&V_tcbinfo); 1465 error = in_pcballoc(so, &V_tcbinfo); 1466 if (error) { 1467 INP_INFO_WUNLOCK(&V_tcbinfo); 1468 return (error); 1469 } 1470 inp = sotoinpcb(so); 1471#ifdef INET6 1472 if (isipv6) { 1473 inp->inp_vflag |= INP_IPV6; 1474 inp->in6p_hops = -1; /* use kernel default */ 1475 } 1476 else 1477#endif 1478 inp->inp_vflag |= INP_IPV4; 1479 tp = tcp_newtcpcb(inp); 1480 if (tp == NULL) { 1481 in_pcbdetach(inp); 1482#ifdef INET6 1483 if (isipv6) 1484 in6_pcbfree(inp); 1485 else 1486#endif 1487 in_pcbfree(inp); 1488 INP_INFO_WUNLOCK(&V_tcbinfo); 1489 return (ENOBUFS); 1490 } 1491 tp->t_state = TCPS_CLOSED; 1492 INP_WUNLOCK(inp); 1493 INP_INFO_WUNLOCK(&V_tcbinfo); 1494 return (0); 1495} 1496 1497/* 1498 * Initiate (or continue) disconnect. 1499 * If embryonic state, just send reset (once). 1500 * If in ``let data drain'' option and linger null, just drop. 1501 * Otherwise (hard), mark socket disconnecting and drop 1502 * current input data; switch states based on user close, and 1503 * send segment to peer (with FIN). 1504 */ 1505static void 1506tcp_disconnect(struct tcpcb *tp) 1507{ 1508 struct inpcb *inp = tp->t_inpcb; 1509 struct socket *so = inp->inp_socket; 1510#ifdef INVARIANTS 1511 INIT_VNET_INET(so->so_vnet); 1512#endif 1513 1514 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 1515 INP_WLOCK_ASSERT(inp); 1516 1517 /* 1518 * Neither tcp_close() nor tcp_drop() should return NULL, as the 1519 * socket is still open. 1520 */ 1521 if (tp->t_state < TCPS_ESTABLISHED) { 1522 tp = tcp_close(tp); 1523 KASSERT(tp != NULL, 1524 ("tcp_disconnect: tcp_close() returned NULL")); 1525 } else if ((so->so_options & SO_LINGER) && so->so_linger == 0) { 1526 tp = tcp_drop(tp, 0); 1527 KASSERT(tp != NULL, 1528 ("tcp_disconnect: tcp_drop() returned NULL")); 1529 } else { 1530 soisdisconnecting(so); 1531 sbflush(&so->so_rcv); 1532 tcp_usrclosed(tp); 1533 if (!(inp->inp_vflag & INP_DROPPED)) 1534 tcp_output_disconnect(tp); 1535 } 1536} 1537 1538/* 1539 * User issued close, and wish to trail through shutdown states: 1540 * if never received SYN, just forget it. If got a SYN from peer, 1541 * but haven't sent FIN, then go to FIN_WAIT_1 state to send peer a FIN. 1542 * If already got a FIN from peer, then almost done; go to LAST_ACK 1543 * state. In all other cases, have already sent FIN to peer (e.g. 1544 * after PRU_SHUTDOWN), and just have to play tedious game waiting 1545 * for peer to send FIN or not respond to keep-alives, etc. 1546 * We can let the user exit from the close as soon as the FIN is acked. 1547 */ 1548static void 1549tcp_usrclosed(struct tcpcb *tp) 1550{ 1551#ifdef INVARIANTS 1552 INIT_VNET_INET(tp->t_inpcb->inp_vnet); 1553#endif 1554 1555 INP_INFO_WLOCK_ASSERT(&V_tcbinfo); 1556 INP_WLOCK_ASSERT(tp->t_inpcb); 1557 1558 switch (tp->t_state) { 1559 case TCPS_LISTEN: 1560 tcp_offload_listen_close(tp); 1561 /* FALLTHROUGH */ 1562 case TCPS_CLOSED: 1563 tp->t_state = TCPS_CLOSED; 1564 tp = tcp_close(tp); 1565 /* 1566 * tcp_close() should never return NULL here as the socket is 1567 * still open. 1568 */ 1569 KASSERT(tp != NULL, 1570 ("tcp_usrclosed: tcp_close() returned NULL")); 1571 break; 1572 1573 case TCPS_SYN_SENT: 1574 case TCPS_SYN_RECEIVED: 1575 tp->t_flags |= TF_NEEDFIN; 1576 break; 1577 1578 case TCPS_ESTABLISHED: 1579 tp->t_state = TCPS_FIN_WAIT_1; 1580 break; 1581 1582 case TCPS_CLOSE_WAIT: 1583 tp->t_state = TCPS_LAST_ACK; 1584 break; 1585 } 1586 if (tp->t_state >= TCPS_FIN_WAIT_2) { 1587 soisdisconnected(tp->t_inpcb->inp_socket); 1588 /* Prevent the connection hanging in FIN_WAIT_2 forever. */ 1589 if (tp->t_state == TCPS_FIN_WAIT_2) { 1590 int timeout; 1591 1592 timeout = (tcp_fast_finwait2_recycle) ? 1593 tcp_finwait2_timeout : tcp_maxidle; 1594 tcp_timer_activate(tp, TT_2MSL, timeout); 1595 } 1596 } 1597} 1598 1599#ifdef DDB 1600static void 1601db_print_indent(int indent) 1602{ 1603 int i; 1604 1605 for (i = 0; i < indent; i++) 1606 db_printf(" "); 1607} 1608 1609static void 1610db_print_tstate(int t_state) 1611{ 1612 1613 switch (t_state) { 1614 case TCPS_CLOSED: 1615 db_printf("TCPS_CLOSED"); 1616 return; 1617 1618 case TCPS_LISTEN: 1619 db_printf("TCPS_LISTEN"); 1620 return; 1621 1622 case TCPS_SYN_SENT: 1623 db_printf("TCPS_SYN_SENT"); 1624 return; 1625 1626 case TCPS_SYN_RECEIVED: 1627 db_printf("TCPS_SYN_RECEIVED"); 1628 return; 1629 1630 case TCPS_ESTABLISHED: 1631 db_printf("TCPS_ESTABLISHED"); 1632 return; 1633 1634 case TCPS_CLOSE_WAIT: 1635 db_printf("TCPS_CLOSE_WAIT"); 1636 return; 1637 1638 case TCPS_FIN_WAIT_1: 1639 db_printf("TCPS_FIN_WAIT_1"); 1640 return; 1641 1642 case TCPS_CLOSING: 1643 db_printf("TCPS_CLOSING"); 1644 return; 1645 1646 case TCPS_LAST_ACK: 1647 db_printf("TCPS_LAST_ACK"); 1648 return; 1649 1650 case TCPS_FIN_WAIT_2: 1651 db_printf("TCPS_FIN_WAIT_2"); 1652 return; 1653 1654 case TCPS_TIME_WAIT: 1655 db_printf("TCPS_TIME_WAIT"); 1656 return; 1657 1658 default: 1659 db_printf("unknown"); 1660 return; 1661 } 1662} 1663 1664static void 1665db_print_tflags(u_int t_flags) 1666{ 1667 int comma; 1668 1669 comma = 0; 1670 if (t_flags & TF_ACKNOW) { 1671 db_printf("%sTF_ACKNOW", comma ? ", " : ""); 1672 comma = 1; 1673 } 1674 if (t_flags & TF_DELACK) { 1675 db_printf("%sTF_DELACK", comma ? ", " : ""); 1676 comma = 1; 1677 } 1678 if (t_flags & TF_NODELAY) { 1679 db_printf("%sTF_NODELAY", comma ? ", " : ""); 1680 comma = 1; 1681 } 1682 if (t_flags & TF_NOOPT) { 1683 db_printf("%sTF_NOOPT", comma ? ", " : ""); 1684 comma = 1; 1685 } 1686 if (t_flags & TF_SENTFIN) { 1687 db_printf("%sTF_SENTFIN", comma ? ", " : ""); 1688 comma = 1; 1689 } 1690 if (t_flags & TF_REQ_SCALE) { 1691 db_printf("%sTF_REQ_SCALE", comma ? ", " : ""); 1692 comma = 1; 1693 } 1694 if (t_flags & TF_RCVD_SCALE) { 1695 db_printf("%sTF_RECVD_SCALE", comma ? ", " : ""); 1696 comma = 1; 1697 } 1698 if (t_flags & TF_REQ_TSTMP) { 1699 db_printf("%sTF_REQ_TSTMP", comma ? ", " : ""); 1700 comma = 1; 1701 } 1702 if (t_flags & TF_RCVD_TSTMP) { 1703 db_printf("%sTF_RCVD_TSTMP", comma ? ", " : ""); 1704 comma = 1; 1705 } 1706 if (t_flags & TF_SACK_PERMIT) { 1707 db_printf("%sTF_SACK_PERMIT", comma ? ", " : ""); 1708 comma = 1; 1709 } 1710 if (t_flags & TF_NEEDSYN) { 1711 db_printf("%sTF_NEEDSYN", comma ? ", " : ""); 1712 comma = 1; 1713 } 1714 if (t_flags & TF_NEEDFIN) { 1715 db_printf("%sTF_NEEDFIN", comma ? ", " : ""); 1716 comma = 1; 1717 } 1718 if (t_flags & TF_NOPUSH) { 1719 db_printf("%sTF_NOPUSH", comma ? ", " : ""); 1720 comma = 1; 1721 } 1722 if (t_flags & TF_NOPUSH) { 1723 db_printf("%sTF_NOPUSH", comma ? ", " : ""); 1724 comma = 1; 1725 } 1726 if (t_flags & TF_MORETOCOME) { 1727 db_printf("%sTF_MORETOCOME", comma ? ", " : ""); 1728 comma = 1; 1729 } 1730 if (t_flags & TF_LQ_OVERFLOW) { 1731 db_printf("%sTF_LQ_OVERFLOW", comma ? ", " : ""); 1732 comma = 1; 1733 } 1734 if (t_flags & TF_LASTIDLE) { 1735 db_printf("%sTF_LASTIDLE", comma ? ", " : ""); 1736 comma = 1; 1737 } 1738 if (t_flags & TF_RXWIN0SENT) { 1739 db_printf("%sTF_RXWIN0SENT", comma ? ", " : ""); 1740 comma = 1; 1741 } 1742 if (t_flags & TF_FASTRECOVERY) { 1743 db_printf("%sTF_FASTRECOVERY", comma ? ", " : ""); 1744 comma = 1; 1745 } 1746 if (t_flags & TF_WASFRECOVERY) { 1747 db_printf("%sTF_WASFRECOVERY", comma ? ", " : ""); 1748 comma = 1; 1749 } 1750 if (t_flags & TF_SIGNATURE) { 1751 db_printf("%sTF_SIGNATURE", comma ? ", " : ""); 1752 comma = 1; 1753 } 1754 if (t_flags & TF_FORCEDATA) { 1755 db_printf("%sTF_FORCEDATA", comma ? ", " : ""); 1756 comma = 1; 1757 } 1758 if (t_flags & TF_TSO) { 1759 db_printf("%sTF_TSO", comma ? ", " : ""); 1760 comma = 1; 1761 } 1762 if (t_flags & TF_ECN_PERMIT) { 1763 db_printf("%sTF_ECN_PERMIT", comma ? ", " : ""); 1764 comma = 1; 1765 } 1766} 1767 1768static void 1769db_print_toobflags(char t_oobflags) 1770{ 1771 int comma; 1772 1773 comma = 0; 1774 if (t_oobflags & TCPOOB_HAVEDATA) { 1775 db_printf("%sTCPOOB_HAVEDATA", comma ? ", " : ""); 1776 comma = 1; 1777 } 1778 if (t_oobflags & TCPOOB_HADDATA) { 1779 db_printf("%sTCPOOB_HADDATA", comma ? ", " : ""); 1780 comma = 1; 1781 } 1782} 1783 1784static void 1785db_print_tcpcb(struct tcpcb *tp, const char *name, int indent) 1786{ 1787 1788 db_print_indent(indent); 1789 db_printf("%s at %p\n", name, tp); 1790 1791 indent += 2; 1792 1793 db_print_indent(indent); 1794 db_printf("t_segq first: %p t_segqlen: %d t_dupacks: %d\n", 1795 LIST_FIRST(&tp->t_segq), tp->t_segqlen, tp->t_dupacks); 1796 1797 db_print_indent(indent); 1798 db_printf("tt_rexmt: %p tt_persist: %p tt_keep: %p\n", 1799 &tp->t_timers->tt_rexmt, &tp->t_timers->tt_persist, &tp->t_timers->tt_keep); 1800 1801 db_print_indent(indent); 1802 db_printf("tt_2msl: %p tt_delack: %p t_inpcb: %p\n", &tp->t_timers->tt_2msl, 1803 &tp->t_timers->tt_delack, tp->t_inpcb); 1804 1805 db_print_indent(indent); 1806 db_printf("t_state: %d (", tp->t_state); 1807 db_print_tstate(tp->t_state); 1808 db_printf(")\n"); 1809 1810 db_print_indent(indent); 1811 db_printf("t_flags: 0x%x (", tp->t_flags); 1812 db_print_tflags(tp->t_flags); 1813 db_printf(")\n"); 1814 1815 db_print_indent(indent); 1816 db_printf("snd_una: 0x%08x snd_max: 0x%08x snd_nxt: x0%08x\n", 1817 tp->snd_una, tp->snd_max, tp->snd_nxt); 1818 1819 db_print_indent(indent); 1820 db_printf("snd_up: 0x%08x snd_wl1: 0x%08x snd_wl2: 0x%08x\n", 1821 tp->snd_up, tp->snd_wl1, tp->snd_wl2); 1822 1823 db_print_indent(indent); 1824 db_printf("iss: 0x%08x irs: 0x%08x rcv_nxt: 0x%08x\n", 1825 tp->iss, tp->irs, tp->rcv_nxt); 1826 1827 db_print_indent(indent); 1828 db_printf("rcv_adv: 0x%08x rcv_wnd: %lu rcv_up: 0x%08x\n", 1829 tp->rcv_adv, tp->rcv_wnd, tp->rcv_up); 1830 1831 db_print_indent(indent); 1832 db_printf("snd_wnd: %lu snd_cwnd: %lu snd_bwnd: %lu\n", 1833 tp->snd_wnd, tp->snd_cwnd, tp->snd_bwnd); 1834 1835 db_print_indent(indent); 1836 db_printf("snd_ssthresh: %lu snd_bandwidth: %lu snd_recover: " 1837 "0x%08x\n", tp->snd_ssthresh, tp->snd_bandwidth, 1838 tp->snd_recover); 1839 1840 db_print_indent(indent); 1841 db_printf("t_maxopd: %u t_rcvtime: %lu t_startime: %lu\n", 1842 tp->t_maxopd, tp->t_rcvtime, tp->t_starttime); 1843 1844 db_print_indent(indent); 1845 db_printf("t_rttime: %d t_rtsq: 0x%08x t_bw_rtttime: %d\n", 1846 tp->t_rtttime, tp->t_rtseq, tp->t_bw_rtttime); 1847 1848 db_print_indent(indent); 1849 db_printf("t_bw_rtseq: 0x%08x t_rxtcur: %d t_maxseg: %u " 1850 "t_srtt: %d\n", tp->t_bw_rtseq, tp->t_rxtcur, tp->t_maxseg, 1851 tp->t_srtt); 1852 1853 db_print_indent(indent); 1854 db_printf("t_rttvar: %d t_rxtshift: %d t_rttmin: %u " 1855 "t_rttbest: %u\n", tp->t_rttvar, tp->t_rxtshift, tp->t_rttmin, 1856 tp->t_rttbest); 1857 1858 db_print_indent(indent); 1859 db_printf("t_rttupdated: %lu max_sndwnd: %lu t_softerror: %d\n", 1860 tp->t_rttupdated, tp->max_sndwnd, tp->t_softerror); 1861 1862 db_print_indent(indent); 1863 db_printf("t_oobflags: 0x%x (", tp->t_oobflags); 1864 db_print_toobflags(tp->t_oobflags); 1865 db_printf(") t_iobc: 0x%02x\n", tp->t_iobc); 1866 1867 db_print_indent(indent); 1868 db_printf("snd_scale: %u rcv_scale: %u request_r_scale: %u\n", 1869 tp->snd_scale, tp->rcv_scale, tp->request_r_scale); 1870 1871 db_print_indent(indent); 1872 db_printf("ts_recent: %u ts_recent_age: %lu\n", 1873 tp->ts_recent, tp->ts_recent_age); 1874 1875 db_print_indent(indent); 1876 db_printf("ts_offset: %u last_ack_sent: 0x%08x snd_cwnd_prev: " 1877 "%lu\n", tp->ts_offset, tp->last_ack_sent, tp->snd_cwnd_prev); 1878 1879 db_print_indent(indent); 1880 db_printf("snd_ssthresh_prev: %lu snd_recover_prev: 0x%08x " 1881 "t_badrxtwin: %lu\n", tp->snd_ssthresh_prev, 1882 tp->snd_recover_prev, tp->t_badrxtwin); 1883 1884 db_print_indent(indent); 1885 db_printf("snd_numholes: %d snd_holes first: %p\n", 1886 tp->snd_numholes, TAILQ_FIRST(&tp->snd_holes)); 1887 1888 db_print_indent(indent); 1889 db_printf("snd_fack: 0x%08x rcv_numsacks: %d sack_newdata: " 1890 "0x%08x\n", tp->snd_fack, tp->rcv_numsacks, tp->sack_newdata); 1891 1892 /* Skip sackblks, sackhint. */ 1893 1894 db_print_indent(indent); 1895 db_printf("t_rttlow: %d rfbuf_ts: %u rfbuf_cnt: %d\n", 1896 tp->t_rttlow, tp->rfbuf_ts, tp->rfbuf_cnt); 1897} 1898 1899DB_SHOW_COMMAND(tcpcb, db_show_tcpcb) 1900{ 1901 struct tcpcb *tp; 1902 1903 if (!have_addr) { 1904 db_printf("usage: show tcpcb <addr>\n"); 1905 return; 1906 } 1907 tp = (struct tcpcb *)addr; 1908 1909 db_print_tcpcb(tp, "tcpcb", 0); 1910} 1911#endif 1912