58#include "opt_tcpdebug.h"
62#include <sys/kernel.h>
66#include <sys/malloc.h>
69#include <sys/protosw.h>
72#include <sys/signalvar.h>
73#include <sys/socket.h>
74#include <sys/socketvar.h>
75#include <sys/sysctl.h>
76#include <sys/syslog.h>
80#include <machine/cpu.h>
85#include <net/if_var.h>
102#include <netinet6/in6_pcb.h>
103#include <netinet6/in6_var.h>
104#include <netinet6/ip6_var.h>
105#include <netinet6/nd6.h>
112#include <netinet6/tcp6_var.h>
129#include <netipsec/ipsec_support.h>
131#include <machine/in_cksum.h>
133#include <security/mac/mac_framework.h>
138SYSCTL_INT(_net_inet_tcp, OID_AUTO, log_in_vain, CTLFLAG_VNET | CTLFLAG_RW,
139 &VNET_NAME(tcp_log_in_vain), 0,
140 "Log all incoming TCP segments to closed ports");
143#define V_blackhole VNET(blackhole)
144SYSCTL_INT(_net_inet_tcp, OID_AUTO, blackhole, CTLFLAG_VNET | CTLFLAG_RW,
145 &VNET_NAME(blackhole), 0,
146 "Do not send RST on segments to closed ports");
149#define V_blackhole_local VNET(blackhole_local)
150SYSCTL_BOOL(_net_inet_tcp, OID_AUTO, blackhole_local, CTLFLAG_VNET |
151 CTLFLAG_RW, &VNET_NAME(blackhole_local),
false,
152 "Enforce net.inet.tcp.blackhole for locally originated packets");
156 &VNET_NAME(tcp_delack_enabled), 0,
157 "Delay ACK to try and piggyback it onto a data packet");
160SYSCTL_INT(_net_inet_tcp, OID_AUTO, drop_synfin, CTLFLAG_VNET | CTLFLAG_RW,
161 &VNET_NAME(drop_synfin), 0,
162 "Drop TCP packets with SYN+FIN set");
165SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_prr_conservative, CTLFLAG_VNET | CTLFLAG_RW,
166 &VNET_NAME(tcp_do_prr_conservative), 0,
167 "Do conservative Proportional Rate Reduction");
170SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_prr, CTLFLAG_VNET | CTLFLAG_RW,
171 &VNET_NAME(tcp_do_prr), 1,
172 "Enable Proportional Rate Reduction per RFC 6937");
175SYSCTL_INT(_net_inet_tcp, OID_AUTO, do_lrd, CTLFLAG_VNET | CTLFLAG_RW,
176 &VNET_NAME(tcp_do_lrd), 1,
177 "Perform Lost Retransmission Detection");
180SYSCTL_INT(_net_inet_tcp, OID_AUTO, newcwv, CTLFLAG_VNET | CTLFLAG_RW,
181 &VNET_NAME(tcp_do_newcwv), 0,
182 "Enable New Congestion Window Validation per RFC7661");
185SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3042, CTLFLAG_VNET | CTLFLAG_RW,
186 &VNET_NAME(tcp_do_rfc3042), 0,
187 "Enable RFC 3042 (Limited Transmit)");
190SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_VNET | CTLFLAG_RW,
191 &VNET_NAME(tcp_do_rfc3390), 0,
192 "Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
196 CTLFLAG_VNET | CTLFLAG_RW, &VNET_NAME(tcp_initcwnd_segments), 0,
197 "Slow-start flight size (initial congestion window) in number of segments");
200SYSCTL_INT(_net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_VNET | CTLFLAG_RW,
201 &VNET_NAME(tcp_do_rfc3465), 0,
202 "Enable RFC 3465 (Appropriate Byte Counting)");
205SYSCTL_INT(_net_inet_tcp, OID_AUTO, abc_l_var, CTLFLAG_VNET | CTLFLAG_RW,
206 &VNET_NAME(tcp_abc_l_var), 2,
207 "Cap the max cwnd increment during slow-start to this number of segments");
210 CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
214SYSCTL_INT(_net_inet_tcp_ecn, OID_AUTO, enable, CTLFLAG_VNET | CTLFLAG_RW,
215 &VNET_NAME(tcp_do_ecn), 0,
219SYSCTL_INT(_net_inet_tcp_ecn, OID_AUTO, maxretries, CTLFLAG_VNET | CTLFLAG_RW,
220 &VNET_NAME(tcp_ecn_maxretries), 0,
221 "Max retries before giving up on ECN");
224SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_syn, CTLFLAG_VNET | CTLFLAG_RW,
225 &VNET_NAME(tcp_insecure_syn), 0,
226 "Follow RFC793 instead of RFC5961 criteria for accepting SYN packets");
229SYSCTL_INT(_net_inet_tcp, OID_AUTO, insecure_rst, CTLFLAG_VNET | CTLFLAG_RW,
230 &VNET_NAME(tcp_insecure_rst), 0,
231 "Follow RFC793 instead of RFC5961 criteria for accepting RST packets");
234#define V_tcp_recvspace VNET(tcp_recvspace)
236 &VNET_NAME(tcp_recvspace), 0,
"Initial receive socket buffer size");
239SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_auto, CTLFLAG_VNET | CTLFLAG_RW,
240 &VNET_NAME(tcp_do_autorcvbuf), 0,
241 "Enable automatic receive buffer sizing");
244SYSCTL_INT(_net_inet_tcp, OID_AUTO, recvbuf_max, CTLFLAG_VNET | CTLFLAG_RW,
245 &VNET_NAME(tcp_autorcvbuf_max), 0,
246 "Max size of automatic receive buffer");
256 tcpstat,
"TCP statistics (struct tcpstat, netinet/tcp_var.h)");
259 CTLFLAG_VNET, &VNET_NAME(tcps_states)[0],
TCP_NSTATES,
260 "TCP connection counts by TCP state");
270 counter_u64_add(VNET(
tcpstat)[statnum], val);
278hhook_run_tcp_est_in(
struct tcpcb *tp,
struct tcphdr *th,
struct tcpopt *to)
419 if (
CC_ALGO(tp)->conn_init != NULL)
477 if (
CC_ALGO(tp)->cong_signal != NULL) {
491 if (
CC_ALGO(tp)->post_recovery != NULL) {
510#define DELAY_ACK(tp, tlen) \
511 ((!tcp_timer_active(tp, TT_DELACK) && \
512 (tp->t_flags & TF_RXWIN0SENT) == 0) && \
513 (tlen <= tp->t_maxseg) && \
514 (V_tcp_delack_enabled || (tp->t_flags & TF_NEEDSYN)))
521 if (
CC_ALGO(tp)->ecnpkt_handler != NULL) {
566tcp6_input_with_port(
struct mbuf **mp,
int *offp,
int proto,
uint16_t port)
569 struct in6_ifaddr *ia6;
573 if (m->m_len < *offp +
sizeof(
struct tcphdr)) {
574 m = m_pullup(m, *offp +
sizeof(
struct tcphdr));
578 return (IPPROTO_DONE);
586 ip6 = mtod(m,
struct ip6_hdr *);
587 ia6 = in6ifa_ifwithaddr(&ip6->
ip6_dst, 0 ,
false);
588 if (ia6 && (ia6->ia6_flags & IN6_IFF_ANYCAST)) {
590 (caddr_t)&ip6->
ip6_dst - (caddr_t)ip6);
592 return (IPPROTO_DONE);
600tcp6_input(
struct mbuf **mp,
int *offp,
int proto)
603 return(tcp6_input_with_port(mp, offp, proto, 0));
610 struct mbuf *m = *mp;
611 struct tcphdr *th = NULL;
612 struct ip *
ip = NULL;
613 struct inpcb *inp = NULL;
614 struct tcpcb *tp = NULL;
615 struct socket *so = NULL;
629 struct m_tag *fwd_tag = NULL;
634 const void *ip6 = NULL;
644 struct tcphdr tcp_savetcp;
651 isipv6 = (mtod(m,
struct ip *)->ip_v == 6) ? 1 : 0;
662 ip6 = mtod(m,
struct ip6_hdr *);
663 th = (
struct tcphdr *)((caddr_t)ip6 + off0);
664 tlen =
sizeof(*ip6) + ntohs(ip6->ip6_plen) - off0;
667 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID_IPV6) {
668 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
669 th->th_sum = m->m_pkthdr.csum_data;
671 th->th_sum = in6_cksum_pseudo(ip6, tlen,
673 th->th_sum ^= 0xffff;
675 th->th_sum = in6_cksum(m,
IPPROTO_TCP, off0, tlen);
689 if (IN6_IS_ADDR_UNSPECIFIED(&ip6->
ip6_src)) {
696#if defined(INET) && defined(INET6)
705 if (off0 >
sizeof (
struct ip)) {
707 off0 =
sizeof(
struct ip);
709 if (m->m_len < sizeof (
struct tcpiphdr)) {
710 if ((m = m_pullup(m,
sizeof (
struct tcpiphdr)))
713 return (IPPROTO_DONE);
716 ip = mtod(m,
struct ip *);
717 th = (
struct tcphdr *)((caddr_t)
ip + off0);
723 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
724 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
725 th->th_sum = m->m_pkthdr.csum_data;
729 htonl(m->m_pkthdr.csum_data + tlen +
731 th->th_sum ^= 0xffff;
741 ipov->
ih_len = htons(tlen);
742 th->th_sum = in_cksum(m, len);
753 if (th->th_sum && (port == 0)) {
764 off = th->th_off << 2;
765 if (off <
sizeof (
struct tcphdr) || off > tlen) {
770 if (off >
sizeof (
struct tcphdr)) {
773 if (m->m_len < off0 + off) {
774 m = m_pullup(m, off0 + off);
777 return (IPPROTO_DONE);
780 ip6 = mtod(m,
struct ip6_hdr *);
781 th = (
struct tcphdr *)((caddr_t)ip6 + off0);
784#if defined(INET) && defined(INET6)
789 if (m->m_len <
sizeof(
struct ip) + off) {
790 if ((m = m_pullup(m,
sizeof (
struct ip) + off))
793 return (IPPROTO_DONE);
795 ip = mtod(m,
struct ip *);
796 th = (
struct tcphdr *)((caddr_t)
ip + off0);
800 optlen = off -
sizeof (
struct tcphdr);
801 optp = (u_char *)(th + 1);
813 drop_hdrlen = off0 + off;
820 (isipv6 && (m->m_flags & M_IP6_NEXTHOP))
822 || (!isipv6 && (m->m_flags & M_IP_NEXTHOP))
825#
if defined(INET) && !defined(INET6)
826 (m->m_flags & M_IP_NEXTHOP)
829 fwd_tag = m_tag_find(m, PACKET_TAG_IPFORWARD, NULL);
836 lookupflag = (thflags & (TH_ACK|TH_SYN)) == TH_SYN ?
840 if (isipv6 && fwd_tag != NULL) {
841 struct sockaddr_in6 *next_hop6;
843 next_hop6 = (
struct sockaddr_in6 *)(fwd_tag + 1);
850 lookupflag, m->m_pkthdr.rcvif, m);
858 th->th_sport, &next_hop6->sin6_addr,
859 next_hop6->sin6_port ? ntohs(next_hop6->sin6_port) :
865 th->th_sport, &ip6->
ip6_dst, th->th_dport,
869#if defined(INET6) && defined(INET)
873 if (fwd_tag != NULL) {
882 ip->
ip_dst, th->th_dport, lookupflag, m->m_pkthdr.rcvif, m);
897 th->th_sport,
ip->
ip_dst, th->th_dport,
914 log(LOG_INFO,
"%s; %s: Connection attempt "
915 "to closed port\n", s, __func__);
924 isipv6 ? !in6_localaddr(&ip6->
ip6_src) :
949 (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) &&
954#if defined(IPSEC) || defined(IPSEC_SUPPORT)
956 if (isipv6 && IPSEC_ENABLED(ipv6) &&
957 IPSEC_CHECK_POLICY(ipv6, m, inp) != 0) {
965 if (IPSEC_ENABLED(ipv4) &&
966 IPSEC_CHECK_POLICY(ipv4, m, inp) != 0) {
994 (thflags & TH_SYN) ?
TO_SYN : 0);
1000 return (IPPROTO_DONE);
1027 if (mac_inpcb_check_deliver(inp, m))
1031 KASSERT(so != NULL, (
"%s: so == NULL", __func__));
1033 if (so->so_options & SO_DEBUG) {
1037 bcopy((
char *)ip6, (
char *)tcp_saveipgen,
sizeof(*ip6));
1040 bcopy((
char *)
ip, (
char *)tcp_saveipgen,
sizeof(*
ip));
1050 (
"%s: so accepting but tp %p not listening", __func__, tp));
1054 bzero(&inc,
sizeof(inc));
1060 inc.inc6_faddr = ip6->
ip6_src;
1061 inc.inc6_laddr = ip6->
ip6_dst;
1065 inc.inc_faddr =
ip->ip_src;
1068 inc.inc_fport = th->th_sport;
1069 inc.inc_lport = th->th_dport;
1077 if ((thflags & (TH_RST|TH_ACK|TH_SYN)) == TH_ACK) {
1089 if (rstreason < 0) {
1097 }
else if (rstreason == 0) {
1120 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1121 "Socket allocation failed due to "
1122 "limits or memory shortage, %s\n",
1125 "sending RST" :
"try again");
1148 (
"%s: ", __func__));
1157 return (IPPROTO_DONE);
1169 if (thflags & TH_RST) {
1176 if ((thflags & TH_SYN) == 0) {
1178 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1179 "SYN is missing, segment ignored\n",
1187 if (thflags & TH_ACK) {
1189 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1190 "SYN|ACK invalid, segment rejected\n",
1210 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1211 "SYN|FIN segment ignored (based on "
1212 "sysctl setting)\n", s, __func__);
1223 KASSERT((thflags & (TH_RST|TH_ACK)) == 0,
1224 (
"%s: Listen socket: TH_RST or TH_ACK set", __func__));
1225 KASSERT(thflags & (TH_SYN),
1226 (
"%s: Listen socket: TH_SYN not set", __func__));
1259 if (isipv6 && !V_ip6_use_deprecated) {
1260 struct in6_ifaddr *ia6;
1262 ia6 = in6ifa_ifwithaddr(&ip6->
ip6_dst, 0 ,
false);
1264 (ia6->ia6_flags & IN6_IFF_DEPRECATED)) {
1266 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1267 "Connection attempt to deprecated "
1268 "IPv6 address rejected\n",
1286 if (m->m_flags & (M_BCAST|M_MCAST)) {
1288 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1289 "Connection attempt from broad- or multicast "
1290 "link layer address ignored\n", s, __func__);
1295 if (th->th_dport == th->th_sport &&
1298 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1299 "Connection attempt to/from self "
1300 "ignored\n", s, __func__);
1303 if (IN6_IS_ADDR_MULTICAST(&ip6->
ip6_dst) ||
1304 IN6_IS_ADDR_MULTICAST(&ip6->
ip6_src)) {
1306 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1307 "Connection attempt from/to multicast "
1308 "address ignored\n", s, __func__);
1313#if defined(INET) && defined(INET6)
1318 if (th->th_dport == th->th_sport &&
1321 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1322 "Connection attempt from/to self "
1323 "ignored\n", s, __func__);
1327 IN_MULTICAST(ntohl(
ip->ip_src.s_addr)) ||
1331 log(LOG_DEBUG,
"%s; %s: Listen socket: "
1332 "Connection attempt from/to broad- "
1333 "or multicast address ignored\n",
1344 if (so->so_options & SO_DEBUG)
1346 (
void *)tcp_saveipgen, &tcp_savetcp, 0);
1350 if ((so =
syncache_add(&inc, &to, th, inp, so, m, NULL, NULL,
1351 iptos, port)) != NULL)
1352 goto tfo_socket_result;
1358 return (IPPROTO_DONE);
1369#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
1376 if (!TCPMD5_ENABLED() ||
1398 return (IPPROTO_DONE);
1423 return (IPPROTO_DONE);
1466 struct tcpcb *tp,
int tlen)
1474 if (tp->
rfbuf_cnt > ((so->so_rcv.sb_hiwat / 2)/ 4 * 3) &&
1478 TCP_PROBE6(receive__autoresize, NULL, tp, m, tp, th, newsize);
1512 SOCKBUF_LOCK_ASSERT(&so->so_rcv);
1513 sorwakeup_locked(so);
1519 struct tcpcb *tp,
int drop_hdrlen,
int tlen,
uint8_t iptos)
1522 int acked, ourfinisacked, needoutput = 0, sack_changed;
1523 int rstreason, todrop, win, incforsyn = 0;
1539 struct tcphdr tcp_savetcp;
1546 nsegs = max(1, m->m_pkthdr.lro_nsegs);
1562 if ((thflags & TH_SYN) && (thflags & TH_FIN) &&
V_drop_synfin) {
1564 log(LOG_DEBUG,
"%s; %s: "
1565 "SYN|FIN segment ignored (based on "
1566 "sysctl setting)\n", s, __func__);
1609 (th->th_off << 2) -
sizeof(
struct tcphdr),
1610 (thflags & TH_SYN) ?
TO_SYN : 0);
1612#if defined(IPSEC_SUPPORT) || defined(TCP_SIGNATURE)
1670 tp->
t_flags &= ~TF_SACK_PERMIT;
1700 log(LOG_DEBUG,
"%s; %s: Timestamp missing, "
1701 "segment processed normally\n",
1707 log(LOG_DEBUG,
"%s; %s: Timestamp missing, "
1708 "segment silently dropped\n", s, __func__);
1722 log(LOG_DEBUG,
"%s; %s: Timestamp not expected, "
1723 "segment processed normally\n", s, __func__);
1747 (thflags & (TH_SYN|TH_FIN|TH_RST|TH_URG|TH_ACK)) == TH_ACK &&
1749 tiwin && tiwin == tp->
snd_wnd &&
1771 TAILQ_EMPTY(&tp->snd_holes)) {
1817 hhook_run_tcp_est_in(tp, th, &to);
1822 sbdrop(&so->so_snd, acked);
1854 if (so->so_options & SO_DEBUG)
1856 (
void *)tcp_saveipgen,
1866 if (sbavail(&so->so_snd))
1867 (void) tcp_output(tp);
1870 }
else if (th->th_ack == tp->
snd_una &&
1871 tlen <= sbspace(&so->so_rcv)) {
1906 if (so->so_options & SO_DEBUG)
1908 (
void *)tcp_saveipgen, &tcp_savetcp, 0);
1915 SOCKBUF_LOCK(&so->so_rcv);
1916 if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
1924 if (!sbreserve_locked(&so->so_rcv,
1926 so->so_rcv.sb_flags &= ~SB_AUTOSIZE;
1927 m_adj(m, drop_hdrlen);
1928 sbappendstream_locked(&so->so_rcv, m, 0);
1931 sorwakeup_locked(so);
1948 win = sbspace(&so->so_rcv);
1959 if ((thflags & TH_ACK) &&
1973 if ((thflags & (TH_SYN|TH_ACK)) == (TH_SYN|TH_ACK)) {
1976 }
else if (thflags & TH_SYN) {
1981 }
else if (!(thflags & (TH_ACK|TH_FIN|TH_RST))) {
2003 if ((thflags & (TH_ACK|TH_RST)) == (TH_ACK|TH_RST)) {
2008 if (thflags & TH_RST)
2010 if (!(thflags & TH_SYN))
2013 tp->
irs = th->th_seq;
2015 if (thflags & TH_ACK) {
2016 int tfo_partial_ack = 0;
2021 mac_socketpeer_set_from_mbuf(m, so);
2038 tfo_partial_ack = 1;
2044 if (
DELAY_ACK(tp, tlen) && tlen != 0 && !tfo_partial_ack)
2110 if (thflags & TH_ACK)
2141 if (thflags & TH_RST) {
2157 (
"%s: TH_RST for TCPS_SYN_SENT th %p tp %p",
2166 so->so_error = ECONNREFUSED;
2174 so->so_error = ECONNRESET;
2256 todrop = tp->
rcv_nxt - th->th_seq;
2258 if (thflags & TH_SYN) {
2271 || (todrop == tlen && (thflags & TH_FIN) == 0)) {
2296 th->th_seq + todrop);
2303 drop_hdrlen += todrop;
2304 th->th_seq += todrop;
2306 if (th->th_urp > todrop)
2307 th->th_urp -= todrop;
2318 if ((so->so_state & SS_NOFDREF) &&
2321 log(LOG_DEBUG,
"%s; %s: %s: Received %d bytes of data "
2322 "after socket was closed, "
2323 "sending RST and removing tcpcb\n",
2324 s, __func__, tcpstates[tp->
t_state], tlen);
2340 if (todrop >= tlen) {
2358 thflags &= ~(TH_PUSH|TH_FIN);
2382 ((thflags & (TH_SYN|TH_FIN)) != 0))) {
2392 if ((thflags & TH_ACK) == 0) {
2465 if (tlen == 0 && (thflags & TH_FIN) == 0) {
2466 (void)
tcp_reass(tp, (
struct tcphdr *)0, NULL, 0,
2493 !TAILQ_EMPTY(&tp->snd_holes))) {
2494 if (((sack_changed =
tcp_sack_doack(tp, &to, th->th_ack)) != 0) &&
2507 hhook_run_tcp_est_in(tp, th, &to);
2522 if ((thflags & TH_FIN) &&
2565 if (th->th_ack != tp->
snd_una ||
2596 if (awnd < tp->snd_ssthresh) {
2603 (void) tcp_output(tp);
2660 imin(INT_MAX / 65536,
2669 tcps_sack_recovery_episode);
2672 (void) tcp_output(tp);
2674 goto resume_partialack;
2679 (void) tcp_output(tp);
2681 (
"%s: tp->snd_limited too big",
2703 tcp_seq oldsndmax = tp->
snd_max;
2709 (
"%s: dupacks not 1 or 2",
2722 SOCKBUF_LOCK(&so->so_snd);
2723 avail = sbavail(&so->so_snd) -
2725 SOCKBUF_UNLOCK(&so->so_snd);
2727 (void) tcp_output(tp);
2728 sent = tp->
snd_max - oldsndmax;
2729 if (sent > maxseg) {
2732 (sent == maxseg + 1 &&
2734 (
"%s: sent too much",
2737 }
else if (sent > 0)
2768 goto enter_recovery;
2775 (
"%s: th_ack <= snd_una", __func__));
2789 (void) tcp_output(tp);
2802 (void) tcp_output(tp);
2842 KASSERT(acked >= 0, (
"%s: acked unexepectedly negative "
2843 "(tp->snd_una=%u, th->th_ack=%u, tp=%p, m=%p)", __func__,
2844 tp->
snd_una, th->th_ack, tp, m));
2896 if (th->th_ack == tp->
snd_max) {
2916 SOCKBUF_LOCK(&so->so_snd);
2917 if (acked > sbavail(&so->so_snd)) {
2918 if (tp->
snd_wnd >= sbavail(&so->so_snd))
2919 tp->
snd_wnd -= sbavail(&so->so_snd);
2922 mfree = sbcut_locked(&so->so_snd,
2923 (
int)sbavail(&so->so_snd));
2926 mfree = sbcut_locked(&so->so_snd, acked);
2934 sowwakeup_locked(so);
2961 if (ourfinisacked) {
2973 if (so->so_rcv.sb_state & SBS_CANTRCVMORE) {
2974 soisdisconnected(so);
2991 if (ourfinisacked) {
3005 if (ourfinisacked) {
3020 if ((thflags & TH_ACK) &&
3039 if ((thflags & TH_URG) && th->th_urp &&
3047 SOCKBUF_LOCK(&so->so_rcv);
3048 if (th->th_urp + sbavail(&so->so_rcv) > sb_max) {
3051 SOCKBUF_UNLOCK(&so->so_rcv);
3069 tp->
rcv_up = th->th_seq + th->th_urp;
3070 so->so_oobmark = sbavail(&so->so_rcv) +
3072 if (so->so_oobmark == 0)
3073 so->so_rcv.sb_state |= SBS_RCVATMARK;
3077 SOCKBUF_UNLOCK(&so->so_rcv);
3084 if (th->th_urp <= (
uint32_t)tlen &&
3085 !(so->so_options & SO_OOBINLINE)) {
3111 if ((tlen || (thflags & TH_FIN) || (tfo_syn && tlen > 0)) &&
3113 tcp_seq save_start = th->th_seq;
3114 tcp_seq save_rnxt = tp->
rcv_nxt;
3115 int save_tlen = tlen;
3116 m_adj(m, drop_hdrlen);
3129 if (th->th_seq == tp->
rcv_nxt &&
3150 SOCKBUF_LOCK(&so->so_rcv);
3151 if (so->so_rcv.sb_state & SBS_CANTRCVMORE)
3154 sbappendstream_locked(&so->so_rcv, m, 0);
3163 tcp_seq temp = save_start;
3165 thflags =
tcp_reass(tp, th, &temp, &tlen, m);
3171 if ((tlen == 0) && (
SEQ_LT(save_start, save_rnxt))) {
3177 save_start + save_tlen);
3190 save_start + save_tlen);
3192 }
else if (tlen >= save_tlen) {
3195 save_start + save_tlen);
3196 }
else if (tlen > 0) {
3212 len = so->so_rcv.sb_hiwat;
3223 if (thflags & TH_FIN) {
3271 if (so->so_options & SO_DEBUG)
3281 (void) tcp_output(tp);
3316 if (so->so_options & SO_DEBUG)
3322 (void) tcp_output(tp);
3358 int tlen,
int rstreason)
3372 if ((
tcp_get_flags(th) & TH_RST) || m->m_flags & (M_BCAST|M_MCAST))
3375 if (mtod(m,
struct ip *)->
ip_v == 6) {
3376 ip6 = mtod(m,
struct ip6_hdr *);
3377 if (IN6_IS_ADDR_MULTICAST(&ip6->
ip6_dst) ||
3378 IN6_IS_ADDR_MULTICAST(&ip6->
ip6_src))
3383#if defined(INET) && defined(INET6)
3388 ip = mtod(m,
struct ip *);
3390 IN_MULTICAST(ntohl(
ip->ip_src.s_addr)) ||
3403 tcp_respond(tp, mtod(m,
void *), th, m, (tcp_seq)0,
3404 th->th_ack, TH_RST);
3410 tcp_respond(tp, mtod(m,
void *), th, m, th->th_seq+tlen,
3411 (tcp_seq)0, TH_RST|TH_ACK);
3427 for (; cnt > 0; cnt -= optlen, cp += optlen) {
3429 if (opt == TCPOPT_EOL)
3431 if (opt == TCPOPT_NOP)
3437 if (optlen < 2 || optlen > cnt)
3442 if (optlen != TCPOLEN_MAXSEG)
3447 bcopy((
char *)cp + 2,
3452 if (optlen != TCPOLEN_WINDOW)
3457 to->
to_wscale = min(cp[2], TCP_MAX_WINSHIFT);
3459 case TCPOPT_TIMESTAMP:
3460 if (optlen != TCPOLEN_TIMESTAMP)
3463 bcopy((
char *)cp + 2,
3466 bcopy((
char *)cp + 6,
3470 case TCPOPT_SIGNATURE:
3478 if (optlen != TCPOLEN_SIGNATURE)
3483 case TCPOPT_SACK_PERMITTED:
3484 if (optlen != TCPOLEN_SACK_PERMITTED)
3493 if (optlen <= 2 || (optlen - 2) % TCPOLEN_SACK != 0)
3498 to->
to_nsacks = (optlen - 2) / TCPOLEN_SACK;
3502 case TCPOPT_FAST_OPEN:
3533 int cnt = off + th->th_urp - 1;
3536 if (m->m_len > cnt) {
3537 char *cp = mtod(m, caddr_t) + cnt;
3544 bcopy(cp+1, cp, (
unsigned)(m->m_len - cnt - 1));
3546 if (m->m_flags & M_PKTHDR)
3555 panic(
"tcp_pulloutofband");
3573 imax(0, rtt * 1000 / hz));
3586 if ((tp->
t_srtt += delta) <= 0)
3674 size_t min_protoh = isipv6 ?
3675 sizeof (
struct ip6_hdr) + sizeof (struct tcphdr) :
3676 sizeof (struct tcpiphdr);
3678 size_t min_protoh = sizeof(struct tcpiphdr);
3685 if (mtuoffer != -1) {
3686 KASSERT(offer == -1, (
"%s: conflict", __func__));
3687 offer = mtuoffer - min_protoh;
3697#if defined(INET) && defined(INET6)
3716 if (metricptr != NULL)
3750 if (metricptr != NULL)
3758 mss = min(metrics.
rmx_mtu, maxmtu) - min_protoh;
3762 mss = maxmtu - min_protoh;
3764 !in6_localaddr(&inp->in6p_faddr))
3765 mss = min(mss, V_tcp_v6mssdflt);
3768#if defined(INET) && defined(INET6)
3773 mss = maxmtu - min_protoh;
3798 mss = min(mss, offer);
3823 KASSERT(tp != NULL, (
"%s: tp == NULL", __func__));
3825 bzero(&cap,
sizeof(cap));
3839 SOCKBUF_LOCK(&so->so_snd);
3843 bufsize = so->so_snd.sb_hiwat;
3847 bufsize = roundup(bufsize, mss);
3848 if (bufsize > sb_max)
3850 if (bufsize > so->so_snd.sb_hiwat)
3851 (void)sbreserve_locked(&so->so_snd, bufsize, so, NULL);
3853 SOCKBUF_UNLOCK(&so->so_snd);
3864 SOCKBUF_LOCK(&so->so_rcv);
3868 bufsize = so->so_rcv.sb_hiwat;
3869 if (bufsize > mss) {
3870 bufsize = roundup(bufsize, mss);
3871 if (bufsize > sb_max)
3873 if (bufsize > so->so_rcv.sb_hiwat)
3874 (void)sbreserve_locked(&so->so_rcv, bufsize, so, NULL);
3876 SOCKBUF_UNLOCK(&so->so_rcv);
3879 if (cap.
ifcap & CSUM_TSO) {
3898 KASSERT(inc != NULL, (
"tcp_mssopt with NULL in_conninfo pointer"));
3902 mss = V_tcp_v6mssdflt;
3904 min_protoh =
sizeof(
struct ip6_hdr) + sizeof(struct tcphdr);
3907#if defined(INET) && defined(INET6)
3914 min_protoh =
sizeof(
struct tcpiphdr);
3917#if defined(INET6) || defined(INET)
3921 if (maxmtu && thcmtu)
3922 mss = min(maxmtu, thcmtu) - min_protoh;
3923 else if (maxmtu || thcmtu)
3924 mss = max(maxmtu, thcmtu) - min_protoh;
3932 int snd_cnt = 0, limit = 0, del_data = 0, pipe = 0;
3957 imin(INT_MAX / 65536, tp->
t_dupacks) * maxseg);
3980 snd_cnt = imax(snd_cnt, 0) / maxseg;
3997 tp->
snd_cwnd = pipe - del_data + (snd_cnt * maxseg);
4025 (void) tcp_output(tp);
4063 return min(4 * maxseg, max(2 * maxseg, 4380));
4067 return (2 * maxseg);
4068 else if (maxseg > 1095)
4069 return (3 * maxseg);
4071 return (4 * maxseg);
void icmp6_error(struct mbuf *, int, int, int)
#define ICMP6_DST_UNREACH
#define ICMP6_DST_UNREACH_ADDR
#define BANDLIM_UNLIMITED
#define BANDLIM_RST_CLOSEDPORT
#define BANDLIM_RST_OPENPORT
bool in_localip(struct in_addr in)
int in_localaddr(struct in_addr in)
int in_broadcast(struct in_addr in, struct ifnet *ifp)
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)
#define TCP_PROBE6(probe, arg0, arg1, arg2, arg3, arg4, arg5)
#define TCP_PROBE3(probe, arg0, arg1, arg2)
#define INP_TRY_UPGRADE(inp)
#define INP_LOCK_ASSERT(inp)
struct inpcb * in_pcblookup(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *)
#define INP_WLOCK_ASSERT(inp)
struct inpcb * in_pcblookup_mbuf(struct inpcbinfo *, struct in_addr, u_int, struct in_addr, u_int, int, struct ifnet *, struct mbuf *)
#define INP_RLOCK_ASSERT(inp)
#define IPV6_TRAFFIC_CLASS(ip6)
void ip_stripoptions(struct mbuf *m)
struct socket * inp_socket
struct in_conninfo inp_inc
struct in_addr ip_src ip_dst
int32_t sack_bytes_rexmit
void(* tfb_tcp_do_segment)(struct mbuf *, struct tcphdr *, struct socket *, struct tcpcb *, int, int, uint8_t)
unsigned int * t_tfo_pending
struct sackblk sackblks[MAX_SACK_BLKS]
int32_t t_stats_gput_prev
struct statsblob * t_stats
uint32_t snd_ssthresh_prev
struct tcp_function_block * t_fb
#define VOI_TCP_CALCFRWINDIFF
void tcp_trace(short act, short ostate, struct tcpcb *tp, void *ipgen, struct tcphdr *th, int req)
int tcp_ecn_input_segment(struct tcpcb *tp, uint16_t thflags, int iptos)
void tcp_ecn_input_syn_sent(struct tcpcb *tp, uint16_t thflags, int iptos)
void tcp_ecn_input_parallel_syn(struct tcpcb *tp, uint16_t thflags, int iptos)
void tcp_fastopen_disable_path(struct tcpcb *tp)
void tcp_fastopen_decrement_counter(unsigned int *counter)
void tcp_fastopen_update_cache(struct tcpcb *tp, uint16_t mss, uint8_t cookie_len, uint8_t *cookie)
#define V_tcp_fastopen_server_enable
#define V_tcp_fastopen_client_enable
#define TCPS_HAVERCVDFIN(s)
#define TCPS_SYN_RECEIVED
#define TCPS_HAVEESTABLISHED(s)
uint32_t tcp_hc_getmtu(struct in_conninfo *inc)
void tcp_hc_get(struct in_conninfo *inc, struct hc_metrics_lite *hc_metrics_lite)
#define TCP_LOG_EVENT(tp, th, rxbuf, txbuf, eventid, errornum, len, stackinfo, th_hostorder)
void tcp_offload_input(struct tcpcb *tp, struct mbuf *m)
void tcp_pcap_add(struct tcphdr *th, struct mbuf *m, struct mbufq *queue)
int tcp_reass(struct tcpcb *tp, struct tcphdr *th, tcp_seq *seq_start, int *tlenp, struct mbuf *m)
void tcp_update_dsack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
void tcp_clean_sackreport(struct tcpcb *tp)
void tcp_sack_partialack(struct tcpcb *tp, struct tcphdr *th)
int tcp_sack_doack(struct tcpcb *tp, struct tcpopt *to, tcp_seq th_ack)
void tcp_update_sack_list(struct tcpcb *tp, tcp_seq rcv_start, tcp_seq rcv_end)
void tcp_sack_lost_retransmission(struct tcpcb *tp, struct tcphdr *th)
static __inline uint32_t tcp_ts_getticks(void)
#define tcp_rcvseqinit(tp)
#define TCP_TS_TO_TICKS(_t)
char * tcp_log_addrs(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr, const void *ip6hdr)
struct tcpcb * tcp_drop(struct tcpcb *tp, int errno)
char * tcp_log_vain(struct in_conninfo *inc, struct tcphdr *th, void *ip4hdr, const void *ip6hdr)
u_int tcp_maxseg(const struct tcpcb *tp)
void tcp_state_change(struct tcpcb *tp, int newstate)
struct tcpcb * tcp_close(struct tcpcb *tp)
void tcp_respond(struct tcpcb *tp, void *ipgen, struct tcphdr *th, struct mbuf *m, tcp_seq ack, tcp_seq seq, int flags)
struct socket * syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, struct inpcb *inp, struct socket *so, struct mbuf *m, void *tod, void *todctx, uint8_t iptos, uint16_t port)
void syncache_chkrst(struct in_conninfo *inc, struct tcphdr *th, struct mbuf *m, uint16_t port)
int syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, struct socket **lsop, struct mbuf *m, uint16_t port)
void syncache_badack(struct in_conninfo *inc, uint16_t port)
int tcp_timer_active(struct tcpcb *tp, uint32_t timer_type)
void tcp_timer_activate(struct tcpcb *tp, uint32_t timer_type, u_int delta)
int tcp_fast_finwait2_recycle
#define TCPT_RANGESET(tv, value, tvmin, tvmax)
#define TCP_RTT_INVALIDATE
void tcp_twstart(struct tcpcb *tp)
int tcp_twcheck(struct inpcb *inp, struct tcpopt *to, struct tcphdr *th, struct mbuf *m, int tlen)
uint32_t tcp_maxmtu6(struct in_conninfo *, struct tcp_ifcap *)
static uint16_t tcp_get_flags(const struct tcphdr *th)
#define IN_CONGRECOVERY(t_flags)
#define IN_FASTRECOVERY(t_flags)
#define V_tcp_autorcvbuf_max
#define V_tcp_insecure_rst
#define V_tcp_udp_tunneling_overhead
#define TCPSTAT_ADD(name, val)
#define TF2_FBYTES_COMPLETE
static void tcp_fields_to_host(struct tcphdr *th)
#define V_tcp_initcwnd_segments
#define V_tcp_log_in_vain
uint32_t tcp_maxmtu(struct in_conninfo *, struct tcp_ifcap *)
#define EXIT_CONGRECOVERY(t_flags)
#define IN_RECOVERY(t_flags)
#define V_tcp_insecure_syn
#define V_tcp_tolerate_missing_ts
#define BYTES_THIS_ACK(tp, th)
#define V_tcp_sc_rst_sock_fail
#define V_tcp_do_autorcvbuf
#define TCPSTAT_INC(name)
#define IS_FASTOPEN(t_flags)
#define ENTER_FASTRECOVERY(t_flags)
#define V_path_mtu_discovery
#define EXIT_RECOVERY(t_flags)
#define ENTER_CONGRECOVERY(t_flags)
#define V_tcp_do_prr_conservative