[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>
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e1a5d29..3639608 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -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 @@
#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 @@
#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 @@
#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 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 @@
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 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);