The branch main has been updated by dchagin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=71bc8bcf660b437b99af1e3d382f7bfdaea5fa9c

commit 71bc8bcf660b437b99af1e3d382f7bfdaea5fa9c
Author:     Dmitry Chagin <dcha...@freebsd.org>
AuthorDate: 2022-05-28 20:46:05 +0000
Commit:     Dmitry Chagin <dcha...@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

Reply via email to