diff options
Diffstat (limited to 'freebsd/sys/netinet/tcp_syncache.c')
-rw-r--r-- | freebsd/sys/netinet/tcp_syncache.c | 92 |
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) |