summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_syncache.c
diff options
context:
space:
mode:
authorps <ps@FreeBSD.org>2005-04-21 20:26:07 +0000
committerps <ps@FreeBSD.org>2005-04-21 20:26:07 +0000
commit38541e09625ba27273e987779d13f149d13e9dff (patch)
treeb566c78aebb49b73581eba6456f55cb64bc0d93d /sys/netinet/tcp_syncache.c
parentebae7f1bff2e5883b998c2cb2781f97dc310961c (diff)
downloadFreeBSD-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.c32
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
OpenPOWER on IntegriCloud