Skip to contentSkip to conversation

tcp: ULP infrastructure

PATCH In review Dave Watson 7 participants 20 messages Jun 14, 2017 – Aug 1, 2017 1 message not in the archive

Subsystems (7)
lore
Share & tools
lore
#1 lore raw

PATCH v3 1/4 tcp: ULP infrastructure

In reply to a message not in the archive

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

---
 include/net/inet_connection_sock.h |   4 ++
 include/net/tcp.h                  |  25 +++++++
 include/uapi/linux/tcp.h           |   1 +
 net/ipv4/Makefile                  |   2 +-
 net/ipv4/sysctl_net_ipv4.c         |  25 +++++++
 net/ipv4/tcp.c                     |  28 ++++++++
 net/ipv4/tcp_ipv4.c                |   2 +
 net/ipv4/tcp_ulp.c                 | 134 +++++++++++++++++++++++++++++++++++++
 8 files changed, 220 insertions(+), 1 deletion(-)
 create mode 100644 net/ipv4/tcp_ulp.c
include/net/inet_connection_sock.h +4 -0
index c7a5779..13e4c89 100644
@@ -75,6 +75,8 @@ struct inet_connection_sock_af_ops {
  * @icsk_pmtu_cookie	   Last pmtu seen by socket
  * @icsk_ca_ops		   Pluggable congestion control hook
  * @icsk_af_ops		   Operations which are AF_INET{4,6} specific
+ * @icsk_ulp_ops	   Pluggable ULP control hook
+ * @icsk_ulp_data	   ULP private data
  * @icsk_ca_state:	   Congestion control state
  * @icsk_retransmits:	   Number of unrecovered [RTO] timeouts
  * @icsk_pending:	   Scheduled timer event
@@ -97,6 +99,8 @@ struct inet_connection_sock {
 	__u32			  icsk_pmtu_cookie;
 	const struct tcp_congestion_ops *icsk_ca_ops;
 	const struct inet_connection_sock_af_ops *icsk_af_ops;
+	const struct tcp_ulp_ops  *icsk_ulp_ops;
+	void			  *icsk_ulp_data;
 	unsigned int		  (*icsk_sync_mss)(struct sock *sk, u32 pmtu);
 	__u8			  icsk_ca_state:6,
 				  icsk_ca_setsockopt:1,
include/net/tcp.h +25 -0
index 3ab677d..b439f46 100644
@@ -1991,4 +1991,29 @@ static inline void tcp_listendrop(const struct sock *sk)
 
 enum hrtimer_restart tcp_pace_kick(struct hrtimer *timer);
 
+/*
+ * Interface for adding Upper Level Protocols over TCP
+ */
+
+#define TCP_ULP_NAME_MAX	16
+#define TCP_ULP_MAX		128
+#define TCP_ULP_BUF_MAX		(TCP_ULP_NAME_MAX*TCP_ULP_MAX)
+
+struct tcp_ulp_ops {
+	struct list_head	list;
+
+	/* initialize ulp */
+	int (*init)(struct sock *sk);
+	/* cleanup ulp */
+	void (*release)(struct sock *sk);
+
+	char		name[TCP_ULP_NAME_MAX];
+	struct module	*owner;
+};
+int tcp_register_ulp(struct tcp_ulp_ops *type);
+void tcp_unregister_ulp(struct tcp_ulp_ops *type);
+int tcp_set_ulp(struct sock *sk, const char *name);
+void tcp_get_available_ulp(char *buf, size_t len);
+void tcp_cleanup_ulp(struct sock *sk);
+
 #endif	/* _TCP_H */
include/uapi/linux/tcp.h +1 -0
index 38a2b07..8204dce 100644
@@ -117,6 +117,7 @@ enum {
 #define TCP_SAVED_SYN		28	/* Get SYN headers recorded for connection */
 #define TCP_REPAIR_WINDOW	29	/* Get/set window parameters */
 #define TCP_FASTOPEN_CONNECT	30	/* Attempt FastOpen with connect */
+#define TCP_ULP		31	/* Attach a ULP to a TCP connection */
 
 struct tcp_repair_opt {
 	__u32	opt_code;
net/ipv4/Makefile +1 -1
index f83de23..afcb435 100644
@@ -8,7 +8,7 @@ obj-y     := route.o inetpeer.o protocol.o \
 	     inet_timewait_sock.o inet_connection_sock.o \
 	     tcp.o tcp_input.o tcp_output.o tcp_timer.o tcp_ipv4.o \
 	     tcp_minisocks.o tcp_cong.o tcp_metrics.o tcp_fastopen.o \
-	     tcp_rate.o tcp_recovery.o \
+	     tcp_rate.o tcp_recovery.o tcp_ulp.o \
 	     tcp_offload.o datagram.o raw.o udp.o udplite.o \
 	     udp_offload.o arp.o icmp.o devinet.o af_inet.o igmp.o \
 	     fib_frontend.o fib_semantics.o fib_trie.o fib_notifier.o \
net/ipv4/sysctl_net_ipv4.c +25 -0
index 7065234a..9bf8097 100644
@@ -360,6 +360,25 @@ static int proc_tfo_blackhole_detect_timeout(struct ctl_table *table,
 	ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
 	if (write && ret == 0)
 		tcp_fastopen_active_timeout_reset();
+
+	return ret;
+}
+
+static int proc_tcp_available_ulp(struct ctl_table *ctl,
+				  int write,
+				  void __user *buffer, size_t *lenp,
+				  loff_t *ppos)
+{
+	struct ctl_table tbl = { .maxlen = TCP_ULP_BUF_MAX, };
+	int ret;
+
+	tbl.data = kmalloc(tbl.maxlen, GFP_USER);
+	if (!tbl.data)
+		return -ENOMEM;
+	tcp_get_available_ulp(tbl.data, TCP_ULP_BUF_MAX);
+	ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
+	kfree(tbl.data);
+
 	return ret;
 }
 
@@ -686,6 +705,12 @@ static struct ctl_table ipv4_table[] = {
 		.proc_handler	= proc_dointvec_ms_jiffies,
 	},
 	{
+		.procname	= "tcp_available_ulp",
+		.maxlen		= TCP_ULP_BUF_MAX,
+		.mode		= 0444,
+		.proc_handler   = proc_tcp_available_ulp,
+	},
+	{
 		.procname	= "icmp_msgs_per_sec",
 		.data		= &sysctl_icmp_msgs_per_sec,
 		.maxlen		= sizeof(int),
net/ipv4/tcp.c +28 -0
index cc8fd8b..b06ee30 100644
@@ -2482,6 +2482,24 @@ static int do_tcp_setsockopt(struct sock *sk, int level,
 		release_sock(sk);
 		return err;
 	}
+	case TCP_ULP: {
+		char name[TCP_ULP_NAME_MAX];
+
+		if (optlen < 1)
+			return -EINVAL;
+
+		val = strncpy_from_user(name, optval,
+					min_t(long, TCP_ULP_NAME_MAX - 1,
+					      optlen));
+		if (val < 0)
+			return -EFAULT;
+		name[val] = 0;
+
+		lock_sock(sk);
+		err = tcp_set_ulp(sk, name);
+		release_sock(sk);
+		return err;
+	}
 	default:
 		/* fallthru */
 		break;
@@ -3038,6 +3056,16 @@ static int do_tcp_getsockopt(struct sock *sk, int level,
 			return -EFAULT;
 		return 0;
 
+	case TCP_ULP:
+		if (get_user(len, optlen))
+			return -EFAULT;
+		len = min_t(unsigned int, len, TCP_ULP_NAME_MAX);
+		if (put_user(len, optlen))
+			return -EFAULT;
+		if (copy_to_user(optval, icsk->icsk_ulp_ops->name, len))
+			return -EFAULT;
+		return 0;
+
 	case TCP_THIN_LINEAR_TIMEOUTS:
 		val = tp->thin_lto;
 		break;
net/ipv4/tcp_ipv4.c +2 -0
index 1dc8c44..eec2ff9 100644
@@ -1860,6 +1860,8 @@ void tcp_v4_destroy_sock(struct sock *sk)
 
 	tcp_cleanup_congestion_control(sk);
 
+	tcp_cleanup_ulp(sk);
+
 	/* Cleanup up the write buffer. */
 	tcp_write_queue_purge(sk);
 
net/ipv4/tcp_ulp.c new file +134 -0

134 lines not on this page · raw message

Signature · 1 line
2.9.3
#10 lore raw

PATCH v3 2/4 tcp: export do_tcp_sendpages and tcp_rate_check_app_limited functions

In reply to a message not in the archive

Export do_tcp_sendpages and tcp_rate_check_app_limited, since tls will need to sendpages while the socket is already locked.

tcp_sendpage is exported, but requires the socket lock to not be held already.

---
 include/net/tcp.h   | 2 ++
 net/ipv4/tcp.c      | 5 +++--
 net/ipv4/tcp_rate.c | 1 +
 3 files changed, 6 insertions(+), 2 deletions(-)
include/net/tcp.h +2 -0
index b439f46..e17ec28 100644
@@ -350,6 +350,8 @@ int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw);
 int tcp_sendmsg(struct sock *sk, struct msghdr *msg, size_t size);
 int tcp_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
 		 int flags);
+ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+		 size_t size, int flags);
 void tcp_release_cb(struct sock *sk);
 void tcp_wfree(struct sk_buff *skb);
 void tcp_write_timer_handler(struct sock *sk);
net/ipv4/tcp.c +3 -2
index b06ee30..11e4ee2 100644
@@ -901,8 +901,8 @@ static int tcp_send_mss(struct sock *sk, int *size_goal, int flags)
 	return mss_now;
 }
 
-static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
-				size_t size, int flags)
+ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
+			 size_t size, int flags)
 {
 	struct tcp_sock *tp = tcp_sk(sk);
 	int mss_now, size_goal;
@@ -1032,6 +1032,7 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page *page, int offset,
 	}
 	return sk_stream_error(sk, flags, err);
 }
+EXPORT_SYMBOL_GPL(do_tcp_sendpages);
 
 int tcp_sendpage(struct sock *sk, struct page *page, int offset,
 		 size_t size, int flags)
net/ipv4/tcp_rate.c +1 -0
index ad99569..3330a37 100644
@@ -185,3 +185,4 @@ void tcp_rate_check_app_limited(struct sock *sk)
 		tp->app_limited =
 			(tp->delivered + tcp_packets_in_flight(tp)) ? : 1;
 }
+EXPORT_SYMBOL_GPL(tcp_rate_check_app_limited);
Signature · 1 line
2.9.3
#11 lore raw

PATCH v3 3/4 tls: kernel TLS support

In reply to a message not in the archive

Software implementation of transport layer security, implemented using ULP infrastructure. tcp proto_ops are replaced with tls equivalents of sendmsg and sendpage.

Only symmetric crypto is done in the kernel, keys are passed by setsockopt after the handshake is complete. All control messages are supported via CMSG data - the actual symmetric encryption is the same, just the message type needs to be passed separately.

For user API, please see Documentation patch.

Pieces that can be shared between hw and sw implementation are in tls_main.c

---
 MAINTAINERS              |  10 +
 include/linux/socket.h   |   1 +
 include/net/tls.h        | 237 +++++++++++++++
 include/uapi/linux/tls.h |  79 +++++
 net/Kconfig              |   1 +
 net/Makefile             |   1 +
 net/tls/Kconfig          |  12 +
 net/tls/Makefile         |   7 +
 net/tls/tls_main.c       | 487 ++++++++++++++++++++++++++++++
 net/tls/tls_sw.c         | 772 +++++++++++++++++++++++++++++++++++++++++++++++
 10 files changed, 1607 insertions(+)
 create mode 100644 include/net/tls.h
 create mode 100644 include/uapi/linux/tls.h
 create mode 100644 net/tls/Kconfig
 create mode 100644 net/tls/Makefile
 create mode 100644 net/tls/tls_main.c
 create mode 100644 net/tls/tls_sw.c
MAINTAINERS +10 -0
index f4e682c..710af53 100644
@@ -8979,6 +8979,16 @@ F:	net/ipv6/
 F:	include/net/ip*
 F:	arch/x86/net/*
 
+NETWORKING [TLS]
+M:	Ilya Lesokhin <[email protected]>
+M:	Aviad Yehezkel <[email protected]>
+M:	Dave Watson <[email protected]>
+L:	[email protected]
+S:	Maintained
+F:	net/tls/*
+F:	include/uapi/linux/tls.h
+F:	include/net/tls.h
+
 NETWORKING [IPSEC]
 M:	Steffen Klassert <[email protected]>
 M:	Herbert Xu <[email protected]>
include/linux/socket.h +1 -0
index 0820274..8b13db5 100644
@@ -334,6 +334,7 @@ struct ucred {
 #define SOL_ALG		279
 #define SOL_NFC		280
 #define SOL_KCM		281
+#define SOL_TLS		282
 
 /* IPX options */
 #define IPX_TYPE	1
include/net/tls.h new file +237 -0

237 lines not on this page · raw message

include/uapi/linux/tls.h new file +79 -0

79 lines not on this page · raw message

net/Kconfig +1 -0
index 102f781..7d57ef3 100644
@@ -55,6 +55,7 @@ menu "Networking options"
 
 source "net/packet/Kconfig"
 source "net/unix/Kconfig"
+source "net/tls/Kconfig"
 source "net/xfrm/Kconfig"
 source "net/iucv/Kconfig"
 source "net/smc/Kconfig"
net/Makefile +1 -0
index 9086ffb..bed80fa 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_LLC)		+= llc/
 obj-$(CONFIG_NET)		+= ethernet/ 802/ sched/ netlink/ bpf/
 obj-$(CONFIG_NETFILTER)		+= netfilter/
 obj-$(CONFIG_INET)		+= ipv4/
+obj-$(CONFIG_TLS)		+= tls/
 obj-$(CONFIG_XFRM)		+= xfrm/
 obj-$(CONFIG_UNIX)		+= unix/
 obj-$(CONFIG_NET)		+= ipv6/
net/tls/Kconfig new file +12 -0
new file mode 100644
index 0000000..61e5329
@@ -0,0 +1,12 @@
+#
+# TLS configuration
+#
+config TLS
+	tristate "Transport Layer Security support"
+	depends on NET
+	default m
+	---help---
+	Enable kernel support for TLS protocol. This allows symmetric
+	encryption handling of the TLS protocol to be done in-kernel.
+
+	If unsure, say M.
net/tls/Makefile new file +7 -0
new file mode 100644
index 0000000..a930fd1
@@ -0,0 +1,7 @@
+#
+# Makefile for the TLS subsystem.
+#
+
+obj-$(CONFIG_TLS) += tls.o
+
+tls-y := tls_main.o tls_sw.o
net/tls/tls_main.c new file +487 -0

487 lines not on this page · raw message

net/tls/tls_sw.c new file +772 -0

772 lines not on this page · raw message

Signature · 1 line
2.9.3
#20 lore raw

PATCH v3 4/4 tls: Documentation

In reply to a message not in the archive

Add documentation for the tcp ULP tls interface.

---
 Documentation/networking/tls.txt | 135 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 135 insertions(+)
 create mode 100644 Documentation/networking/tls.txt
Documentation/networking/tls.txt new file +135 -0
new file mode 100644
index 0000000..77ed006
@@ -0,0 +1,135 @@
+Overview
+========
+
+Transport Layer Security (TLS) is a Upper Layer Protocol (ULP) that runs over
+TCP. TLS provides end-to-end data integrity and confidentiality.
+
+User interface
+==============
+
+Creating a TLS connection
+-------------------------
+
+First create a new TCP socket and set the TLS ULP.
+
+  sock = socket(AF_INET, SOCK_STREAM, 0);
+  setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));
+
+Setting the TLS ULP allows us to set/get TLS socket options. Currently
+only the symmetric encryption is handled in the kernel.  After the TLS
+handshake is complete, we have all the parameters required to move the
+data-path to the kernel. There is a separate socket option for moving
+the transmit and the receive into the kernel.
+
+  /* From linux/tls.h */
+  struct tls_crypto_info {
+          unsigned short version;
+          unsigned short cipher_type;
+  };
+
+  struct tls12_crypto_info_aes_gcm_128 {
+          struct tls_crypto_info info;
+          unsigned char iv[TLS_CIPHER_AES_GCM_128_IV_SIZE];
+          unsigned char key[TLS_CIPHER_AES_GCM_128_KEY_SIZE];
+          unsigned char salt[TLS_CIPHER_AES_GCM_128_SALT_SIZE];
+          unsigned char rec_seq[TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE];
+  };
+
+
+  struct tls12_crypto_info_aes_gcm_128 crypto_info;
+
+  crypto_info.info.version = TLS_1_2_VERSION;
+  crypto_info.info.cipher_type = TLS_CIPHER_AES_GCM_128;
+  memcpy(crypto_info.iv, iv_write, TLS_CIPHER_AES_GCM_128_IV_SIZE);
+  memcpy(crypto_info.rec_seq, seq_number_write,
+					TLS_CIPHER_AES_GCM_128_REC_SEQ_SIZE);
+  memcpy(crypto_info.key, cipher_key_write, TLS_CIPHER_AES_GCM_128_KEY_SIZE);
+  memcpy(crypto_info.salt, implicit_iv_write, TLS_CIPHER_AES_GCM_128_SALT_SIZE);
+
+  setsockopt(sock, SOL_TLS, TLS_TX, &crypto_info, sizeof(crypto_info));
+
+Sending TLS application data
+----------------------------
+
+After setting the TLS_TX socket option all application data sent over this
+socket is encrypted using TLS and the parameters provided in the socket option.
+For example, we can send an encrypted hello world record as follows:
+
+  const char *msg = "hello world\n";
+  send(sock, msg, strlen(msg));
+
+send() data is directly encrypted from the userspace buffer provided
+to the encrypted kernel send buffer if possible.
+
+The sendfile system call will send the file's data over TLS records of maximum
+length (2^14).
+
+  file = open(filename, O_RDONLY);
+  fstat(file, &stat);
+  sendfile(sock, file, &offset, stat.st_size);
+
+TLS records are created and sent after each send() call, unless
+MSG_MORE is passed.  MSG_MORE will delay creation of a record until
+MSG_MORE is not passed, or the maximum record size is reached.
+
+The kernel will need to allocate a buffer for the encrypted data.
+This buffer is allocated at the time send() is called, such that
+either the entire send() call will return -ENOMEM (or block waiting
+for memory), or the encryption will always succeed.  If send() returns
+-ENOMEM and some data was left on the socket buffer from a previous
+call using MSG_MORE, the MSG_MORE data is left on the socket buffer.
+
+Send TLS control messages
+-------------------------
+
+Other than application data, TLS has control messages such as alert
+messages (record type 21) and handshake messages (record type 22), etc.
+These messages can be sent over the socket by providing the TLS record type
+via a CMSG. For example the following function sends @data of @length bytes
+using a record of type @record_type.
+
+/* send TLS control message using record_type */
+  static int klts_send_ctrl_message(int sock, unsigned char record_type,
+                                  void *data, size_t length)
+  {
+        struct msghdr msg = {0};
+        int cmsg_len = sizeof(record_type);
+        struct cmsghdr *cmsg;
+        char buf[CMSG_SPACE(cmsg_len)];
+        struct iovec msg_iov;   /* Vector of data to send/receive into.  */
+
+        msg.msg_control = buf;
+        msg.msg_controllen = sizeof(buf);
+        cmsg = CMSG_FIRSTHDR(&msg);
+        cmsg->cmsg_level = SOL_TLS;
+        cmsg->cmsg_type = TLS_SET_RECORD_TYPE;
+        cmsg->cmsg_len = CMSG_LEN(cmsg_len);
+        *CMSG_DATA(cmsg) = record_type;
+        msg.msg_controllen = cmsg->cmsg_len;
+
+        msg_iov.iov_base = data;
+        msg_iov.iov_len = length;
+        msg.msg_iov = &msg_iov;
+        msg.msg_iovlen = 1;
+
+        return sendmsg(sock, &msg, 0);
+  }
+
+Control message data should be provided unencrypted, and will be
+encrypted by the kernel.
+
+Integrating in to userspace TLS library
+---------------------------------------
+
+At a high level, the kernel TLS ULP is a replacement for the record
+layer of a userspace TLS library.
+
+A patchset to OpenSSL to use ktls as the record layer is here:
+
+https://github.com/Mellanox/tls-openssl
+
+An example of calling send directly after a handshake using
+gnutls.  Since it doesn't implement a full record layer, control
+messages are not supported:
+
+https://github.com/Mellanox/tls-af_ktls_tool
Signature · 1 line
2.9.3
#12 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

In reply to Dave Watson
Quoted 10 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
include/net/tls.h new file +10 -0
+
+static inline struct tls_context *tls_get_ctx(const struct sock *sk)
+{
+	struct inet_connection_sock *icsk = inet_csk(sk);
+
+	return icsk->icsk_ulp_data;
+}
+
+static inline struct tls_sw_context *tls_sw_ctx(
+		const struct tls_context *tls_ctx)

include/net/tls.h line 233

Quoted 10 lines
include/net/tls.h new file +10 -0
+{
+	return (struct tls_sw_context *)tls_ctx->priv_ctx;
+}
+
+static inline struct tls_offload_context *tls_offload_ctx(
+		const struct tls_context *tls_ctx)
+{
+	return (struct tls_offload_context *)tls_ctx->priv_ctx;
+}
+

Since priv_ctx is void *, casts here are unnecessary.

#13 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

In reply to Dave Watson
Quoted 5 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
net/tls/Kconfig new file +2 -0
@@ -0,0 +1,12 @@
+#
+# TLS configuration

net/tls/Kconfig line 12

Quoted 10 lines
net/tls/Kconfig new file +10 -0
+#
+config TLS
+	tristate "Transport Layer Security support"
+	depends on NET
+	default m
+	---help---
+	Enable kernel support for TLS protocol. This allows symmetric
+	encryption handling of the TLS protocol to be done in-kernel.
+
+	If unsure, say M.

I understand that this will be useful to lots of people and most distributions will enable it. But the defacto policy in kernel configuration has been that new features in kernel default to being disabled.

#2 lore raw
In reply to Dave Watson

Hello,

Quoted 25 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

Quoted 11 lines
---
 include/net/inet_connection_sock.h |   4 ++
 include/net/tcp.h                  |  25 +++++++
 include/uapi/linux/tcp.h           |   1 +
 net/ipv4/Makefile                  |   2 +-
 net/ipv4/sysctl_net_ipv4.c         |  25 +++++++
 net/ipv4/tcp.c                     |  28 ++++++++
 net/ipv4/tcp_ipv4.c                |   2 +
 net/ipv4/tcp_ulp.c                 | 134 +++++++++++++++++++++++++++++++++++++
 8 files changed, 220 insertions(+), 1 deletion(-)
 create mode 100644 net/ipv4/tcp_ulp.c

I know I'm pretty late to the game (and maybe this has already been discussed but I couldn't find anything in the archives), but I am wondering what the take is on potential races of the setsockopt() vs other system-calls.

For example one might race the setsockopt() with a sendmsg() and the sendmsg might end up blocking on the lock_sock in tcp_sendmsg, waiting for tcp_set_ulp() to finish changing sk_prot. When the setsockopt() finishes, we are then inside tcp_sendmsg() coming directly from sendmsg(), while we should have been in the ULP's sendmsg.

It seems like TLS-ULP is resilient to this (or at least, won't cause a panic), but there might be more exotic users of ULP in the future, that change other callbacks and then things might go wrong.

Thoughts?

Thanks,
Christoph

#14 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

In reply to Stephen Hemminger
Quoted 14 lines · Stephen Hemminger
Quoted 11 lines · On Wed, 14 Jun 2017 11:37:39 -0700 Dave Watson <[email protected]> wrote:
net/tls/Kconfig new file +8 -0
@@ -0,0 +1,12 @@
+#
+# TLS configuration
+#
+config TLS
+	tristate "Transport Layer Security support"
+	depends on NET
+	default m
+	---help---
Quoted 8 lines

net/tls/Kconfig line 12

Quoted 4 lines
net/tls/Kconfig new file +4 -0
+	Enable kernel support for TLS protocol. This allows symmetric
+	encryption handling of the TLS protocol to be done in-kernel.
+
+	If unsure, say M.

I understand that this will be useful to lots of people and most distributions will enable it. But the defacto policy in kernel configuration has been that new features in kernel default to being disabled.

Sure, will send a patch to switch to default n.

#4 lore raw
In reply to Dave Watson
Quoted 17 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

Hey Dave,

I'm seeing the following while fuzzing, which was bisected to this commit:

==================================================================

BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline]
BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057
Read of size 4 at addr 0000000000000020 by task syz-executor1/15452

CPU: 0 PID: 15452 Comm: syz-executor1 Not tainted 4.12.0-rc6-next-20170623+ #173
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
Call Trace:
 __dump_stack lib/dump_stack.c:16 [inline]
 dump_stack+0x11d/0x1e5 lib/dump_stack.c:52
 kasan_report_error mm/kasan/report.c:349 [inline]
 kasan_report+0x15e/0x370 mm/kasan/report.c:408
 check_memory_region_inline mm/kasan/kasan.c:260 [inline]
 check_memory_region+0x14b/0x1a0 mm/kasan/kasan.c:267
 kasan_check_read+0x11/0x20 mm/kasan/kasan.c:272
 copy_to_user include/linux/uaccess.h:168 [inline]
 do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057
 tcp_getsockopt+0xb0/0xd0 net/ipv4/tcp.c:3194
 sock_common_getsockopt+0x95/0xd0 net/core/sock.c:2863
 SYSC_getsockopt net/socket.c:1869 [inline]
 SyS_getsockopt+0x180/0x360 net/socket.c:1851
 do_syscall_64+0x267/0x740 arch/x86/entry/common.c:284
 entry_SYSCALL64_slow_path+0x25/0x25
RIP: 0033:0x451759
RSP: 002b:00007f5dc2b1fc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000037
RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451759
RDX: 000000000000001f RSI: 0000000000000006 RDI: 0000000000000005
RBP: 0000000000000c30 R08: 00000000207bf000 R09: 0000000000000000
R10: 0000000020000ffc R11: 0000000000000216 R12: 00000000004b824b
R13: 00000000ffffffff R14: 0000000000000005 R15: 0000000000000006
==================================================================
Disabling lock debugging due to kernel taint
Kernel panic - not syncing: panic_on_warn set ...

CPU: 0 PID: 15452 Comm: syz-executor1 Tainted: G    B           4.12.0-rc6-next-20170623+ #173
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014
Call Trace:
 __dump_stack lib/dump_stack.c:16 [inline]
 dump_stack+0x11d/0x1e5 lib/dump_stack.c:52
 panic+0x1bc/0x3ad kernel/panic.c:180
 kasan_end_report+0x47/0x4f mm/kasan/report.c:176
 kasan_report_error mm/kasan/report.c:356 [inline]
 kasan_report+0x167/0x370 mm/kasan/report.c:408
 check_memory_region_inline mm/kasan/kasan.c:260 [inline]
 check_memory_region+0x14b/0x1a0 mm/kasan/kasan.c:267
 kasan_check_read+0x11/0x20 mm/kasan/kasan.c:272
 copy_to_user include/linux/uaccess.h:168 [inline]
 do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057
 tcp_getsockopt+0xb0/0xd0 net/ipv4/tcp.c:3194
 sock_common_getsockopt+0x95/0xd0 net/core/sock.c:2863
 SYSC_getsockopt net/socket.c:1869 [inline]
 SyS_getsockopt+0x180/0x360 net/socket.c:1851
 do_syscall_64+0x267/0x740 arch/x86/entry/common.c:284
 entry_SYSCALL64_slow_path+0x25/0x25
RIP: 0033:0x451759
RSP: 002b:00007f5dc2b1fc08 EFLAGS: 00000216 ORIG_RAX: 0000000000000037
RAX: ffffffffffffffda RBX: 0000000000718000 RCX: 0000000000451759
RDX: 000000000000001f RSI: 0000000000000006 RDI: 0000000000000005
RBP: 0000000000000c30 R08: 00000000207bf000 R09: 0000000000000000
R10: 0000000020000ffc R11: 0000000000000216 R12: 00000000004b824b
R13: 00000000ffffffff R14: 0000000000000005 R15: 0000000000000006

Dumping ftrace buffer:
(ftrace buffer empty)
Kernel Offset: 0x24800000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) Rebooting in 86400 seconds..

Signature · 2 lines
Thanks,
Sasha
#5 lore raw
Quoted 27 lines · Alexander (Sasha Levin)
Quoted 17 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

Quoted 8 lines

Hey Dave,

I'm seeing the following while fuzzing, which was bisected to this commit:

==================================================================

BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline]
BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057
Read of size 4 at addr 0000000000000020 by task syz-executor1/15452

At a glance, this looks like it was fixed already by

https://www.mail-archive.com/[email protected]/msg175226.html

Can you recheck with that patch, or verify that you already have it? Thanks.

#6 lore raw
Quoted 37 lines · Dave Watson
Quoted 27 lines · Alexander (Sasha Levin)
Quoted 17 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

Quoted 8 lines
$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

Quoted 8 lines

Hey Dave,

I'm seeing the following while fuzzing, which was bisected to this commit:

==================================================================

BUG: KASAN: null-ptr-deref in copy_to_user include/linux/uaccess.h:168 [inline]
BUG: KASAN: null-ptr-deref in do_tcp_getsockopt.isra.33+0x24f/0x1e30 net/ipv4/tcp.c:3057
Read of size 4 at addr 0000000000000020 by task syz-executor1/15452
Quoted 6 lines

At a glance, this looks like it was fixed already by

https://www.mail-archive.com/[email protected]/msg175226.html

Can you recheck with that patch, or verify that you already have it? Thanks.

I've already tried this patch, it doesn't fix the issue I've reported.

Signature · 2 lines
Thanks,
Sasha
#15 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

In reply to Dave Watson

Sorry for replying to old mail...

Quoted 28 lines · Dave Watson
net/tls/tls_sw.c new file +28 -0
+static int tls_do_encryption(struct tls_context *tls_ctx,
+			     struct tls_sw_context *ctx, size_t data_len,
+			     gfp_t flags)
+{
+	unsigned int req_size = sizeof(struct aead_request) +
+		crypto_aead_reqsize(ctx->aead_send);
+	struct aead_request *aead_req;
+	int rc;
+
+	aead_req = kmalloc(req_size, flags);
+	if (!aead_req)
+		return -ENOMEM;
+
+	ctx->sg_encrypted_data[0].offset += tls_ctx->prepend_size;
+	ctx->sg_encrypted_data[0].length -= tls_ctx->prepend_size;
+
+	aead_request_set_tfm(aead_req, ctx->aead_send);
+	aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
+	aead_request_set_crypt(aead_req, ctx->sg_aead_in, ctx->sg_aead_out,
+			       data_len, tls_ctx->iv);
+	rc = crypto_aead_encrypt(aead_req);
+
+	ctx->sg_encrypted_data[0].offset -= tls_ctx->prepend_size;
+	ctx->sg_encrypted_data[0].length += tls_ctx->prepend_size;
+
+	kfree(aead_req);
+	return rc;
+}

...

Quoted 2 lines
net/tls/tls_sw.c new file +2 -0
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{

...

net/tls/tls_sw.c line 747

Quoted 10 lines
net/tls/tls_sw.c new file +10 -0
+
+	if (!sw_ctx->aead_send) {
+		sw_ctx->aead_send = crypto_alloc_aead("gcm(aes)", 0, 0);
+		if (IS_ERR(sw_ctx->aead_send)) {
+			rc = PTR_ERR(sw_ctx->aead_send);
+			sw_ctx->aead_send = NULL;
+			goto free_rec_seq;
+		}
+	}
+

When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.

Otherwise you will crash on an asynchronous crypto return, no?

Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?

#16 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

Quoted 21 lines · Steffen Klassert

Sorry for replying to old mail...

Quoted 2 lines
net/tls/tls_sw.c new file +2 -0
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{

...

net/tls/tls_sw.c line 747

Quoted 10 lines
net/tls/tls_sw.c new file +10 -0
+
+	if (!sw_ctx->aead_send) {
+		sw_ctx->aead_send = crypto_alloc_aead("gcm(aes)", 0, 0);
+		if (IS_ERR(sw_ctx->aead_send)) {
+			rc = PTR_ERR(sw_ctx->aead_send);
+			sw_ctx->aead_send = NULL;
+			goto free_rec_seq;
+		}
+	}
+

When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.

Quoted 1 line

Otherwise you will crash on an asynchronous crypto return, no?

The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC) is the correct way to request synchronous algorithms only?

Quoted 2 lines

Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?

We hold the socket lock and only one crypto op can happen at a time, so we reuse the scatterlists.

#17 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

Quoted 22 lines · Dave Watson
Quoted 21 lines · Steffen Klassert

Sorry for replying to old mail...

Quoted 2 lines
net/tls/tls_sw.c new file +2 -0
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{

...

net/tls/tls_sw.c line 747

Quoted 10 lines
net/tls/tls_sw.c new file +10 -0
+
+	if (!sw_ctx->aead_send) {
+		sw_ctx->aead_send = crypto_alloc_aead("gcm(aes)", 0, 0);
+		if (IS_ERR(sw_ctx->aead_send)) {
+			rc = PTR_ERR(sw_ctx->aead_send);
+			sw_ctx->aead_send = NULL;
+			goto free_rec_seq;
+		}
+	}
+

When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.

Quoted 7 lines
Quoted 1 line

Otherwise you will crash on an asynchronous crypto return, no?

The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC) is the correct way to request synchronous algorithms only?

Yes, that means the CRYPTO_ALG_ASYNC bit is required to be 0, i.e. the algorithm must be synchronous. Currently it's requesting either a synchronous or asynchronous algorithm, and it will crash if it gets an async one.

Also I think even with a synchronous algorithm, tls_do_encryption() still needs to call aead_request_set_callback(), passing NULL for the callback and data, so that the request flags are initialized.

Eric

#18 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

In reply to Dave Watson
Quoted 22 lines · Dave Watson
Quoted 21 lines · Steffen Klassert

Sorry for replying to old mail...

Quoted 2 lines
net/tls/tls_sw.c new file +2 -0
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{

...

net/tls/tls_sw.c line 747

Quoted 10 lines
net/tls/tls_sw.c new file +10 -0
+
+	if (!sw_ctx->aead_send) {
+		sw_ctx->aead_send = crypto_alloc_aead("gcm(aes)", 0, 0);
+		if (IS_ERR(sw_ctx->aead_send)) {
+			rc = PTR_ERR(sw_ctx->aead_send);
+			sw_ctx->aead_send = NULL;
+			goto free_rec_seq;
+		}
+	}
+

When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.

Quoted 6 lines
Quoted 1 line

Otherwise you will crash on an asynchronous crypto return, no?

The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC) is the correct way to request synchronous algorithms only?

Yes, but then you loose the aes-ni based algorithms because they are asynchronous. If you want to have good crypto performance, it is better to implement the asynchronous callbacks.

Quoted 6 lines
Quoted 3 lines

Also, it seems that you have your scatterlists on a per crypto transformation base istead of per crypto request. Is this intentional?

We hold the socket lock and only one crypto op can happen at a time, so we reuse the scatterlists.

This is OK as long as the crypto happens synchronous. But as said above, I think this is not what you want.

#19 lore raw

Re: [PATCH v3 net-next 3/4] tls: kernel TLS support

Quoted 25 lines · Steffen Klassert
Quoted 24 lines · Dave Watson
Quoted 22 lines · Steffen Klassert

Sorry for replying to old mail...

Quoted 2 lines
net/tls/tls_sw.c new file +2 -0
+int tls_set_sw_offload(struct sock *sk, struct tls_context *ctx)
+{

...

net/tls/tls_sw.c line 747

Quoted 10 lines
net/tls/tls_sw.c new file +10 -0
+
+	if (!sw_ctx->aead_send) {
+		sw_ctx->aead_send = crypto_alloc_aead("gcm(aes)", 0, 0);
+		if (IS_ERR(sw_ctx->aead_send)) {
+			rc = PTR_ERR(sw_ctx->aead_send);
+			sw_ctx->aead_send = NULL;
+			goto free_rec_seq;
+		}
+	}
+

When I look on how you allocate the aead transformation, it seems that you should either register an asynchronous callback with aead_request_set_callback(), or request for a synchronous algorithm.

Otherwise you will crash on an asynchronous crypto return, no?

Quoted 8 lines
Quoted 4 lines

The intention is for it to be synchronous, and gather directly from userspace buffers. It looks like calling crypto_alloc_aead("gcm(aes)", 0, CRYPTO_ALG_ASYNC) is the correct way to request synchronous algorithms only?

Yes, but then you loose the aes-ni based algorithms because they are asynchronous. If you want to have good crypto performance, it is better to implement the asynchronous callbacks.

Right, the trick is we want both aesni, and to guarantee that we are done using the input buffers before sendmsg() returns. For now I can set a callback, and wait on a completion. The initial use case of userspace openssl integration shouldn't hit the aesni async case anyway (!irq_fpu_usable())

#7 lore raw
In reply to Dave Watson
Quoted 9 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

Hi Dave,

Thanks for this work. I think this functionality is going to have many uses!

One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:

setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));

Where ulp_param is a structure containing the ULP name as well as some ULP specific parameters that are passed to init_ulp. ulp_init could determine whether the socket family is appropriate for the ULP being requested.

Thanks,
Tom

#3 lore raw
In reply to Christoph Paasch
Quoted 50 lines · Christoph Paasch

Hello,

Quoted 25 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

modules will call:
tcp_register_ulp(&tcp_tls_ulp_ops);

to register/unregister their ulp, with an init function and name.

A list of registered ulps will be returned by tcp_get_available_ulp, which is hooked up to /proc. Example:

$ cat /proc/sys/net/ipv4/tcp_available_ulp
tls

There is currently no functionality to remove or chain ULPs, but it should be possible to add these in the future if needed.

Quoted 11 lines
---
 include/net/inet_connection_sock.h |   4 ++
 include/net/tcp.h                  |  25 +++++++
 include/uapi/linux/tcp.h           |   1 +
 net/ipv4/Makefile                  |   2 +-
 net/ipv4/sysctl_net_ipv4.c         |  25 +++++++
 net/ipv4/tcp.c                     |  28 ++++++++
 net/ipv4/tcp_ipv4.c                |   2 +
 net/ipv4/tcp_ulp.c                 | 134 +++++++++++++++++++++++++++++++++++++
 8 files changed, 220 insertions(+), 1 deletion(-)
 create mode 100644 net/ipv4/tcp_ulp.c

I know I'm pretty late to the game (and maybe this has already been discussed but I couldn't find anything in the archives), but I am wondering what the take is on potential races of the setsockopt() vs other system-calls.

For example one might race the setsockopt() with a sendmsg() and the sendmsg might end up blocking on the lock_sock in tcp_sendmsg, waiting for tcp_set_ulp() to finish changing sk_prot. When the setsockopt() finishes, we are then inside tcp_sendmsg() coming directly from sendmsg(), while we should have been in the ULP's sendmsg.

Quoted 3 lines

It seems like TLS-ULP is resilient to this (or at least, won't cause a panic), but there might be more exotic users of ULP in the future, that change other callbacks and then things might go wrong.

Christoph,

I noticed this also. I think the easiest answer would be to just assume the caller understands the race condition and can synchronize itself. Other than that we'd probably have wake up everyone blocking on the socket without something like EAGAIN so they're forced to retry the operation. But even that might not easily yield an obvious point at which the socket can be safely changed.

Tom

Quoted 8 lines

Thoughts?

Thanks,
Christoph

#8 lore raw
In reply to Tom Herbert
Quoted 14 lines · Tom Herbert
Quoted 9 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:

Quoted 6 lines

setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));

Where ulp_param is a structure containing the ULP name as well as some ULP specific parameters that are passed to init_ulp. ulp_init could determine whether the socket family is appropriate for the ULP being requested.

Using SOL_SOCKET instead seems reasonable to me. I can see how ulp_params could have some use, perhaps at a slight loss in clarity. TLS needs its own setsockopts anyway though, for renegotiate for example.

#9 lore raw
Quoted 22 lines · Dave Watson
Quoted 14 lines · Tom Herbert
Quoted 9 lines · Dave Watson

Add the infrustructure for attaching Upper Layer Protocols (ULPs) over TCP sockets. Based on a similar infrastructure in tcp_cong. The idea is that any ULP can add its own logic by changing the TCP proto_ops structure to its own methods.

Example usage:

setsockopt(sock, SOL_TCP, TCP_ULP, "tls", sizeof("tls"));

One question: is there a good reason why the ULP infrastructure should just be for TCP sockets. For example, I'd really like to be able something like:

Quoted 6 lines

setsockopt(sock, SOL_SOCKET, SO_ULP, &ulp_param, sizeof(ulp_param));

Where ulp_param is a structure containing the ULP name as well as some ULP specific parameters that are passed to init_ulp. ulp_init could determine whether the socket family is appropriate for the ULP being requested.

Quoted 4 lines

Using SOL_SOCKET instead seems reasonable to me. I can see how ulp_params could have some use, perhaps at a slight loss in clarity. TLS needs its own setsockopts anyway though, for renegotiate for example.

I'll post the changes shortly. The reason to include parameters with the setsockopt is so that we can push the ULP and start operations in one shot.

Tom