[v2,06/25] linux: Add fallback for 64-bit time_t SO_TIMESTAMP{NS}
Checks
Commit Message
The recvmsg handling is more complicated because it requires check the
returned kernel control message and make some convertions. For
!__ASSUME_TIME64_SYSCALLS it converts the first 32-bit time SO_TIMESTAMP
or SO_TIMESTAMPNS and appends it to the control buffer if has extra
space or returns MSG_CTRUNC otherwise. The 32-bit time field is kept
as-is.
Calls with __TIMESIZE=32 will see the converted 64-bit time control
messages as spurious control message of unknown type. Calls with
__TIMESIZE=64 running on pre-time64 kernels will see the original
message as a spurious control ones of unknown typ while running on
kernel with native 64-bit time support will only see the time64 version
of the control message.
Checked on x86_64-linux-gnu and i686-linux-gnu (on 5.4 and on 4.15
kernel).
---
include/sys/socket.h | 5 +
sysdeps/unix/sysv/linux/Makefile | 2 +-
sysdeps/unix/sysv/linux/Versions | 1 +
.../unix/sysv/linux/convert_scm_timestamps.c | 96 +++++++++++++++++++
sysdeps/unix/sysv/linux/getsockopt.c | 12 +++
.../sysv/linux/hppa/socket-constants-time64.h | 5 +
.../sysv/linux/mips/socket-constants-time64.h | 5 +
.../linux/powerpc/socket-constants-time64.h | 5 +
sysdeps/unix/sysv/linux/recvmsg.c | 23 +++--
sysdeps/unix/sysv/linux/setsockopt.c | 12 +++
.../unix/sysv/linux/socket-constants-time64.h | 5 +
.../linux/sparc/socket-constants-time64.h | 5 +
12 files changed, 169 insertions(+), 7 deletions(-)
create mode 100644 sysdeps/unix/sysv/linux/convert_scm_timestamps.c
Comments
On Tue, 18 May 2021 17:55:54 -0300
Adhemerval Zanella <adhemerval.zanella@linaro.org> wrote:
> The recvmsg handling is more complicated because it requires check the
> returned kernel control message and make some convertions. For
> !__ASSUME_TIME64_SYSCALLS it converts the first 32-bit time
> SO_TIMESTAMP or SO_TIMESTAMPNS and appends it to the control buffer
> if has extra space or returns MSG_CTRUNC otherwise. The 32-bit time
> field is kept as-is.
>
> Calls with __TIMESIZE=32 will see the converted 64-bit time control
> messages as spurious control message of unknown type. Calls with
> __TIMESIZE=64 running on pre-time64 kernels will see the original
> message as a spurious control ones of unknown typ while running on
> kernel with native 64-bit time support will only see the time64
> version of the control message.
>
Reviewed-by: Lukasz Majewski <lukma@denx.de>
> Checked on x86_64-linux-gnu and i686-linux-gnu (on 5.4 and on 4.15
> kernel).
> ---
> include/sys/socket.h | 5 +
> sysdeps/unix/sysv/linux/Makefile | 2 +-
> sysdeps/unix/sysv/linux/Versions | 1 +
> .../unix/sysv/linux/convert_scm_timestamps.c | 96
> +++++++++++++++++++ sysdeps/unix/sysv/linux/getsockopt.c |
> 12 +++ .../sysv/linux/hppa/socket-constants-time64.h | 5 +
> .../sysv/linux/mips/socket-constants-time64.h | 5 +
> .../linux/powerpc/socket-constants-time64.h | 5 +
> sysdeps/unix/sysv/linux/recvmsg.c | 23 +++--
> sysdeps/unix/sysv/linux/setsockopt.c | 12 +++
> .../unix/sysv/linux/socket-constants-time64.h | 5 +
> .../linux/sparc/socket-constants-time64.h | 5 +
> 12 files changed, 169 insertions(+), 7 deletions(-)
> create mode 100644 sysdeps/unix/sysv/linux/convert_scm_timestamps.c
>
> diff --git a/include/sys/socket.h b/include/sys/socket.h
> index 0e39dd2a3a..15d4a62b26 100644
> --- a/include/sys/socket.h
> +++ b/include/sys/socket.h
> @@ -164,5 +164,10 @@ libc_hidden_proto (__libc_sa_len)
>
> libc_hidden_proto (__cmsg_nxthdr)
>
> +#ifndef __ASSUME_TIME64_SYSCALLS
> +extern void __convert_scm_timestamps (struct msghdr *msg, socklen_t
> msgsize) ; +libc_hidden_proto (__convert_scm_timestamps)
> +#endif
> +
> #endif
> #endif
> diff --git a/sysdeps/unix/sysv/linux/Makefile
> b/sysdeps/unix/sysv/linux/Makefile index fb155cf856..e28f6470e3 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -64,7 +64,7 @@ sysdep_routines += adjtimex clone umount umount2
> readahead sysctl \ time64-support pselect32 \
> xstat fxstat lxstat xstat64 fxstat64 lxstat64 \
> fxstatat fxstatat64 \
> - xmknod xmknodat
> + xmknod xmknodat convert_scm_timestamps
>
> CFLAGS-gethostid.c = -fexceptions
> CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables
> diff --git a/sysdeps/unix/sysv/linux/Versions
> b/sysdeps/unix/sysv/linux/Versions index 220bb2dffe..148f04c50a 100644
> --- a/sysdeps/unix/sysv/linux/Versions
> +++ b/sysdeps/unix/sysv/linux/Versions
> @@ -177,6 +177,7 @@ libc {
> __pread64_nocancel;
> __close_nocancel;
> __sigtimedwait;
> + __convert_scm_timestamps;
> # functions used by nscd
> __netlink_assert_response;
> }
> diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
> b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c new file mode
> 100644 index 0000000000..3c123c28ce
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
> @@ -0,0 +1,96 @@
> +/* Socket timestamp conversion routines.
> + Copyright (C) 2021 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be
> useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <kernel-features.h>
> +
> +#ifndef __ASSUME_TIME64_SYSCALLS
> +# include <stdint.h>
> +# include <string.h>
> +# include <sys/socket.h>
> +# include <socket-constants-time64.h>
> +
> +/* It converts the first SO_TIMESTAMP or SO_TIMESTAMPNS with 32-bit
> time and
> + appends it to the control buffer. The 32-bit time field is kept
> as-is. +
> + Calls with __TIMESIZE=32 will see the converted 64-bit time
> control
> + messages as spurious control message of unknown type.
> +
> + Calls with __TIMESIZE=64 running on pre-time64 kernels will see
> the
> + original message as a spurious control ones of unknown typ while
> running
> + on kernel with native 64-bit time support will only see the
> time64 version
> + of the control message. */
> +void
> +__convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
> +{
> + if (msg->msg_control == NULL || msg->msg_controllen == 0)
> + return;
> +
> + /* The returned control message format for SO_TIMESTAMP_NEW is a
> + 'struct __kernel_sock_timeval' while for SO_TIMESTAMPNS_NEW is a
> + 'struct __kernel_timespec'. In either case it is two uint64_t
> + members. */
> + uint64_t tvts[2];
> +
> + struct cmsghdr *cmsg, *last = NULL;
> + int type = 0;
> +
> + for (cmsg = CMSG_FIRSTHDR (msg);
> + cmsg != NULL;
> + cmsg = CMSG_NXTHDR (msg, cmsg))
> + {
> + if (cmsg->cmsg_level != SOL_SOCKET)
> + continue;
> +
> + switch (cmsg->cmsg_type)
> + {
> + case COMPAT_SO_TIMESTAMP_OLD:
> + if (type != 0)
> + break;
> + type = COMPAT_SO_TIMESTAMP_NEW;
> + goto common;
> +
> + case COMPAT_SO_TIMESTAMPNS_OLD:
> + type = COMPAT_SO_TIMESTAMPNS_NEW;
> +
> + /* fallthrough */
> + common:
> + memcpy (tvts, CMSG_DATA (cmsg), sizeof (tvts));
> + break;
> + }
> +
> + last = cmsg;
> + }
> +
> + if (last == NULL || type == 0)
> + return;
> +
> + if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen)
> + {
> + msg->msg_flags |= MSG_CTRUNC;
> + return;
> + }
> +
> + msg->msg_controllen += CMSG_SPACE (sizeof tvts);
> + cmsg = CMSG_NXTHDR(msg, last);
> + cmsg->cmsg_level = SOL_SOCKET;
> + cmsg->cmsg_type = type;
> + cmsg->cmsg_len = CMSG_LEN (sizeof tvts);
> + memcpy (CMSG_DATA (cmsg), tvts, sizeof tvts);
> +}
> +libc_hidden_def (__convert_scm_timestamps)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/getsockopt.c
> b/sysdeps/unix/sysv/linux/getsockopt.c index c8e502d976..14b782d0da
> 100644 --- a/sysdeps/unix/sysv/linux/getsockopt.c
> +++ b/sysdeps/unix/sysv/linux/getsockopt.c
> @@ -67,6 +67,18 @@ getsockopt32 (int fd, int level, int optname, void
> *optval, *tv64 = valid_timeval32_to_timeval64 (tv32);
> *len = sizeof (*tv64);
> }
> + break;
> +
> + case COMPAT_SO_TIMESTAMP_NEW:
> + case COMPAT_SO_TIMESTAMPNS_NEW:
> + {
> + if (optname == COMPAT_SO_TIMESTAMP_NEW)
> + optname = COMPAT_SO_TIMESTAMP_OLD;
> + if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
> + optname = COMPAT_SO_TIMESTAMPNS_OLD;
> + r = getsockopt_syscall (fd, level, optname, optval, len);
> + }
> + break;
> }
>
> return r;
> diff --git a/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h
> b/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h index
> ea721e0fc2..f3b98012d5 100644 ---
> a/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h +++
> b/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h @@ -27,4
> +27,9 @@ #define COMPAT_SO_RCVTIMEO_NEW 16448
> #define COMPAT_SO_SNDTIMEO_NEW 16449
>
> +#define COMPAT_SO_TIMESTAMP_OLD 0x4012
> +#define COMPAT_SO_TIMESTAMPNS_OLD 0x4013
> +#define COMPAT_SO_TIMESTAMP_NEW 0x4038
> +#define COMPAT_SO_TIMESTAMPNS_NEW 0x4039
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h
> b/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h index
> ab8bd62853..31fa69fa9f 100644 ---
> a/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h +++
> b/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h @@ -27,4
> +27,9 @@ #define COMPAT_SO_RCVTIMEO_NEW 66
> #define COMPAT_SO_SNDTIMEO_NEW 67
>
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git
> a/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h
> b/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h index
> 1e48dcca8d..889251895b 100644 ---
> a/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h +++
> b/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h @@ -27,4
> +27,9 @@ #define COMPAT_SO_RCVTIMEO_NEW 66 #define
> COMPAT_SO_SNDTIMEO_NEW 67
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/recvmsg.c
> b/sysdeps/unix/sysv/linux/recvmsg.c index b209b4ad99..a2a600228b
> 100644 --- a/sysdeps/unix/sysv/linux/recvmsg.c
> +++ b/sysdeps/unix/sysv/linux/recvmsg.c
> @@ -19,16 +19,27 @@
> #include <sys/socket.h>
> #include <sysdep-cancel.h>
> #include <socketcall.h>
> -#include <shlib-compat.h>
>
> ssize_t
> __libc_recvmsg (int fd, struct msghdr *msg, int flags)
> {
> -# ifdef __ASSUME_RECVMSG_SYSCALL
> - return SYSCALL_CANCEL (recvmsg, fd, msg, flags);
> -# else
> - return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
> -# endif
> + ssize_t r;
> +#ifndef __ASSUME_TIME64_SYSCALLS
> + socklen_t orig_controllen = msg->msg_controllen;
> +#endif
> +
> +#ifdef __ASSUME_RECVMSG_SYSCALL
> + r = SYSCALL_CANCEL (recvmsg, fd, msg, flags);
> +#else
> + r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
> +#endif
> +
> +#ifndef __ASSUME_TIME64_SYSCALLS
> + if (r >= 0)
> + __convert_scm_timestamps (msg, orig_controllen);
> +#endif
> +
> + return r;
> }
> weak_alias (__libc_recvmsg, recvmsg)
> weak_alias (__libc_recvmsg, __recvmsg)
> diff --git a/sysdeps/unix/sysv/linux/setsockopt.c
> b/sysdeps/unix/sysv/linux/setsockopt.c index 6505202265..a4780a9d33
> 100644 --- a/sysdeps/unix/sysv/linux/setsockopt.c
> +++ b/sysdeps/unix/sysv/linux/setsockopt.c
> @@ -69,6 +69,18 @@ setsockopt32 (int fd, int level, int optname,
> const void *optval,
> r = setsockopt_syscall (fd, level, optname, &tv32, sizeof
> (tv32)); }
> + break;
> +
> + case COMPAT_SO_TIMESTAMP_NEW:
> + case COMPAT_SO_TIMESTAMPNS_NEW:
> + {
> + if (optname == COMPAT_SO_TIMESTAMP_NEW)
> + optname = COMPAT_SO_TIMESTAMP_OLD;
> + if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
> + optname = COMPAT_SO_TIMESTAMPNS_OLD;
> + r = setsockopt_syscall (fd, level, optname, NULL, 0);
> + }
> + break;
> }
>
> return r;
> diff --git a/sysdeps/unix/sysv/linux/socket-constants-time64.h
> b/sysdeps/unix/sysv/linux/socket-constants-time64.h index
> e5a3777f28..7f7ca05504 100644 ---
> a/sysdeps/unix/sysv/linux/socket-constants-time64.h +++
> b/sysdeps/unix/sysv/linux/socket-constants-time64.h @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 66
> #define COMPAT_SO_SNDTIMEO_NEW 67
>
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h
> b/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h index
> b137abdeea..56358923e1 100644 ---
> a/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h +++
> b/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h @@ -27,4
> +27,9 @@ #define COMPAT_SO_RCVTIMEO_NEW 68
> #define COMPAT_SO_SNDTIMEO_NEW 69
>
> +#define COMPAT_SO_TIMESTAMP_OLD 0x001d
> +#define COMPAT_SO_TIMESTAMPNS_OLD 0x0021
> +#define COMPAT_SO_TIMESTAMP_NEW 0x0046
> +#define COMPAT_SO_TIMESTAMPNS_NEW 0x0042
> +
> #endif
Best regards,
Lukasz Majewski
--
DENX Software Engineering GmbH, Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-59 Fax: (+49)-8142-66989-80 Email: lukma@denx.de
* Adhemerval Zanella via Libc-alpha:
> Calls with __TIMESIZE=32 will see the converted 64-bit time control
> messages as spurious control message of unknown type. Calls with
> __TIMESIZE=64 running on pre-time64 kernels will see the original
> message as a spurious control ones of unknown typ while running on
> kernel with native 64-bit time support will only see the time64 version
> of the control message.
Does the mirror what the kernel does? I have some concerns about
backwards compatibility here, but if the kernel does it as well, that is
likely a non-issue.
I think this kind of emulation goes against our general guidance of not
emulating system calls in userspace. It would probably be necessary if
we switch an existing 32-bit target to 64-bit time_t by default, though.
Thanks,
Florian
On 20/05/2021 03:50, Florian Weimer wrote:
> * Adhemerval Zanella via Libc-alpha:
>
>> Calls with __TIMESIZE=32 will see the converted 64-bit time control
>> messages as spurious control message of unknown type. Calls with
>> __TIMESIZE=64 running on pre-time64 kernels will see the original
>> message as a spurious control ones of unknown typ while running on
>> kernel with native 64-bit time support will only see the time64 version
>> of the control message.
>
> Does the mirror what the kernel does? I have some concerns about
> backwards compatibility here, but if the kernel does it as well, that is
> likely a non-issue.
The SO_TIMESTAMP{NS}_OLD to SO_TIMESTAMP{NS}_NEW for _TIME_BITS=64 is
what this patch does to add some compatibility. From kernel code:
net/socket.c
772 void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
773 struct sk_buff *skb)
774 {
775 int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
776 int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
[...]
790 if (need_software_tstamp) {
791 if (!sock_flag(sk, SOCK_RCVTSTAMPNS)) {
792 if (new_tstamp) {
793 struct __kernel_sock_timeval tv;
794
795 skb_get_new_timestamp(skb, &tv);
796 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_NEW,
797 sizeof(tv), &tv);
798 } else {
799 struct __kernel_old_timeval tv;
800
801 skb_get_timestamp(skb, &tv);
802 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMP_OLD,
803 sizeof(tv), &tv);
804 }
805 } else {
806 if (new_tstamp) {
807 struct __kernel_timespec ts;
808
809 skb_get_new_timestampns(skb, &ts);
810 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
811 sizeof(ts), &ts);
812 } else {
813 struct __kernel_old_timespec ts;
814
815 skb_get_timestampns(skb, &ts);
816 put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
817 sizeof(ts), &ts);
818 }
819 }
820 }
For _TIME_BITS=32, SO_TIMESTAMP{NS} will be exported as the
SO_TIMESTAMP{NS}_OLD and if the process sets a SO_TIMESTAMPING{NS}_NEW
somehow the control message will be unknown.
For _TIME_BITS=64, SO_TIMESTAMP will be exported as the SO_TIMESTAMP_NEW.
Programs that set SO_TIMESTAMP{NS}_OLD will be converted to
SO_TIMESTAMP{NS}_NEW. This translation is *not* done by the kernel,
but the conversion should be safe as long CMSG_SPACE is large enough (and
the __convert_scm_timestamps does check for it).
>
> I think this kind of emulation goes against our general guidance of not
> emulating system calls in userspace. It would probably be necessary if
> we switch an existing 32-bit target to 64-bit time_t by default, though.
I am not sure this characterize as emulation, but rather fall in what we
do for 64 time support. Otherwise newer code won't see SO_TIMESTAMP{NS}_OLD
values and I think it might be a more difficult breakage than getting
32-bit timestamp values.
* Adhemerval Zanella:
> On 20/05/2021 03:50, Florian Weimer wrote:
>> * Adhemerval Zanella via Libc-alpha:
>>
>>> Calls with __TIMESIZE=32 will see the converted 64-bit time control
>>> messages as spurious control message of unknown type. Calls with
>>> __TIMESIZE=64 running on pre-time64 kernels will see the original
>>> message as a spurious control ones of unknown typ while running on
>>> kernel with native 64-bit time support will only see the time64 version
>>> of the control message.
>>
>> Does the mirror what the kernel does? I have some concerns about
>> backwards compatibility here, but if the kernel does it as well, that is
>> likely a non-issue.
>
> The SO_TIMESTAMP{NS}_OLD to SO_TIMESTAMP{NS}_NEW for _TIME_BITS=64 is
> what this patch does to add some compatibility. From kernel code:
> net/socket.c
Will anything new show up for _TIME_BITS=32 on legacy architectures?
Thanks,
Florian
On 21/05/2021 15:38, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> On 20/05/2021 03:50, Florian Weimer wrote:
>>> * Adhemerval Zanella via Libc-alpha:
>>>
>>>> Calls with __TIMESIZE=32 will see the converted 64-bit time control
>>>> messages as spurious control message of unknown type. Calls with
>>>> __TIMESIZE=64 running on pre-time64 kernels will see the original
>>>> message as a spurious control ones of unknown typ while running on
>>>> kernel with native 64-bit time support will only see the time64 version
>>>> of the control message.
>>>
>>> Does the mirror what the kernel does? I have some concerns about
>>> backwards compatibility here, but if the kernel does it as well, that is
>>> likely a non-issue.
>>
>> The SO_TIMESTAMP{NS}_OLD to SO_TIMESTAMP{NS}_NEW for _TIME_BITS=64 is
>> what this patch does to add some compatibility. From kernel code:
>> net/socket.c
>
> Will anything new show up for _TIME_BITS=32 on legacy architectures?
It will if a library setup a SO_TIMESTAMP{NS}_NEW (assuming running on
newer kernels), since afaik the timestamp is set on socket buffer within
kernel (so my understanding is in theory one can see multiple different
timestamps formats on same socket).
On 5/18/21 4:55 PM, Adhemerval Zanella wrote:
> The recvmsg handling is more complicated because it requires check the
> returned kernel control message and make some convertions. For
> !__ASSUME_TIME64_SYSCALLS it converts the first 32-bit time SO_TIMESTAMP
> or SO_TIMESTAMPNS and appends it to the control buffer if has extra
> space or returns MSG_CTRUNC otherwise. The 32-bit time field is kept
> as-is.
>
> Calls with __TIMESIZE=32 will see the converted 64-bit time control
> messages as spurious control message of unknown type. Calls with
> __TIMESIZE=64 running on pre-time64 kernels will see the original
> message as a spurious control ones of unknown typ while running on
> kernel with native 64-bit time support will only see the time64 version
> of the control message.
>
> Checked on x86_64-linux-gnu and i686-linux-gnu (on 5.4 and on 4.15
> kernel).
LGTM.
No regressions on x86_64, i686, ppc64le, aarch64, s390x.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Tested-by: Carlos O'Donell <carlos@redhat.com>
> ---
> include/sys/socket.h | 5 +
> sysdeps/unix/sysv/linux/Makefile | 2 +-
> sysdeps/unix/sysv/linux/Versions | 1 +
> .../unix/sysv/linux/convert_scm_timestamps.c | 96 +++++++++++++++++++
> sysdeps/unix/sysv/linux/getsockopt.c | 12 +++
> .../sysv/linux/hppa/socket-constants-time64.h | 5 +
> .../sysv/linux/mips/socket-constants-time64.h | 5 +
> .../linux/powerpc/socket-constants-time64.h | 5 +
> sysdeps/unix/sysv/linux/recvmsg.c | 23 +++--
> sysdeps/unix/sysv/linux/setsockopt.c | 12 +++
> .../unix/sysv/linux/socket-constants-time64.h | 5 +
> .../linux/sparc/socket-constants-time64.h | 5 +
> 12 files changed, 169 insertions(+), 7 deletions(-)
> create mode 100644 sysdeps/unix/sysv/linux/convert_scm_timestamps.c
>
> diff --git a/include/sys/socket.h b/include/sys/socket.h
> index 0e39dd2a3a..15d4a62b26 100644
> --- a/include/sys/socket.h
> +++ b/include/sys/socket.h
> @@ -164,5 +164,10 @@ libc_hidden_proto (__libc_sa_len)
>
> libc_hidden_proto (__cmsg_nxthdr)
>
> +#ifndef __ASSUME_TIME64_SYSCALLS
> +extern void __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) ;
> +libc_hidden_proto (__convert_scm_timestamps)
> +#endif
> +
> #endif
> #endif
> diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
> index fb155cf856..e28f6470e3 100644
> --- a/sysdeps/unix/sysv/linux/Makefile
> +++ b/sysdeps/unix/sysv/linux/Makefile
> @@ -64,7 +64,7 @@ sysdep_routines += adjtimex clone umount umount2 readahead sysctl \
> time64-support pselect32 \
> xstat fxstat lxstat xstat64 fxstat64 lxstat64 \
> fxstatat fxstatat64 \
> - xmknod xmknodat
> + xmknod xmknodat convert_scm_timestamps
>
> CFLAGS-gethostid.c = -fexceptions
> CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables
> diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
> index 220bb2dffe..148f04c50a 100644
> --- a/sysdeps/unix/sysv/linux/Versions
> +++ b/sysdeps/unix/sysv/linux/Versions
> @@ -177,6 +177,7 @@ libc {
> __pread64_nocancel;
> __close_nocancel;
> __sigtimedwait;
> + __convert_scm_timestamps;
> # functions used by nscd
> __netlink_assert_response;
> }
> diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
> new file mode 100644
> index 0000000000..3c123c28ce
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
> @@ -0,0 +1,96 @@
> +/* Socket timestamp conversion routines.
> + Copyright (C) 2021 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#include <kernel-features.h>
> +
> +#ifndef __ASSUME_TIME64_SYSCALLS
> +# include <stdint.h>
> +# include <string.h>
> +# include <sys/socket.h>
> +# include <socket-constants-time64.h>
> +
> +/* It converts the first SO_TIMESTAMP or SO_TIMESTAMPNS with 32-bit time and
> + appends it to the control buffer. The 32-bit time field is kept as-is.
> +
> + Calls with __TIMESIZE=32 will see the converted 64-bit time control
> + messages as spurious control message of unknown type.
> +
> + Calls with __TIMESIZE=64 running on pre-time64 kernels will see the
> + original message as a spurious control ones of unknown typ while running
> + on kernel with native 64-bit time support will only see the time64 version
> + of the control message. */
> +void
> +__convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
> +{
> + if (msg->msg_control == NULL || msg->msg_controllen == 0)
> + return;
> +
> + /* The returned control message format for SO_TIMESTAMP_NEW is a
> + 'struct __kernel_sock_timeval' while for SO_TIMESTAMPNS_NEW is a
> + 'struct __kernel_timespec'. In either case it is two uint64_t
> + members. */
> + uint64_t tvts[2];
> +
> + struct cmsghdr *cmsg, *last = NULL;
> + int type = 0;
> +
> + for (cmsg = CMSG_FIRSTHDR (msg);
> + cmsg != NULL;
> + cmsg = CMSG_NXTHDR (msg, cmsg))
> + {
> + if (cmsg->cmsg_level != SOL_SOCKET)
> + continue;
> +
> + switch (cmsg->cmsg_type)
> + {
> + case COMPAT_SO_TIMESTAMP_OLD:
> + if (type != 0)
> + break;
> + type = COMPAT_SO_TIMESTAMP_NEW;
> + goto common;
> +
> + case COMPAT_SO_TIMESTAMPNS_OLD:
> + type = COMPAT_SO_TIMESTAMPNS_NEW;
> +
> + /* fallthrough */
> + common:
> + memcpy (tvts, CMSG_DATA (cmsg), sizeof (tvts));
> + break;
> + }
> +
> + last = cmsg;
> + }
> +
> + if (last == NULL || type == 0)
> + return;
> +
> + if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen)
> + {
> + msg->msg_flags |= MSG_CTRUNC;
> + return;
> + }
> +
> + msg->msg_controllen += CMSG_SPACE (sizeof tvts);
> + cmsg = CMSG_NXTHDR(msg, last);
> + cmsg->cmsg_level = SOL_SOCKET;
> + cmsg->cmsg_type = type;
> + cmsg->cmsg_len = CMSG_LEN (sizeof tvts);
> + memcpy (CMSG_DATA (cmsg), tvts, sizeof tvts);
> +}
> +libc_hidden_def (__convert_scm_timestamps)
> +#endif
> diff --git a/sysdeps/unix/sysv/linux/getsockopt.c b/sysdeps/unix/sysv/linux/getsockopt.c
> index c8e502d976..14b782d0da 100644
> --- a/sysdeps/unix/sysv/linux/getsockopt.c
> +++ b/sysdeps/unix/sysv/linux/getsockopt.c
> @@ -67,6 +67,18 @@ getsockopt32 (int fd, int level, int optname, void *optval,
> *tv64 = valid_timeval32_to_timeval64 (tv32);
> *len = sizeof (*tv64);
> }
> + break;
> +
> + case COMPAT_SO_TIMESTAMP_NEW:
> + case COMPAT_SO_TIMESTAMPNS_NEW:
> + {
> + if (optname == COMPAT_SO_TIMESTAMP_NEW)
> + optname = COMPAT_SO_TIMESTAMP_OLD;
> + if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
> + optname = COMPAT_SO_TIMESTAMPNS_OLD;
> + r = getsockopt_syscall (fd, level, optname, optval, len);
> + }
> + break;
> }
>
> return r;
> diff --git a/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h b/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h
> index ea721e0fc2..f3b98012d5 100644
> --- a/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h
> +++ b/sysdeps/unix/sysv/linux/hppa/socket-constants-time64.h
> @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 16448
> #define COMPAT_SO_SNDTIMEO_NEW 16449
>
> +#define COMPAT_SO_TIMESTAMP_OLD 0x4012
> +#define COMPAT_SO_TIMESTAMPNS_OLD 0x4013
> +#define COMPAT_SO_TIMESTAMP_NEW 0x4038
> +#define COMPAT_SO_TIMESTAMPNS_NEW 0x4039
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h b/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h
> index ab8bd62853..31fa69fa9f 100644
> --- a/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h
> +++ b/sysdeps/unix/sysv/linux/mips/socket-constants-time64.h
> @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 66
> #define COMPAT_SO_SNDTIMEO_NEW 67
>
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h b/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h
> index 1e48dcca8d..889251895b 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h
> +++ b/sysdeps/unix/sysv/linux/powerpc/socket-constants-time64.h
> @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 66
> #define COMPAT_SO_SNDTIMEO_NEW 67
>
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c
> index b209b4ad99..a2a600228b 100644
> --- a/sysdeps/unix/sysv/linux/recvmsg.c
> +++ b/sysdeps/unix/sysv/linux/recvmsg.c
> @@ -19,16 +19,27 @@
> #include <sys/socket.h>
> #include <sysdep-cancel.h>
> #include <socketcall.h>
> -#include <shlib-compat.h>
>
> ssize_t
> __libc_recvmsg (int fd, struct msghdr *msg, int flags)
> {
> -# ifdef __ASSUME_RECVMSG_SYSCALL
> - return SYSCALL_CANCEL (recvmsg, fd, msg, flags);
> -# else
> - return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
> -# endif
> + ssize_t r;
> +#ifndef __ASSUME_TIME64_SYSCALLS
> + socklen_t orig_controllen = msg->msg_controllen;
> +#endif
> +
> +#ifdef __ASSUME_RECVMSG_SYSCALL
> + r = SYSCALL_CANCEL (recvmsg, fd, msg, flags);
> +#else
> + r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
> +#endif
> +
> +#ifndef __ASSUME_TIME64_SYSCALLS
> + if (r >= 0)
> + __convert_scm_timestamps (msg, orig_controllen);
> +#endif
> +
> + return r;
> }
> weak_alias (__libc_recvmsg, recvmsg)
> weak_alias (__libc_recvmsg, __recvmsg)
> diff --git a/sysdeps/unix/sysv/linux/setsockopt.c b/sysdeps/unix/sysv/linux/setsockopt.c
> index 6505202265..a4780a9d33 100644
> --- a/sysdeps/unix/sysv/linux/setsockopt.c
> +++ b/sysdeps/unix/sysv/linux/setsockopt.c
> @@ -69,6 +69,18 @@ setsockopt32 (int fd, int level, int optname, const void *optval,
>
> r = setsockopt_syscall (fd, level, optname, &tv32, sizeof (tv32));
> }
> + break;
> +
> + case COMPAT_SO_TIMESTAMP_NEW:
> + case COMPAT_SO_TIMESTAMPNS_NEW:
> + {
> + if (optname == COMPAT_SO_TIMESTAMP_NEW)
> + optname = COMPAT_SO_TIMESTAMP_OLD;
> + if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
> + optname = COMPAT_SO_TIMESTAMPNS_OLD;
> + r = setsockopt_syscall (fd, level, optname, NULL, 0);
> + }
> + break;
> }
>
> return r;
> diff --git a/sysdeps/unix/sysv/linux/socket-constants-time64.h b/sysdeps/unix/sysv/linux/socket-constants-time64.h
> index e5a3777f28..7f7ca05504 100644
> --- a/sysdeps/unix/sysv/linux/socket-constants-time64.h
> +++ b/sysdeps/unix/sysv/linux/socket-constants-time64.h
> @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 66
> #define COMPAT_SO_SNDTIMEO_NEW 67
>
> +#define COMPAT_SO_TIMESTAMP_OLD 29
> +#define COMPAT_SO_TIMESTAMPNS_OLD 35
> +#define COMPAT_SO_TIMESTAMP_NEW 63
> +#define COMPAT_SO_TIMESTAMPNS_NEW 64
> +
> #endif
> diff --git a/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h b/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h
> index b137abdeea..56358923e1 100644
> --- a/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h
> +++ b/sysdeps/unix/sysv/linux/sparc/socket-constants-time64.h
> @@ -27,4 +27,9 @@
> #define COMPAT_SO_RCVTIMEO_NEW 68
> #define COMPAT_SO_SNDTIMEO_NEW 69
>
> +#define COMPAT_SO_TIMESTAMP_OLD 0x001d
> +#define COMPAT_SO_TIMESTAMPNS_OLD 0x0021
> +#define COMPAT_SO_TIMESTAMP_NEW 0x0046
> +#define COMPAT_SO_TIMESTAMPNS_NEW 0x0042
> +
> #endif
>
@@ -164,5 +164,10 @@ libc_hidden_proto (__libc_sa_len)
libc_hidden_proto (__cmsg_nxthdr)
+#ifndef __ASSUME_TIME64_SYSCALLS
+extern void __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize) ;
+libc_hidden_proto (__convert_scm_timestamps)
+#endif
+
#endif
#endif
@@ -64,7 +64,7 @@ sysdep_routines += adjtimex clone umount umount2 readahead sysctl \
time64-support pselect32 \
xstat fxstat lxstat xstat64 fxstat64 lxstat64 \
fxstatat fxstatat64 \
- xmknod xmknodat
+ xmknod xmknodat convert_scm_timestamps
CFLAGS-gethostid.c = -fexceptions
CFLAGS-tee.c = -fexceptions -fasynchronous-unwind-tables
@@ -177,6 +177,7 @@ libc {
__pread64_nocancel;
__close_nocancel;
__sigtimedwait;
+ __convert_scm_timestamps;
# functions used by nscd
__netlink_assert_response;
}
new file mode 100644
@@ -0,0 +1,96 @@
+/* Socket timestamp conversion routines.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <kernel-features.h>
+
+#ifndef __ASSUME_TIME64_SYSCALLS
+# include <stdint.h>
+# include <string.h>
+# include <sys/socket.h>
+# include <socket-constants-time64.h>
+
+/* It converts the first SO_TIMESTAMP or SO_TIMESTAMPNS with 32-bit time and
+ appends it to the control buffer. The 32-bit time field is kept as-is.
+
+ Calls with __TIMESIZE=32 will see the converted 64-bit time control
+ messages as spurious control message of unknown type.
+
+ Calls with __TIMESIZE=64 running on pre-time64 kernels will see the
+ original message as a spurious control ones of unknown typ while running
+ on kernel with native 64-bit time support will only see the time64 version
+ of the control message. */
+void
+__convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
+{
+ if (msg->msg_control == NULL || msg->msg_controllen == 0)
+ return;
+
+ /* The returned control message format for SO_TIMESTAMP_NEW is a
+ 'struct __kernel_sock_timeval' while for SO_TIMESTAMPNS_NEW is a
+ 'struct __kernel_timespec'. In either case it is two uint64_t
+ members. */
+ uint64_t tvts[2];
+
+ struct cmsghdr *cmsg, *last = NULL;
+ int type = 0;
+
+ for (cmsg = CMSG_FIRSTHDR (msg);
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (msg, cmsg))
+ {
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+ switch (cmsg->cmsg_type)
+ {
+ case COMPAT_SO_TIMESTAMP_OLD:
+ if (type != 0)
+ break;
+ type = COMPAT_SO_TIMESTAMP_NEW;
+ goto common;
+
+ case COMPAT_SO_TIMESTAMPNS_OLD:
+ type = COMPAT_SO_TIMESTAMPNS_NEW;
+
+ /* fallthrough */
+ common:
+ memcpy (tvts, CMSG_DATA (cmsg), sizeof (tvts));
+ break;
+ }
+
+ last = cmsg;
+ }
+
+ if (last == NULL || type == 0)
+ return;
+
+ if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen)
+ {
+ msg->msg_flags |= MSG_CTRUNC;
+ return;
+ }
+
+ msg->msg_controllen += CMSG_SPACE (sizeof tvts);
+ cmsg = CMSG_NXTHDR(msg, last);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = type;
+ cmsg->cmsg_len = CMSG_LEN (sizeof tvts);
+ memcpy (CMSG_DATA (cmsg), tvts, sizeof tvts);
+}
+libc_hidden_def (__convert_scm_timestamps)
+#endif
@@ -67,6 +67,18 @@ getsockopt32 (int fd, int level, int optname, void *optval,
*tv64 = valid_timeval32_to_timeval64 (tv32);
*len = sizeof (*tv64);
}
+ break;
+
+ case COMPAT_SO_TIMESTAMP_NEW:
+ case COMPAT_SO_TIMESTAMPNS_NEW:
+ {
+ if (optname == COMPAT_SO_TIMESTAMP_NEW)
+ optname = COMPAT_SO_TIMESTAMP_OLD;
+ if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
+ optname = COMPAT_SO_TIMESTAMPNS_OLD;
+ r = getsockopt_syscall (fd, level, optname, optval, len);
+ }
+ break;
}
return r;
@@ -27,4 +27,9 @@
#define COMPAT_SO_RCVTIMEO_NEW 16448
#define COMPAT_SO_SNDTIMEO_NEW 16449
+#define COMPAT_SO_TIMESTAMP_OLD 0x4012
+#define COMPAT_SO_TIMESTAMPNS_OLD 0x4013
+#define COMPAT_SO_TIMESTAMP_NEW 0x4038
+#define COMPAT_SO_TIMESTAMPNS_NEW 0x4039
+
#endif
@@ -27,4 +27,9 @@
#define COMPAT_SO_RCVTIMEO_NEW 66
#define COMPAT_SO_SNDTIMEO_NEW 67
+#define COMPAT_SO_TIMESTAMP_OLD 29
+#define COMPAT_SO_TIMESTAMPNS_OLD 35
+#define COMPAT_SO_TIMESTAMP_NEW 63
+#define COMPAT_SO_TIMESTAMPNS_NEW 64
+
#endif
@@ -27,4 +27,9 @@
#define COMPAT_SO_RCVTIMEO_NEW 66
#define COMPAT_SO_SNDTIMEO_NEW 67
+#define COMPAT_SO_TIMESTAMP_OLD 29
+#define COMPAT_SO_TIMESTAMPNS_OLD 35
+#define COMPAT_SO_TIMESTAMP_NEW 63
+#define COMPAT_SO_TIMESTAMPNS_NEW 64
+
#endif
@@ -19,16 +19,27 @@
#include <sys/socket.h>
#include <sysdep-cancel.h>
#include <socketcall.h>
-#include <shlib-compat.h>
ssize_t
__libc_recvmsg (int fd, struct msghdr *msg, int flags)
{
-# ifdef __ASSUME_RECVMSG_SYSCALL
- return SYSCALL_CANCEL (recvmsg, fd, msg, flags);
-# else
- return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
-# endif
+ ssize_t r;
+#ifndef __ASSUME_TIME64_SYSCALLS
+ socklen_t orig_controllen = msg->msg_controllen;
+#endif
+
+#ifdef __ASSUME_RECVMSG_SYSCALL
+ r = SYSCALL_CANCEL (recvmsg, fd, msg, flags);
+#else
+ r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
+#endif
+
+#ifndef __ASSUME_TIME64_SYSCALLS
+ if (r >= 0)
+ __convert_scm_timestamps (msg, orig_controllen);
+#endif
+
+ return r;
}
weak_alias (__libc_recvmsg, recvmsg)
weak_alias (__libc_recvmsg, __recvmsg)
@@ -69,6 +69,18 @@ setsockopt32 (int fd, int level, int optname, const void *optval,
r = setsockopt_syscall (fd, level, optname, &tv32, sizeof (tv32));
}
+ break;
+
+ case COMPAT_SO_TIMESTAMP_NEW:
+ case COMPAT_SO_TIMESTAMPNS_NEW:
+ {
+ if (optname == COMPAT_SO_TIMESTAMP_NEW)
+ optname = COMPAT_SO_TIMESTAMP_OLD;
+ if (optname == COMPAT_SO_TIMESTAMPNS_NEW)
+ optname = COMPAT_SO_TIMESTAMPNS_OLD;
+ r = setsockopt_syscall (fd, level, optname, NULL, 0);
+ }
+ break;
}
return r;
@@ -27,4 +27,9 @@
#define COMPAT_SO_RCVTIMEO_NEW 66
#define COMPAT_SO_SNDTIMEO_NEW 67
+#define COMPAT_SO_TIMESTAMP_OLD 29
+#define COMPAT_SO_TIMESTAMPNS_OLD 35
+#define COMPAT_SO_TIMESTAMP_NEW 63
+#define COMPAT_SO_TIMESTAMPNS_NEW 64
+
#endif
@@ -27,4 +27,9 @@
#define COMPAT_SO_RCVTIMEO_NEW 68
#define COMPAT_SO_SNDTIMEO_NEW 69
+#define COMPAT_SO_TIMESTAMP_OLD 0x001d
+#define COMPAT_SO_TIMESTAMPNS_OLD 0x0021
+#define COMPAT_SO_TIMESTAMP_NEW 0x0046
+#define COMPAT_SO_TIMESTAMPNS_NEW 0x0042
+
#endif