[libc-commits] [libc] [libc] Add remaining SO_ constants (PR #202278)

Pavel Labath via libc-commits libc-commits at lists.llvm.org
Mon Jun 8 00:50:13 PDT 2026


https://github.com/labath created https://github.com/llvm/llvm-project/pull/202278

There are two complications here:
- These options have different values on some architectures. These aren't architectures we're likely to support soon, but I've left a #error so that it lights up in a porting attempt.
- The time-related options have two flavours, depending on the sizeof(time_t). Since we now support only 64-bit time_t, and only kernels up to 5.10, we can unconditionally use the new versions (released in 5.1). I added a test for one of the time options to verify that it works.

>From 483f0490f381b77e47b44ceffcbed9976f463563 Mon Sep 17 00:00:00 2001
From: Pavel Labath <pavel at labath.sk>
Date: Mon, 8 Jun 2026 07:07:08 +0000
Subject: [PATCH] [libc] Add remaining SO_ constants

There are two complications here:
- These options have different values on some architectures. These
  aren't architectures we're likely to support soon, but I've left a
  #error so that it lights up in a porting attempt.
- The time-related options have two flavours, depending on the
  sizeof(time_t). Since we now support only 64-bit time_t, and only
  kernels up to 5.10, we can unconditionally use the new versions
  (released in 5.1). I added a test for one of the time options to
  verify that it works.
---
 .../linux/sys-socket-macros.h                 | 83 +++++++++++++++++++
 libc/test/src/sys/socket/linux/CMakeLists.txt |  6 ++
 .../src/sys/socket/linux/socketopt_test.cpp   | 49 +++++++++++
 3 files changed, 138 insertions(+)

diff --git a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
index 1c6ae9f394f63..1d38d840aa342 100644
--- a/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
+++ b/libc/include/llvm-libc-macros/linux/sys-socket-macros.h
@@ -30,6 +30,12 @@
 
 #define SOL_SOCKET 1
 
+// The values of the following constants differ on some architectures
+#if defined(__parisc__) || defined(__alpha__) || defined(__sparc__) ||         \
+    defined(__powerpc__) || defined(__mips__)
+#error "Please check SO_ constant values"
+#endif
+
 #define SO_DEBUG 1
 #define SO_REUSEADDR 2
 #define SO_TYPE 3
@@ -45,6 +51,83 @@
 #define SO_LINGER 13
 #define SO_BSDCOMPAT 14
 #define SO_REUSEPORT 15
+#define SO_PASSCRED 16
+#define SO_PEERCRED 17
+#define SO_RCVLOWAT 18
+#define SO_SNDLOWAT 19
+
+// The "old" options use a 32-bit time_t on 32-bit systems.
+// #define SO_RCVTIMEO_OLD 20
+// #define SO_SNDTIMEO_OLD 21
+
+#define SO_SECURITY_AUTHENTICATION 22
+#define SO_SECURITY_ENCRYPTION_TRANSPORT 23
+#define SO_SECURITY_ENCRYPTION_NETWORK 24
+#define SO_BINDTODEVICE 25
+#define SO_ATTACH_FILTER 26
+#define SO_DETACH_FILTER 27
+#define SO_GET_FILTER SO_ATTACH_FILTER
+#define SO_PEERNAME 28
+// #define SO_TIMESTAMP_OLD 29
+#define SO_ACCEPTCONN 30
+#define SO_PEERSEC 31
+#define SO_SNDBUFFORCE 32
+#define SO_RCVBUFFORCE 33
+#define SO_PASSSEC 34
+// #define SO_TIMESTAMPNS_OLD 35
+#define SO_MARK 36
+// #define SO_TIMESTAMPING_OLD 37
+#define SO_PROTOCOL 38
+#define SO_DOMAIN 39
+#define SO_RXQ_OVFL 40
+#define SO_WIFI_STATUS 41
+#define SO_PEEK_OFF 42
+#define SO_NOFCS 43
+#define SO_LOCK_FILTER 44
+#define SO_SELECT_ERR_QUEUE 45
+#define SO_BUSY_POLL 46
+#define SO_MAX_PACING_RATE 47
+#define SO_BPF_EXTENSIONS 48
+#define SO_INCOMING_CPU 49
+#define SO_ATTACH_BPF 50
+#define SO_DETACH_BPF SO_DETACH_FILTER
+#define SO_ATTACH_REUSEPORT_CBPF 51
+#define SO_ATTACH_REUSEPORT_EBPF 52
+#define SO_CNX_ADVICE 53
+#define SCM_TIMESTAMPING_OPT_STATS 54
+#define SO_MEMINFO 55
+#define SO_INCOMING_NAPI_ID 56
+#define SO_COOKIE 57
+#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+#define SO_ZEROCOPY 60
+#define SO_TXTIME 61
+#define SO_BINDTOIFINDEX 62
+
+// These are the "new" options, which assume a 64-bit time_t, regardless of the
+// pointer size.
+#define SO_TIMESTAMP 63
+#define SO_TIMESTAMPNS 64
+#define SO_TIMESTAMPING 65
+#define SO_RCVTIMEO 66
+#define SO_SNDTIMEO 67
+
+#define SO_DETACH_REUSEPORT_BPF 68
+#define SO_PREFER_BUSY_POLL 69
+#define SO_BUSY_POLL_BUDGET 70
+#define SO_NETNS_COOKIE 71
+#define SO_BUF_LOCK 72
+#define SO_RESERVE_MEM 73
+#define SO_TXREHASH 74
+#define SO_RCVMARK 75
+#define SO_PASSPIDFD 76
+#define SO_PEERPIDFD 77
+#define SO_DEVMEM_LINEAR 78
+#define SO_DEVMEM_DMABUF 79
+#define SO_DEVMEM_DONTNEED 80
+#define SO_RCVPRIORITY 82
+#define SO_PASSRIGHTS 83
+#define SO_INQ 84
 
 #define SHUT_RD 0
 #define SHUT_WR 1
diff --git a/libc/test/src/sys/socket/linux/CMakeLists.txt b/libc/test/src/sys/socket/linux/CMakeLists.txt
index bcda617c4b28d..5e39b90813cb9 100644
--- a/libc/test/src/sys/socket/linux/CMakeLists.txt
+++ b/libc/test/src/sys/socket/linux/CMakeLists.txt
@@ -116,10 +116,16 @@ add_libc_unittest(
     libc.hdr.sys_socket_macros
     libc.hdr.types.socklen_t
     libc.hdr.types.struct_linger
+    libc.hdr.time_macros
+    libc.hdr.types.struct_timespec
+    libc.hdr.types.struct_timeval
     libc.src.errno.errno
     libc.src.sys.socket.getsockopt
     libc.src.sys.socket.setsockopt
     libc.src.sys.socket.socket
+    libc.src.sys.socket.socketpair
+    libc.src.sys.socket.recv
+    libc.src.time.clock_gettime
     libc.src.unistd.close
     libc.src.unistd.pipe
     libc.src.__support.CPP.scope
diff --git a/libc/test/src/sys/socket/linux/socketopt_test.cpp b/libc/test/src/sys/socket/linux/socketopt_test.cpp
index 5dcccf1095ae5..3af47c3f18a7d 100644
--- a/libc/test/src/sys/socket/linux/socketopt_test.cpp
+++ b/libc/test/src/sys/socket/linux/socketopt_test.cpp
@@ -7,10 +7,16 @@
 //===----------------------------------------------------------------------===//
 
 #include "hdr/sys_socket_macros.h"
+#include "hdr/time_macros.h"
 #include "hdr/types/struct_linger.h"
+#include "hdr/types/struct_timespec.h"
+#include "hdr/types/struct_timeval.h"
 #include "src/sys/socket/getsockopt.h"
+#include "src/sys/socket/recv.h"
 #include "src/sys/socket/setsockopt.h"
 #include "src/sys/socket/socket.h"
+#include "src/sys/socket/socketpair.h"
+#include "src/time/clock_gettime.h"
 
 #include "src/unistd/close.h"
 #include "src/unistd/pipe.h"
@@ -108,3 +114,46 @@ TEST_F(LlvmLibcSocketOptTest, InvalidSocket) {
                                          &optlen),
               Fails(EBADF));
 }
+
+TEST_F(LlvmLibcSocketOptTest, ReceiveTimeout) {
+  int sv[2] = {0, 0};
+  ASSERT_THAT(LIBC_NAMESPACE::socketpair(AF_UNIX, SOCK_STREAM, 0, sv),
+              Succeeds(0));
+  scope_exit close_sv([&] {
+    ASSERT_THAT(LIBC_NAMESPACE::close(sv[0]), Succeeds(0));
+    ASSERT_THAT(LIBC_NAMESPACE::close(sv[1]), Succeeds(0));
+  });
+
+  struct timeval tv;
+  tv.tv_sec = 1;
+  tv.tv_usec = 0;
+  socklen_t optlen = sizeof(tv);
+  ASSERT_THAT(
+      LIBC_NAMESPACE::setsockopt(sv[0], SOL_SOCKET, SO_RCVTIMEO, &tv, optlen),
+      Succeeds(0));
+
+  // Retrieve option to verify it was set correctly.
+  struct timeval retrieved_tv;
+  retrieved_tv.tv_sec = 0;
+  retrieved_tv.tv_usec = 0;
+  socklen_t retrieved_optlen = sizeof(retrieved_tv);
+  ASSERT_THAT(LIBC_NAMESPACE::getsockopt(sv[0], SOL_SOCKET, SO_RCVTIMEO,
+                                         &retrieved_tv, &retrieved_optlen),
+              Succeeds(0));
+  ASSERT_EQ(retrieved_optlen, optlen);
+  ASSERT_EQ(retrieved_tv.tv_sec, tv.tv_sec);
+
+  char buffer[10];
+  struct timespec start, end;
+  ASSERT_EQ(LIBC_NAMESPACE::clock_gettime(CLOCK_MONOTONIC, &start), 0);
+  // Read/recv on empty socket should block for ~1s and fail with EAGAIN.
+  ASSERT_THAT(LIBC_NAMESPACE::recv(sv[0], buffer, sizeof(buffer), 0),
+              Fails<ssize_t>(EAGAIN));
+  ASSERT_EQ(LIBC_NAMESPACE::clock_gettime(CLOCK_MONOTONIC, &end), 0);
+
+  int64_t elapsed_seconds = end.tv_sec - start.tv_sec;
+  int64_t elapsed_nseconds = end.tv_nsec - start.tv_nsec;
+  int64_t elapsed_ms = elapsed_seconds * 1000 + elapsed_nseconds / 1000000;
+  ASSERT_GE(elapsed_ms, static_cast<int64_t>(1000));
+  ASSERT_LT(elapsed_ms, static_cast<int64_t>(10000));
+}



More information about the libc-commits mailing list