aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp_ipv4.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/ipv4/tcp_ipv4.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/ipv4/tcp_ipv4.c')
-rw-r--r--net/ipv4/tcp_ipv4.c52
1 files changed, 4 insertions, 48 deletions
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index f25445d21bdf..e331cdbd0953 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -1006,15 +1006,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1006 struct tcphdr *th, 1006 struct tcphdr *th,
1007 unsigned int tcplen) 1007 unsigned int tcplen)
1008{ 1008{
1009 struct scatterlist sg[4];
1010 __u16 data_len;
1011 int block = 0;
1012 __sum16 old_checksum;
1013 struct tcp_md5sig_pool *hp; 1009 struct tcp_md5sig_pool *hp;
1014 struct tcp4_pseudohdr *bp; 1010 struct tcp4_pseudohdr *bp;
1015 struct hash_desc *desc;
1016 int err; 1011 int err;
1017 unsigned int nbytes = 0;
1018 1012
1019 /* 1013 /*
1020 * Okay, so RFC2385 is turned on for this connection, 1014 * Okay, so RFC2385 is turned on for this connection,
@@ -1026,10 +1020,9 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1026 goto clear_hash_noput; 1020 goto clear_hash_noput;
1027 1021
1028 bp = &hp->md5_blk.ip4; 1022 bp = &hp->md5_blk.ip4;
1029 desc = &hp->md5_desc;
1030 1023
1031 /* 1024 /*
1032 * 1. the TCP pseudo-header (in the order: source IP address, 1025 * The TCP pseudo-header (in the order: source IP address,
1033 * destination IP address, zero-padded protocol number, and 1026 * destination IP address, zero-padded protocol number, and
1034 * segment length) 1027 * segment length)
1035 */ 1028 */
@@ -1039,50 +1032,13 @@ static int tcp_v4_do_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
1039 bp->protocol = IPPROTO_TCP; 1032 bp->protocol = IPPROTO_TCP;
1040 bp->len = htons(tcplen); 1033 bp->len = htons(tcplen);
1041 1034
1042 sg_init_table(sg, 4); 1035 err = tcp_calc_md5_hash(md5_hash, key, sizeof(*bp),
1043 1036 th, tcplen, hp);
1044 sg_set_buf(&sg[block++], bp, sizeof(*bp));
1045 nbytes += sizeof(*bp);
1046
1047 /* 2. the TCP header, excluding options, and assuming a
1048 * checksum of zero/
1049 */
1050 old_checksum = th->check;
1051 th->check = 0;
1052 sg_set_buf(&sg[block++], th, sizeof(struct tcphdr));
1053 nbytes += sizeof(struct tcphdr);
1054
1055 /* 3. the TCP segment data (if any) */
1056 data_len = tcplen - (th->doff << 2);
1057 if (data_len > 0) {
1058 unsigned char *data = (unsigned char *)th + (th->doff << 2);
1059 sg_set_buf(&sg[block++], data, data_len);
1060 nbytes += data_len;
1061 }
1062
1063 /* 4. an independently-specified key or password, known to both
1064 * TCPs and presumably connection-specific
1065 */
1066 sg_set_buf(&sg[block++], key->key, key->keylen);
1067 nbytes += key->keylen;
1068
1069 sg_mark_end(&sg[block - 1]);
1070
1071 /* Now store the Hash into the packet */
1072 err = crypto_hash_init(desc);
1073 if (err)
1074 goto clear_hash;
1075 err = crypto_hash_update(desc, sg, nbytes);
1076 if (err)
1077 goto clear_hash;
1078 err = crypto_hash_final(desc, md5_hash);
1079 if (err) 1037 if (err)
1080 goto clear_hash; 1038 goto clear_hash;
1081 1039
1082 /* Reset header, and free up the crypto */ 1040 /* Free up the crypto pool */
1083 tcp_put_md5sig_pool(); 1041 tcp_put_md5sig_pool();
1084 th->check = old_checksum;
1085
1086out: 1042out:
1087 return 0; 1043 return 0;
1088clear_hash: 1044clear_hash: