40#include "opt_tcpdebug.h"
44#include <sys/callout.h>
45#include <sys/kernel.h>
46#include <sys/sysctl.h>
47#include <sys/malloc.h>
51#include <sys/socket.h>
52#include <sys/socketvar.h>
54#include <sys/syslog.h>
56#include <sys/protosw.h>
57#include <sys/random.h>
63#include <net/if_var.h>
76#include <netinet6/in6_pcb.h>
77#include <netinet6/ip6_var.h>
78#include <netinet6/scope6_var.h>
79#include <netinet6/nd6.h>
88#include <netinet6/tcp6_var.h>
95#include <netinet6/ip6protosw.h>
101#include <netipsec/ipsec_support.h>
103#include <machine/in_cksum.h>
105#include <security/mac/mac_framework.h>
108#define V_tcptw_zone VNET(tcptw_zone)
123#define V_twq_2msl VNET(twq_2msl)
127#define V_tw_lock VNET(tw_lock)
129#define TW_LOCK_INIT(tw, d) rw_init_flags(&(tw), (d), 0)
130#define TW_LOCK_DESTROY(tw) rw_destroy(&(tw))
131#define TW_RLOCK(tw) rw_rlock(&(tw))
132#define TW_WLOCK(tw) rw_wlock(&(tw))
133#define TW_RUNLOCK(tw) rw_runlock(&(tw))
134#define TW_WUNLOCK(tw) rw_wunlock(&(tw))
135#define TW_LOCK_ASSERT(tw) rw_assert(&(tw), RA_LOCKED)
136#define TW_RLOCK_ASSERT(tw) rw_assert(&(tw), RA_RLOCKED)
137#define TW_WLOCK_ASSERT(tw) rw_assert(&(tw), RA_WLOCKED)
138#define TW_UNLOCK_ASSERT(tw) rw_assert(&(tw), RA_UNLOCKED)
158 return (imin(imax(halfrange, 32), maxsockets / 5));
170 error = sysctl_handle_int(oidp, &
new, 0, req);
171 if (error == 0 && req->newptr)
180 CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_NEEDGIANT,
182 "Maximum number of compressed TCP TIME_WAIT entries");
185#define V_nolocaltimewait VNET(nolocaltimewait)
186SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_VNET | CTLFLAG_RW,
187 &VNET_NAME(nolocaltimewait),
true,
188 "Do not create compressed TCP TIME_WAIT entries for local connections");
203 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
204 TUNABLE_INT_FETCH(
"net.inet.tcp.maxtcptw", &
maxtcptw);
218 struct epoch_tracker et;
221 while ((tw = TAILQ_FIRST(&
V_twq_2msl)) != NULL)
238 struct tcptw twlocal, *tw;
252 "(inp->inp_flags & INP_DROPPED) != 0"));
257 local = in6_localaddr(&inp->in6p_faddr);
306 recwin = lmin(lmax(sbspace(&so->so_rcv), 0),
308 if (recwin < (so->so_rcv.sb_hiwat / 4) &&
309 recwin < tp->t_maxseg)
353 soisdisconnected(so);
362 tw->
tw_cred = crhold(so->so_cred);
373 KASSERT(so->so_state & SS_PROTOREF,
374 (
"tcp_twstart: !SS_PROTOREF"));
378 so->so_state &= ~SS_PROTOREF;
393 struct mbuf *m,
int tlen)
414 if ((thflags & (TH_SYN | TH_ACK)) == TH_SYN)
419 (
"%s: called without options on a non-SYN segment",
434 if (thflags & TH_RST)
445 if ((thflags & TH_ACK) == 0)
466 if (((thflags & (TH_SYN | TH_ACK)) == TH_SYN) &&
477 if (tw->
t_port != m->m_pkthdr.tcp_tun_port) {
480 (tcp_seq)0, th->th_ack, TH_RST);
487 th->th_seq+tlen, (tcp_seq)0, TH_RST|TH_ACK);
497 if ((thflags & TH_ACK) == 0)
516 if (thflags & TH_FIN) {
517 seq = th->th_seq + tlen + (thflags & TH_SYN ? 1 : 0);
525 if (thflags != TH_ACK || tlen != 0 ||
557 KASSERT(
intotw(inp) == tw, (
"tcp_twclose: inp_ppcb != tw"));
577 KASSERT(so->so_state & SS_PROTOREF,
578 (
"tcp_twclose: INP_SOCKREF && !SS_PROTOREF"));
579 so->so_state &= ~SS_PROTOREF;
603#if defined(INET6) || defined(INET)
604 struct tcphdr *th = NULL;
608 struct ip *
ip = NULL;
610 u_int hdrlen, optlen, ulen;
617 struct udphdr *udp = NULL;
622 m = m_gethdr(M_NOWAIT, MT_DATA);
625 m->m_data += max_linkhdr;
628 mac_inpcb_create_mbuf(inp, m);
633 hdrlen =
sizeof(
struct ip6_hdr) + sizeof(struct tcphdr);
634 ip6 = mtod(m,
struct ip6_hdr *);
636 udp = (
struct udphdr *)(ip6 + 1);
637 hdrlen +=
sizeof(
struct udphdr);
640 ulen = (hdrlen -
sizeof(
struct ip6_hdr));
641 th = (
struct tcphdr *)(udp + 1);
643 th = (
struct tcphdr *)(ip6 + 1);
647#if defined(INET6) && defined(INET)
653 ip = mtod(m,
struct ip *);
656 hdrlen +=
sizeof(
struct udphdr);
659 ulen = (hdrlen -
sizeof(
struct ip));
660 th = (
struct tcphdr *)(udp + 1);
662 th = (
struct tcphdr *)(
ip + 1);
672 if (tw->
t_recent && flags == TH_ACK) {
677#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
687 m->m_len = hdrlen + optlen;
688 m->m_pkthdr.len = m->m_len;
690 KASSERT(max_linkhdr + m->m_len <= MHLEN, (
"tcptw: mbuf too small"));
692 th->th_seq = htonl(tw->
snd_nxt);
693 th->th_ack = htonl(tw->
rcv_nxt);
694 th->th_off = (
sizeof(
struct tcphdr) + optlen) >> 2;
698#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
700 if (!TCPMD5_ENABLED() ||
708 m->m_pkthdr.csum_flags = CSUM_UDP_IPV6;
709 m->m_pkthdr.csum_data = offsetof(
struct udphdr, uh_sum);
711 th->th_sum = htons(0);
713 m->m_pkthdr.csum_flags = CSUM_TCP_IPV6;
714 m->m_pkthdr.csum_data = offsetof(
struct tcphdr, th_sum);
715 th->th_sum = in6_cksum_pseudo(ip6,
718 ip6->ip6_hlim = in6_selecthlim(inp, NULL);
724#if defined(INET6) && defined(INET)
730 m->m_pkthdr.csum_flags = CSUM_UDP;
731 m->m_pkthdr.csum_data = offsetof(
struct udphdr, uh_sum);
734 th->th_sum = htons(0);
736 m->m_pkthdr.csum_flags = CSUM_TCP;
737 m->m_pkthdr.csum_data = offsetof(
struct tcphdr, th_sum);
739 htons(
sizeof(
struct tcphdr) + optlen +
IPPROTO_TCP));
741 ip->
ip_len = htons(m->m_pkthdr.len);
778 int released __unused;
795 KASSERT(!released, (
"%s: inp should not be released here", __func__));
813 if (tw == NULL || (!reuse && (tw->
tw_time - ticks) > 0)) {
817 KASSERT(tw->
tw_inpcb != NULL, (
"%s: tw->tw_inpcb == NULL",
827 if (__predict_true(tw == NULL)) {
836 panic(
"%s: Panic before an infinite "
837 "loop: INP_TIMEWAIT && (INP_FREED "
838 "|| inp last reference) && tw != "
841 log(LOG_ERR,
"%s: Avoid an infinite "
842 "loop: INP_TIMEWAIT && (INP_FREED "
843 "|| inp last reference) && tw != "
static TAILQ_HEAD(handler_chain, proto_handler)
bool in_localip(struct in_addr in)
u_short in_pseudo(u_int32_t a, u_int32_t b, u_int32_t c)
#define TCP_PROBE5(probe, arg0, arg1, arg2, arg3, arg4)
void in_pcbdrop(struct inpcb *inp)
void in_pcbref(struct inpcb *inp)
bool in_pcbrele_wlocked(struct inpcb *inp)
void in_pcbfree(struct inpcb *inp)
#define INP_TRY_UPGRADE(inp)
#define INP_LOCK_ASSERT(inp)
#define V_ipport_lastauto
#define INP_WLOCK_ASSERT(inp)
#define V_ipport_firstauto
#define INP_RLOCK_ASSERT(inp)
int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp)
struct socket * inp_socket
struct ip6_pktopts * in6p_outputopts
struct mbuf * inp_options
struct in_conninfo inp_inc
struct in_addr ip_src ip_dst
void tcp_hpts_remove(struct inpcb *inp)
int tcp_addoptions(struct tcpopt *to, u_char *optp)
static __inline uint32_t tcp_ts_getticks(void)
void tcp_discardcb(struct tcpcb *tp)
void tcpip_fillheaders(struct inpcb *inp, uint16_t port, void *ip_ptr, void *tcp_ptr)
void tcp_state_change(struct tcpcb *tp, int newstate)
void tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
void tcp_twclose(struct tcptw *tw, int reuse)
static int sysctl_maxtcptw(SYSCTL_HANDLER_ARGS)
SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, nolocaltimewait, CTLFLAG_VNET|CTLFLAG_RW, &VNET_NAME(nolocaltimewait), true, "Do not create compressed TCP TIME_WAIT entries for local connections")
static int tcp_twrespond(struct tcptw *, int)
VNET_DEFINE_STATIC(uma_zone_t, tcptw_zone)
void tcp_twstart(struct tcpcb *tp)
#define V_nolocaltimewait
SYSCTL_PROC(_net_inet_tcp, OID_AUTO, maxtcptw, CTLTYPE_INT|CTLFLAG_RW|CTLFLAG_NEEDGIANT, &maxtcptw, 0, sysctl_maxtcptw, "IU", "Maximum number of compressed TCP TIME_WAIT entries")
#define TW_LOCK_INIT(tw, d)
void tcp_tw_zone_change(void)
struct tcptw * tcp_tw_2msl_scan(int reuse)
static void tcp_tw_2msl_stop(struct tcptw *, int)
#define TW_LOCK_DESTROY(tw)
static int tcptw_auto_size(void)
static void tcp_tw_2msl_reset(struct tcptw *, int)
int tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th, struct mbuf *m, int tlen)
static uint16_t tcp_get_flags(const struct tcphdr *th)
static void tcp_set_flags(struct tcphdr *th, uint16_t flags)
#define TCPSTATES_DEC(state)
#define V_tcp_udp_tunneling_port
#define TCPSTATES_INC(state)
#define V_tcp_tolerate_missing_ts
#define TCPSTAT_INC(name)
#define V_path_mtu_discovery