[PATCH] Properly handle Linux TCP socket options

John Baldwin jhb at freebsd.org
Sat Jan 19 16:26:17 UTC 2013


The current setsockopt() wrapper for the Linux ABI claims that Linux and 
FreeBSD use the same values for TCP socket options.  This is true for 
TCP_NODELAY and TCP_MAXSEG but not for any other options.  This patch adds a 
mapping routine for TCP options similar to that used for other socket option 
levels.  I believe this mapping to be correct in terms of which FreeBSD 
options have the same semantics as Linux options based on comparing code in 
the two kernels, but I'm not 100% certain about TCP_MD5SIG since the Linux 
code that it maps to is not as clear (it calls some function pointer and it is 
not clear if it is accepting a simple boolean value similar to FreeBSD's).

Also, almost all of the socket stuff in the linux.h headers appears to be 
identical and at least some of it are in MI headers in Linux (such as the TCP 
options).  It seems to me that a lot of that should move into linux_socket.h 
instead.

Index: amd64/linux32/linux.h
===================================================================
--- amd64/linux32/linux.h	(revision 245225)
+++ amd64/linux32/linux.h	(working copy)
@@ -725,6 +725,13 @@
 #define	LINUX_IP_ADD_MEMBERSHIP		35
 #define	LINUX_IP_DROP_MEMBERSHIP	36
 
+#define	LINUX_TCP_NODELAY	1
+#define	LINUX_TCP_MAXSEG	2
+#define	LINUX_TCP_KEEPIDLE	4
+#define	LINUX_TCP_KEEPINTVL	5
+#define	LINUX_TCP_KEEPCNT	6
+#define	LINUX_TCP_MD5SIG	14
+
 struct l_sockaddr {
 	l_ushort	sa_family;
 	char		sa_data[14];
Index: compat/linux/linux_socket.c
===================================================================
--- compat/linux/linux_socket.c	(revision 245225)
+++ compat/linux/linux_socket.c	(working copy)
@@ -56,6 +56,7 @@
 #include <netinet/in.h>
 #include <netinet/in_systm.h>
 #include <netinet/ip.h>
+#include <netinet/tcp.h>
 #ifdef INET6
 #include <netinet/ip6.h>
 #include <netinet6/ip6_var.h>
@@ -326,6 +327,27 @@
 }
 
 static int
+linux_to_bsd_tcp_sockopt(int opt)
+{
+
+	switch (opt) {
+	case LINUX_TCP_NODELAY:
+		return (TCP_NODELAY);
+	case LINUX_TCP_MAXSEG:
+		return (TCP_MAXSEG);
+	case LINUX_TCP_KEEPIDLE:
+		return (TCP_KEEPIDLE);
+	case LINUX_TCP_KEEPINTVL:
+		return (TCP_KEEPINTVL);
+	case LINUX_TCP_KEEPCNT:
+		return (TCP_KEEPCNT);
+	case LINUX_TCP_MD5SIG:
+		return (TCP_MD5SIG);
+	}
+	return (-1);
+}
+
+static int
 linux_to_bsd_msg_flags(int flags)
 {
 	int ret_flags = 0;
@@ -1496,8 +1518,7 @@
 		name = linux_to_bsd_ip_sockopt(args->optname);
 		break;
 	case IPPROTO_TCP:
-		/* Linux TCP option values match BSD's */
-		name = args->optname;
+		name = linux_to_bsd_tcp_sockopt(args->optname);
 		break;
 	default:
 		name = -1;
Index: i386/linux/linux.h
===================================================================
--- i386/linux/linux.h	(revision 245225)
+++ i386/linux/linux.h	(working copy)
@@ -701,6 +701,13 @@
 #define	LINUX_IP_ADD_MEMBERSHIP		35
 #define	LINUX_IP_DROP_MEMBERSHIP	36
 
+#define	LINUX_TCP_NODELAY	1
+#define	LINUX_TCP_MAXSEG	2
+#define	LINUX_TCP_KEEPIDLE	4
+#define	LINUX_TCP_KEEPINTVL	5
+#define	LINUX_TCP_KEEPCNT	6
+#define	LINUX_TCP_MD5SIG	14
+
 struct l_sockaddr {
 	l_ushort	sa_family;
 	char		sa_data[14];


-- 
John Baldwin


More information about the freebsd-net mailing list