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 <stdint.h> 33 #include <string.h> 34 #include <sys/socket.h> 35 #include "netlink.h" 36 #include <linux/rtnetlink.h> 37 38 static void 39 init_nlattr(struct nlattr *const nla, 40 const uint16_t nla_len, 41 const uint16_t nla_type, 42 const void *const src, 43 const size_t n) 44 { 45 SET_STRUCT(struct nlattr, nla, 46 .nla_len = nla_len, 47 .nla_type = nla_type, 48 ); 49 50 memcpy(RTA_DATA(nla), src, n); 51 } 52 53 static void 54 print_nlattr(const unsigned int nla_len, const char *const nla_type) 55 { 56 printf(", {{nla_len=%u, nla_type=%s}, ", nla_len, nla_type); 57 } 58 59 #define TEST_NLATTR_(fd_, nlh0_, hdrlen_, \ 60 init_msg_, print_msg_, \ 61 nla_type_, nla_type_str_, \ 62 nla_data_len_, src_, slen_, ...) \ 63 do { \ 64 struct nlmsghdr *const nlh = \ 65 (nlh0_) - (NLA_HDRLEN + (slen_)); \ 66 struct nlattr *const TEST_NLATTR_nla = \ 67 NLMSG_ATTR(nlh, (hdrlen_)); \ 68 const unsigned int nla_len = \ 69 NLA_HDRLEN + (nla_data_len_); \ 70 const unsigned int msg_len = \ 71 NLMSG_SPACE(hdrlen_) + nla_len; \ 72 \ 73 (init_msg_)(nlh, msg_len); \ 74 init_nlattr(TEST_NLATTR_nla, nla_len, (nla_type_), \ 75 (src_), (slen_)); \ 76 \ 77 const char *const errstr = \ 78 sprintrc(sendto((fd_), nlh, msg_len, \ 79 MSG_DONTWAIT, NULL, 0)); \ 80 \ 81 printf("sendto(%d, {", (fd_)); \ 82 (print_msg_)(msg_len); \ 83 print_nlattr(nla_len, (nla_type_str_)); \ 84 \ 85 { __VA_ARGS__; } \ 86 \ 87 printf("}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n", \ 88 msg_len, errstr); \ 89 } while (0) 90 91 #define TEST_NLATTR(fd_, nlh0_, hdrlen_, \ 92 init_msg_, print_msg_, \ 93 nla_type_, \ 94 nla_data_len_, src_, slen_, ...) \ 95 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 96 (init_msg_), (print_msg_), \ 97 (nla_type_), #nla_type_, \ 98 (nla_data_len_), (src_), (slen_), __VA_ARGS__) 99 100 #define TEST_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \ 101 init_msg_, print_msg_, \ 102 nla_type_, nla_type_str_, \ 103 pattern_, obj_, fallback_func, ...) \ 104 do { \ 105 const unsigned int plen = \ 106 sizeof(obj_) - 1 > DEFAULT_STRLEN \ 107 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \ 108 /* len < sizeof(obj_) */ \ 109 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 110 (init_msg_), (print_msg_), \ 111 (nla_type_), (nla_type_str_), \ 112 plen, (pattern_), plen, \ 113 (fallback_func)((pattern_), plen)); \ 114 /* short read of sizeof(obj_) */ \ 115 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 116 (init_msg_), (print_msg_), \ 117 (nla_type_), (nla_type_str_), \ 118 sizeof(obj_), \ 119 (pattern_), sizeof(obj_) - 1, \ 120 printf("%p", \ 121 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))))); \ 122 /* sizeof(obj_) */ \ 123 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 124 (init_msg_), (print_msg_), \ 125 (nla_type_), (nla_type_str_), \ 126 sizeof(obj_), \ 127 &(obj_), sizeof(obj_), \ 128 __VA_ARGS__); \ 129 } while (0) 130 131 #define TEST_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \ 132 init_msg_, print_msg_, \ 133 nla_type_, \ 134 pattern_, obj_, fallback_func, ...) \ 135 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \ 136 (init_msg_), (print_msg_), \ 137 (nla_type_), #nla_type_, \ 138 (pattern_), (obj_), (fallback_func), \ 139 __VA_ARGS__) 140 141 #define TEST_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \ 142 init_msg_, print_msg_, \ 143 nla_type_, pattern_, obj_, ...) \ 144 TEST_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \ 145 (init_msg_), (print_msg_), \ 146 (nla_type_), #nla_type_, \ 147 (pattern_), (obj_), print_quoted_hex, \ 148 __VA_ARGS__) 149 150 #define TEST_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \ 151 init_msg_, print_msg_, \ 152 nla_type_, pattern_, obj_, print_elem_) \ 153 do { \ 154 const unsigned int plen = \ 155 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \ 156 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \ 157 /* len < sizeof((obj_)[0]) */ \ 158 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 159 (init_msg_), (print_msg_), \ 160 (nla_type_), #nla_type_, \ 161 plen, (pattern_), plen, \ 162 print_quoted_hex((pattern_), plen)); \ 163 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \ 164 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 165 (init_msg_), (print_msg_), \ 166 (nla_type_), #nla_type_, \ 167 sizeof(obj_) - 1, \ 168 &(obj_), sizeof(obj_) - 1, \ 169 printf("["); \ 170 size_t i; \ 171 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 172 if (i) printf(", "); \ 173 (print_elem_)(&(obj_)[i]); \ 174 } \ 175 printf("]")); \ 176 /* short read of sizeof(obj_) */ \ 177 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 178 (init_msg_), (print_msg_), \ 179 (nla_type_), #nla_type_, \ 180 sizeof(obj_), \ 181 &(obj_), sizeof(obj_) - 1, \ 182 printf("["); \ 183 size_t i; \ 184 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 185 if (i) printf(", "); \ 186 (print_elem_)(&(obj_)[i]); \ 187 } \ 188 printf(", %p]", \ 189 RTA_DATA(NLMSG_ATTR(nlh, (hdrlen_))) \ 190 + sizeof((obj_)[0]))); \ 191 /* sizeof(obj_) */ \ 192 TEST_NLATTR_((fd_), (nlh0_), (hdrlen_), \ 193 (init_msg_), (print_msg_), \ 194 (nla_type_), #nla_type_, \ 195 sizeof(obj_), \ 196 &(obj_), sizeof(obj_), \ 197 printf("["); \ 198 size_t i; \ 199 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \ 200 if (i) printf(", "); \ 201 (print_elem_)(&(obj_)[i]); \ 202 } \ 203 printf("]")); \ 204 } while (0) 205 206 #define TEST_NESTED_NLATTR_OBJECT_EX_(fd_, nlh0_, hdrlen_, \ 207 init_msg_, print_msg_, \ 208 nla_type_, nla_type_str_, \ 209 pattern_, obj_, depth_, ...) \ 210 do { \ 211 const unsigned int plen = \ 212 sizeof(obj_) - 1 > DEFAULT_STRLEN \ 213 ? DEFAULT_STRLEN : (int) sizeof(obj_) - 1; \ 214 /* len < sizeof(obj_) */ \ 215 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \ 216 (hdrlen_) + NLA_HDRLEN * depth_, \ 217 (init_msg_), (print_msg_), \ 218 (nla_type_), (nla_type_str_), \ 219 plen, (pattern_), plen, \ 220 print_quoted_hex((pattern_), plen); \ 221 size_t i; \ 222 for (i = 0; i < depth_; ++i) \ 223 printf("}")); \ 224 /* short read of sizeof(obj_) */ \ 225 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \ 226 (hdrlen_) + NLA_HDRLEN * depth_, \ 227 (init_msg_), (print_msg_), \ 228 (nla_type_), (nla_type_str_), \ 229 sizeof(obj_), \ 230 (pattern_), sizeof(obj_) - 1, \ 231 printf("%p", RTA_DATA(TEST_NLATTR_nla)); \ 232 size_t i; \ 233 for (i = 0; i < depth_; ++i) \ 234 printf("}")); \ 235 /* sizeof(obj_) */ \ 236 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN * depth_, \ 237 (hdrlen_) + NLA_HDRLEN * depth_, \ 238 (init_msg_), (print_msg_), \ 239 (nla_type_), (nla_type_str_), \ 240 sizeof(obj_), \ 241 &(obj_), sizeof(obj_), \ 242 __VA_ARGS__; \ 243 size_t i; \ 244 for (i = 0; i < depth_; ++i) \ 245 printf("}")); \ 246 } while (0) 247 248 #define TEST_NESTED_NLATTR_OBJECT_EX(fd_, nlh0_, hdrlen_, \ 249 init_msg_, print_msg_, \ 250 nla_type_, pattern_, obj_, \ 251 depth_, ...) \ 252 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \ 253 (init_msg_), (print_msg_), \ 254 (nla_type_), #nla_type_, \ 255 (pattern_), (obj_), (depth_), \ 256 __VA_ARGS__) 257 258 #define TEST_NESTED_NLATTR_OBJECT(fd_, nlh0_, hdrlen_, \ 259 init_msg_, print_msg_, \ 260 nla_type_, pattern_, obj_, ...) \ 261 TEST_NESTED_NLATTR_OBJECT_EX_((fd_), (nlh0_), (hdrlen_), \ 262 (init_msg_), (print_msg_), \ 263 (nla_type_), #nla_type_, \ 264 (pattern_), (obj_), 1, \ 265 __VA_ARGS__) 266 267 #define TEST_NESTED_NLATTR_ARRAY(fd_, nlh0_, hdrlen_, \ 268 init_msg_, print_msg_, \ 269 nla_type_, pattern_, obj_, print_elem_)\ 270 do { \ 271 const unsigned int plen = \ 272 sizeof((obj_)[0]) - 1 > DEFAULT_STRLEN \ 273 ? DEFAULT_STRLEN : (int) sizeof((obj_)[0]) - 1; \ 274 /* len < sizeof((obj_)[0]) */ \ 275 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \ 276 (hdrlen_) + NLA_HDRLEN, \ 277 (init_msg_), (print_msg_), \ 278 (nla_type_), #nla_type_, \ 279 plen, (pattern_), plen, \ 280 print_quoted_hex((pattern_), plen); \ 281 printf("}")); \ 282 /* sizeof((obj_)[0]) < len < sizeof(obj_) */ \ 283 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \ 284 (hdrlen_) + NLA_HDRLEN, \ 285 (init_msg_), (print_msg_), \ 286 (nla_type_), #nla_type_, \ 287 sizeof(obj_) - 1, \ 288 &(obj_), sizeof(obj_) - 1, \ 289 printf("["); \ 290 size_t i; \ 291 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 292 if (i) printf(", "); \ 293 (print_elem_)(&(obj_)[i]); \ 294 } \ 295 printf("]}")); \ 296 /* short read of sizeof(obj_) */ \ 297 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \ 298 (hdrlen_) + NLA_HDRLEN, \ 299 (init_msg_), (print_msg_), \ 300 (nla_type_), #nla_type_, \ 301 sizeof(obj_), \ 302 &(obj_), sizeof(obj_) - 1, \ 303 printf("["); \ 304 size_t i; \ 305 for (i = 0; i < ARRAY_SIZE(obj_) - 1; ++i) { \ 306 if (i) printf(", "); \ 307 (print_elem_)(&(obj_)[i]); \ 308 } \ 309 printf(", %p]}", \ 310 RTA_DATA(TEST_NLATTR_nla) \ 311 + sizeof((obj_)[0]))); \ 312 /* sizeof(obj_) */ \ 313 TEST_NLATTR_((fd_), (nlh0_) - NLA_HDRLEN, \ 314 (hdrlen_) + NLA_HDRLEN, \ 315 (init_msg_), (print_msg_), \ 316 (nla_type_), #nla_type_, \ 317 sizeof(obj_), \ 318 &(obj_), sizeof(obj_), \ 319 printf("["); \ 320 size_t i; \ 321 for (i = 0; i < ARRAY_SIZE(obj_); ++i) { \ 322 if (i) printf(", "); \ 323 (print_elem_)(&(obj_)[i]); \ 324 } \ 325 printf("]}")); \ 326 } while (0) 327