aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c144
1 files changed, 27 insertions, 117 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 40ea9c36d24..30dbab7cc3c 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
73static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb); 71static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb);
74static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req); 72static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req);
75static void tcp_v6_send_check(struct sock *sk, int len,
76 struct sk_buff *skb);
77 73
78static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); 74static 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
83static struct tcp_sock_af_ops tcp_sock_ipv6_specific; 79static struct tcp_sock_af_ops tcp_sock_ipv6_specific;
84static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; 80static struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific;
81#else
82static 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
87static void tcp_v6_hash(struct sock *sk) 89static void tcp_v6_hash(struct sock *sk)
@@ -736,78 +738,34 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval,
736static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key, 738static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
737 struct in6_addr *saddr, 739 struct in6_addr *saddr,
738 struct in6_addr *daddr, 740 struct in6_addr *daddr,
739 struct tcphdr *th, int protocol, 741 struct tcphdr *th, unsigned int tcplen)
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; 743 struct tcp_md5sig_pool *hp;
747 struct tcp6_pseudohdr *bp; 744 struct tcp6_pseudohdr *bp;
748 struct hash_desc *desc;
749 int err; 745 int err;
750 unsigned int nbytes = 0;
751 746
752 hp = tcp_get_md5sig_pool(); 747 hp = tcp_get_md5sig_pool();
753 if (!hp) { 748 if (!hp) {
754 printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); 749 printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
755 goto clear_hash_noput; 750 goto clear_hash_noput;
756 } 751 }
752
757 bp = &hp->md5_blk.ip6; 753 bp = &hp->md5_blk.ip6;
758 desc = &hp->md5_desc;
759 754
760 /* 1. TCP pseudo-header (RFC2460) */ 755 /* 1. TCP pseudo-header (RFC2460) */
761 ipv6_addr_copy(&bp->saddr, saddr); 756 ipv6_addr_copy(&bp->saddr, saddr);
762 ipv6_addr_copy(&bp->daddr, daddr); 757 ipv6_addr_copy(&bp->daddr, daddr);
763 bp->len = htonl(tcplen); 758 bp->len = htonl(tcplen);
764 bp->protocol = htonl(protocol); 759 bp->protocol = htonl(IPPROTO_TCP);
765
766 sg_init_table(sg, 4);
767 760
768 sg_set_buf(&sg[block++], bp, sizeof(*bp)); 761 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
769 nbytes += sizeof(*bp); 762 th, tcplen, hp);
770 763
771 /* 2. TCP header, excluding options */ 764 if (err)
772 cksum = th->check;
773 th->check = 0;
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
785 /* 4. shared key */
786 sg_set_buf(&sg[block++], key->key, key->keylen);
787 nbytes += key->keylen;
788
789 sg_mark_end(&sg[block - 1]);
790
791 /* Now store the hash into the packet */
792 err = crypto_hash_init(desc);
793 if (err) {
794 printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
795 goto clear_hash;
796 }
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;
801 }
802 err = crypto_hash_final(desc, md5_hash);
803 if (err) {
804 printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
805 goto clear_hash; 765 goto clear_hash;
806 }
807 766
808 /* Reset header, and free up the crypto */ 767 /* Free up the crypto pool */
809 tcp_put_md5sig_pool(); 768 tcp_put_md5sig_pool();
810 th->check = cksum;
811out: 769out:
812 return 0; 770 return 0;
813clear_hash: 771clear_hash:
@@ -821,8 +779,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
821 struct sock *sk, 779 struct sock *sk,
822 struct dst_entry *dst, 780 struct dst_entry *dst,
823 struct request_sock *req, 781 struct request_sock *req,
824 struct tcphdr *th, int protocol, 782 struct tcphdr *th, unsigned int tcplen)
825 unsigned int tcplen)
826{ 783{
827 struct in6_addr *saddr, *daddr; 784 struct in6_addr *saddr, *daddr;
828 785
@@ -835,7 +792,7 @@ static int tcp_v6_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
835 } 792 }
836 return tcp_v6_do_calc_md5_hash(md5_hash, key, 793 return tcp_v6_do_calc_md5_hash(md5_hash, key,
837 saddr, daddr, 794 saddr, daddr,
838 th, protocol, tcplen); 795 th, tcplen);
839} 796}
840 797
841static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) 798static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
@@ -844,43 +801,12 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb)
844 struct tcp_md5sig_key *hash_expected; 801 struct tcp_md5sig_key *hash_expected;
845 struct ipv6hdr *ip6h = ipv6_hdr(skb); 802 struct ipv6hdr *ip6h = ipv6_hdr(skb);
846 struct tcphdr *th = tcp_hdr(skb); 803 struct tcphdr *th = tcp_hdr(skb);
847 int length = (th->doff << 2) - sizeof (*th);
848 int genhash; 804 int genhash;
849 u8 *ptr;
850 u8 newhash[16]; 805 u8 newhash[16];
851 806
852 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr); 807 hash_expected = tcp_v6_md5_do_lookup(sk, &ip6h->saddr);
808 hash_location = tcp_parse_md5sig_option(th);
853 809
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
883done_opts:
884 /* do we have a hash as expected? */ 810 /* do we have a hash as expected? */
885 if (!hash_expected) { 811 if (!hash_expected) {
886 if (!hash_location) 812 if (!hash_location)
@@ -910,8 +836,7 @@ done_opts:
910 genhash = tcp_v6_do_calc_md5_hash(newhash, 836 genhash = tcp_v6_do_calc_md5_hash(newhash,
911 hash_expected, 837 hash_expected,
912 &ip6h->saddr, &ip6h->daddr, 838 &ip6h->saddr, &ip6h->daddr,
913 th, sk->sk_protocol, 839 th, skb->len);
914 skb->len);
915 if (genhash || memcmp(hash_location, newhash, 16) != 0) { 840 if (genhash || memcmp(hash_location, newhash, 16) != 0) {
916 if (net_ratelimit()) { 841 if (net_ratelimit()) {
917 printk(KERN_INFO "MD5 Hash %s for " 842 printk(KERN_INFO "MD5 Hash %s for "
@@ -1051,7 +976,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1051 tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key, 976 tcp_v6_do_calc_md5_hash((__u8 *)&opt[1], key,
1052 &ipv6_hdr(skb)->daddr, 977 &ipv6_hdr(skb)->daddr,
1053 &ipv6_hdr(skb)->saddr, 978 &ipv6_hdr(skb)->saddr,
1054 t1, IPPROTO_TCP, tot_len); 979 t1, tot_len);
1055 } 980 }
1056#endif 981#endif
1057 982
@@ -1088,8 +1013,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb)
1088 kfree_skb(buff); 1013 kfree_skb(buff);
1089} 1014}
1090 1015
1091static void tcp_v6_send_ack(struct tcp_timewait_sock *tw, 1016static 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) 1017 struct tcp_md5sig_key *key)
1093{ 1018{
1094 struct tcphdr *th = tcp_hdr(skb), *t1; 1019 struct tcphdr *th = tcp_hdr(skb), *t1;
1095 struct sk_buff *buff; 1020 struct sk_buff *buff;
@@ -1098,22 +1023,6 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
1098 struct sock *ctl_sk = net->ipv6.tcp_sk; 1023 struct sock *ctl_sk = net->ipv6.tcp_sk;
1099 unsigned int tot_len = sizeof(struct tcphdr); 1024 unsigned int tot_len = sizeof(struct tcphdr);
1100 __be32 *topt; 1025 __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 1026
1118 if (ts) 1027 if (ts)
1119 tot_len += TCPOLEN_TSTAMP_ALIGNED; 1028 tot_len += TCPOLEN_TSTAMP_ALIGNED;
@@ -1157,7 +1066,7 @@ static void tcp_v6_send_ack(struct tcp_timewait_sock *tw,
1157 tcp_v6_do_calc_md5_hash((__u8 *)topt, key, 1066 tcp_v6_do_calc_md5_hash((__u8 *)topt, key,
1158 &ipv6_hdr(skb)->daddr, 1067 &ipv6_hdr(skb)->daddr,
1159 &ipv6_hdr(skb)->saddr, 1068 &ipv6_hdr(skb)->saddr,
1160 t1, IPPROTO_TCP, tot_len); 1069 t1, tot_len);
1161 } 1070 }
1162#endif 1071#endif
1163 1072
@@ -1193,16 +1102,17 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)
1193 struct inet_timewait_sock *tw = inet_twsk(sk); 1102 struct inet_timewait_sock *tw = inet_twsk(sk);
1194 struct tcp_timewait_sock *tcptw = tcp_twsk(sk); 1103 struct tcp_timewait_sock *tcptw = tcp_twsk(sk);
1195 1104
1196 tcp_v6_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, 1105 tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
1197 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, 1106 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
1198 tcptw->tw_ts_recent); 1107 tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw));
1199 1108
1200 inet_twsk_put(tw); 1109 inet_twsk_put(tw);
1201} 1110}
1202 1111
1203static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req) 1112static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req)
1204{ 1113{
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); 1114 tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, req->ts_recent,
1115 tcp_v6_md5_do_lookup(skb->sk, &ipv6_hdr(skb)->daddr));
1206} 1116}
1207 1117
1208 1118
@@ -1960,7 +1870,7 @@ static int tcp_v6_init_sock(struct sock *sk)
1960 return 0; 1870 return 0;
1961} 1871}
1962 1872
1963static int tcp_v6_destroy_sock(struct sock *sk) 1873static void tcp_v6_destroy_sock(struct sock *sk)
1964{ 1874{
1965#ifdef CONFIG_TCP_MD5SIG 1875#ifdef CONFIG_TCP_MD5SIG
1966 /* Clean up the MD5 key list */ 1876 /* Clean up the MD5 key list */
@@ -1968,7 +1878,7 @@ static int tcp_v6_destroy_sock(struct sock *sk)
1968 tcp_v6_clear_md5_list(sk); 1878 tcp_v6_clear_md5_list(sk);
1969#endif 1879#endif
1970 tcp_v4_destroy_sock(sk); 1880 tcp_v4_destroy_sock(sk);
1971 return inet6_destroy_sock(sk); 1881 inet6_destroy_sock(sk);
1972} 1882}
1973 1883
1974#ifdef CONFIG_PROC_FS 1884#ifdef CONFIG_PROC_FS