diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 7cdad8401434..f73a97f6e68e 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1348,6 +1348,15 @@ static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | |||
1348 | TCP_SKB_CB(skb)->sacked = 0; | 1348 | TCP_SKB_CB(skb)->sacked = 0; |
1349 | } | 1349 | } |
1350 | 1350 | ||
1351 | static void tcp_v6_restore_cb(struct sk_buff *skb) | ||
1352 | { | ||
1353 | /* We need to move header back to the beginning if xfrm6_policy_check() | ||
1354 | * and tcp_v6_fill_cb() are going to be called again. | ||
1355 | */ | ||
1356 | memmove(IP6CB(skb), &TCP_SKB_CB(skb)->header.h6, | ||
1357 | sizeof(struct inet6_skb_parm)); | ||
1358 | } | ||
1359 | |||
1351 | static int tcp_v6_rcv(struct sk_buff *skb) | 1360 | static int tcp_v6_rcv(struct sk_buff *skb) |
1352 | { | 1361 | { |
1353 | const struct tcphdr *th; | 1362 | const struct tcphdr *th; |
@@ -1480,6 +1489,7 @@ do_time_wait: | |||
1480 | inet_twsk_deschedule(tw, &tcp_death_row); | 1489 | inet_twsk_deschedule(tw, &tcp_death_row); |
1481 | inet_twsk_put(tw); | 1490 | inet_twsk_put(tw); |
1482 | sk = sk2; | 1491 | sk = sk2; |
1492 | tcp_v6_restore_cb(skb); | ||
1483 | goto process; | 1493 | goto process; |
1484 | } | 1494 | } |
1485 | /* Fall through to ACK */ | 1495 | /* Fall through to ACK */ |
@@ -1488,6 +1498,7 @@ do_time_wait: | |||
1488 | tcp_v6_timewait_ack(sk, skb); | 1498 | tcp_v6_timewait_ack(sk, skb); |
1489 | break; | 1499 | break; |
1490 | case TCP_TW_RST: | 1500 | case TCP_TW_RST: |
1501 | tcp_v6_restore_cb(skb); | ||
1491 | goto no_tcp_socket; | 1502 | goto no_tcp_socket; |
1492 | case TCP_TW_SUCCESS: | 1503 | case TCP_TW_SUCCESS: |
1493 | ; | 1504 | ; |
@@ -1522,7 +1533,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb) | |||
1522 | skb->sk = sk; | 1533 | skb->sk = sk; |
1523 | skb->destructor = sock_edemux; | 1534 | skb->destructor = sock_edemux; |
1524 | if (sk_fullsock(sk)) { | 1535 | if (sk_fullsock(sk)) { |
1525 | struct dst_entry *dst = sk->sk_rx_dst; | 1536 | struct dst_entry *dst = READ_ONCE(sk->sk_rx_dst); |
1526 | 1537 | ||
1527 | if (dst) | 1538 | if (dst) |
1528 | dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); | 1539 | dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); |