(root)/
strace-6.5/
tests-m32/
test_nlattr.h
       1  /*
       2   * Copyright (c) 2017-2022 The strace developers.
       3   * All rights reserved.
       4   *
       5   * SPDX-License-Identifier: GPL-2.0-or-later
       6   */
       7  
       8  #include "tests.h"
       9  #include "print_fields.h"
      10  
      11  #include <inttypes.h>
      12  #include <stdio.h>
      13  #include <stdint.h>
      14  #include <string.h>
      15  #include <sys/socket.h>
      16  #include <unistd.h>
      17  #include "netlink.h"
      18  #include <linux/rtnetlink.h>
      19  
      20  #ifndef PRINT_SOCK
      21  # define PRINT_SOCK 0
      22  #endif
      23  
      24  static void
      25  init_nlattr(struct nlattr *const nla,
      26  	    const uint16_t nla_len,
      27  	    const uint16_t nla_type,
      28  	    const void *const src,
      29  	    const size_t n)
      30  {
      31  	SET_STRUCT(struct nlattr, nla,
      32  		.nla_len = nla_len,
      33  		.nla_type = nla_type,
      34  	);
      35  
      36  	memcpy(RTA_DATA(nla), src, n);
      37  }
      38  
      39  static void
      40  print_nlattr(const unsigned int nla_len, const char *const nla_type, bool add_data)
      41  {
      42  	printf(", %s[{nla_len=%u, nla_type=%s}, ",
      43  	       add_data ? "[" : "", nla_len, nla_type);
      44  }
      45  
      46  static void
      47  print_sockfd(int sockfd, const char *pfx, const char *sfx)
      48  {
      49  #if PRINT_SOCK
      50  	static int fd = -1;
      51  	static unsigned long inode;
      52  
      53  	if (sockfd < 0) {
      54  		printf("%s%d%s", pfx, sockfd, sfx);
      55  		return;
      56  	}
      57  
      58  	if (sockfd != fd) {
      59  		fd = sockfd;
      60  		inode = inode_of_sockfd(fd);
      61  	}
      62  
      63  	printf("%s%d<socket:[%lu]>%s", pfx, sockfd, inode, sfx);
      64  #else
      65  	printf("%s%d%s", pfx, sockfd, sfx);
      66  #endif
      67  }
      68  
      69  #define TEST_NLATTR_EX_(fd_, nlh0_, hdrlen_,				\
      70  		     init_msg_, print_msg_,				\
      71  		     nla_type_, nla_type_str_,				\
      72  		     nla_data_len_, nla_total_len_,			\
      73  		     src_, slen_, ...)					\
      74  	do {								\
      75  		struct nlmsghdr *const nlh =				\
      76  			(nlh0_) - (NLA_HDRLEN + (slen_));		\
      77  		struct nlattr *const TEST_NLATTR_nla =			\
      78  			NLMSG_ATTR(nlh, (hdrlen_));			\
      79  		const unsigned int nla_len =				\
      80  			NLA_HDRLEN + (nla_data_len_);			\
      81  		const unsigned int msg_len =				\
      82  			NLMSG_SPACE(hdrlen_) + NLA_HDRLEN + (nla_total_len_); \
      83  									\
      84  		(init_msg_)(nlh, msg_len);				\
      85  		init_nlattr(TEST_NLATTR_nla, nla_len, (nla_type_),	\
      86  			   (src_), (slen_));				\
      87  									\
      88  		const char *const errstr =				\
      89  			sprintrc(sendto((fd_), nlh, msg_len,		\
      90  					MSG_DONTWAIT, NULL, 0));	\
      91  									\
      92  		print_sockfd((fd_), "sendto(", ", [");			\
      93  		(print_msg_)(msg_len);					\
      94  		print_nlattr(nla_len, (nla_type_str_),			\
      95  			     (nla_total_len_) > (nla_data_len_));	\
      96  									\
      97  		{ __VA_ARGS__; }					\
      98  									\
      99  		if ((nla_total_len_) > (nla_data_len_))			\
     100  			printf("]");					\
     101  									\
     102  		printf("]], %u, " XLAT_FMT ", NULL, 0) = %s\n",		\
     103  		       msg_len, XLAT_ARGS(MSG_DONTWAIT), errstr);	\
     104  	} while (0)
     105  
     106  #define TEST_NLATTR_(fd_, nlh0_, hdrlen_,				\
     107  		     init_msg_, print_msg_,				\
     108  		     nla_type_, nla_type_str_,				\
     109  		     nla_data_len_, src_, slen_, ...)			\
     110  	TEST_NLATTR_EX_((fd_), (nlh0_), (hdrlen_),			\
     111  			(init_msg_), (print_msg_),			\
     112  			(nla_type_), (nla_type_str_),			\
     113  			(nla_data_len_), (nla_data_len_),		\
     114  			(src_), (slen_), __VA_ARGS__)
     115  
     116  #define TEST_NLATTR(fd_, nlh0_, hdrlen_,				\
     117  		    init_msg_, print_msg_,				\
     118  		    nla_type_,						\
     119  		    nla_data_len_, src_, slen_, ...)			\
     120  	TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),				\
     121  		(init_msg_), (print_msg_),				\
     122  		(nla_type_), #nla_type_,				\
     123  		(nla_data_len_), (src_), (slen_), __VA_ARGS__)
     124  
     125  #define TEST_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_,			\
     126  			       init_msg_, print_msg_,			\
     127  			       nla_type_, nla_type_str_,		\
     128  			       pattern_, obj_, minsz_, fallback_func, ...) \
     129  	do {								\
     130  		const unsigned int plen = MIN((minsz_) - 1, DEFAULT_STRLEN); \
     131  		/* len < sizeof(obj_) */				\
     132  		if (plen > 0)						\
     133  			TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     134  				(init_msg_), (print_msg_),		\
     135  				(nla_type_), (nla_type_str_),		\
     136  				plen, (pattern_), plen,			\
     137  				(fallback_func)((pattern_), plen));	\
     138  		/* short read of sizeof(obj_) */			\
     139  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     140  			(init_msg_), (print_msg_),			\
     141  			(nla_type_), (nla_type_str_),			\
     142  			sizeof(obj_),					\
     143  			(pattern_), (minsz_) - 1,			\
     144  			printf("%p",					\
     145  			       RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_)))));	\
     146  		/* sizeof(obj_) */					\
     147  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     148  			(init_msg_), (print_msg_),			\
     149  			(nla_type_), (nla_type_str_),			\
     150  			sizeof(obj_),					\
     151  			&(obj_), sizeof(obj_),				\
     152  			__VA_ARGS__);					\
     153  	} while (0)
     154  
     155  #define TEST_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_,			\
     156  			      init_msg_, print_msg_,			\
     157  			      nla_type_,				\
     158  			      pattern_, obj_, minsz_, fallback_func, ...) \
     159  	TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),		\
     160  			       (init_msg_), (print_msg_),		\
     161  			       (nla_type_), #nla_type_,			\
     162  			       (pattern_), (obj_), (minsz_),		\
     163  			       (fallback_func),	__VA_ARGS__)
     164  
     165  #define TEST_NLATTR_OBJECT(fd_, nlh0_, hdrlen_,				\
     166  			   init_msg_, print_msg_,			\
     167  			   nla_type_, pattern_, obj_, ...)		\
     168  	TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),		\
     169  			       (init_msg_), (print_msg_),		\
     170  			       (nla_type_), #nla_type_,			\
     171  			       (pattern_), (obj_), sizeof(obj_),	\
     172  			       print_quoted_hex, __VA_ARGS__)
     173  
     174  #define TEST_NLATTR_OBJECT_(fd_, nlh0_, hdrlen_,			\
     175  			    init_msg_, print_msg_,			\
     176  			    nla_type_, nla_type_str_, pattern_, obj_, ...) \
     177  	TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),		\
     178  			       (init_msg_), (print_msg_),		\
     179  			       (nla_type_), (nla_type_str_),		\
     180  			       (pattern_), (obj_), sizeof(obj_),	\
     181  			       print_quoted_hex, __VA_ARGS__)
     182  
     183  #define TEST_NLATTR_OBJECT_MINSZ(fd_, nlh0_, hdrlen_,			\
     184  			   init_msg_, print_msg_,			\
     185  			   nla_type_, pattern_, obj_, minsz_, ...)	\
     186  	TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),		\
     187  			       (init_msg_), (print_msg_),		\
     188  			       (nla_type_), #nla_type_,			\
     189  			       (pattern_), (obj_), (minsz_),		\
     190  			       print_quoted_hex, __VA_ARGS__)
     191  
     192  #define TEST_NLATTR_ARRAY_(fd_, nlh0_, hdrlen_,				\
     193  			   init_msg_, print_msg_,			\
     194  			   nla_type_, nla_type_str_,			\
     195  			   pattern_, obj_, print_elem_)			\
     196  	do {								\
     197  		const unsigned int plen =				\
     198  			sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN		\
     199  			? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1;	\
     200  		/* len < sizeof((obj_)[0]) */				\
     201  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     202  			(init_msg_), (print_msg_),			\
     203  			(nla_type_), (nla_type_str_),			\
     204  			plen, (pattern_), plen,				\
     205  			print_quoted_hex((pattern_), plen));		\
     206  		/* sizeof((obj_)[0]) < len < sizeof(obj_) */		\
     207  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     208  			(init_msg_), (print_msg_),			\
     209  			(nla_type_), (nla_type_str_),			\
     210  			sizeof(obj_) - 1,				\
     211  			&(obj_), sizeof(obj_) - 1,			\
     212  			printf("[");					\
     213  			for (size_t i = 0;				\
     214  			    i < ARRAY_SIZE(obj_) - 1; ++i) {		\
     215  				if (i) printf(", ");			\
     216  				(print_elem_)(&(obj_)[i], i);		\
     217  			}						\
     218  			printf("]"));					\
     219  		/* short read of sizeof(obj_) */			\
     220  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     221  			(init_msg_), (print_msg_),			\
     222  			(nla_type_), (nla_type_str_),			\
     223  			sizeof(obj_),					\
     224  			&(obj_), sizeof(obj_) - 1,			\
     225  			printf("[");					\
     226  			for (size_t i = 0;				\
     227  			     i < ARRAY_SIZE(obj_) - 1; ++i) {		\
     228  				if (i) printf(", ");			\
     229  				(print_elem_)(&(obj_)[i], i);		\
     230  			}						\
     231  			printf(", ... /* %p */]",			\
     232  			       RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_)))	\
     233  			        + sizeof(obj_) - sizeof((obj_)[0])));	\
     234  		/* sizeof(obj_) */					\
     235  		TEST_NLATTR_((fd_), (nlh0_), (hdrlen_),			\
     236  			(init_msg_), (print_msg_),			\
     237  			(nla_type_), (nla_type_str_),			\
     238  			sizeof(obj_),					\
     239  			&(obj_), sizeof(obj_),				\
     240  			printf("[");					\
     241  			for (size_t i = 0; i < ARRAY_SIZE(obj_); ++i) {	\
     242  				if (i) printf(", ");			\
     243  				(print_elem_)(&(obj_)[i], i);		\
     244  			}						\
     245  			printf("]"));					\
     246  	} while (0)
     247  
     248  #define TEST_NLATTR_ARRAY(fd_, nlh0_, hdrlen_,				\
     249  			  init_msg_, print_msg_,			\
     250  			  nla_type_, pattern_, obj_, print_elem_)	\
     251  	TEST_NLATTR_ARRAY_((fd_), (nlh0_), (hdrlen_),			\
     252  			   (init_msg_), (print_msg_),			\
     253  			   (nla_type_), #nla_type_,			\
     254  			   (pattern_), (obj_), (print_elem_))
     255  
     256  #define TEST_NESTED_NLATTR_(fd_, nlh0_, hdrlen_,			\
     257  			    init_msg_, print_msg_,			\
     258  			    nla_type_, nla_type_str_,			\
     259  			    nla_data_len_, src_, slen_, depth_, ...)	\
     260  	TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * (depth_),		\
     261  		(hdrlen_) + NLA_HDRLEN * (depth_),			\
     262  		(init_msg_), (print_msg_),				\
     263  		(nla_type_), (nla_type_str_),				\
     264  		(nla_data_len_), (src_), (slen_),			\
     265  		__VA_ARGS__;						\
     266  		for (size_t i = 0; i < (depth_); ++i)			\
     267  			printf("]"))
     268  
     269  #define TEST_NESTED_NLATTR_OBJECT_EX_MINSZ_(fd_, nlh0_, hdrlen_,	\
     270  					    init_msg_, print_msg_,	\
     271  					    nla_type_, nla_type_str_,	\
     272  					    pattern_, obj_, minsz_,	\
     273  					    fallback_func, depth_, ...)	\
     274  	do {								\
     275  		const unsigned int plen =				\
     276  			sizeof(obj_) - 1 > DEFAULT_STRLEN		\
     277  			? DEFAULT_STRLEN : (int) sizeof(obj_) - 1;	\
     278  		/* len < sizeof(obj_) */				\
     279  		if (plen > 0)						\
     280  			TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),	\
     281  				(init_msg_), (print_msg_),		\
     282  				(nla_type_), (nla_type_str_),		\
     283  				plen, (pattern_), plen, (depth_),	\
     284  				(fallback_func)((pattern_), plen));	\
     285  		/* short read of sizeof(obj_) */			\
     286  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     287  			(init_msg_), (print_msg_),			\
     288  			(nla_type_), (nla_type_str_),			\
     289  			sizeof(obj_), (pattern_), (minsz_) - 1, (depth_), \
     290  			printf("%p", RTA_DATA(TEST_NLATTR_nla)));	\
     291  		/* sizeof(obj_) */					\
     292  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     293  			(init_msg_), (print_msg_),			\
     294  			(nla_type_), (nla_type_str_),			\
     295  			sizeof(obj_), &(obj_), sizeof(obj_), (depth_),	\
     296  			__VA_ARGS__);					\
     297  	} while (0)
     298  
     299  #define TEST_NESTED_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_,		\
     300  				      init_msg_, print_msg_,		\
     301  				      nla_type_, nla_type_str_,		\
     302  				      pattern_, obj_,			\
     303  				      fallback_func, depth_, ...)	\
     304  	TEST_NESTED_NLATTR_OBJECT_EX_MINSZ_((fd_), (nlh0_), (hdrlen_),	\
     305  					    (init_msg_), (print_msg_),	\
     306  					    (nla_type_), (nla_type_str_), \
     307  					    (pattern_), (obj_), sizeof(obj_), \
     308  					    (fallback_func), (depth_),	\
     309  					    __VA_ARGS__)
     310  
     311  #define TEST_NESTED_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_,		\
     312  				     init_msg_, print_msg_,		\
     313  				     nla_type_, pattern_, obj_,		\
     314  				     depth_, ...)			\
     315  	TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),	\
     316  				      (init_msg_), (print_msg_),	\
     317  				      (nla_type_), #nla_type_,		\
     318  				      (pattern_), (obj_),		\
     319  				      print_quoted_hex, (depth_),	\
     320  				      __VA_ARGS__)
     321  
     322  #define TEST_NESTED_NLATTR_OBJECT(fd_, nlh0_, hdrlen_,			\
     323  				  init_msg_, print_msg_,		\
     324  				  nla_type_, pattern_, obj_, ...)	\
     325  	TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_),	\
     326  				      (init_msg_), (print_msg_),	\
     327  				      (nla_type_), #nla_type_,		\
     328  				      (pattern_), (obj_),		\
     329  				      print_quoted_hex, 1,		\
     330  				      __VA_ARGS__)
     331  
     332  #define TEST_NESTED_NLATTR_ARRAY_EX_(fd_, nlh0_, hdrlen_,		\
     333  				     init_msg_, print_msg_,		\
     334  				     nla_type_, nla_type_str_,		\
     335  				     pattern_, obj_, depth_,		\
     336  				     print_elem_)			\
     337  	do {								\
     338  		const unsigned int plen =				\
     339  			sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN		\
     340  			? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1;	\
     341  		/* len < sizeof((obj_)[0]) */				\
     342  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     343  			(init_msg_), (print_msg_),			\
     344  			(nla_type_), (nla_type_str_),			\
     345  			plen, (pattern_), plen,	(depth_),		\
     346  			print_quoted_hex((pattern_), plen));		\
     347  		/* sizeof((obj_)[0]) < len < sizeof(obj_) */		\
     348  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     349  			(init_msg_), (print_msg_),			\
     350  			(nla_type_), (nla_type_str_),			\
     351  			sizeof(obj_) - 1,				\
     352  			&(obj_), sizeof(obj_) - 1, (depth_),		\
     353  			printf("[");					\
     354  			for (size_t i = 0;				\
     355  			     i < ARRAY_SIZE(obj_) - 1; ++i) {		\
     356  				if (i) printf(", ");			\
     357  				(print_elem_)(&(obj_)[i], i);		\
     358  			}						\
     359  			printf("]"));					\
     360  		/* short read of sizeof(obj_) */			\
     361  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     362  			(init_msg_), (print_msg_),			\
     363  			(nla_type_), (nla_type_str_),			\
     364  			sizeof(obj_),					\
     365  			&(obj_), sizeof(obj_) - 1, (depth_),		\
     366  			printf("[");					\
     367  			for (size_t i = 0;				\
     368  			     i < ARRAY_SIZE(obj_) - 1; ++i) {		\
     369  				if (i) printf(", ");			\
     370  				(print_elem_)(&(obj_)[i], i);		\
     371  			}						\
     372  			printf(", ... /* %p */]",			\
     373  			       RTA_DATA(TEST_NLATTR_nla)		\
     374  			        + sizeof(obj_) - sizeof((obj_)[0])));	\
     375  		/* sizeof(obj_) */					\
     376  		TEST_NESTED_NLATTR_((fd_), (nlh0_), (hdrlen_),		\
     377  			(init_msg_), (print_msg_),			\
     378  			(nla_type_), (nla_type_str_),			\
     379  			sizeof(obj_), &(obj_), sizeof(obj_), (depth_),	\
     380  			printf("[");					\
     381  			for (size_t i = 0; i < ARRAY_SIZE(obj_); ++i) {	\
     382  				if (i) printf(", ");			\
     383  				(print_elem_)(&(obj_)[i], i);		\
     384  			}						\
     385  			printf("]"));					\
     386  	} while (0)
     387  
     388  #define TEST_NESTED_NLATTR_ARRAY_EX(fd_, nlh0_, hdrlen_,		\
     389  				    init_msg_, print_msg_,		\
     390  				    nla_type_, pattern_, obj_, depth_,	\
     391  				    print_elem_)			\
     392  	TEST_NESTED_NLATTR_ARRAY_EX_(fd_, nlh0_, hdrlen_,		\
     393  				     init_msg_, print_msg_,		\
     394  				     nla_type_, #nla_type_, pattern_,	\
     395  				     obj_, depth_, print_elem_)
     396  
     397  #define TEST_NESTED_NLATTR_ARRAY(fd_, nlh0_, hdrlen_,			\
     398  				 init_msg_, print_msg_,			\
     399  				 nla_type_, pattern_, obj_, print_elem_)\
     400  	TEST_NESTED_NLATTR_ARRAY_EX((fd_), (nlh0_), (hdrlen_),		\
     401  				    (init_msg_), (print_msg_),		\
     402  				    nla_type_, (pattern_), (obj_), 1,	\
     403  				    (print_elem_))
     404  
     405  
     406  /* Checks for specific typical decoders */
     407  #define DEF_NLATTR_INTEGER_CHECK_(nla_data_name_, nla_data_type_, fmt_)	\
     408  	static inline void						\
     409  	check_##nla_data_name_##_nlattr(int fd, void *nlh0, size_t hdrlen, \
     410  					void (*init_msg)(struct nlmsghdr *, \
     411  							 unsigned int),	\
     412  					void (*print_msg)(unsigned int), \
     413  					unsigned int nla_type,		\
     414  					const char *nla_type_str,	\
     415  					void *pattern, size_t depth)	\
     416  	{								\
     417  		static const nla_data_type_ vecs[] = {			\
     418  			(nla_data_type_) 0,				\
     419  			(nla_data_type_) 1,				\
     420  			(nla_data_type_) 0xdeadfacebeeffeedULL,		\
     421  		};							\
     422  		static char buf[sizeof(nla_data_type_) + 8];		\
     423  		for (size_t i = 0; i < ARRAY_SIZE(vecs); i++) {		\
     424  			TEST_NESTED_NLATTR_OBJECT_EX_(fd, nlh0, hdrlen,	\
     425  						      init_msg, print_msg, \
     426  						      nla_type, nla_type_str, \
     427  						      pattern, vecs[i],	\
     428  						      print_quoted_hex,	depth, \
     429  						      printf(fmt_, vecs[i])); \
     430  			fill_memory(buf, sizeof(buf));			\
     431  			memcpy(buf, vecs + i, sizeof(vecs[i]));		\
     432  			TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN * depth,	\
     433  				    hdrlen + NLA_HDRLEN * depth,	\
     434  				    init_msg, print_msg,		\
     435  				    nla_type, nla_type_str,		\
     436  				    sizeof(vecs[i]) + 8,		\
     437  				    buf, sizeof(vecs[i]) + 8,		\
     438  				    printf(fmt_, vecs[i]);		\
     439  				    for (size_t i = 0; i < depth; i++)	\
     440  					    printf("]"));		\
     441  		}							\
     442  	}
     443  
     444  DEF_NLATTR_INTEGER_CHECK_(u8, uint8_t, "%hhu")
     445  DEF_NLATTR_INTEGER_CHECK_(u16, uint16_t, "%hu")
     446  DEF_NLATTR_INTEGER_CHECK_(u32, uint32_t, "%u")
     447  DEF_NLATTR_INTEGER_CHECK_(u64, uint64_t, "%" PRIu64)
     448  
     449  DEF_NLATTR_INTEGER_CHECK_(x16, uint16_t, "%#hx")
     450  DEF_NLATTR_INTEGER_CHECK_(x32, uint32_t, "%#x")
     451  
     452  #define TEST_NLATTR_VAL(type_, fd_, nlh0_, hdrlen_,			\
     453  			init_msg_, print_msg_,				\
     454  			nla_type_, pattern_, depth_)			\
     455  	check_##type_##_nlattr((fd_), (nlh0_), (hdrlen_),		\
     456  			       (init_msg_), (print_msg_),		\
     457  			       (nla_type_), #nla_type_, (pattern_), (depth_))
     458  
     459  static inline void
     460  check_clock_t_nlattr(int fd, void *nlh0, size_t hdrlen,
     461  		     void (*init_msg)(struct nlmsghdr *, unsigned int),
     462  		     void (*print_msg)(unsigned int),
     463  		     unsigned int nla_type, const char *nla_type_str,
     464  		     size_t depth)
     465  {
     466  	static const uint64_t vecs[] = { 0, 1, 9, 10, 99, 100, 249, 250, 999,
     467  					 1000, 1023, 1024, 0xdefacebeeffedULL };
     468  	static char buf[sizeof(uint64_t) + 1];
     469  #if !XLAT_RAW
     470  	static long clk_tck;
     471  	static int precision;
     472  
     473  	if (!clk_tck) {
     474  		clk_tck = sysconf(_SC_CLK_TCK);
     475  		precision = clk_tck > 100000000 ? 9
     476  				: clk_tck > 10000000 ? 8
     477  				: clk_tck > 1000000 ? 7
     478  				: clk_tck > 100000 ? 6
     479  				: clk_tck > 10000 ? 5
     480  				: clk_tck > 1000 ? 4
     481  				: clk_tck > 100 ? 3
     482  				: clk_tck > 10 ? 2
     483  				: clk_tck > 1 ? 1 : 0;
     484  	}
     485  #endif
     486  
     487  	fill_memory(buf, sizeof(buf));
     488  	TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN * depth, hdrlen + NLA_HDRLEN * depth,
     489  		     init_msg, print_msg, nla_type, nla_type_str,
     490  		     sizeof(vecs[0]) + 1, buf, sizeof(vecs[0]) + 1,
     491  		     print_quoted_hex(buf, sizeof(vecs[0]) + 1);
     492  		     for (size_t i = 0; i < depth; i++)
     493  			    printf("]"));
     494  
     495  	for (size_t i = 0; i < ARRAY_SIZE(vecs); i++) {
     496  		memcpy(buf, vecs + i, sizeof(vecs[i]));
     497  		TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN * depth,
     498  			     hdrlen + NLA_HDRLEN * depth,
     499  			     init_msg, print_msg, nla_type, nla_type_str,
     500  			     sizeof(vecs[i]),
     501  			     buf, sizeof(vecs[i]),
     502  			     printf("%" PRIu64, vecs[i]);
     503  #if !XLAT_RAW
     504  			     if (i)
     505  				     printf(" /* %.*f s */", precision,
     506  					    (double) vecs[i] / clk_tck);
     507  #endif
     508  			     for (size_t i = 0; i < depth; i++)
     509  				    printf("]"));
     510  	}
     511  	for (size_t i = 1; i < sizeof(vecs[0]); i++) {
     512  		uint64_t val = vecs[ARRAY_SIZE(vecs) - 1] & MASK64(i * 8);
     513  		TEST_NLATTR_(fd, nlh0 - NLA_HDRLEN * depth,
     514  			     hdrlen + NLA_HDRLEN * depth,
     515  			     init_msg, print_msg, nla_type, nla_type_str,
     516  			     i, buf + BE_LE(sizeof(vecs[0]) - i, 0), i,
     517  			     printf("%" PRIu64, val);
     518  #if !XLAT_RAW
     519  			     printf(" /* %.*f s */", precision,
     520  				    (double) val / clk_tck);
     521  #endif
     522  			     for (size_t i = 0; i < depth; i++)
     523  				    printf("]"));
     524  	}
     525  }