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>
This commit is contained in:
parent
97d771159b
commit
c0a127d163
3
NEWS
3
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.
|
||||
|
26
msghdr.c
26
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) },
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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_???");
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user