1 /* 2 * Copyright (c) 2017 The strace developers. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include "tests.h" 29 #include "print_fields.h" 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <sys/socket.h> 34 #include "netlink.h" 35 #include <linux/rtnetlink.h> 36 37 static void 38 init_nlattr(struct nlattr *const nla, 39 const uint16_t nla_len, 40 const uint16_t nla_type, 41 const void *const src, 42 const size_t n) 43 { 44 SET_STRUCT(struct nlattr, nla, 45 .nla_len = nla_len, 46 .nla_type = nla_type, 47 ); 48 49 memcpy(RTA_DATA(nla), src, n); 50 } 51 52 static void 53 print_nlattr(const unsigned int nla_len, const char *const nla_type) 54 { 55 printf(", {{nla_len=%u, nla_type=%s}, ", nla_len, nla_type); 56 } 57 58 #define TEST_NLATTR_(fd_, nlh0_, hdrlen_, \ 59 init_msg_, print_msg_, \ 60 nla_type_, nla_type_str_, \ 61 nla_data_len_, src_, slen_, ...) \ 62 do { \ 63 struct nlmsghdr *const nlh = \ 64 (nlh0_) - (NLA_HDRLEN + (slen_)); \ 65 struct nlattr *const nla = NLMSG_ATTR(nlh, (hdrlen_)); \ 66 const unsigned int nla_len = \ 67 NLA_HDRLEN + (nla_data_len_); \ 68 const unsigned int msg_len = \ 69 NLMSG_SPACE(hdrlen_) + nla_len; \ 70 \ 71 (init_msg_)(nlh, msg_len); \ 72 init_nlattr(nla, nla_len, (nla_type_), \ 73 (src_), (slen_)); \ 74 \ 75 const char *const errstr = \ 76 sprintrc(sendto((fd_), nlh, msg_len, \ 77 MSG_DONTWAIT, NULL, 0)); \ 78 \ 79 printf("sendto(%d, {", (fd_)); \ 80 (print_msg_)(msg_len); \ 81 print_nlattr(nla_len, (nla_type_str_)); \ 82 \ 83 { __VA_ARGS__; } \ 84 \ 85 printf("}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n", \ 86 msg_len, errstr); \ 87 } while (0) 88 89 #define TEST_NLATTR(fd_, nlh0_, hdrlen_, \ 90 init_msg_, print_msg_, \ 91 nla_type_, \ 92 nla_data_len_, src_, slen_, ...) \ 93 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 94 (init_msg_), (print_msg_), \ 95 (nla_type_), #nla_type_, \ 96 (nla_data_len_), (src_), (slen_), __VA_ARGS__) 97 98 #define TEST_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \ 99 init_msg_, print_msg_, \ 100 nla_type_, pattern_, obj_, ...) \ 101 do { \ 102 const int plen = sizeof(obj_) - 1 > DEFAULT_STRLEN \ 103 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \ 104 /* len < sizeof(obj_) */ \ 105 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 106 (init_msg_), (print_msg_), \ 107 (nla_type_), #nla_type_, \ 108 sizeof(obj_) - 1, \ 109 (pattern_), sizeof(obj_) - 1, \ 110 printf("\"%.*s\"", plen, (pattern_))); \ 111 /* short read of sizeof(obj_) */ \ 112 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 113 (init_msg_), (print_msg_), \ 114 (nla_type_), #nla_type_, \ 115 sizeof(obj_), \ 116 (pattern_), sizeof(obj_) - 1, \ 117 printf("%p", \ 118 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))))); \ 119 /* sizeof(obj_) */ \ 120 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 121 (init_msg_), (print_msg_), \ 122 (nla_type_), #nla_type_, \ 123 sizeof(obj_), \ 124 &(obj_), sizeof(obj_), \ 125 __VA_ARGS__); \ 126 } while (0) 127 128 #define TEST_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \ 129 init_msg_, print_msg_, \ 130 nla_type_, pattern_, obj_, print_elem_) \ 131 do { \ 132 const int plen = \ 133 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \ 134 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \ 135 /* len < sizeof((obj_)[0]) */ \ 136 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 137 (init_msg_), (print_msg_), \ 138 (nla_type_), #nla_type_, \ 139 sizeof((obj_)[0]) - 1, \ 140 (pattern_), sizeof((obj_)[0]) - 1, \ 141 printf("\"%.*s\"", plen, (pattern_))); \ 142 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \ 143 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 144 (init_msg_), (print_msg_), \ 145 (nla_type_), #nla_type_, \ 146 sizeof(obj_) - 1, \ 147 &(obj_), sizeof(obj_) - 1, \ 148 printf("["); \ 149 size_t i; \ 150 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 151 if (i) printf(", "); \ 152 (print_elem_)(&(obj_)[i]); \ 153 } \ 154 printf("]")); \ 155 /* short read of sizeof(obj_) */ \ 156 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 157 (init_msg_), (print_msg_), \ 158 (nla_type_), #nla_type_, \ 159 sizeof(obj_), \ 160 &(obj_), sizeof(obj_) - 1, \ 161 printf("["); \ 162 size_t i; \ 163 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 164 if (i) printf(", "); \ 165 (print_elem_)(&(obj_)[i]); \ 166 } \ 167 printf(", %p]", \ 168 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))) \ 169 + sizeof((obj_)[0]))); \ 170 /* sizeof(obj_) */ \ 171 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 172 (init_msg_), (print_msg_), \ 173 (nla_type_), #nla_type_, \ 174 sizeof(obj_), \ 175 &(obj_), sizeof(obj_), \ 176 printf("["); \ 177 size_t i; \ 178 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \ 179 if (i) printf(", "); \ 180 (print_elem_)(&(obj_)[i]); \ 181 } \ 182 printf("]")); \ 183 } while (0) 184