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
This commit is contained in:
David Malone 2004-07-17 19:44:13 +00:00
parent d75300bfa5
commit 969860f3ed
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=132307
2 changed files with 32 additions and 6 deletions

View File

@ -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
{

View File

@ -254,6 +254,7 @@ struct syncache {
struct mbuf *sc_ipopts; /* source route */
struct in_conninfo sc_inc; /* addresses */
u_int32_t sc_tsrecent;
u_int32_t sc_flowlabel; /* IPv6 flowlabel */
tcp_cc sc_cc_send; /* holds CC or CCnew */
tcp_cc sc_cc_recv;
tcp_seq sc_irs; /* seq from peer */