From 51fd67fcbfa598e2fe1885b517451b84c0bfe3b7 Mon Sep 17 00:00:00 2001 From: Rich Felker Date: Tue, 30 Jul 2019 22:11:39 -0400 Subject: get/setsockopt: add fallback for new time64 SO_RCVTIMEO/SO_SNDTIMEO without this, the SO_RCVTIMEO and SO_SNDTIMEO socket options would stop working on pre-5.1 kernels after time_t is switched to 64-bit and their values are changed to the new time64 versions. new code is written such that it's statically unreachable on 64-bit archs, and on existing 32-bit archs until the macro values are changed to activate 64-bit time_t. --- src/network/getsockopt.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'src/network/getsockopt.c') diff --git a/src/network/getsockopt.c b/src/network/getsockopt.c index 28079d8c..e871d624 100644 --- a/src/network/getsockopt.c +++ b/src/network/getsockopt.c @@ -1,7 +1,32 @@ #include +#include +#include #include "syscall.h" int getsockopt(int fd, int level, int optname, void *restrict optval, socklen_t *restrict optlen) { - return socketcall(getsockopt, fd, level, optname, optval, optlen, 0); + long tv32[2]; + struct timeval *tv; + + int r = __socketcall(getsockopt, fd, level, optname, optval, optlen, 0); + + if (r==-ENOPROTOOPT) switch (level) { + case SOL_SOCKET: + switch (optname) { + case SO_RCVTIMEO: + case SO_SNDTIMEO: + if (SO_RCVTIMEO == SO_RCVTIMEO_OLD) break; + if (*optlen < sizeof *tv) return __syscall_ret(-EINVAL); + if (optname==SO_RCVTIMEO) optname=SO_RCVTIMEO_OLD; + if (optname==SO_SNDTIMEO) optname=SO_SNDTIMEO_OLD; + r = __socketcall(getsockopt, fd, level, optname, + tv32, (socklen_t[]){sizeof tv32}, 0); + if (r<0) break; + tv = optval; + tv->tv_sec = tv32[0]; + tv->tv_usec = tv32[1]; + *optlen = sizeof *tv; + } + } + return __syscall_ret(r); } -- cgit v1.2.1