diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 5ff87805258e..5d46832c6f72 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -1199,6 +1199,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1199 | inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + | 1199 | inet_csk(newsk)->icsk_ext_hdr_len = (newnp->opt->opt_nflen + |
1200 | newnp->opt->opt_flen); | 1200 | newnp->opt->opt_flen); |
1201 | 1201 | ||
1202 | tcp_ca_openreq_child(newsk, dst); | ||
1203 | |||
1202 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1204 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1203 | newtp->advmss = dst_metric_advmss(dst); | 1205 | newtp->advmss = dst_metric_advmss(dst); |
1204 | if (tcp_sk(sk)->rx_opt.user_mss && | 1206 | if (tcp_sk(sk)->rx_opt.user_mss && |
@@ -1387,6 +1389,28 @@ ipv6_pktoptions: | |||
1387 | return 0; | 1389 | return 0; |
1388 | } | 1390 | } |
1389 | 1391 | ||
1392 | static void tcp_v6_fill_cb(struct sk_buff *skb, const struct ipv6hdr *hdr, | ||
1393 | const struct tcphdr *th) | ||
1394 | { | ||
1395 | /* This is tricky: we move IP6CB at its correct location into | ||
1396 | * TCP_SKB_CB(). It must be done after xfrm6_policy_check(), because | ||
1397 | * _decode_session6() uses IP6CB(). | ||
1398 | * barrier() makes sure compiler won't play aliasing games. | ||
1399 | */ | ||
1400 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
1401 | sizeof(struct inet6_skb_parm)); | ||
1402 | barrier(); | ||
1403 | |||
1404 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
1405 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
1406 | skb->len - th->doff*4); | ||
1407 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
1408 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
1409 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
1410 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
1411 | TCP_SKB_CB(skb)->sacked = 0; | ||
1412 | } | ||
1413 | |||
1390 | static int tcp_v6_rcv(struct sk_buff *skb) | 1414 | static int tcp_v6_rcv(struct sk_buff *skb) |
1391 | { | 1415 | { |
1392 | const struct tcphdr *th; | 1416 | const struct tcphdr *th; |
@@ -1418,24 +1442,9 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1418 | 1442 | ||
1419 | th = tcp_hdr(skb); | 1443 | th = tcp_hdr(skb); |
1420 | hdr = ipv6_hdr(skb); | 1444 | hdr = ipv6_hdr(skb); |
1421 | /* This is tricky : We move IPCB at its correct location into TCP_SKB_CB() | ||
1422 | * barrier() makes sure compiler wont play fool^Waliasing games. | ||
1423 | */ | ||
1424 | memmove(&TCP_SKB_CB(skb)->header.h6, IP6CB(skb), | ||
1425 | sizeof(struct inet6_skb_parm)); | ||
1426 | barrier(); | ||
1427 | |||
1428 | TCP_SKB_CB(skb)->seq = ntohl(th->seq); | ||
1429 | TCP_SKB_CB(skb)->end_seq = (TCP_SKB_CB(skb)->seq + th->syn + th->fin + | ||
1430 | skb->len - th->doff*4); | ||
1431 | TCP_SKB_CB(skb)->ack_seq = ntohl(th->ack_seq); | ||
1432 | TCP_SKB_CB(skb)->tcp_flags = tcp_flag_byte(th); | ||
1433 | TCP_SKB_CB(skb)->tcp_tw_isn = 0; | ||
1434 | TCP_SKB_CB(skb)->ip_dsfield = ipv6_get_dsfield(hdr); | ||
1435 | TCP_SKB_CB(skb)->sacked = 0; | ||
1436 | 1445 | ||
1437 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, | 1446 | sk = __inet6_lookup_skb(&tcp_hashinfo, skb, th->source, th->dest, |
1438 | tcp_v6_iif(skb)); | 1447 | inet6_iif(skb)); |
1439 | if (!sk) | 1448 | if (!sk) |
1440 | goto no_tcp_socket; | 1449 | goto no_tcp_socket; |
1441 | 1450 | ||
@@ -1451,6 +1460,8 @@ process: | |||
1451 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1460 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
1452 | goto discard_and_relse; | 1461 | goto discard_and_relse; |
1453 | 1462 | ||
1463 | tcp_v6_fill_cb(skb, hdr, th); | ||
1464 | |||
1454 | #ifdef CONFIG_TCP_MD5SIG | 1465 | #ifdef CONFIG_TCP_MD5SIG |
1455 | if (tcp_v6_inbound_md5_hash(sk, skb)) | 1466 | if (tcp_v6_inbound_md5_hash(sk, skb)) |
1456 | goto discard_and_relse; | 1467 | goto discard_and_relse; |
@@ -1482,6 +1493,8 @@ no_tcp_socket: | |||
1482 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | 1493 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
1483 | goto discard_it; | 1494 | goto discard_it; |
1484 | 1495 | ||
1496 | tcp_v6_fill_cb(skb, hdr, th); | ||
1497 | |||
1485 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1498 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1486 | csum_error: | 1499 | csum_error: |
1487 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); | 1500 | TCP_INC_STATS_BH(net, TCP_MIB_CSUMERRORS); |
@@ -1505,6 +1518,8 @@ do_time_wait: | |||
1505 | goto discard_it; | 1518 | goto discard_it; |
1506 | } | 1519 | } |
1507 | 1520 | ||
1521 | tcp_v6_fill_cb(skb, hdr, th); | ||
1522 | |||
1508 | if (skb->len < (th->doff<<2)) { | 1523 | if (skb->len < (th->doff<<2)) { |
1509 | inet_twsk_put(inet_twsk(sk)); | 1524 | inet_twsk_put(inet_twsk(sk)); |
1510 | goto bad_packet; | 1525 | goto bad_packet; |