Skip to content

Commit

Permalink
tcp: md5: rcu conversion
Browse files Browse the repository at this point in the history
In order to be able to support proper RST messages for TCP MD5 flows, we
need to allow access to MD5 keys without locking listener socket.

This conversion is a nice cleanup, and shrinks size of timewait sockets
by 80 bytes.

IPv6 code reuses generic code found in IPv4 instead of duplicating it.

Control path uses GFP_KERNEL allocations instead of GFP_ATOMIC.

Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Cc: Shawn Lu <shawn.lu@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Eric Dumazet authored and David S. Miller committed Jan 31, 2012
1 parent a2d9124 commit a915da9
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 335 deletions.
3 changes: 1 addition & 2 deletions include/linux/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -486,8 +486,7 @@ struct tcp_timewait_sock {
u32 tw_ts_recent;
long tw_ts_recent_stamp;
#ifdef CONFIG_TCP_MD5SIG
u16 tw_md5_keylen;
u8 tw_md5_key[TCP_MD5SIG_MAXKEYLEN];
struct tcp_md5sig_key *tw_md5_key;
#endif
/* Few sockets in timewait have cookies; in that case, then this
* object holds a reference to them (tw_cookie_values->kref).
Expand Down
61 changes: 29 additions & 32 deletions include/net/tcp.h
Original file line number Diff line number Diff line change
Expand Up @@ -1130,35 +1130,26 @@ static inline void tcp_clear_all_retrans_hints(struct tcp_sock *tp)
/* MD5 Signature */
struct crypto_hash;

union tcp_md5_addr {
struct in_addr a4;
#if IS_ENABLED(CONFIG_IPV6)
struct in6_addr a6;
#endif
};

/* - key database */
struct tcp_md5sig_key {
u8 *key;
struct hlist_node node;
u8 keylen;
};

struct tcp4_md5sig_key {
struct tcp_md5sig_key base;
__be32 addr;
};

struct tcp6_md5sig_key {
struct tcp_md5sig_key base;
#if 0
u32 scope_id; /* XXX */
#endif
struct in6_addr addr;
u8 family; /* AF_INET or AF_INET6 */
union tcp_md5_addr addr;
u8 key[TCP_MD5SIG_MAXKEYLEN];
struct rcu_head rcu;
};

/* - sock block */
struct tcp_md5sig_info {
struct tcp4_md5sig_key *keys4;
#if IS_ENABLED(CONFIG_IPV6)
struct tcp6_md5sig_key *keys6;
u32 entries6;
u32 alloced6;
#endif
u32 entries4;
u32 alloced4;
struct hlist_head head;
};

/* - pseudo header */
Expand Down Expand Up @@ -1195,19 +1186,25 @@ extern int tcp_v4_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key,
const struct sock *sk,
const struct request_sock *req,
const struct sk_buff *skb);
extern struct tcp_md5sig_key * tcp_v4_md5_lookup(struct sock *sk,
struct sock *addr_sk);
extern int tcp_v4_md5_do_add(struct sock *sk, __be32 addr, u8 *newkey,
u8 newkeylen);
extern int tcp_v4_md5_do_del(struct sock *sk, __be32 addr);
extern int tcp_md5_do_add(struct sock *sk, const union tcp_md5_addr *addr,
int family, const u8 *newkey,
u8 newkeylen, gfp_t gfp);
extern int tcp_md5_do_del(struct sock *sk, const union tcp_md5_addr *addr,
int family);
extern struct tcp_md5sig_key *tcp_v4_md5_lookup(struct sock *sk,
struct sock *addr_sk);

#ifdef CONFIG_TCP_MD5SIG
#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_keylen ? \
&(struct tcp_md5sig_key) { \
.key = (twsk)->tw_md5_key, \
.keylen = (twsk)->tw_md5_keylen, \
} : NULL)
extern struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
const union tcp_md5_addr *addr, int family);
#define tcp_twsk_md5_key(twsk) ((twsk)->tw_md5_key)
#else
static inline struct tcp_md5sig_key *tcp_md5_do_lookup(struct sock *sk,
const union tcp_md5_addr *addr,
int family)
{
return NULL;
}
#define tcp_twsk_md5_key(twsk) NULL
#endif

Expand Down
Loading

0 comments on commit a915da9

Please sign in to comment.