[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