]> granicus.if.org Git - strace/commitdiff
msghdr: print SCM_TIMESTAMP* control messages
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 15 Jun 2017 14:02:40 +0000 (16:02 +0200)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 15 Jun 2017 23:52:48 +0000 (23:52 +0000)
Add support for printing control messages containing software and/or
hardware timestamps, which are typically enabled by NTP and PTP
implementations.

* print_timeval.c (print_struct_timeval_data_size): New mpers printer.
* print_timespec.c (print_struct_timespec_data_size,
print_struct_timespec_array_data_size): Likewise.
* msghdr.c (print_scm_timestamp, print_scm_timestampns,
print_scm_timestamping): New functions.
(cmsg_socket_printers): Add them.
* NEWS: Mention this change.
* tests/msg_control.c: Include "xlat.h" and "xlat/scmvals.h".
(test_scm_timestamp, test_scm_timestampns, test_scm_timestamping):
New functions.
(test_sol_socket): Use them.

Signed-off-by: Miroslav Lichvar <mlichvar@redhat.com>
Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
NEWS
msghdr.c
print_timespec.c
print_timeval.c
tests/msg_control.c

diff --git a/NEWS b/NEWS
index 7503a4f4d9cd5ab6f8c9fbd866af749f02e8a149..41ec2e0a2b8574e5fa8f98d73a3f13f3d5aa82e3 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,9 @@
 Noteworthy changes in release ?.?? (????-??-??)
 ===============================================
 
+* Improvements
+  * Implemented decoding of SCM_TIMESTAMP* control messages.
+
 * Bug fixes
   * In interactive mode (-I2), those signals that were blocked at startup
     will remain blocked for the whole period of strace execution.
index 56ba54983077ba9d058f5bc62f73088ac37a2f9a..b699f26b027ae5d09147f0014fe01e7e7e0dd456 100644 (file)
--- a/msghdr.c
+++ b/msghdr.c
@@ -95,6 +95,27 @@ print_scm_security(struct tcb *tcp, const void *cmsg_data,
        print_quoted_string(cmsg_data, data_len, 0);
 }
 
+static void
+print_scm_timestamp(struct tcb *tcp, const void *cmsg_data,
+                   const unsigned int data_len)
+{
+       print_struct_timeval_data_size(cmsg_data, data_len);
+}
+
+static void
+print_scm_timestampns(struct tcb *tcp, const void *cmsg_data,
+                     const unsigned int data_len)
+{
+       print_struct_timespec_data_size(cmsg_data, data_len);
+}
+
+static void
+print_scm_timestamping(struct tcb *tcp, const void *cmsg_data,
+                      const unsigned int data_len)
+{
+       print_struct_timespec_array_data_size(cmsg_data, 3, data_len);
+}
+
 static void
 print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data,
                      const unsigned int data_len)
@@ -191,7 +212,10 @@ static const struct {
 } cmsg_socket_printers[] = {
        [SCM_RIGHTS] = { print_scm_rights, sizeof(int) },
        [SCM_CREDENTIALS] = { print_scm_creds, sizeof(struct ucred) },
-       [SCM_SECURITY] = { print_scm_security, 1 }
+       [SCM_SECURITY] = { print_scm_security, 1 },
+       [SCM_TIMESTAMP] = { print_scm_timestamp, 1 },
+       [SCM_TIMESTAMPNS] = { print_scm_timestampns, 1 },
+       [SCM_TIMESTAMPING] = { print_scm_timestamping, 1 }
 }, cmsg_ip_printers[] = {
        [IP_PKTINFO] = { print_cmsg_ip_pktinfo, sizeof(struct in_pktinfo) },
        [IP_TTL] = { print_cmsg_uint, sizeof(unsigned int) },
index 1e99074b69c235638743ba6200d10b9b0f991f96..c8ab5b7bb68bbaf485e31ea3434edca34bffbcf5 100644 (file)
@@ -68,6 +68,42 @@ print_timespec_t_utime(const timespec_t *t)
        }
 }
 
+MPERS_PRINTER_DECL(bool, print_struct_timespec_data_size,
+                  const void *arg, const size_t size)
+{
+       if (size < sizeof(timespec_t)) {
+               tprints("?");
+               return false;
+       }
+
+       print_timespec_t(arg);
+       return true;
+}
+
+MPERS_PRINTER_DECL(bool, print_struct_timespec_array_data_size,
+                  const void *arg, const unsigned int nmemb,
+                  const size_t size)
+{
+       const timespec_t *ts = arg;
+       unsigned int i;
+
+       if (nmemb > size / sizeof(timespec_t)) {
+               tprints("?");
+               return false;
+       }
+
+       tprints("[");
+
+       for (i = 0; i < nmemb; i++) {
+               if (i)
+                       tprints(", ");
+               print_timespec_t(&ts[i]);
+       }
+
+       tprints("]");
+       return true;
+}
+
 MPERS_PRINTER_DECL(void, print_timespec,
                   struct tcb *const tcp, const kernel_ulong_t addr)
 {
index 8d625546fed1b508a66da964bb3a5bcb2de9ea22..8e0708f4e03e3c826608a1748b21ac846a163ef6 100644 (file)
@@ -55,6 +55,18 @@ MPERS_PRINTER_DECL(void, print_struct_timeval, const void *arg)
        print_timeval_t(arg);
 }
 
+MPERS_PRINTER_DECL(bool, print_struct_timeval_data_size,
+                  const void *arg, const size_t size)
+{
+       if (size < sizeof(timeval_t)) {
+               tprints("?");
+               return false;
+       }
+
+       print_timeval_t(arg);
+       return true;
+}
+
 MPERS_PRINTER_DECL(void, print_timeval,
                   struct tcb *const tcp, const kernel_ulong_t addr)
 {
index 1e64f1abf1b92c3debd74a564c86ece74bcedbe7..551a183881989cb69ab70227d146af0c7fdd685c 100644 (file)
@@ -40,6 +40,9 @@
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+#include "xlat.h"
+#include "xlat/scmvals.h"
+
 #ifndef SOL_IP
 # define SOL_IP 0
 #endif
@@ -229,6 +232,96 @@ test_scm_rights3(struct msghdr *const mh, void *const page, const size_t nfds)
               (unsigned long) len, rc, errno2name());
 }
 
+static void
+test_scm_timestamp(struct msghdr *const mh, void *const page)
+{
+       const size_t len = CMSG_SPACE(sizeof(struct timeval));
+       struct cmsghdr *cmsg = get_cmsghdr(page, len);
+
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct timeval));
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_type = SCM_TIMESTAMP;
+       struct timeval *tv = (struct timeval *) CMSG_DATA(cmsg);
+       tv->tv_sec = 123456789;
+       tv->tv_usec = 987654;
+
+       mh->msg_control = cmsg;
+       mh->msg_controllen = len;
+
+       int rc = sendmsg(-1, mh, 0);
+       printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL"
+              ", msg_iovlen=0, msg_control=[{cmsg_len=%u"
+              ", cmsg_level=SOL_SOCKET, cmsg_type=SCM_TIMESTAMP"
+              ", cmsg_data={tv_sec=%lld, tv_usec=%llu}}]"
+              ", msg_controllen=%lu, msg_flags=0}, 0) = %d %s (%m)\n",
+              (unsigned) cmsg->cmsg_len,
+              (long long) tv->tv_sec, zero_extend_signed_to_ull(tv->tv_usec),
+              (unsigned long) len, rc, errno2name());
+}
+
+static void
+test_scm_timestampns(struct msghdr *const mh, void *const page)
+{
+       const size_t len = CMSG_SPACE(sizeof(struct timespec));
+       struct cmsghdr *cmsg = get_cmsghdr(page, len);
+
+       cmsg->cmsg_len = CMSG_LEN(sizeof(struct timespec));
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_type = SCM_TIMESTAMPNS;
+       struct timespec *ts = (struct timespec *) CMSG_DATA(cmsg);
+       ts->tv_sec = 123456789;
+       ts->tv_nsec = 987654321;
+
+       mh->msg_control = cmsg;
+       mh->msg_controllen = len;
+
+       int rc = sendmsg(-1, mh, 0);
+       printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL"
+              ", msg_iovlen=0, msg_control=[{cmsg_len=%u"
+              ", cmsg_level=SOL_SOCKET, cmsg_type=SCM_TIMESTAMPNS"
+              ", cmsg_data={tv_sec=%lld, tv_nsec=%llu}}]"
+              ", msg_controllen=%lu, msg_flags=0}, 0) = %d %s (%m)\n",
+              (unsigned) cmsg->cmsg_len,
+              (long long) ts->tv_sec, zero_extend_signed_to_ull(ts->tv_nsec),
+              (unsigned long) len, rc, errno2name());
+}
+
+static void
+test_scm_timestamping(struct msghdr *const mh, void *const page)
+{
+       const size_t len = CMSG_SPACE(3 * sizeof(struct timespec));
+       struct cmsghdr *cmsg = get_cmsghdr(page, len);
+
+       cmsg->cmsg_len = CMSG_LEN(3 * sizeof(struct timespec));
+       cmsg->cmsg_level = SOL_SOCKET;
+       cmsg->cmsg_type = SCM_TIMESTAMPING;
+       struct timespec *ts = (struct timespec *) CMSG_DATA(cmsg);
+       ts[0].tv_sec = 123456789;
+       ts[0].tv_nsec = 987654321;
+       ts[1].tv_sec = 123456790;
+       ts[1].tv_nsec = 987654320;
+       ts[2].tv_sec = 123456791;
+       ts[2].tv_nsec = 987654319;
+
+       mh->msg_control = cmsg;
+       mh->msg_controllen = len;
+
+       int rc = sendmsg(-1, mh, 0);
+       printf("sendmsg(-1, {msg_name=NULL, msg_namelen=0, msg_iov=NULL"
+              ", msg_iovlen=0, msg_control=[{cmsg_len=%u"
+              ", cmsg_level=SOL_SOCKET, cmsg_type=SCM_TIMESTAMPING"
+              ", cmsg_data=[{tv_sec=%lld, tv_nsec=%llu}"
+              ", {tv_sec=%lld, tv_nsec=%llu}, {tv_sec=%lld, tv_nsec=%llu}]}]"
+              ", msg_controllen=%lu, msg_flags=0}, 0) = %d %s (%m)\n",
+              (unsigned) cmsg->cmsg_len, (long long) ts[0].tv_sec,
+              zero_extend_signed_to_ull(ts[0].tv_nsec),
+              (long long) ts[1].tv_sec,
+              zero_extend_signed_to_ull(ts[1].tv_nsec),
+              (long long) ts[2].tv_sec,
+              zero_extend_signed_to_ull(ts[2].tv_nsec),
+              (unsigned long) len, rc, errno2name());
+}
+
 static void
 print_security(const struct cmsghdr *const cmsg, const size_t cmsg_len)
 {
@@ -378,6 +471,10 @@ test_sol_socket(struct msghdr *const mh, void *const page)
        test_scm_rights3(mh, page, DEFAULT_STRLEN);
        test_scm_rights3(mh, page, DEFAULT_STRLEN + 1);
 
+       test_scm_timestamp(mh, page);
+       test_scm_timestampns(mh, page);
+       test_scm_timestamping(mh, page);
+
        test_unknown_type(mh, page, ARG_STR(SOL_SOCKET), "SCM_???");
 }