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:
parent
d75300bfa5
commit
969860f3ed
@ -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
|
||||
{
|
||||
|
@ -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 */
|
||||
|
Loading…
x
Reference in New Issue
Block a user