Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfb6eeb4 authored by YOSHIFUJI Hideaki's avatar YOSHIFUJI Hideaki Committed by David S. Miller
Browse files

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



Based on implementation by Rick Payne.

Signed-off-by: default avatarYOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent bf6bce71
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2598,6 +2598,9 @@ S: Ucitelska 1576
S: Prague 8
S: 182 00 Czech Republic

N: Rick Payne
D: RFC2385 Support for TCP

N: Barak A. Pearlmutter
E: bap@cs.unm.edu
W: http://www.cs.unm.edu/~bap/
+32 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <linux/types.h>
#include <asm/byteorder.h>
#include <linux/socket.h>

struct tcphdr {
	__be16	source;
@@ -94,6 +95,7 @@ enum {
#define TCP_INFO		11	/* Information about this connection. */
#define TCP_QUICKACK		12	/* Block/reenable quick acks */
#define TCP_CONGESTION		13	/* Congestion control algorithm */
#define TCP_MD5SIG		14	/* TCP MD5 Signature (RFC2385) */

#define TCPI_OPT_TIMESTAMPS	1
#define TCPI_OPT_SACK		2
@@ -157,6 +159,17 @@ struct tcp_info
	__u32	tcpi_total_retrans;
};

/* for TCP_MD5SIG socket option */
#define TCP_MD5SIG_MAXKEYLEN	80

struct tcp_md5sig {
	struct __kernel_sockaddr_storage tcpm_addr;	/* address associated */
	__u16	__tcpm_pad1;				/* zero */
	__u16	tcpm_keylen;				/* key length */
	__u32	__tcpm_pad2;				/* zero */
	__u8	tcpm_key[TCP_MD5SIG_MAXKEYLEN];		/* key (binary) */
};

#ifdef __KERNEL__

#include <linux/skbuff.h>
@@ -198,6 +211,10 @@ struct tcp_options_received {

struct tcp_request_sock {
	struct inet_request_sock 	req;
#ifdef CONFIG_TCP_MD5SIG
	/* Only used by TCP MD5 Signature so far. */
	struct tcp_request_sock_ops	*af_specific;
#endif
	__u32			 	rcv_isn;
	__u32			 	snt_isn;
};
@@ -363,6 +380,14 @@ struct tcp_sock {
		__u32		  probe_seq_start;
		__u32		  probe_seq_end;
	} mtu_probe;

#ifdef CONFIG_TCP_MD5SIG
/* TCP AF-Specific parts; only used by MD5 Signature support so far */
	struct tcp_sock_af_ops	*af_specific;

/* TCP MD5 Signagure Option information */
	struct tcp_md5sig_info	*md5sig_info;
#endif
};

static inline struct tcp_sock *tcp_sk(const struct sock *sk)
@@ -377,6 +402,10 @@ struct tcp_timewait_sock {
	__u32			  tw_rcv_wnd;
	__u32			  tw_ts_recent;
	long			  tw_ts_recent_stamp;
#ifdef CONFIG_TCP_MD5SIG
	__u16			  tw_md5_keylen;
	__u8			  tw_md5_key[TCP_MD5SIG_MAXKEYLEN];
#endif
};

static inline struct tcp_timewait_sock *tcp_twsk(const struct sock *sk)
+2 −1
Original line number Diff line number Diff line
@@ -35,7 +35,8 @@ struct request_sock_ops {
				       struct dst_entry *dst);
	void		(*send_ack)(struct sk_buff *skb,
				    struct request_sock *req);
	void		(*send_reset)(struct sk_buff *skb);
	void		(*send_reset)(struct sock *sk,
				      struct sk_buff *skb);
	void		(*destructor)(struct request_sock *req);
};

+143 −0
Original line number Diff line number Diff line
@@ -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);

+3 −0
Original line number Diff line number Diff line
@@ -31,6 +31,9 @@ static inline int twsk_unique(struct sock *sk, struct sock *sktw, void *twp)

static inline void twsk_destructor(struct sock *sk)
{
	BUG_ON(sk == NULL);
	BUG_ON(sk->sk_prot == NULL);
	BUG_ON(sk->sk_prot->twsk_prot == NULL);
	if (sk->sk_prot->twsk_prot->twsk_destructor != NULL)
		sk->sk_prot->twsk_prot->twsk_destructor(sk);
}
Loading