From c0a127d16341ed7fd574d2367761b721a1c91aca Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar <mlichvar@redhat.com> Date: Thu, 15 Jun 2017 16:02:40 +0200 Subject: [PATCH] msghdr: print SCM_TIMESTAMP* control messages 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 | 3 ++ msghdr.c | 26 +++++++++++- print_timespec.c | 36 +++++++++++++++++ print_timeval.c | 12 ++++++ tests/msg_control.c | 97 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 173 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7503a4f4..41ec2e0a 100644 --- 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. diff --git a/msghdr.c b/msghdr.c index 56ba5498..b699f26b 100644 --- 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) }, diff --git a/print_timespec.c b/print_timespec.c index 1e99074b..c8ab5b7b 100644 --- a/print_timespec.c +++ b/print_timespec.c @@ -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) { diff --git a/print_timeval.c b/print_timeval.c index 8d625546..8e0708f4 100644 --- a/print_timeval.c +++ b/print_timeval.c @@ -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) { diff --git a/tests/msg_control.c b/tests/msg_control.c index 1e64f1ab..551a1838 100644 --- a/tests/msg_control.c +++ b/tests/msg_control.c @@ -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_???"); } -- 2.40.0