[PATCH] msghdr: print SCM_TIMESTAMP* control messages

Miroslav Lichvar mlichvar at redhat.com
Wed Jun 14 14:23:31 UTC 2017


Add support for printing control messages containing software or
hardware timestamps, which are typically enabled by NTP and PTP
implementations.

* print_timespec.c (print_struct_timespec): New function.
* xlat/scmvals.in: Add SCM_TIMESTAMP* values.
* msghdr.c (print_scm_timestamp, print_scm_timestampns,
  print_scm_timestamping): New functions.
  (cmsg_socket_printers): Add them.
* tests/msg_control.c (test_scm_timestamp, test_scm_timestampns,
  test_scm_timestamping): New functions.
  (test_sol_socket): Use them.

Signed-off-by: Miroslav Lichvar <mlichvar at redhat.com>
---
 msghdr.c            |  38 +++++++++++++++++++-
 print_timespec.c    |   5 +++
 tests/msg_control.c | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 xlat/scmvals.in     |   4 +++
 4 files changed, 146 insertions(+), 1 deletion(-)

diff --git a/msghdr.c b/msghdr.c
index 56ba549..a1902d6 100644
--- a/msghdr.c
+++ b/msghdr.c
@@ -96,6 +96,39 @@ print_scm_security(struct tcb *tcp, const void *cmsg_data,
 }
 
 static void
+print_scm_timestamp(struct tcb *tcp, const void *cmsg_data,
+		    const unsigned int data_len)
+{
+	const struct timeval *tv = cmsg_data;
+
+	print_struct_timeval(tv);
+}
+
+static void
+print_scm_timestampns(struct tcb *tcp, const void *cmsg_data,
+		      const unsigned int data_len)
+{
+	const struct timespec *ts = cmsg_data;
+
+	print_struct_timespec(ts);
+}
+
+static void
+print_scm_timestamping(struct tcb *tcp, const void *cmsg_data,
+		       const unsigned int data_len)
+{
+	const struct timespec *ts = cmsg_data;
+
+	tprints("[");
+	print_struct_timespec(&ts[0]);
+	tprints(", ");
+	print_struct_timespec(&ts[1]);
+	tprints(", ");
+	print_struct_timespec(&ts[2]);
+	tprints("]");
+}
+
+static void
 print_cmsg_ip_pktinfo(struct tcb *tcp, const void *cmsg_data,
 		      const unsigned int data_len)
 {
@@ -191,7 +224,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, sizeof(struct timeval) },
+	[SCM_TIMESTAMPNS] = { print_scm_timestampns, sizeof(struct timespec) },
+	[SCM_TIMESTAMPING] = { print_scm_timestamping, 3 * sizeof(struct timespec) }
 }, 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 1e99074..6d6a415 100644
--- a/print_timespec.c
+++ b/print_timespec.c
@@ -68,6 +68,11 @@ print_timespec_t_utime(const timespec_t *t)
 	}
 }
 
+MPERS_PRINTER_DECL(void, print_struct_timespec, const void *arg)
+{
+	print_timespec_t(arg);
+}
+
 MPERS_PRINTER_DECL(void, print_timespec,
 		   struct tcb *const tcp, const kernel_ulong_t addr)
 {
diff --git a/tests/msg_control.c b/tests/msg_control.c
index 1e64f1a..c9e17fd 100644
--- a/tests/msg_control.c
+++ b/tests/msg_control.c
@@ -50,6 +50,12 @@
 #ifndef SCM_SECURITY
 # define SCM_SECURITY 3
 #endif
+#ifndef SCM_TIMESTAMPNS
+# define SCM_TIMESTAMPNS 35
+#endif
+#ifndef SCM_TIMESTAMPING
+# define SCM_TIMESTAMPING 37
+#endif
 
 #define MIN_SIZE_OF(type, member) \
 	(offsetof(type, member) + sizeof(((type *) 0)->member))
@@ -230,6 +236,96 @@ test_scm_rights3(struct msghdr *const mh, void *const page, const size_t nfds)
 }
 
 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)
 {
 	int n = cmsg_len > CMSG_LEN(0) ? cmsg_len - CMSG_LEN(0) : 0;
@@ -378,6 +474,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_???");
 }
 
diff --git a/xlat/scmvals.in b/xlat/scmvals.in
index 3d61f9e..b83e7c2 100644
--- a/xlat/scmvals.in
+++ b/xlat/scmvals.in
@@ -1,3 +1,7 @@
 SCM_RIGHTS	1
 SCM_CREDENTIALS	2
 SCM_SECURITY	3
+
+SCM_TIMESTAMP	29
+SCM_TIMESTAMPNS	35
+SCM_TIMESTAMPING	37
-- 
2.9.3





More information about the Strace-devel mailing list