diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 43 |
1 files changed, 21 insertions, 22 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 3c23e70885f4..202cf09c4cd4 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -519,26 +519,31 @@ out: | |||
519 | sock_put(sk); | 519 | sock_put(sk); |
520 | } | 520 | } |
521 | 521 | ||
522 | /* This routine computes an IPv4 TCP checksum. */ | 522 | static void __tcp_v4_send_check(struct sk_buff *skb, |
523 | void tcp_v4_send_check(struct sock *sk, int len, struct sk_buff *skb) | 523 | __be32 saddr, __be32 daddr) |
524 | { | 524 | { |
525 | struct inet_sock *inet = inet_sk(sk); | ||
526 | struct tcphdr *th = tcp_hdr(skb); | 525 | struct tcphdr *th = tcp_hdr(skb); |
527 | 526 | ||
528 | if (skb->ip_summed == CHECKSUM_PARTIAL) { | 527 | if (skb->ip_summed == CHECKSUM_PARTIAL) { |
529 | th->check = ~tcp_v4_check(len, inet->inet_saddr, | 528 | th->check = ~tcp_v4_check(skb->len, saddr, daddr, 0); |
530 | inet->inet_daddr, 0); | ||
531 | skb->csum_start = skb_transport_header(skb) - skb->head; | 529 | skb->csum_start = skb_transport_header(skb) - skb->head; |
532 | skb->csum_offset = offsetof(struct tcphdr, check); | 530 | skb->csum_offset = offsetof(struct tcphdr, check); |
533 | } else { | 531 | } else { |
534 | th->check = tcp_v4_check(len, inet->inet_saddr, | 532 | th->check = tcp_v4_check(skb->len, saddr, daddr, |
535 | inet->inet_daddr, | ||
536 | csum_partial(th, | 533 | csum_partial(th, |
537 | th->doff << 2, | 534 | th->doff << 2, |
538 | skb->csum)); | 535 | skb->csum)); |
539 | } | 536 | } |
540 | } | 537 | } |
541 | 538 | ||
539 | /* This routine computes an IPv4 TCP checksum. */ | ||
540 | void tcp_v4_send_check(struct sock *sk, struct sk_buff *skb) | ||
541 | { | ||
542 | struct inet_sock *inet = inet_sk(sk); | ||
543 | |||
544 | __tcp_v4_send_check(skb, inet->inet_saddr, inet->inet_daddr); | ||
545 | } | ||
546 | |||
542 | int tcp_v4_gso_send_check(struct sk_buff *skb) | 547 | int tcp_v4_gso_send_check(struct sk_buff *skb) |
543 | { | 548 | { |
544 | const struct iphdr *iph; | 549 | const struct iphdr *iph; |
@@ -551,10 +556,8 @@ int tcp_v4_gso_send_check(struct sk_buff *skb) | |||
551 | th = tcp_hdr(skb); | 556 | th = tcp_hdr(skb); |
552 | 557 | ||
553 | th->check = 0; | 558 | th->check = 0; |
554 | th->check = ~tcp_v4_check(skb->len, iph->saddr, iph->daddr, 0); | ||
555 | skb->csum_start = skb_transport_header(skb) - skb->head; | ||
556 | skb->csum_offset = offsetof(struct tcphdr, check); | ||
557 | skb->ip_summed = CHECKSUM_PARTIAL; | 559 | skb->ip_summed = CHECKSUM_PARTIAL; |
560 | __tcp_v4_send_check(skb, iph->saddr, iph->daddr); | ||
558 | return 0; | 561 | return 0; |
559 | } | 562 | } |
560 | 563 | ||
@@ -763,13 +766,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
763 | skb = tcp_make_synack(sk, dst, req, rvp); | 766 | skb = tcp_make_synack(sk, dst, req, rvp); |
764 | 767 | ||
765 | if (skb) { | 768 | if (skb) { |
766 | struct tcphdr *th = tcp_hdr(skb); | 769 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); |
767 | |||
768 | th->check = tcp_v4_check(skb->len, | ||
769 | ireq->loc_addr, | ||
770 | ireq->rmt_addr, | ||
771 | csum_partial(th, skb->len, | ||
772 | skb->csum)); | ||
773 | 770 | ||
774 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, | 771 | err = ip_build_and_send_pkt(skb, sk, ireq->loc_addr, |
775 | ireq->rmt_addr, | 772 | ireq->rmt_addr, |
@@ -894,7 +891,7 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, | |||
894 | kfree(newkey); | 891 | kfree(newkey); |
895 | return -ENOMEM; | 892 | return -ENOMEM; |
896 | } | 893 | } |
897 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 894 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
898 | } | 895 | } |
899 | if (tcp_alloc_md5sig_pool(sk) == NULL) { | 896 | if (tcp_alloc_md5sig_pool(sk) == NULL) { |
900 | kfree(newkey); | 897 | kfree(newkey); |
@@ -1024,7 +1021,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1024 | return -EINVAL; | 1021 | return -EINVAL; |
1025 | 1022 | ||
1026 | tp->md5sig_info = p; | 1023 | tp->md5sig_info = p; |
1027 | sk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1024 | sk_nocaps_add(sk, NETIF_F_GSO_MASK); |
1028 | } | 1025 | } |
1029 | 1026 | ||
1030 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); | 1027 | newkey = kmemdup(cmd.tcpm_key, cmd.tcpm_keylen, sk->sk_allocation); |
@@ -1289,8 +1286,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1289 | goto drop_and_release; | 1286 | goto drop_and_release; |
1290 | 1287 | ||
1291 | /* Secret recipe starts with IP addresses */ | 1288 | /* Secret recipe starts with IP addresses */ |
1292 | *mess++ ^= daddr; | 1289 | *mess++ ^= (__force u32)daddr; |
1293 | *mess++ ^= saddr; | 1290 | *mess++ ^= (__force u32)saddr; |
1294 | 1291 | ||
1295 | /* plus variable length Initiator Cookie */ | 1292 | /* plus variable length Initiator Cookie */ |
1296 | c = (u8 *)mess; | 1293 | c = (u8 *)mess; |
@@ -1465,7 +1462,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1465 | if (newkey != NULL) | 1462 | if (newkey != NULL) |
1466 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, | 1463 | tcp_v4_md5_do_add(newsk, newinet->inet_daddr, |
1467 | newkey, key->keylen); | 1464 | newkey, key->keylen); |
1468 | newsk->sk_route_caps &= ~NETIF_F_GSO_MASK; | 1465 | sk_nocaps_add(newsk, NETIF_F_GSO_MASK); |
1469 | } | 1466 | } |
1470 | #endif | 1467 | #endif |
1471 | 1468 | ||
@@ -1675,6 +1672,8 @@ process: | |||
1675 | 1672 | ||
1676 | skb->dev = NULL; | 1673 | skb->dev = NULL; |
1677 | 1674 | ||
1675 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1676 | |||
1678 | bh_lock_sock_nested(sk); | 1677 | bh_lock_sock_nested(sk); |
1679 | ret = 0; | 1678 | ret = 0; |
1680 | if (!sock_owned_by_user(sk)) { | 1679 | if (!sock_owned_by_user(sk)) { |