diff options
author | andre <andre@FreeBSD.org> | 2007-05-18 21:42:25 +0000 |
---|---|---|
committer | andre <andre@FreeBSD.org> | 2007-05-18 21:42:25 +0000 |
commit | 8a6eb18a6972643916e50e8328c5242b2f819d18 (patch) | |
tree | 8af6d944f6b103ae7fdab0dcbcb58eeb6236cf94 | |
parent | 1411450edd3c7b6c5950eca22263e283cf3b9865 (diff) | |
download | FreeBSD-src-8a6eb18a6972643916e50e8328c5242b2f819d18.zip FreeBSD-src-8a6eb18a6972643916e50e8328c5242b2f819d18.tar.gz |
Be more restrictive with segment validity checks in syncache_expand()
and log check failures to syslog at LOG_DEBUG level.
Always prefill the sc->sc_ts field to use it in the checks.
-rw-r--r-- | sys/netinet/tcp_syncache.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index 90b7c16..4143700 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -830,6 +830,44 @@ syncache_expand(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, s, __func__, th->th_ack, sc->sc_iss); goto failed; } + /* + * The SEQ must match the received initial receive sequence + * number + 1 (the SYN) because we didn't ACK any data that + * may have come with the SYN. + */ + if (th->th_seq != sc->sc_irs + 1) { + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: SEQ %u != IRS+1 %u\n", + s, __func__, th->th_ack, sc->sc_iss); + goto failed; + } + /* + * If timestamps were present in the SYN and we accepted + * them in our SYN|ACK we require them to be present from + * now on. And vice versa. + */ + if ((sc->sc_flags & SCF_TIMESTAMP) && !(to->to_flags & TOF_TS)) { + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: Timestamp missing\n", + s, __func__); + goto failed; + } + if (!(sc->sc_flags & SCF_TIMESTAMP) && (to->to_flags & TOF_TS)) { + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: Timestamp not expected\n", + s, __func__); + goto failed; + } + /* + * If timestamps were negotiated the reflected timestamp + * must be equal to what we actually sent in the SYN|ACK. + */ + if ((to->to_flags & TOF_TS) && to->to_tsecr != sc->sc_ts) { + if ((s = tcp_log_addrs(inc, th, NULL, NULL))) + log(LOG_DEBUG, "%s; %s: TSECR %u != TS %u\n", + s, __func__, to->to_tsecr, sc->sc_ts); + goto failed; + } *lsop = syncache_socket(sc, *lsop, m); @@ -1031,6 +1069,7 @@ syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th, */ if (to->to_flags & TOF_TS) { sc->sc_tsreflect = to->to_tsval; + sc->sc_ts = ticks; sc->sc_flags |= SCF_TIMESTAMP; } if (to->to_flags & TOF_SCALE) { @@ -1218,7 +1257,7 @@ syncache_respond(struct syncache *sc) } if (sc->sc_flags & SCF_TIMESTAMP) { /* Virgin timestamp or TCP cookie enhanced one. */ - to.to_tsval = sc->sc_ts ? sc->sc_ts : ticks; + to.to_tsval = sc->sc_ts; to.to_tsecr = sc->sc_tsreflect; to.to_flags |= TOF_TS; } @@ -1412,8 +1451,7 @@ syncookie_generate(struct syncache_head *sch, struct syncache *sc, data ^= md5_buffer[3]; sc->sc_ts = data; sc->sc_tsoff = data - ticks; /* after XOR */ - } else - sc->sc_ts = 0; + } return; } @@ -1496,6 +1534,7 @@ syncookie_lookup(struct in_conninfo *inc, struct syncache_head *sch, if (data) { sc->sc_flags |= SCF_TIMESTAMP; sc->sc_tsreflect = to->to_tsval; + sc->sc_ts = to->to_tsecr; sc->sc_tsoff = to->to_tsecr - ticks; sc->sc_flags |= (data & 0x1) ? SCF_SIGNATURE : 0; sc->sc_flags |= ((data >> 1) & 0x1) ? SCF_SACK : 0; |