diff options
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 275 |
1 files changed, 113 insertions, 162 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index cb46749d4c32..ae45f9835014 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -5,8 +5,6 @@ | |||
5 | * Authors: | 5 | * Authors: |
6 | * Pedro Roque <roque@di.fc.ul.pt> | 6 | * Pedro Roque <roque@di.fc.ul.pt> |
7 | * | 7 | * |
8 | * $Id: tcp_ipv6.c,v 1.144 2002/02/01 22:01:04 davem Exp $ | ||
9 | * | ||
10 | * Based on: | 8 | * Based on: |
11 | * linux/net/ipv4/tcp.c | 9 | * linux/net/ipv4/tcp.c |
12 | * linux/net/ipv4/tcp_input.c | 10 | * linux/net/ipv4/tcp_input.c |
@@ -72,8 +70,6 @@ | |||
72 | 70 | ||
73 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); | 71 | static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); |
74 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); | 72 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); |
75 | static void tcp_v6_send_check(struct sock *sk, int len, | ||
76 | struct sk_buff *skb); | ||
77 | 73 | ||
78 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 74 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
79 | 75 | ||
@@ -82,6 +78,12 @@ static struct inet_connection_sock_af_ops ipv6_specific; | |||
82 | #ifdef CONFIG_TCP_MD5SIG | 78 | #ifdef CONFIG_TCP_MD5SIG |
83 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; | 79 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific; |
84 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 80 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
81 | #else | ||
82 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | ||
83 | struct in6_addr *addr) | ||
84 | { | ||
85 | return NULL; | ||
86 | } | ||
85 | #endif | 87 | #endif |
86 | 88 | ||
87 | static void tcp_v6_hash(struct sock *sk) | 89 | static void tcp_v6_hash(struct sock *sk) |
@@ -321,8 +323,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
321 | int err; | 323 | int err; |
322 | struct tcp_sock *tp; | 324 | struct tcp_sock *tp; |
323 | __u32 seq; | 325 | __u32 seq; |
326 | struct net *net = dev_net(skb->dev); | ||
324 | 327 | ||
325 | sk = inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, &hdr->daddr, | 328 | sk = inet6_lookup(net, &tcp_hashinfo, &hdr->daddr, |
326 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); | 329 | th->dest, &hdr->saddr, th->source, skb->dev->ifindex); |
327 | 330 | ||
328 | if (sk == NULL) { | 331 | if (sk == NULL) { |
@@ -337,7 +340,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
337 | 340 | ||
338 | bh_lock_sock(sk); | 341 | bh_lock_sock(sk); |
339 | if (sock_owned_by_user(sk)) | 342 | if (sock_owned_by_user(sk)) |
340 | NET_INC_STATS_BH(LINUX_MIB_LOCKDROPPEDICMPS); | 343 | NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); |
341 | 344 | ||
342 | if (sk->sk_state == TCP_CLOSE) | 345 | if (sk->sk_state == TCP_CLOSE) |
343 | goto out; | 346 | goto out; |
@@ -346,7 +349,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
346 | seq = ntohl(th->seq); | 349 | seq = ntohl(th->seq); |
347 | if (sk->sk_state != TCP_LISTEN && | 350 | if (sk->sk_state != TCP_LISTEN && |
348 | !between(seq, tp->snd_una, tp->snd_nxt)) { | 351 | !between(seq, tp->snd_una, tp->snd_nxt)) { |
349 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); | 352 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); |
350 | goto out; | 353 | goto out; |
351 | } | 354 | } |
352 | 355 | ||
@@ -421,7 +424,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
421 | BUG_TRAP(req->sk == NULL); | 424 | BUG_TRAP(req->sk == NULL); |
422 | 425 | ||
423 | if (seq != tcp_rsk(req)->snt_isn) { | 426 | if (seq != tcp_rsk(req)->snt_isn) { |
424 | NET_INC_STATS_BH(LINUX_MIB_OUTOFWINDOWICMPS); | 427 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); |
425 | goto out; | 428 | goto out; |
426 | } | 429 | } |
427 | 430 | ||
@@ -733,109 +736,105 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
733 | return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); | 736 | return tcp_v6_md5_do_add(sk, &sin6->sin6_addr, newkey, cmd.tcpm_keylen); |
734 | } | 737 | } |
735 | 738 | ||
736 | static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 739 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
737 | struct in6_addr *saddr, | 740 | struct in6_addr *daddr, |
738 | struct in6_addr *daddr, | 741 | struct in6_addr *saddr, int nbytes) |
739 | struct tcphdr *th, int protocol, | ||
740 | unsigned int tcplen) | ||
741 | { | 742 | { |
742 | struct scatterlist sg[4]; | ||
743 | __u16 data_len; | ||
744 | int block = 0; | ||
745 | __sum16 cksum; | ||
746 | struct tcp_md5sig_pool *hp; | ||
747 | struct tcp6_pseudohdr *bp; | 743 | struct tcp6_pseudohdr *bp; |
748 | struct hash_desc *desc; | 744 | struct scatterlist sg; |
749 | int err; | ||
750 | unsigned int nbytes = 0; | ||
751 | 745 | ||
752 | hp = tcp_get_md5sig_pool(); | ||
753 | if (!hp) { | ||
754 | printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); | ||
755 | goto clear_hash_noput; | ||
756 | } | ||
757 | bp = &hp->md5_blk.ip6; | 746 | bp = &hp->md5_blk.ip6; |
758 | desc = &hp->md5_desc; | ||
759 | |||
760 | /* 1. TCP pseudo-header (RFC2460) */ | 747 | /* 1. TCP pseudo-header (RFC2460) */ |
761 | ipv6_addr_copy(&bp->saddr, saddr); | 748 | ipv6_addr_copy(&bp->saddr, saddr); |
762 | ipv6_addr_copy(&bp->daddr, daddr); | 749 | ipv6_addr_copy(&bp->daddr, daddr); |
763 | bp->len = htonl(tcplen); | 750 | bp->protocol = cpu_to_be32(IPPROTO_TCP); |
764 | bp->protocol = htonl(protocol); | 751 | bp->len = cpu_to_be16(nbytes); |
765 | |||
766 | sg_init_table(sg, 4); | ||
767 | |||
768 | sg_set_buf(&sg[block++], bp, sizeof(*bp)); | ||
769 | nbytes += sizeof(*bp); | ||
770 | 752 | ||
771 | /* 2. TCP header, excluding options */ | 753 | sg_init_one(&sg, bp, sizeof(*bp)); |
772 | cksum = th->check; | 754 | return crypto_hash_update(&hp->md5_desc, &sg, sizeof(*bp)); |
773 | th->check = 0; | 755 | } |
774 | sg_set_buf(&sg[block++], th, sizeof(*th)); | ||
775 | nbytes += sizeof(*th); | ||
776 | |||
777 | /* 3. TCP segment data (if any) */ | ||
778 | data_len = tcplen - (th->doff << 2); | ||
779 | if (data_len > 0) { | ||
780 | u8 *data = (u8 *)th + (th->doff << 2); | ||
781 | sg_set_buf(&sg[block++], data, data_len); | ||
782 | nbytes += data_len; | ||
783 | } | ||
784 | 756 | ||
785 | /* 4. shared key */ | 757 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, |
786 | sg_set_buf(&sg[block++], key->key, key->keylen); | 758 | struct in6_addr *daddr, struct in6_addr *saddr, |
787 | nbytes += key->keylen; | 759 | struct tcphdr *th) |
760 | { | ||
761 | struct tcp_md5sig_pool *hp; | ||
762 | struct hash_desc *desc; | ||
788 | 763 | ||
789 | sg_mark_end(&sg[block - 1]); | 764 | hp = tcp_get_md5sig_pool(); |
765 | if (!hp) | ||
766 | goto clear_hash_noput; | ||
767 | desc = &hp->md5_desc; | ||
790 | 768 | ||
791 | /* Now store the hash into the packet */ | 769 | if (crypto_hash_init(desc)) |
792 | err = crypto_hash_init(desc); | ||
793 | if (err) { | ||
794 | printk(KERN_WARNING "%s(): hash_init failed\n", __func__); | ||
795 | goto clear_hash; | 770 | goto clear_hash; |
796 | } | 771 | if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, th->doff << 2)) |
797 | err = crypto_hash_update(desc, sg, nbytes); | ||
798 | if (err) { | ||
799 | printk(KERN_WARNING "%s(): hash_update failed\n", __func__); | ||
800 | goto clear_hash; | 772 | goto clear_hash; |
801 | } | 773 | if (tcp_md5_hash_header(hp, th)) |
802 | err = crypto_hash_final(desc, md5_hash); | 774 | goto clear_hash; |
803 | if (err) { | 775 | if (tcp_md5_hash_key(hp, key)) |
804 | printk(KERN_WARNING "%s(): hash_final failed\n", __func__); | 776 | goto clear_hash; |
777 | if (crypto_hash_final(desc, md5_hash)) | ||
805 | goto clear_hash; | 778 | goto clear_hash; |
806 | } | ||
807 | 779 | ||
808 | /* Reset header, and free up the crypto */ | ||
809 | tcp_put_md5sig_pool(); | 780 | tcp_put_md5sig_pool(); |
810 | th->check = cksum; | ||
811 | out: | ||
812 | return 0; | 781 | return 0; |
782 | |||
813 | clear_hash: | 783 | clear_hash: |
814 | tcp_put_md5sig_pool(); | 784 | tcp_put_md5sig_pool(); |
815 | clear_hash_noput: | 785 | clear_hash_noput: |
816 | memset(md5_hash, 0, 16); | 786 | memset(md5_hash, 0, 16); |
817 | goto out; | 787 | return 1; |
818 | } | 788 | } |
819 | 789 | ||
820 | static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, | 790 | static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, |
821 | struct sock *sk, | 791 | struct sock *sk, struct request_sock *req, |
822 | struct dst_entry *dst, | 792 | struct sk_buff *skb) |
823 | struct request_sock *req, | ||
824 | struct tcphdr *th, int protocol, | ||
825 | unsigned int tcplen) | ||
826 | { | 793 | { |
827 | struct in6_addr *saddr, *daddr; | 794 | struct in6_addr *saddr, *daddr; |
795 | struct tcp_md5sig_pool *hp; | ||
796 | struct hash_desc *desc; | ||
797 | struct tcphdr *th = tcp_hdr(skb); | ||
828 | 798 | ||
829 | if (sk) { | 799 | if (sk) { |
830 | saddr = &inet6_sk(sk)->saddr; | 800 | saddr = &inet6_sk(sk)->saddr; |
831 | daddr = &inet6_sk(sk)->daddr; | 801 | daddr = &inet6_sk(sk)->daddr; |
832 | } else { | 802 | } else if (req) { |
833 | saddr = &inet6_rsk(req)->loc_addr; | 803 | saddr = &inet6_rsk(req)->loc_addr; |
834 | daddr = &inet6_rsk(req)->rmt_addr; | 804 | daddr = &inet6_rsk(req)->rmt_addr; |
805 | } else { | ||
806 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | ||
807 | saddr = &ip6h->saddr; | ||
808 | daddr = &ip6h->daddr; | ||
835 | } | 809 | } |
836 | return tcp_v6_do_calc_md5_hash(md5_hash, key, | 810 | |
837 | saddr, daddr, | 811 | hp = tcp_get_md5sig_pool(); |
838 | th, protocol, tcplen); | 812 | if (!hp) |
813 | goto clear_hash_noput; | ||
814 | desc = &hp->md5_desc; | ||
815 | |||
816 | if (crypto_hash_init(desc)) | ||
817 | goto clear_hash; | ||
818 | |||
819 | if (tcp_v6_md5_hash_pseudoheader(hp, daddr, saddr, skb->len)) | ||
820 | goto clear_hash; | ||
821 | if (tcp_md5_hash_header(hp, th)) | ||
822 | goto clear_hash; | ||
823 | if (tcp_md5_hash_skb_data(hp, skb, th->doff << 2)) | ||
824 | goto clear_hash; | ||
825 | if (tcp_md5_hash_key(hp, key)) | ||
826 | goto clear_hash; | ||
827 | if (crypto_hash_final(desc, md5_hash)) | ||
828 | goto clear_hash; | ||
829 | |||
830 | tcp_put_md5sig_pool(); | ||
831 | return 0; | ||
832 | |||
833 | clear_hash: | ||
834 | tcp_put_md5sig_pool(); | ||
835 | clear_hash_noput: | ||
836 | memset(md5_hash, 0, 16); | ||
837 | return 1; | ||
839 | } | 838 | } |
840 | 839 | ||
841 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | 840 | static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) |
@@ -844,43 +843,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
844 | struct tcp_md5sig_key *hash_expected; | 843 | struct tcp_md5sig_key *hash_expected; |
845 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 844 | struct ipv6hdr *ip6h = ipv6_hdr(skb); |
846 | struct tcphdr *th = tcp_hdr(skb); | 845 | struct tcphdr *th = tcp_hdr(skb); |
847 | int length = (th->doff << 2) - sizeof (*th); | ||
848 | int genhash; | 846 | int genhash; |
849 | u8 *ptr; | ||
850 | u8 newhash[16]; | 847 | u8 newhash[16]; |
851 | 848 | ||
852 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); | 849 | hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); |
850 | hash_location = tcp_parse_md5sig_option(th); | ||
853 | 851 | ||
854 | /* If the TCP option is too short, we can short cut */ | ||
855 | if (length < TCPOLEN_MD5SIG) | ||
856 | return hash_expected ? 1 : 0; | ||
857 | |||
858 | /* parse options */ | ||
859 | ptr = (u8*)(th + 1); | ||
860 | while (length > 0) { | ||
861 | int opcode = *ptr++; | ||
862 | int opsize; | ||
863 | |||
864 | switch(opcode) { | ||
865 | case TCPOPT_EOL: | ||
866 | goto done_opts; | ||
867 | case TCPOPT_NOP: | ||
868 | length--; | ||
869 | continue; | ||
870 | default: | ||
871 | opsize = *ptr++; | ||
872 | if (opsize < 2 || opsize > length) | ||
873 | goto done_opts; | ||
874 | if (opcode == TCPOPT_MD5SIG) { | ||
875 | hash_location = ptr; | ||
876 | goto done_opts; | ||
877 | } | ||
878 | } | ||
879 | ptr += opsize - 2; | ||
880 | length -= opsize; | ||
881 | } | ||
882 | |||
883 | done_opts: | ||
884 | /* do we have a hash as expected? */ | 852 | /* do we have a hash as expected? */ |
885 | if (!hash_expected) { | 853 | if (!hash_expected) { |
886 | if (!hash_location) | 854 | if (!hash_location) |
@@ -907,11 +875,10 @@ done_opts: | |||
907 | } | 875 | } |
908 | 876 | ||
909 | /* check the signature */ | 877 | /* check the signature */ |
910 | genhash = tcp_v6_do_calc_md5_hash(newhash, | 878 | genhash = tcp_v6_md5_hash_skb(newhash, |
911 | hash_expected, | 879 | hash_expected, |
912 | &ip6h->saddr, &ip6h->daddr, | 880 | NULL, NULL, skb); |
913 | th, sk->sk_protocol, | 881 | |
914 | skb->len); | ||
915 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { | 882 | if (genhash || memcmp(hash_location, newhash, 16) != 0) { |
916 | if (net_ratelimit()) { | 883 | if (net_ratelimit()) { |
917 | printk(KERN_INFO "MD5 Hash %s for " | 884 | printk(KERN_INFO "MD5 Hash %s for " |
@@ -1048,10 +1015,9 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1048 | (TCPOPT_NOP << 16) | | 1015 | (TCPOPT_NOP << 16) | |
1049 | (TCPOPT_MD5SIG << 8) | | 1016 | (TCPOPT_MD5SIG << 8) | |
1050 | TCPOLEN_MD5SIG); | 1017 | TCPOLEN_MD5SIG); |
1051 | tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, | 1018 | tcp_v6_md5_hash_hdr((__u8 *)&opt[1], key, |
1052 | &ipv6_hdr(skb)->daddr, | 1019 | &ipv6_hdr(skb)->daddr, |
1053 | &ipv6_hdr(skb)->saddr, | 1020 | &ipv6_hdr(skb)->saddr, t1); |
1054 | t1, IPPROTO_TCP, tot_len); | ||
1055 | } | 1021 | } |
1056 | #endif | 1022 | #endif |
1057 | 1023 | ||
@@ -1079,8 +1045,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1079 | 1045 | ||
1080 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1046 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1081 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | 1047 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1082 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1048 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1083 | TCP_INC_STATS_BH(TCP_MIB_OUTRSTS); | 1049 | TCP_INC_STATS_BH(net, TCP_MIB_OUTRSTS); |
1084 | return; | 1050 | return; |
1085 | } | 1051 | } |
1086 | } | 1052 | } |
@@ -1088,8 +1054,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
1088 | kfree_skb(buff); | 1054 | kfree_skb(buff); |
1089 | } | 1055 | } |
1090 | 1056 | ||
1091 | static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | 1057 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts, |
1092 | struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 ts) | 1058 | struct tcp_md5sig_key *key) |
1093 | { | 1059 | { |
1094 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1060 | struct tcphdr *th = tcp_hdr(skb), *t1; |
1095 | struct sk_buff *buff; | 1061 | struct sk_buff *buff; |
@@ -1098,22 +1064,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1098 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1064 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
1099 | unsigned int tot_len = sizeof(struct tcphdr); | 1065 | unsigned int tot_len = sizeof(struct tcphdr); |
1100 | __be32 *topt; | 1066 | __be32 *topt; |
1101 | #ifdef CONFIG_TCP_MD5SIG | ||
1102 | struct tcp_md5sig_key *key; | ||
1103 | struct tcp_md5sig_key tw_key; | ||
1104 | #endif | ||
1105 | |||
1106 | #ifdef CONFIG_TCP_MD5SIG | ||
1107 | if (!tw && skb->sk) { | ||
1108 | key = tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr); | ||
1109 | } else if (tw && tw->tw_md5_keylen) { | ||
1110 | tw_key.key = tw->tw_md5_key; | ||
1111 | tw_key.keylen = tw->tw_md5_keylen; | ||
1112 | key = &tw_key; | ||
1113 | } else { | ||
1114 | key = NULL; | ||
1115 | } | ||
1116 | #endif | ||
1117 | 1067 | ||
1118 | if (ts) | 1068 | if (ts) |
1119 | tot_len += TCPOLEN_TSTAMP_ALIGNED; | 1069 | tot_len += TCPOLEN_TSTAMP_ALIGNED; |
@@ -1154,10 +1104,9 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1154 | if (key) { | 1104 | if (key) { |
1155 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | | 1105 | *topt++ = htonl((TCPOPT_NOP << 24) | (TCPOPT_NOP << 16) | |
1156 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); | 1106 | (TCPOPT_MD5SIG << 8) | TCPOLEN_MD5SIG); |
1157 | tcp_v6_do_calc_md5_hash((__u8 *)topt, key, | 1107 | tcp_v6_md5_hash_hdr((__u8 *)topt, key, |
1158 | &ipv6_hdr(skb)->daddr, | 1108 | &ipv6_hdr(skb)->daddr, |
1159 | &ipv6_hdr(skb)->saddr, | 1109 | &ipv6_hdr(skb)->saddr, t1); |
1160 | t1, IPPROTO_TCP, tot_len); | ||
1161 | } | 1110 | } |
1162 | #endif | 1111 | #endif |
1163 | 1112 | ||
@@ -1180,7 +1129,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, | |||
1180 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { | 1129 | if (!ip6_dst_lookup(ctl_sk, &buff->dst, &fl)) { |
1181 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { | 1130 | if (xfrm_lookup(&buff->dst, &fl, NULL, 0) >= 0) { |
1182 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); | 1131 | ip6_xmit(ctl_sk, buff, &fl, NULL, 0); |
1183 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1132 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
1184 | return; | 1133 | return; |
1185 | } | 1134 | } |
1186 | } | 1135 | } |
@@ -1193,16 +1142,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
1193 | struct inet_timewait_sock *tw = inet_twsk(sk); | 1142 | struct inet_timewait_sock *tw = inet_twsk(sk); |
1194 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); | 1143 | struct tcp_timewait_sock *tcptw = tcp_twsk(sk); |
1195 | 1144 | ||
1196 | tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 1145 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
1197 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 1146 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
1198 | tcptw->tw_ts_recent); | 1147 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw)); |
1199 | 1148 | ||
1200 | inet_twsk_put(tw); | 1149 | inet_twsk_put(tw); |
1201 | } | 1150 | } |
1202 | 1151 | ||
1203 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) | 1152 | static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) |
1204 | { | 1153 | { |
1205 | tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent); | 1154 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent, |
1155 | tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr)); | ||
1206 | } | 1156 | } |
1207 | 1157 | ||
1208 | 1158 | ||
@@ -1538,9 +1488,9 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1538 | return newsk; | 1488 | return newsk; |
1539 | 1489 | ||
1540 | out_overflow: | 1490 | out_overflow: |
1541 | NET_INC_STATS_BH(LINUX_MIB_LISTENOVERFLOWS); | 1491 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); |
1542 | out: | 1492 | out: |
1543 | NET_INC_STATS_BH(LINUX_MIB_LISTENDROPS); | 1493 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
1544 | if (opt && opt != np->opt) | 1494 | if (opt && opt != np->opt) |
1545 | sock_kfree_s(sk, opt, opt->tot_len); | 1495 | sock_kfree_s(sk, opt, opt->tot_len); |
1546 | dst_release(dst); | 1496 | dst_release(dst); |
@@ -1669,7 +1619,7 @@ discard: | |||
1669 | kfree_skb(skb); | 1619 | kfree_skb(skb); |
1670 | return 0; | 1620 | return 0; |
1671 | csum_err: | 1621 | csum_err: |
1672 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1622 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_INERRS); |
1673 | goto discard; | 1623 | goto discard; |
1674 | 1624 | ||
1675 | 1625 | ||
@@ -1707,6 +1657,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1707 | struct tcphdr *th; | 1657 | struct tcphdr *th; |
1708 | struct sock *sk; | 1658 | struct sock *sk; |
1709 | int ret; | 1659 | int ret; |
1660 | struct net *net = dev_net(skb->dev); | ||
1710 | 1661 | ||
1711 | if (skb->pkt_type != PACKET_HOST) | 1662 | if (skb->pkt_type != PACKET_HOST) |
1712 | goto discard_it; | 1663 | goto discard_it; |
@@ -1714,7 +1665,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1714 | /* | 1665 | /* |
1715 | * Count it even if it's bad. | 1666 | * Count it even if it's bad. |
1716 | */ | 1667 | */ |
1717 | TCP_INC_STATS_BH(TCP_MIB_INSEGS); | 1668 | TCP_INC_STATS_BH(net, TCP_MIB_INSEGS); |
1718 | 1669 | ||
1719 | if (!pskb_may_pull(skb, sizeof(struct tcphdr))) | 1670 | if (!pskb_may_pull(skb, sizeof(struct tcphdr))) |
1720 | goto discard_it; | 1671 | goto discard_it; |
@@ -1738,7 +1689,7 @@ static int tcp_v6_rcv(struct sk_buff *skb) | |||
1738 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); | 1689 | TCP_SKB_CB(skb)->flags = ipv6_get_dsfield(ipv6_hdr(skb)); |
1739 | TCP_SKB_CB(skb)->sacked = 0; | 1690 | TCP_SKB_CB(skb)->sacked = 0; |
1740 | 1691 | ||
1741 | sk = __inet6_lookup(dev_net(skb->dev), &tcp_hashinfo, | 1692 | sk = __inet6_lookup(net, &tcp_hashinfo, |
1742 | &ipv6_hdr(skb)->saddr, th->source, | 1693 | &ipv6_hdr(skb)->saddr, th->source, |
1743 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), | 1694 | &ipv6_hdr(skb)->daddr, ntohs(th->dest), |
1744 | inet6_iif(skb)); | 1695 | inet6_iif(skb)); |
@@ -1786,7 +1737,7 @@ no_tcp_socket: | |||
1786 | 1737 | ||
1787 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1738 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1788 | bad_packet: | 1739 | bad_packet: |
1789 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1740 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); |
1790 | } else { | 1741 | } else { |
1791 | tcp_v6_send_reset(NULL, skb); | 1742 | tcp_v6_send_reset(NULL, skb); |
1792 | } | 1743 | } |
@@ -1811,7 +1762,7 @@ do_time_wait: | |||
1811 | } | 1762 | } |
1812 | 1763 | ||
1813 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { | 1764 | if (skb->len < (th->doff<<2) || tcp_checksum_complete(skb)) { |
1814 | TCP_INC_STATS_BH(TCP_MIB_INERRS); | 1765 | TCP_INC_STATS_BH(net, TCP_MIB_INERRS); |
1815 | inet_twsk_put(inet_twsk(sk)); | 1766 | inet_twsk_put(inet_twsk(sk)); |
1816 | goto discard_it; | 1767 | goto discard_it; |
1817 | } | 1768 | } |
@@ -1871,7 +1822,7 @@ static struct inet_connection_sock_af_ops ipv6_specific = { | |||
1871 | #ifdef CONFIG_TCP_MD5SIG | 1822 | #ifdef CONFIG_TCP_MD5SIG |
1872 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { | 1823 | static struct tcp_sock_af_ops tcp_sock_ipv6_specific = { |
1873 | .md5_lookup = tcp_v6_md5_lookup, | 1824 | .md5_lookup = tcp_v6_md5_lookup, |
1874 | .calc_md5_hash = tcp_v6_calc_md5_hash, | 1825 | .calc_md5_hash = tcp_v6_md5_hash_skb, |
1875 | .md5_add = tcp_v6_md5_add_func, | 1826 | .md5_add = tcp_v6_md5_add_func, |
1876 | .md5_parse = tcp_v6_parse_md5_keys, | 1827 | .md5_parse = tcp_v6_parse_md5_keys, |
1877 | }; | 1828 | }; |
@@ -1903,7 +1854,7 @@ static struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1903 | #ifdef CONFIG_TCP_MD5SIG | 1854 | #ifdef CONFIG_TCP_MD5SIG |
1904 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { | 1855 | static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific = { |
1905 | .md5_lookup = tcp_v4_md5_lookup, | 1856 | .md5_lookup = tcp_v4_md5_lookup, |
1906 | .calc_md5_hash = tcp_v4_calc_md5_hash, | 1857 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1907 | .md5_add = tcp_v6_md5_add_func, | 1858 | .md5_add = tcp_v6_md5_add_func, |
1908 | .md5_parse = tcp_v6_parse_md5_keys, | 1859 | .md5_parse = tcp_v6_parse_md5_keys, |
1909 | }; | 1860 | }; |
@@ -1960,7 +1911,7 @@ static int tcp_v6_init_sock(struct sock *sk) | |||
1960 | return 0; | 1911 | return 0; |
1961 | } | 1912 | } |
1962 | 1913 | ||
1963 | static int tcp_v6_destroy_sock(struct sock *sk) | 1914 | static void tcp_v6_destroy_sock(struct sock *sk) |
1964 | { | 1915 | { |
1965 | #ifdef CONFIG_TCP_MD5SIG | 1916 | #ifdef CONFIG_TCP_MD5SIG |
1966 | /* Clean up the MD5 key list */ | 1917 | /* Clean up the MD5 key list */ |
@@ -1968,7 +1919,7 @@ static int tcp_v6_destroy_sock(struct sock *sk) | |||
1968 | tcp_v6_clear_md5_list(sk); | 1919 | tcp_v6_clear_md5_list(sk); |
1969 | #endif | 1920 | #endif |
1970 | tcp_v4_destroy_sock(sk); | 1921 | tcp_v4_destroy_sock(sk); |
1971 | return inet6_destroy_sock(sk); | 1922 | inet6_destroy_sock(sk); |
1972 | } | 1923 | } |
1973 | 1924 | ||
1974 | #ifdef CONFIG_PROC_FS | 1925 | #ifdef CONFIG_PROC_FS |
@@ -2036,7 +1987,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2036 | 1987 | ||
2037 | seq_printf(seq, | 1988 | seq_printf(seq, |
2038 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " | 1989 | "%4d: %08X%08X%08X%08X:%04X %08X%08X%08X%08X:%04X " |
2039 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %u %u %u %u %d\n", | 1990 | "%02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %p %lu %lu %u %u %d\n", |
2040 | i, | 1991 | i, |
2041 | src->s6_addr32[0], src->s6_addr32[1], | 1992 | src->s6_addr32[0], src->s6_addr32[1], |
2042 | src->s6_addr32[2], src->s6_addr32[3], srcp, | 1993 | src->s6_addr32[2], src->s6_addr32[3], srcp, |
@@ -2052,8 +2003,8 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2052 | icsk->icsk_probes_out, | 2003 | icsk->icsk_probes_out, |
2053 | sock_i_ino(sp), | 2004 | sock_i_ino(sp), |
2054 | atomic_read(&sp->sk_refcnt), sp, | 2005 | atomic_read(&sp->sk_refcnt), sp, |
2055 | icsk->icsk_rto, | 2006 | jiffies_to_clock_t(icsk->icsk_rto), |
2056 | icsk->icsk_ack.ato, | 2007 | jiffies_to_clock_t(icsk->icsk_ack.ato), |
2057 | (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, | 2008 | (icsk->icsk_ack.quick << 1 ) | icsk->icsk_ack.pingpong, |
2058 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh | 2009 | tp->snd_cwnd, tp->snd_ssthresh>=0xFFFF?-1:tp->snd_ssthresh |
2059 | ); | 2010 | ); |