diff options
author | David S. Miller <davem@sunset.davemloft.net> | 2007-09-28 15:18:35 -0700 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-09-28 15:18:35 -0700 |
commit | f8ab18d2d987a59ccbf0495032b2aef05b730037 (patch) | |
tree | 7a24c79632c91e22235888875813950c6c30d929 | |
parent | e79ad711a0108475c1b3a03815527e7237020b08 (diff) | |
download | linux-f8ab18d2d987a59ccbf0495032b2aef05b730037.tar.gz linux-f8ab18d2d987a59ccbf0495032b2aef05b730037.tar.bz2 linux-f8ab18d2d987a59ccbf0495032b2aef05b730037.zip |
[TCP]: Fix MD5 signature handling on big-endian.
Based upon a report and initial patch by Peter Lieven.
tcp4_md5sig_key and tcp6_md5sig_key need to start with
the exact same members as tcp_md5sig_key. Because they
are both cast to that type by tcp_v{4,6}_md5_do_lookup().
Unfortunately tcp{4,6}_md5sig_key use a u16 for the key
length instead of a u8, which is what tcp_md5sig_key
uses. This just so happens to work by accident on
little-endian, but on big-endian it doesn't.
Instead of casting, just place tcp_md5sig_key as the first member of
the address-family specific structures, adjust the access sites, and
kill off the ugly casts.
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/net/tcp.h | 6 | ||||
-rw-r--r-- | net/ipv4/tcp_ipv4.c | 19 | ||||
-rw-r--r-- | net/ipv6/tcp_ipv6.c | 18 |
3 files changed, 20 insertions, 23 deletions
diff --git a/include/net/tcp.h b/include/net/tcp.h index 185c7ecce4cc..54053de0bdd7 100644 --- a/include/net/tcp.h +++ b/include/net/tcp.h @@ -1059,14 +1059,12 @@ struct tcp_md5sig_key { }; struct tcp4_md5sig_key { - u8 *key; - u16 keylen; + struct tcp_md5sig_key base; __be32 addr; }; struct tcp6_md5sig_key { - u8 *key; - u16 keylen; + struct tcp_md5sig_key base; #if 0 u32 scope_id; /* XXX */ #endif diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 9c94627c8c7e..e089a978e128 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c @@ -833,8 +833,7 @@ static struct tcp_md5sig_key * return NULL; for (i = 0; i < tp->md5sig_info->entries4; i++) { if (tp->md5sig_info->keys4[i].addr == addr) - return (struct tcp_md5sig_key *) - &tp->md5sig_info->keys4[i]; + return &tp->md5sig_info->keys4[i].base; } return NULL; } @@ -865,9 +864,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, key = (struct tcp4_md5sig_key *)tcp_v4_md5_do_lookup(sk, addr); if (key) { /* Pre-existing entry - just update that one. */ - kfree(key->key); - key->key = newkey; - key->keylen = newkeylen; + kfree(key->base.key); + key->base.key = newkey; + key->base.keylen = newkeylen; } else { struct tcp_md5sig_info *md5sig; @@ -906,9 +905,9 @@ int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, md5sig->alloced4++; } md5sig->entries4++; - md5sig->keys4[md5sig->entries4 - 1].addr = addr; - md5sig->keys4[md5sig->entries4 - 1].key = newkey; - md5sig->keys4[md5sig->entries4 - 1].keylen = newkeylen; + md5sig->keys4[md5sig->entries4 - 1].addr = addr; + md5sig->keys4[md5sig->entries4 - 1].base.key = newkey; + md5sig->keys4[md5sig->entries4 - 1].base.keylen = newkeylen; } return 0; } @@ -930,7 +929,7 @@ int tcp_v4_md5_do_del(struct sock *sk, __be32 addr) for (i = 0; i < tp->md5sig_info->entries4; i++) { if (tp->md5sig_info->keys4[i].addr == addr) { /* Free the key */ - kfree(tp->md5sig_info->keys4[i].key); + kfree(tp->md5sig_info->keys4[i].base.key); tp->md5sig_info->entries4--; if (tp->md5sig_info->entries4 == 0) { @@ -964,7 +963,7 @@ static void tcp_v4_clear_md5_list(struct sock *sk) if (tp->md5sig_info->entries4) { int i; for (i = 0; i < tp->md5sig_info->entries4; i++) - kfree(tp->md5sig_info->keys4[i].key); + kfree(tp->md5sig_info->keys4[i].base.key); tp->md5sig_info->entries4 = 0; tcp_free_md5sig_pool(); } diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 0f7defb482e9..3e06799b37a6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c @@ -539,7 +539,7 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, for (i = 0; i < tp->md5sig_info->entries6; i++) { if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, addr) == 0) - return (struct tcp_md5sig_key *)&tp->md5sig_info->keys6[i]; + return &tp->md5sig_info->keys6[i].base; } return NULL; } @@ -567,9 +567,9 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, key = (struct tcp6_md5sig_key*) tcp_v6_md5_do_lookup(sk, peer); if (key) { /* modify existing entry - just update that one */ - kfree(key->key); - key->key = newkey; - key->keylen = newkeylen; + kfree(key->base.key); + key->base.key = newkey; + key->base.keylen = newkeylen; } else { /* reallocate new list if current one is full. */ if (!tp->md5sig_info) { @@ -603,8 +603,8 @@ static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, ipv6_addr_copy(&tp->md5sig_info->keys6[tp->md5sig_info->entries6].addr, peer); - tp->md5sig_info->keys6[tp->md5sig_info->entries6].key = newkey; - tp->md5sig_info->keys6[tp->md5sig_info->entries6].keylen = newkeylen; + tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.key = newkey; + tp->md5sig_info->keys6[tp->md5sig_info->entries6].base.keylen = newkeylen; tp->md5sig_info->entries6++; } @@ -626,7 +626,7 @@ static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) for (i = 0; i < tp->md5sig_info->entries6; i++) { if (ipv6_addr_cmp(&tp->md5sig_info->keys6[i].addr, peer) == 0) { /* Free the key */ - kfree(tp->md5sig_info->keys6[i].key); + kfree(tp->md5sig_info->keys6[i].base.key); tp->md5sig_info->entries6--; if (tp->md5sig_info->entries6 == 0) { @@ -657,7 +657,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) if (tp->md5sig_info->entries6) { for (i = 0; i < tp->md5sig_info->entries6; i++) - kfree(tp->md5sig_info->keys6[i].key); + kfree(tp->md5sig_info->keys6[i].base.key); tp->md5sig_info->entries6 = 0; tcp_free_md5sig_pool(); } @@ -668,7 +668,7 @@ static void tcp_v6_clear_md5_list (struct sock *sk) if (tp->md5sig_info->entries4) { for (i = 0; i < tp->md5sig_info->entries4; i++) - kfree(tp->md5sig_info->keys4[i].key); + kfree(tp->md5sig_info->keys4[i].base.key); tp->md5sig_info->entries4 = 0; tcp_free_md5sig_pool(); } |