diff options
author | ps <ps@FreeBSD.org> | 2005-04-21 20:26:07 +0000 |
---|---|---|
committer | ps <ps@FreeBSD.org> | 2005-04-21 20:26:07 +0000 |
commit | 38541e09625ba27273e987779d13f149d13e9dff (patch) | |
tree | b566c78aebb49b73581eba6456f55cb64bc0d93d /sys/netinet/tcp_syncache.c | |
parent | ebae7f1bff2e5883b998c2cb2781f97dc310961c (diff) | |
download | FreeBSD-src-38541e09625ba27273e987779d13f149d13e9dff.zip FreeBSD-src-38541e09625ba27273e987779d13f149d13e9dff.tar.gz |
Fix for interaction problems between TCP SACK and TCP Signature.
If TCP Signatures are enabled, the maximum allowed sack blocks aren't
going to fit. The fix is to compute how many sack blocks fit and tack
these on last. Also on SYNs, defer padding until after the SACK
PERMITTED option has been added.
Found by: Mohan Srinivasan.
Submitted by: Mohan Srinivasan, Noritoshi Demizu.
Reviewed by: Raja Mukerji.
Diffstat (limited to 'sys/netinet/tcp_syncache.c')
-rw-r--r-- | sys/netinet/tcp_syncache.c | 32 |
1 files changed, 22 insertions, 10 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c index b95efb6..1e46d70 100644 --- a/sys/netinet/tcp_syncache.c +++ b/sys/netinet/tcp_syncache.c @@ -983,9 +983,14 @@ syncache_add(inc, to, th, sop, m) * XXX Currently we always record the option by default and will * attempt to use it in syncache_respond(). */ +#if 1 + if (tp->t_flags & TF_SIGNATURE) + sc->sc_flags |= SCF_SIGNATURE; +#else if (to->to_flags & TOF_SIGNATURE) sc->sc_flags = SCF_SIGNATURE; #endif +#endif if (to->to_flags & TOF_SACK) sc->sc_flags |= SCF_SACK; @@ -1051,10 +1056,12 @@ syncache_respond(sc, m) ((sc->sc_flags & SCF_WINSCALE) ? 4 : 0) + ((sc->sc_flags & SCF_TIMESTAMP) ? TCPOLEN_TSTAMP_APPA : 0); #ifdef TCP_SIGNATURE - optlen += (sc->sc_flags & SCF_SIGNATURE) ? - TCPOLEN_SIGNATURE + 2 : 0; + if (sc->sc_flags & SCF_SIGNATURE) + optlen += TCPOLEN_SIGNATURE; #endif - optlen += ((sc->sc_flags & SCF_SACK) ? 4 : 0); + if (sc->sc_flags & SCF_SACK) + optlen += TCPOLEN_SACK_PERMITTED; + optlen = roundup2(optlen, 4); } tlen = hlen + sizeof(struct tcphdr) + optlen; @@ -1175,16 +1182,21 @@ syncache_respond(sc, m) *bp++ = 0; tcp_signature_compute(m, sizeof(struct ip), 0, optlen, optp + 2, IPSEC_DIR_OUTBOUND); - *bp++ = TCPOPT_NOP; - *bp++ = TCPOPT_EOL; - optp += TCPOLEN_SIGNATURE + 2; + optp += TCPOLEN_SIGNATURE; } #endif /* TCP_SIGNATURE */ - if (sc->sc_flags & SCF_SACK) { - *(u_int32_t *)optp = htonl(TCPOPT_SACK_PERMIT_HDR); - optp += 4; - } + if (sc->sc_flags & SCF_SACK) { + *optp++ = TCPOPT_SACK_PERMITTED; + *optp++ = TCPOLEN_SACK_PERMITTED; + } + + { + /* Pad TCP options to a 4 byte boundary */ + int padlen = optlen - (optp - (u_int8_t *)(th + 1)); + while (padlen-- > 0) + *optp++ = TCPOPT_EOL; + } } #ifdef INET6 |