git: 71bc8bcf660b - main - linux(4): Handle SO_TIMESTAMPNS socket option
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Sat, 28 May 2022 20:53:25 UTC
The branch main has been updated by dchagin: URL: https://cgit.FreeBSD.org/src/commit/?id=71bc8bcf660b437b99af1e3d382f7bfdaea5fa9c commit 71bc8bcf660b437b99af1e3d382f7bfdaea5fa9c Author: Dmitry Chagin <dchagin@FreeBSD.org> AuthorDate: 2022-05-28 20:46:05 +0000 Commit: Dmitry Chagin <dchagin@FreeBSD.org> CommitDate: 2022-05-28 20:46:05 +0000 linux(4): Handle SO_TIMESTAMPNS socket option The SO_TIMESTAMPNS enables or disables the receiving of the SCM_TIMESTAMPNS control message. The cmsg_data field is a struct timespec. To distinguish between SO_TIMESTAMP and SO_TIMESTAMPNS in the recvmsg() map the last one to the SO_BINTIME and convert bintime to the timespec. In the rest, implementation is identical to the SO_TIMESTAMP. MFC after: 2 weeks --- sys/compat/linux/linux_emul.h | 1 + sys/compat/linux/linux_socket.c | 62 +++++++++++++++++++++++++++++++++++++++++ sys/compat/linux/linux_socket.h | 4 +++ 3 files changed, 67 insertions(+) diff --git a/sys/compat/linux/linux_emul.h b/sys/compat/linux/linux_emul.h index e801bf09ba72..9b552ab9c720 100644 --- a/sys/compat/linux/linux_emul.h +++ b/sys/compat/linux/linux_emul.h @@ -77,6 +77,7 @@ struct linux_pemuldata { uint32_t ptrace_flags; /* used by ptrace(2) */ uint32_t oom_score_adj; /* /proc/self/oom_score_adj */ uint32_t so_timestamp; /* requested timeval */ + uint32_t so_timestampns; /* requested timespec */ }; #define LINUX_PEM_XLOCK(p) sx_xlock(&(p)->pem_sx) diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c index 3360cf48cb16..14f034eb8037 100644 --- a/sys/compat/linux/linux_socket.c +++ b/sys/compat/linux/linux_socket.c @@ -551,6 +551,9 @@ linux_to_bsd_so_sockopt(int opt) case LINUX_SO_TIMESTAMPO: case LINUX_SO_TIMESTAMPN: return (SO_TIMESTAMP); + case LINUX_SO_TIMESTAMPNSO: + case LINUX_SO_TIMESTAMPNSN: + return (SO_BINTIME); case LINUX_SO_ACCEPTCONN: return (SO_ACCEPTCONN); case LINUX_SO_PROTOCOL: @@ -661,6 +664,8 @@ bsd_to_linux_cmsg_type(struct proc *p, int cmsg_type) return (LINUX_SCM_CREDENTIALS); case SCM_TIMESTAMP: return (pem->so_timestamp); + case SCM_BINTIME: + return (pem->so_timestampns); } return (-1); } @@ -1554,6 +1559,7 @@ recvmsg_scm_rights(struct thread *td, l_uint flags, socklen_t *datalen, return (0); } + static int recvmsg_scm_creds(socklen_t *datalen, void **data, void **udata) { @@ -1632,6 +1638,53 @@ _Static_assert(sizeof(struct timeval) == sizeof(l_timeval), "scm_timestamp sizeof l_timeval"); #endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ +#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32)) +static int +recvmsg_scm_timestampns(l_int msg_type, socklen_t *datalen, void **data, + void **udata) +{ + struct l_timespec64 ts64; + struct l_timespec ts32; + struct timespec ts; + socklen_t len; + void *buf; + + if (msg_type == LINUX_SCM_TIMESTAMPNSO) + len = sizeof(ts32); + else + len = sizeof(ts64); + + buf = malloc(len, M_LINUX, M_WAITOK); + bintime2timespec(*data, &ts); + if (msg_type == LINUX_SCM_TIMESTAMPNSO) { + ts32.tv_sec = ts.tv_sec; + ts32.tv_nsec = ts.tv_nsec; + memmove(buf, &ts32, len); + } else { + ts64.tv_sec = ts.tv_sec; + ts64.tv_nsec = ts.tv_nsec; + memmove(buf, &ts64, len); + } + *data = *udata = buf; + *datalen = len; + return (0); +} +#else +static int +recvmsg_scm_timestampns(l_int msg_type, socklen_t *datalen, void **data, + void **udata) +{ + struct timespec ts; + + bintime2timespec(*data, &ts); + memmove(*data, &ts, sizeof(struct timespec)); + *datalen = sizeof(struct timespec); + return (0); +} +_Static_assert(sizeof(struct bintime) >= sizeof(struct timespec), + "scm_timestampns sizeof timespec"); +#endif /* __i386__ || (__amd64__ && COMPAT_LINUX32) */ + static int linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, l_uint flags, struct msghdr *msg) @@ -1755,6 +1808,11 @@ linux_recvmsg_common(struct thread *td, l_int s, struct l_msghdr *msghdr, &datalen, &data, &udata); #endif break; + + case SCM_BINTIME: + error = recvmsg_scm_timestampns(linux_cmsg->cmsg_type, + &datalen, &data, &udata); + break; } if (error != 0) goto bad; @@ -1960,6 +2018,10 @@ linux_setsockopt(struct thread *td, struct linux_setsockopt_args *args) pem = pem_find(p); pem->so_timestamp = args->optname; break; + case SO_BINTIME: + pem = pem_find(p); + pem->so_timestampns = args->optname; + break; default: break; } diff --git a/sys/compat/linux/linux_socket.h b/sys/compat/linux/linux_socket.h index 77537afad6ee..ef0c1f24f10a 100644 --- a/sys/compat/linux/linux_socket.h +++ b/sys/compat/linux/linux_socket.h @@ -189,6 +189,8 @@ int linux_accept(struct thread *td, struct linux_accept_args *args); #endif #define LINUX_SO_TIMESTAMPO 29 #define LINUX_SO_TIMESTAMPN 63 +#define LINUX_SO_TIMESTAMPNSO 35 +#define LINUX_SO_TIMESTAMPNSN 64 #define LINUX_SO_ACCEPTCONN 30 #define LINUX_SO_PEERSEC 31 #define LINUX_SO_SNDBUFFORCE 32 @@ -203,6 +205,8 @@ int linux_accept(struct thread *td, struct linux_accept_args *args); #define LINUX_SCM_CREDENTIALS 0x02 #define LINUX_SCM_TIMESTAMPO LINUX_SO_TIMESTAMPO #define LINUX_SCM_TIMESTAMPN LINUX_SO_TIMESTAMPN +#define LINUX_SCM_TIMESTAMPNSO LINUX_SO_TIMESTAMPNSO +#define LINUX_SCM_TIMESTAMPNSN LINUX_SO_TIMESTAMPNSN /* Socket options */ #define LINUX_IP_TOS 1