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