summaryrefslogtreecommitdiffstats
path: root/sys/netinet/tcp_syncache.c
diff options
context:
space:
mode:
authordwmalone <dwmalone@FreeBSD.org>2004-07-17 19:44:13 +0000
committerdwmalone <dwmalone@FreeBSD.org>2004-07-17 19:44:13 +0000
commit71eccf2cf55ca05d858bd43ea8dcf26e64a94c66 (patch)
treee3253b105d7c3ba69e7b3d55d4fcea1bbdd49f7c /sys/netinet/tcp_syncache.c
parent4c16bbdae3c2b668d0d9672affa2e8749490f8ae (diff)
downloadFreeBSD-src-71eccf2cf55ca05d858bd43ea8dcf26e64a94c66.zip
FreeBSD-src-71eccf2cf55ca05d858bd43ea8dcf26e64a94c66.tar.gz
The tcp syncache code was leaving the IPv6 flowlabel uninitialised
for the SYN|ACK packet and then letting in6_pcbconnect set the flowlabel later. Arange for the syncache/syncookie code to set and recall the flow label so that the flowlabel used for the SYN|ACK is consistent. This is done by using some of the cookie (when tcp cookies are enabeled) and by stashing the flowlabel in syncache. Tested and Discovered by: Orla McGann <orly@cnri.dit.ie> Approved by: ume, silby MFC after: 1 month
Diffstat (limited to 'sys/netinet/tcp_syncache.c')
-rw-r--r--sys/netinet/tcp_syncache.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index dbbfbb1..9947d53 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -38,6 +38,7 @@
#include "opt_inet6.h"
#include "opt_ipsec.h"
#include "opt_mac.h"
+#include "opt_random_ip_id.h"
#include "opt_tcpdebug.h"
#include "opt_tcp_sack.h"
@@ -120,7 +121,7 @@ static int syncache_respond(struct syncache *, struct mbuf *);
static struct socket *syncache_socket(struct syncache *, struct socket *,
struct mbuf *m);
static void syncache_timer(void *);
-static u_int32_t syncookie_generate(struct syncache *);
+static u_int32_t syncookie_generate(struct syncache *, u_int32_t *);
static struct syncache *syncookie_lookup(struct in_conninfo *,
struct tcphdr *, struct socket *);
@@ -640,6 +641,9 @@ syncache_socket(sc, lso, m)
inp->in6p_laddr = laddr6;
goto abort;
}
+ /* Override flowlabel from in6_pcbconnect. */
+ inp->in6p_flowinfo &= ~IPV6_FLOWLABEL_MASK;
+ inp->in6p_flowinfo |= sc->sc_flowlabel;
} else
#endif
{
@@ -829,6 +833,7 @@ syncache_add(inc, to, th, sop, m)
struct syncache_head *sch;
struct mbuf *ipopts = NULL;
struct rmxp_tao tao;
+ u_int32_t flowtmp;
int i, win;
INP_INFO_WLOCK_ASSERT(&tcbinfo);
@@ -938,10 +943,25 @@ syncache_add(inc, to, th, sop, m)
sc->sc_irs = th->th_seq;
sc->sc_flags = 0;
sc->sc_peer_mss = to->to_flags & TOF_MSS ? to->to_mss : 0;
- if (tcp_syncookies)
- sc->sc_iss = syncookie_generate(sc);
- else
+ sc->sc_flowlabel = 0;
+ if (tcp_syncookies) {
+ sc->sc_iss = syncookie_generate(sc, &flowtmp);
+ if (inc->inc_isipv6 &&
+ (sc->sc_tp->t_inpcb->in6p_flags & IN6P_AUTOFLOWLABEL)) {
+ sc->sc_flowlabel = flowtmp & IPV6_FLOWLABEL_MASK;
+ }
+ } else {
sc->sc_iss = arc4random();
+ if (inc->inc_isipv6 &&
+ (sc->sc_tp->t_inpcb->in6p_flags & IN6P_AUTOFLOWLABEL)) {
+ sc->sc_flowlabel =
+#ifdef RANDOM_IP_ID
+ (htonl(ip6_randomflowlabel()) & IPV6_FLOWLABEL_MASK);
+#else
+ (htonl(ip6_flow_seq++) & IPV6_FLOWLABEL_MASK);
+#endif
+ }
+ }
/* Initial receive window: clip sbspace to [0 .. TCP_MAXWIN] */
win = sbspace(&so->so_rcv);
@@ -1153,7 +1173,8 @@ syncache_respond(sc, m)
ip6->ip6_dst = sc->sc_inc.inc6_faddr;
ip6->ip6_plen = htons(tlen - hlen);
/* ip6_hlim is set after checksum */
- /* ip6_flow = ??? */
+ ip6->ip6_flow &= ~IPV6_FLOWLABEL_MASK;
+ ip6->ip6_flow |= sc->sc_flowlabel;
th = (struct tcphdr *)(ip6 + 1);
} else
@@ -1344,7 +1365,7 @@ CTASSERT(sizeof(struct md5_add) == 28);
*/
static u_int32_t
-syncookie_generate(struct syncache *sc)
+syncookie_generate(struct syncache *sc, u_int32_t *flowid)
{
u_int32_t md5_buffer[4];
u_int32_t data;
@@ -1386,6 +1407,7 @@ syncookie_generate(struct syncache *sc)
MD5Add(add);
MD5Final((u_char *)&md5_buffer, &syn_ctx);
data ^= (md5_buffer[0] & ~SYNCOOKIE_WNDMASK);
+ *flowid = md5_buffer[1];
return (data);
}
@@ -1444,11 +1466,14 @@ syncookie_lookup(inc, th, so)
sc->sc_ipopts = NULL;
sc->sc_inc.inc_fport = inc->inc_fport;
sc->sc_inc.inc_lport = inc->inc_lport;
+ sc->sc_tp = sototcpcb(so);
#ifdef INET6
sc->sc_inc.inc_isipv6 = inc->inc_isipv6;
if (inc->inc_isipv6) {
sc->sc_inc.inc6_faddr = inc->inc6_faddr;
sc->sc_inc.inc6_laddr = inc->inc6_laddr;
+ if (sc->sc_tp->t_inpcb->in6p_flags & IN6P_AUTOFLOWLABEL)
+ sc->sc_flowlabel = md5_buffer[1] & IPV6_FLOWLABEL_MASK;
} else
#endif
{
OpenPOWER on IntegriCloud