Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 103649
b: refs/heads/master
c: 49a72df
h: refs/heads/master
i:
  103647: bde3050
v: v3
  • Loading branch information
Adam Langley authored and David S. Miller committed Jul 19, 2008
1 parent 0940ed5 commit 635c5af
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 196 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 845525a642c1c9e1335c33a274d4273906ee58eb
refs/heads/master: 49a72dfb8814c2d65bd9f8c9c6daf6395a1ec58d
29 changes: 12 additions & 17 deletions trunk/include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1112,20 +1112,12 @@ struct tcp_md5sig_pool {
#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */

/* - functions */
extern int tcp_calc_md5_hash(char *md5_hash,
struct tcp_md5sig_key *key,
int bplen,
struct tcphdr *th,
unsigned int tcplen,
struct tcp_md5sig_pool *hp);

extern int tcp_v4_calc_md5_hash(char *md5_hash,
struct tcp_md5sig_key *key,
struct sock *sk,
struct dst_entry *dst,
struct request_sock *req,
struct tcphdr *th,
unsigned int tcplen);
extern int tcp_v4_md5_hash_skb(char *md5_hash,
struct tcp_md5sig_key *key,
struct sock *sk,
struct request_sock *req,
struct sk_buff *skb);

extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
struct sock *addr_sk);

Expand All @@ -1152,6 +1144,11 @@ extern void tcp_free_md5sig_pool(void);

extern struct tcp_md5sig_pool *__tcp_get_md5sig_pool(int cpu);
extern void __tcp_put_md5sig_pool(void);
extern int tcp_md5_hash_header(struct tcp_md5sig_pool *, struct tcphdr *);
extern int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *, struct sk_buff *,
unsigned header_len);
extern int tcp_md5_hash_key(struct tcp_md5sig_pool *hp,
struct tcp_md5sig_key *key);

static inline
struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
Expand Down Expand Up @@ -1381,10 +1378,8 @@ struct tcp_sock_af_ops {
int (*calc_md5_hash) (char *location,
struct tcp_md5sig_key *md5,
struct sock *sk,
struct dst_entry *dst,
struct request_sock *req,
struct tcphdr *th,
unsigned int len);
struct sk_buff *skb);
int (*md5_add) (struct sock *sk,
struct sock *addr_sk,
u8 *newkey,
Expand Down
127 changes: 57 additions & 70 deletions trunk/net/ipv4/tcp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2465,76 +2465,6 @@ static unsigned long tcp_md5sig_users;
static struct tcp_md5sig_pool **tcp_md5sig_pool;
static DEFINE_SPINLOCK(tcp_md5sig_pool_lock);

int tcp_calc_md5_hash(char *md5_hash, struct tcp_md5sig_key *key,
int bplen,
struct tcphdr *th, unsigned int tcplen,
struct tcp_md5sig_pool *hp)
{
struct scatterlist sg[4];
__u16 data_len;
int block = 0;
__sum16 cksum;
struct hash_desc *desc = &hp->md5_desc;
int err;
unsigned int nbytes = 0;

sg_init_table(sg, 4);

/* 1. The TCP pseudo-header */
sg_set_buf(&sg[block++], &hp->md5_blk, bplen);
nbytes += bplen;

/* 2. The TCP header, excluding options, and assuming a
* checksum of zero
*/
cksum = th->check;
th->check = 0;
sg_set_buf(&sg[block++], th, sizeof(*th));
nbytes += sizeof(*th);

/* 3. The TCP segment data (if any) */
data_len = tcplen - (th->doff << 2);
if (data_len > 0) {
u8 *data = (u8 *)th + (th->doff << 2);
sg_set_buf(&sg[block++], data, data_len);
nbytes += data_len;
}

/* 4. an independently-specified key or password, known to both
* TCPs and presumably connection-specific
*/
sg_set_buf(&sg[block++], key->key, key->keylen);
nbytes += key->keylen;

sg_mark_end(&sg[block - 1]);

/* Now store the hash into the packet */
err = crypto_hash_init(desc);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_init failed\n", __func__);
return -1;
}
err = crypto_hash_update(desc, sg, nbytes);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_update failed\n", __func__);
return -1;
}
err = crypto_hash_final(desc, md5_hash);
if (err) {
if (net_ratelimit())
printk(KERN_WARNING "%s(): hash_final failed\n", __func__);
return -1;
}

/* Reset header */
th->check = cksum;

return 0;
}
EXPORT_SYMBOL(tcp_calc_md5_hash);

static void __tcp_free_md5sig_pool(struct tcp_md5sig_pool **pool)
{
int cpu;
Expand Down Expand Up @@ -2658,6 +2588,63 @@ void __tcp_put_md5sig_pool(void)
}

EXPORT_SYMBOL(__tcp_put_md5sig_pool);

int tcp_md5_hash_header(struct tcp_md5sig_pool *hp,
struct tcphdr *th)
{
struct scatterlist sg;
int err;

__sum16 old_checksum = th->check;
th->check = 0;
/* options aren't included in the hash */
sg_init_one(&sg, th, sizeof(struct tcphdr));
err = crypto_hash_update(&hp->md5_desc, &sg, sizeof(struct tcphdr));
th->check = old_checksum;
return err;
}

EXPORT_SYMBOL(tcp_md5_hash_header);

int tcp_md5_hash_skb_data(struct tcp_md5sig_pool *hp,
struct sk_buff *skb, unsigned header_len)
{
struct scatterlist sg;
const struct tcphdr *tp = tcp_hdr(skb);
struct hash_desc *desc = &hp->md5_desc;
unsigned i;
const unsigned head_data_len = skb_headlen(skb) > header_len ?
skb_headlen(skb) - header_len : 0;
const struct skb_shared_info *shi = skb_shinfo(skb);

sg_init_table(&sg, 1);

sg_set_buf(&sg, ((u8 *) tp) + header_len, head_data_len);
if (crypto_hash_update(desc, &sg, head_data_len))
return 1;

for (i = 0; i < shi->nr_frags; ++i) {
const struct skb_frag_struct *f = &shi->frags[i];
sg_set_page(&sg, f->page, f->size, f->page_offset);
if (crypto_hash_update(desc, &sg, f->size))
return 1;
}

return 0;
}

EXPORT_SYMBOL(tcp_md5_hash_skb_data);

int tcp_md5_hash_key(struct tcp_md5sig_pool *hp, struct tcp_md5sig_key *key)
{
struct scatterlist sg;

sg_init_one(&sg, key->key, key->keylen);
return crypto_hash_update(&hp->md5_desc, &sg, key->keylen);
}

EXPORT_SYMBOL(tcp_md5_hash_key);

#endif

void tcp_done(struct sock *sk)
Expand Down
Loading

0 comments on commit 635c5af

Please sign in to comment.