diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 7f22973d8a0..7e50c9ded6a 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -1142,6 +1142,28 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, } } #endif /* TCP_SIGNATURE */ + + /* + * RFC 7323 PAWS: If we have a timestamp on this segment and + * it's less than ts_recent, drop it. + * XXXMT: RFC 7323 also requires to send an ACK. + * In tcp_input.c this is only done for TCP segments + * with user data, so be consistent here and just drop + * the segment. + */ + if (sc->sc_flags & SCF_TIMESTAMP && to->to_flags & TOF_TS && + TSTMP_LT(to->to_tsval, sc->sc_tsreflect)) { + SCH_UNLOCK(sch); + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) { + log(LOG_DEBUG, + "%s; %s: SEG.TSval %u < TS.Recent %u, " + "segment dropped\n", s, __func__, + to->to_tsval, sc->sc_tsreflect); + free(s, M_TCPLOG); + } + return (-1); /* Do not send RST */ + } + /* * Pull out the entry to unlock the bucket row. *