summaryrefslogtreecommitdiffstats
path: root/freebsd/sys/netinet/tcp_syncache.c
diff options
context:
space:
mode:
Diffstat (limited to 'freebsd/sys/netinet/tcp_syncache.c')
-rw-r--r--freebsd/sys/netinet/tcp_syncache.c92
1 files changed, 51 insertions, 41 deletions
diff --git a/freebsd/sys/netinet/tcp_syncache.c b/freebsd/sys/netinet/tcp_syncache.c
index e163aa54..6fdd859d 100644
--- a/freebsd/sys/netinet/tcp_syncache.c
+++ b/freebsd/sys/netinet/tcp_syncache.c
@@ -71,6 +71,7 @@ __FBSDID("$FreeBSD$");
#include <net/vnet.h>
#include <netinet/in.h>
+#include <netinet/in_kdtrace.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/in_var.h>
@@ -104,19 +105,19 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
-static VNET_DEFINE(int, tcp_syncookies) = 1;
+VNET_DEFINE_STATIC(int, tcp_syncookies) = 1;
#define V_tcp_syncookies VNET(tcp_syncookies)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_syncookies), 0,
"Use TCP SYN cookies if the syncache overflows");
-static VNET_DEFINE(int, tcp_syncookiesonly) = 0;
+VNET_DEFINE_STATIC(int, tcp_syncookiesonly) = 0;
#define V_tcp_syncookiesonly VNET(tcp_syncookiesonly)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, syncookies_only, CTLFLAG_VNET | CTLFLAG_RW,
&VNET_NAME(tcp_syncookiesonly), 0,
"Use only TCP SYN cookies");
-static VNET_DEFINE(int, functions_inherit_listen_socket_stack) = 1;
+VNET_DEFINE_STATIC(int, functions_inherit_listen_socket_stack) = 1;
#define V_functions_inherit_listen_socket_stack \
VNET(functions_inherit_listen_socket_stack)
SYSCTL_INT(_net_inet_tcp, OID_AUTO, functions_inherit_listen_socket_stack,
@@ -164,7 +165,7 @@ static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch,
#define TCP_SYNCACHE_HASHSIZE 512
#define TCP_SYNCACHE_BUCKETLIMIT 30
-static VNET_DEFINE(struct tcp_syncache, tcp_syncache);
+VNET_DEFINE_STATIC(struct tcp_syncache, tcp_syncache);
#define V_tcp_syncache VNET(tcp_syncache)
static SYSCTL_NODE(_net_inet_tcp, OID_AUTO, syncache, CTLFLAG_RW, 0,
@@ -185,8 +186,27 @@ SYSCTL_UINT(_net_inet_tcp_syncache, OID_AUTO, hashsize, CTLFLAG_VNET | CTLFLAG_R
&VNET_NAME(tcp_syncache.hashsize), 0,
"Size of TCP syncache hashtable");
-SYSCTL_UINT(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit, CTLFLAG_VNET | CTLFLAG_RW,
+static int
+sysctl_net_inet_tcp_syncache_rexmtlimit_check(SYSCTL_HANDLER_ARGS)
+{
+ int error;
+ u_int new;
+
+ new = V_tcp_syncache.rexmt_limit;
+ error = sysctl_handle_int(oidp, &new, 0, req);
+ if ((error == 0) && (req->newptr != NULL)) {
+ if (new > TCP_MAXRXTSHIFT)
+ error = EINVAL;
+ else
+ V_tcp_syncache.rexmt_limit = new;
+ }
+ return (error);
+}
+
+SYSCTL_PROC(_net_inet_tcp_syncache, OID_AUTO, rexmtlimit,
+ CTLFLAG_VNET | CTLTYPE_UINT | CTLFLAG_RW,
&VNET_NAME(tcp_syncache.rexmt_limit), 0,
+ sysctl_net_inet_tcp_syncache_rexmtlimit_check, "UI",
"Limit on SYN/ACK retransmissions");
VNET_DEFINE(int, tcp_sc_rst_sock_fail) = 1;
@@ -398,8 +418,14 @@ syncache_drop(struct syncache *sc, struct syncache_head *sch)
static void
syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout)
{
- sc->sc_rxttime = ticks +
- TCPTV_RTOBASE * (tcp_syn_backoff[sc->sc_rxmits]);
+ int rexmt;
+
+ if (sc->sc_rxmits == 0)
+ rexmt = TCPTV_RTOBASE;
+ else
+ TCPT_RANGESET(rexmt, TCPTV_RTOBASE * tcp_syn_backoff[sc->sc_rxmits],
+ tcp_rexmit_min, TCPTV_REXMTMAX);
+ sc->sc_rxttime = ticks + rexmt;
sc->sc_rxmits++;
if (TSTMP_LT(sc->sc_rxttime, sch->sch_nextc)) {
sch->sch_nextc = sc->sc_rxttime;
@@ -746,10 +772,9 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
goto abort;
}
#ifdef INET6
- if (sc->sc_inc.inc_flags & INC_ISIPV6) {
+ if (inp->inp_vflag & INP_IPV6PROTO) {
struct inpcb *oinp = sotoinpcb(lso);
- struct in6_addr laddr6;
- struct sockaddr_in6 sin6;
+
/*
* Inherit socket options from the listening socket.
* Note that in6p_inputopts are not (and should not be)
@@ -763,6 +788,11 @@ syncache_socket(struct syncache *sc, struct socket *lso, struct mbuf *m)
if (oinp->in6p_outputopts)
inp->in6p_outputopts =
ip6_copypktopts(oinp->in6p_outputopts, M_NOWAIT);
+ }
+
+ if (sc->sc_inc.inc_flags & INC_ISIPV6) {
+ struct in6_addr laddr6;
+ struct sockaddr_in6 sin6;
sin6.sin6_family = AF_INET6;
sin6.sin6_len = sizeof(sin6);
@@ -1153,25 +1183,6 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
}
}
- /*
- * If timestamps were negotiated, the reflected timestamp
- * must be equal to what we actually sent in the SYN|ACK
- * except in the case of 0. Some boxes are known for sending
- * broken timestamp replies during the 3whs (and potentially
- * during the connection also).
- *
- * Accept the final ACK of 3whs with reflected timestamp of 0
- * instead of sending a RST and deleting the syncache entry.
- */
- if ((to->to_flags & TOF_TS) && to->to_tsecr &&
- to->to_tsecr != sc->sc_ts) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
- log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u, "
- "segment rejected\n",
- s, __func__, to->to_tsecr, sc->sc_ts);
- goto failed;
- }
-
*lsop = syncache_socket(sc, *lsop, m);
if (*lsop == NULL)
@@ -1404,6 +1415,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
mac_syncache_destroy(&maclabel);
#endif
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
/* Retransmit SYN|ACK and reset retransmit count. */
if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) {
log(LOG_DEBUG, "%s; %s: Received duplicate SYN, "
@@ -1418,7 +1430,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
TCPSTAT_INC(tcps_sndtotal);
}
SCH_UNLOCK(sch);
- goto done;
+ goto donenoprobe;
}
if (tfo_cookie_valid) {
@@ -1498,8 +1510,8 @@ skip_alloc:
*/
if (to->to_flags & TOF_TS) {
sc->sc_tsreflect = to->to_tsval;
- sc->sc_ts = tcp_ts_getticks();
sc->sc_flags |= SCF_TIMESTAMP;
+ sc->sc_tsoff = tcp_new_ts_offset(inc);
}
if (to->to_flags & TOF_SCALE) {
int wscale = 0;
@@ -1571,6 +1583,7 @@ skip_alloc:
goto tfo_expanded;
}
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
/*
* Do a standard 3-way handshake.
*/
@@ -1586,8 +1599,11 @@ skip_alloc:
syncache_free(sc);
TCPSTAT_INC(tcps_sc_dropped);
}
+ goto donenoprobe;
done:
+ TCP_PROBE5(receive, NULL, NULL, m, NULL, th);
+donenoprobe:
if (m) {
*lsop = NULL;
m_freem(m);
@@ -1727,8 +1743,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
to.to_flags |= TOF_SCALE;
}
if (sc->sc_flags & SCF_TIMESTAMP) {
- /* Virgin timestamp or TCP cookie enhanced one. */
- to.to_tsval = sc->sc_ts;
+ to.to_tsval = sc->sc_tsoff + tcp_ts_getticks();
to.to_tsecr = sc->sc_tsreflect;
to.to_flags |= TOF_TS;
}
@@ -1799,6 +1814,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
return (error);
}
#endif
+ TCP_PROBE5(send, NULL, NULL, ip6, NULL, th);
error = ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL);
}
#endif
@@ -1819,6 +1835,7 @@ syncache_respond(struct syncache *sc, struct syncache_head *sch, int locked,
return (error);
}
#endif
+ TCP_PROBE5(send, NULL, NULL, ip, NULL, th);
error = ip_output(m, sc->sc_ipopts, NULL, 0, NULL, NULL);
}
#endif
@@ -2033,12 +2050,6 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc)
iss = hash & ~0xff;
iss |= cookie.cookie ^ (hash >> 24);
- /* Randomize the timestamp. */
- if (sc->sc_flags & SCF_TIMESTAMP) {
- sc->sc_ts = arc4random();
- sc->sc_tsoff = sc->sc_ts - tcp_ts_getticks();
- }
-
TCPSTAT_INC(tcps_sc_sendcookie);
return (iss);
}
@@ -2125,8 +2136,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
if (to->to_flags & TOF_TS) {
sc->sc_flags |= SCF_TIMESTAMP;
sc->sc_tsreflect = to->to_tsval;
- sc->sc_ts = to->to_tsecr;
- sc->sc_tsoff = to->to_tsecr - tcp_ts_getticks();
+ sc->sc_tsoff = tcp_new_ts_offset(inc);
}
if (to->to_flags & TOF_SIGNATURE)