|
@@ -1387,6 +1387,28 @@ ipv6_pktoptions:
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr,
|
|
|
+ const struct tcphdr *th)
|
|
|
+{
|
|
|
+ /* This is tricky: we move IP6CB at its correct location into
|
|
|
+ * TCP_SKB_CB(). It must be done after xfrm6_policy_check(), because
|
|
|
+ * _decode_session6() uses IP6CB().
|
|
|
+ * barrier() makes sure compiler won't play aliasing games.
|
|
|
+ */
|
|
|
+ memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb),
|
|
|
+ sizeof(struct inet6_skb_parm));
|
|
|
+ barrier();
|
|
|
+
|
|
|
+ TCP_SKB_CB(skb)->seq = ntohl(th->seq);
|
|
|
+ TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
|
|
|
+ skb->len - th->doff*4);
|
|
|
+ TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
|
|
|
+ TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
|
|
|
+ TCP_SKB_CB(skb)->tcp_tw_isn = 0;
|
|
|
+ TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
|
|
|
+ TCP_SKB_CB(skb)->sacked = 0;
|
|
|
+}
|
|
|
+
|
|
|
static int tcp_v6_rcv(struct sk_buff *skb)
|
|
|
{
|
|
|
const struct tcphdr *th;
|
|
@@ -1418,24 +1440,9 @@ static int tcp_v6_rcv(struct sk_buff *skb)
|
|
|
|
|
|
th = tcp_hdr(skb);
|
|
|
hdr = ipv6_hdr(skb);
|
|
|
- /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB()
|
|
|
- * barrier() makes sure compiler wont play fool^Waliasing games.
|
|
|
- */
|
|
|
- memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb),
|
|
|
- sizeof(struct inet6_skb_parm));
|
|
|
- barrier();
|
|
|
-
|
|
|
- TCP_SKB_CB(skb)->seq = ntohl(th->seq);
|
|
|
- TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin +
|
|
|
- skb->len - th->doff*4);
|
|
|
- TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq);
|
|
|
- TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th);
|
|
|
- TCP_SKB_CB(skb)->tcp_tw_isn = 0;
|
|
|
- TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr);
|
|
|
- TCP_SKB_CB(skb)->sacked = 0;
|
|
|
|
|
|
sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest,
|
|
|
- tcp_v6_iif(skb));
|
|
|
+ inet6_iif(skb));
|
|
|
if (!sk)
|
|
|
goto no_tcp_socket;
|
|
|
|
|
@@ -1451,6 +1458,8 @@ process:
|
|
|
if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
|
|
|
goto discard_and_relse;
|
|
|
|
|
|
+ tcp_v6_fill_cb(skb, hdr, th);
|
|
|
+
|
|
|
#ifdef CONFIG_TCP_MD5SIG
|
|
|
if (tcp_v6_inbound_md5_hash(sk, skb))
|
|
|
goto discard_and_relse;
|
|
@@ -1482,6 +1491,8 @@ no_tcp_socket:
|
|
|
if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
|
|
|
goto discard_it;
|
|
|
|
|
|
+ tcp_v6_fill_cb(skb, hdr, th);
|
|
|
+
|
|
|
if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) {
|
|
|
csum_error:
|
|
|
TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS);
|
|
@@ -1505,6 +1516,8 @@ do_time_wait:
|
|
|
goto discard_it;
|
|
|
}
|
|
|
|
|
|
+ tcp_v6_fill_cb(skb, hdr, th);
|
|
|
+
|
|
|
if (skb->len < (th->doff<<2)) {
|
|
|
inet_twsk_put(inet_twsk(sk));
|
|
|
goto bad_packet;
|