[TCP]: MD5 Signature Option (RFC2385) support.

Based on implementation by Rick Payne.

Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
YOSHIFUJI Hideaki
2006-11-14 19:07:45 -08:00
committed by David S. Miller
parent bf6bce71ea
commit cfb6eeb4c8
15 changed files with 1714 additions and 64 deletions

View File

@@ -28,6 +28,7 @@
#include <linux/percpu.h>
#include <linux/skbuff.h>
#include <linux/dmaengine.h>
#include <linux/crypto.h>
#include <net/inet_connection_sock.h>
#include <net/inet_timewait_sock.h>
@@ -161,6 +162,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOPT_SACK_PERM 4 /* SACK Permitted */
#define TCPOPT_SACK 5 /* SACK Block */
#define TCPOPT_TIMESTAMP 8 /* Better RTT estimations/PAWS */
#define TCPOPT_MD5SIG 19 /* MD5 Signature (RFC2385) */
/*
* TCP option lengths
@@ -170,6 +172,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_WINDOW 3
#define TCPOLEN_SACK_PERM 2
#define TCPOLEN_TIMESTAMP 10
#define TCPOLEN_MD5SIG 18
/* But this is what stacks really send out. */
#define TCPOLEN_TSTAMP_ALIGNED 12
@@ -178,6 +181,7 @@ extern void tcp_time_wait(struct sock *sk, int state, int timeo);
#define TCPOLEN_SACK_BASE 2
#define TCPOLEN_SACK_BASE_ALIGNED 4
#define TCPOLEN_SACK_PERBLOCK 8
#define TCPOLEN_MD5SIG_ALIGNED 20
/* Flags in tp->nonagle */
#define TCP_NAGLE_OFF 1 /* Nagle's algo is disabled */
@@ -299,6 +303,8 @@ extern void tcp_cleanup_rbuf(struct sock *sk, int copied);
extern int tcp_twsk_unique(struct sock *sk,
struct sock *sktw, void *twp);
extern void tcp_twsk_destructor(struct sock *sk);
static inline void tcp_dec_quickack_mode(struct sock *sk,
const unsigned int pkts)
{
@@ -1064,6 +1070,114 @@ static inline void clear_all_retrans_hints(struct tcp_sock *tp){
tp->fastpath_skb_hint = NULL;
}
/* MD5 Signature */
struct crypto_hash;
/* - key database */
struct tcp_md5sig_key {
u8 *key;
u8 keylen;
};
struct tcp4_md5sig_key {
u8 *key;
u16 keylen;
__be32 addr;
};
struct tcp6_md5sig_key {
u8 *key;
u16 keylen;
#if 0
u32 scope_id; /* XXX */
#endif
struct in6_addr addr;
};
/* - sock block */
struct tcp_md5sig_info {
struct tcp4_md5sig_key *keys4;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct tcp6_md5sig_key *keys6;
u32 entries6;
u32 alloced6;
#endif
u32 entries4;
u32 alloced4;
};
/* - pseudo header */
struct tcp4_pseudohdr {
__be32 saddr;
__be32 daddr;
__u8 pad;
__u8 protocol;
__be16 len;
};
struct tcp6_pseudohdr {
struct in6_addr saddr;
struct in6_addr daddr;
__be32 len;
__be32 protocol; /* including padding */
};
union tcp_md5sum_block {
struct tcp4_pseudohdr ip4;
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
struct tcp6_pseudohdr ip6;
#endif
};
/* - pool: digest algorithm, hash description and scratch buffer */
struct tcp_md5sig_pool {
struct hash_desc md5_desc;
union tcp_md5sum_block md5_blk;
};
#define TCP_MD5SIG_MAXKEYS (~(u32)0) /* really?! */
/* - functions */
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,
int protocol, int tcplen);
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,
u32 addr);
extern struct tcp_md5sig_pool **tcp_alloc_md5sig_pool(void);
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);
static inline
struct tcp_md5sig_pool *tcp_get_md5sig_pool(void)
{
int cpu = get_cpu();
struct tcp_md5sig_pool *ret = __tcp_get_md5sig_pool(cpu);
if (!ret)
put_cpu();
return ret;
}
static inline void tcp_put_md5sig_pool(void)
{
__tcp_put_md5sig_pool();
put_cpu();
}
/* /proc */
enum tcp_seq_states {
TCP_SEQ_STATE_LISTENING,
@@ -1103,6 +1217,35 @@ extern int tcp4_proc_init(void);
extern void tcp4_proc_exit(void);
#endif
/* TCP af-specific functions */
struct tcp_sock_af_ops {
#ifdef CONFIG_TCP_MD5SIG
struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
struct sock *addr_sk);
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,
int protocol, int len);
int (*md5_add) (struct sock *sk,
struct sock *addr_sk,
u8 *newkey,
u8 len);
int (*md5_parse) (struct sock *sk,
char __user *optval,
int optlen);
#endif
};
struct tcp_request_sock_ops {
#ifdef CONFIG_TCP_MD5SIG
struct tcp_md5sig_key *(*md5_lookup) (struct sock *sk,
struct request_sock *req);
#endif
};
extern void tcp_v4_init(struct net_proto_family *ops);
extern void tcp_init(void);