aboutsummaryrefslogtreecommitdiff
path: root/sys/netinet/tcp_syncache.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/tcp_syncache.c')
-rw-r--r--sys/netinet/tcp_syncache.c72
1 files changed, 39 insertions, 33 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 606d808676e1..80e6b53d10df 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -131,17 +131,18 @@ static void syncache_timer(void *);
static uint32_t syncookie_mac(struct in_conninfo *, tcp_seq, uint8_t,
uint8_t *, uintptr_t);
static tcp_seq syncookie_generate(struct syncache_head *, struct syncache *);
-static struct syncache
- *syncookie_lookup(struct in_conninfo *, struct syncache_head *,
- struct syncache *, struct tcphdr *, struct tcpopt *,
- struct socket *, uint16_t);
+static bool syncookie_expand(struct in_conninfo *,
+ const struct syncache_head *, struct syncache *,
+ struct tcphdr *, struct tcpopt *, struct socket *,
+ uint16_t);
static void syncache_pause(struct in_conninfo *);
static void syncache_unpause(void *);
static void syncookie_reseed(void *);
#ifdef INVARIANTS
-static int syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch,
- struct syncache *sc, struct tcphdr *th, struct tcpopt *to,
- struct socket *lso, uint16_t port);
+static void syncookie_cmp(struct in_conninfo *,
+ const struct syncache_head *, struct syncache *,
+ struct tcphdr *, struct tcpopt *, struct socket *,
+ uint16_t);
#endif
/*
@@ -442,7 +443,7 @@ syncache_timeout(struct syncache *sc, struct syncache_head *sch, int docallout)
else
TCPT_RANGESET(rexmt,
tcp_rexmit_initial * tcp_backoff[sc->sc_rxmits],
- tcp_rexmit_min, TCPTV_REXMTMAX);
+ tcp_rexmit_min, tcp_rexmit_max);
sc->sc_rxttime = ticks + rexmt;
sc->sc_rxmits++;
if (TSTMP_LT(sc->sc_rxttime, sch->sch_nextc)) {
@@ -1096,6 +1097,7 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
*/
if (locked && !V_tcp_syncookies) {
SCH_UNLOCK(sch);
+ TCPSTAT_INC(tcps_sc_spurcookie);
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected (syncookies disabled)\n",
@@ -1105,17 +1107,21 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
if (locked && !V_tcp_syncookiesonly &&
sch->sch_last_overflow < time_uptime - SYNCOOKIE_LIFETIME) {
SCH_UNLOCK(sch);
+ TCPSTAT_INC(tcps_sc_spurcookie);
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: Spurious ACK, "
"segment rejected (no syncache entry)\n",
s, __func__);
goto failed;
}
- bzero(&scs, sizeof(scs));
- sc = syncookie_lookup(inc, sch, &scs, th, to, *lsop, port);
if (locked)
SCH_UNLOCK(sch);
- if (sc == NULL) {
+ bzero(&scs, sizeof(scs));
+ if (syncookie_expand(inc, sch, &scs, th, to, *lsop, port)) {
+ sc = &scs;
+ TCPSTAT_INC(tcps_sc_recvcookie);
+ } else {
+ TCPSTAT_INC(tcps_sc_failcookie);
if ((s = tcp_log_addrs(inc, th, NULL, NULL)))
log(LOG_DEBUG, "%s; %s: Segment failed "
"SYNCOOKIE authentication, segment rejected "
@@ -2251,8 +2257,8 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc)
return (iss);
}
-static struct syncache *
-syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
+static bool
+syncookie_expand(struct in_conninfo *inc, const struct syncache_head *sch,
struct syncache *sc, struct tcphdr *th, struct tcpopt *to,
struct socket *lso, uint16_t port)
{
@@ -2282,7 +2288,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
/* The recomputed hash matches the ACK if this was a genuine cookie. */
if ((ack & ~0xff) != (hash & ~0xff))
- return (NULL);
+ return (false);
/* Fill in the syncache values. */
sc->sc_flags = 0;
@@ -2342,47 +2348,47 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch,
sc->sc_port = port;
- TCPSTAT_INC(tcps_sc_recvcookie);
- return (sc);
+ return (true);
}
#ifdef INVARIANTS
-static int
-syncookie_cmp(struct in_conninfo *inc, struct syncache_head *sch,
+static void
+syncookie_cmp(struct in_conninfo *inc, const struct syncache_head *sch,
struct syncache *sc, struct tcphdr *th, struct tcpopt *to,
struct socket *lso, uint16_t port)
{
- struct syncache scs, *scx;
+ struct syncache scs;
char *s;
bzero(&scs, sizeof(scs));
- scx = syncookie_lookup(inc, sch, &scs, th, to, lso, port);
+ if (syncookie_expand(inc, sch, &scs, th, to, lso, port) &&
+ (sc->sc_peer_mss != scs.sc_peer_mss ||
+ sc->sc_requested_r_scale != scs.sc_requested_r_scale ||
+ sc->sc_requested_s_scale != scs.sc_requested_s_scale ||
+ (sc->sc_flags & SCF_SACK) != (scs.sc_flags & SCF_SACK))) {
- if ((s = tcp_log_addrs(inc, th, NULL, NULL)) == NULL)
- return (0);
+ if ((s = tcp_log_addrs(inc, th, NULL, NULL)) == NULL)
+ return;
- if (scx != NULL) {
- if (sc->sc_peer_mss != scx->sc_peer_mss)
+ if (sc->sc_peer_mss != scs.sc_peer_mss)
log(LOG_DEBUG, "%s; %s: mss different %i vs %i\n",
- s, __func__, sc->sc_peer_mss, scx->sc_peer_mss);
+ s, __func__, sc->sc_peer_mss, scs.sc_peer_mss);
- if (sc->sc_requested_r_scale != scx->sc_requested_r_scale)
+ if (sc->sc_requested_r_scale != scs.sc_requested_r_scale)
log(LOG_DEBUG, "%s; %s: rwscale different %i vs %i\n",
s, __func__, sc->sc_requested_r_scale,
- scx->sc_requested_r_scale);
+ scs.sc_requested_r_scale);
- if (sc->sc_requested_s_scale != scx->sc_requested_s_scale)
+ if (sc->sc_requested_s_scale != scs.sc_requested_s_scale)
log(LOG_DEBUG, "%s; %s: swscale different %i vs %i\n",
s, __func__, sc->sc_requested_s_scale,
- scx->sc_requested_s_scale);
+ scs.sc_requested_s_scale);
- if ((sc->sc_flags & SCF_SACK) != (scx->sc_flags & SCF_SACK))
+ if ((sc->sc_flags & SCF_SACK) != (scs.sc_flags & SCF_SACK))
log(LOG_DEBUG, "%s; %s: SACK different\n", s, __func__);
- }
- if (s != NULL)
free(s, M_TCPLOG);
- return (0);
+ }
}
#endif /* INVARIANTS */