aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/tcp_ipv6.c
diff options
context:
space:
mode:
authorYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-04-17 00:19:16 -0400
committerYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>2008-06-11 13:38:20 -0400
commit8d26d76dd4a4c87ef037a44a42a0608ffc730199 (patch)
tree884ff53a83e460aa3f1837cc336a5a34f364156e /net/ipv6/tcp_ipv6.c
parent076fb7223357769c39f3ddf900bba6752369c76a (diff)
tcp md5sig: Share most of hash calcucaltion bits between IPv4 and IPv6.
We can share most part of the hash calculation code because the only difference between IPv4 and IPv6 is their pseudo headers. Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Diffstat (limited to 'net/ipv6/tcp_ipv6.c')
-rw-r--r--net/ipv6/tcp_ipv6.c53
1 files changed, 5 insertions, 48 deletions
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index 334d21c23da9..0ae0311082fb 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -738,23 +738,17 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
738 struct in6_addr *daddr, 738 struct in6_addr *daddr,
739 struct tcphdr *th, unsigned int tcplen) 739 struct tcphdr *th, unsigned int tcplen)
740{ 740{
741 struct scatterlist sg[4];
742 __u16 data_len;
743 int block = 0;
744 __sum16 cksum;
745 struct tcp_md5sig_pool *hp; 741 struct tcp_md5sig_pool *hp;
746 struct tcp6_pseudohdr *bp; 742 struct tcp6_pseudohdr *bp;
747 struct hash_desc *desc;
748 int err; 743 int err;
749 unsigned int nbytes = 0;
750 744
751 hp = tcp_get_md5sig_pool(); 745 hp = tcp_get_md5sig_pool();
752 if (!hp) { 746 if (!hp) {
753 printk(KERN_WARNING "%s(): hash pool not found...\n", __func__); 747 printk(KERN_WARNING "%s(): hash pool not found...\n", __func__);
754 goto clear_hash_noput; 748 goto clear_hash_noput;
755 } 749 }
750
756 bp = &hp->md5_blk.ip6; 751 bp = &hp->md5_blk.ip6;
757 desc = &hp->md5_desc;
758 752
759 /* 1. TCP pseudo-header (RFC2460) */ 753 /* 1. TCP pseudo-header (RFC2460) */
760 ipv6_addr_copy(&bp->saddr, saddr); 754 ipv6_addr_copy(&bp->saddr, saddr);
@@ -762,51 +756,14 @@ static int tcp_v6_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
762 bp->len = htonl(tcplen); 756 bp->len = htonl(tcplen);
763 bp->protocol = htonl(IPPROTO_TCP); 757 bp->protocol = htonl(IPPROTO_TCP);
764 758
765 sg_init_table(sg, 4); 759 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
766 760 th, tcplen, hp);
767 sg_set_buf(&sg[block++], bp, sizeof(*bp));
768 nbytes += sizeof(*bp);
769
770 /* 2. TCP header, excluding options */
771 cksum = th->check;
772 th->check = 0;
773 sg_set_buf(&sg[block++], th, sizeof(*th));
774 nbytes += sizeof(*th);
775
776 /* 3. TCP segment data (if any) */
777 data_len = tcplen - (th->doff << 2);
778 if (data_len > 0) {
779 u8 *data = (u8 *)th + (th->doff << 2);
780 sg_set_buf(&sg[block++], data, data_len);
781 nbytes += data_len;
782 }
783
784 /* 4. shared key */
785 sg_set_buf(&sg[block++], key->key, key->keylen);
786 nbytes += key->keylen;
787
788 sg_mark_end(&sg[block - 1]);
789 761
790 /* Now store the hash into the packet */ 762 if (err)
791 err = crypto_hash_init(desc);
792 if (err) {
793 printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
794 goto clear_hash;
795 }
796 err = crypto_hash_update(desc, sg, nbytes);
797 if (err) {
798 printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
799 goto clear_hash;
800 }
801 err = crypto_hash_final(desc, md5_hash);
802 if (err) {
803 printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
804 goto clear_hash; 763 goto clear_hash;
805 }
806 764
807 /* Reset header, and free up the crypto */ 765 /* Free up the crypto pool */
808 tcp_put_md5sig_pool(); 766 tcp_put_md5sig_pool();
809 th->check = cksum;
810out: 767out:
811 return 0; 768 return 0;
812clear_hash: 769clear_hash: