diff options
Diffstat (limited to 'net/ipv4/tcp_ipv4.c')
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 52 |
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 | |||
1086 | out: | 1042 | out: |
1087 | return 0; | 1043 | return 0; |
1088 | clear_hash: | 1044 | clear_hash: |