1 /* 2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com> 3 * Copyright (c) 2017-2018 The strace developers. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include "tests.h" 30 31 #include <stdio.h> 32 #include <string.h> 33 #include <sys/socket.h> 34 #include <arpa/inet.h> 35 #include <net/if.h> 36 #include <netinet/tcp.h> 37 #include "test_nlattr.h" 38 #include <linux/inet_diag.h> 39 #include <linux/rtnetlink.h> 40 #include <linux/sock_diag.h> 41 42 static const char address[] = "10.11.12.13"; 43 static const unsigned int hdrlen = sizeof(struct inet_diag_req_v2); 44 static void *nlh0; 45 static char pattern[4096]; 46 47 static void 48 init_inet_diag_req_v2(struct nlmsghdr *const nlh, const unsigned int msg_len) 49 { 50 SET_STRUCT(struct nlmsghdr, nlh, 51 .nlmsg_len = msg_len, 52 .nlmsg_type = SOCK_DIAG_BY_FAMILY, 53 .nlmsg_flags = NLM_F_REQUEST 54 ); 55 56 struct inet_diag_req_v2 *const req = NLMSG_DATA(nlh); 57 SET_STRUCT(struct inet_diag_req_v2, req, 58 .sdiag_family = AF_INET, 59 .idiag_ext = 1 << (INET_DIAG_CONG - 1), 60 .sdiag_protocol = IPPROTO_TCP, 61 .idiag_states = 1 << TCP_CLOSE, 62 .id.idiag_if = ifindex_lo() 63 ); 64 65 if (!inet_pton(AF_INET, address, req->id.idiag_src) || 66 !inet_pton(AF_INET, address, req->id.idiag_dst)) 67 perror_msg_and_skip("inet_pton"); 68 } 69 70 static void 71 print_inet_diag_req_v2(const unsigned int msg_len) 72 { 73 printf("{len=%u, type=SOCK_DIAG_BY_FAMILY" 74 ", flags=NLM_F_REQUEST, seq=0, pid=0}" 75 ", {sdiag_family=AF_INET, sdiag_protocol=IPPROTO_TCP" 76 ", idiag_ext=1<<(INET_DIAG_CONG-1)" 77 ", idiag_states=1<<TCP_CLOSE" 78 ", id={idiag_sport=htons(0), idiag_dport=htons(0)" 79 ", idiag_src=inet_addr(\"%s\")" 80 ", idiag_dst=inet_addr(\"%s\")" 81 ", idiag_if=" IFINDEX_LO_STR 82 ", idiag_cookie=[0, 0]}}", 83 msg_len, address, address); 84 } 85 86 static void 87 test_inet_diag_bc_op(const int fd) 88 { 89 static const struct inet_diag_bc_op op = { 90 .code = INET_DIAG_BC_S_COND, 91 .yes = 0xaf, 92 .no = 0xafcd 93 }; 94 TEST_NLATTR_OBJECT(fd, nlh0, hdrlen, 95 init_inet_diag_req_v2, print_inet_diag_req_v2, 96 INET_DIAG_REQ_BYTECODE, pattern, op, 97 printf("{code=INET_DIAG_BC_S_COND"); 98 PRINT_FIELD_U(", ", op, yes); 99 PRINT_FIELD_U(", ", op, no); 100 printf("}")); 101 } 102 103 static void 104 print_inet_diag_bc_op(const char *const code) 105 { 106 printf("{{code=%s, yes=0, no=0}, ", code); 107 } 108 109 static void 110 test_inet_diag_bc_s_cond(const int fd) 111 { 112 static const struct inet_diag_bc_op op = { 113 .code = INET_DIAG_BC_S_COND, 114 }; 115 static const struct inet_diag_hostcond cond = { 116 .family = AF_UNSPEC, 117 .prefix_len = 0xad, 118 .port = 0xadfa 119 }; 120 char buf[sizeof(op) + sizeof(cond)]; 121 memcpy(buf, &op, sizeof(op)); 122 123 const unsigned int plen = sizeof(cond) - 1 > DEFAULT_STRLEN ? 124 sizeof(op) + DEFAULT_STRLEN : sizeof(buf) - 1; 125 memcpy(buf + sizeof(op), &pattern, sizeof(cond)); 126 TEST_NLATTR(fd, nlh0, hdrlen, 127 init_inet_diag_req_v2, print_inet_diag_req_v2, 128 INET_DIAG_REQ_BYTECODE, 129 plen, buf, plen, 130 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 131 print_quoted_hex(buf + sizeof(op), plen - sizeof(op)); 132 printf("}")); 133 134 TEST_NLATTR(fd, nlh0, hdrlen, 135 init_inet_diag_req_v2, print_inet_diag_req_v2, 136 INET_DIAG_REQ_BYTECODE, 137 sizeof(buf), buf, sizeof(buf) - 1, 138 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 139 printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op))); 140 141 memcpy(buf + sizeof(op), &cond, sizeof(cond)); 142 TEST_NLATTR(fd, nlh0, hdrlen, 143 init_inet_diag_req_v2, print_inet_diag_req_v2, 144 INET_DIAG_REQ_BYTECODE, 145 sizeof(buf), buf, sizeof(buf), 146 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 147 printf("{family=AF_UNSPEC"); 148 PRINT_FIELD_U(", ", cond, prefix_len); 149 PRINT_FIELD_U(", ", cond, port); 150 printf("}}")); 151 } 152 153 static void 154 print_inet_diag_hostcond(const char *const family) 155 { 156 printf("{family=%s, prefix_len=0, port=0, ", family); 157 } 158 159 static void 160 test_in_addr(const int fd) 161 { 162 static const struct inet_diag_bc_op op = { 163 .code = INET_DIAG_BC_S_COND, 164 }; 165 static const struct inet_diag_hostcond cond = { 166 .family = AF_INET, 167 }; 168 struct in_addr addr; 169 if (!inet_pton(AF_INET, address, &addr)) 170 perror_msg_and_skip("inet_pton"); 171 172 char buf[sizeof(op) + sizeof(cond) + sizeof(addr)]; 173 memcpy(buf, &op, sizeof(op)); 174 memcpy(buf + sizeof(op), &cond, sizeof(cond)); 175 176 const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ? 177 sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1; 178 memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr)); 179 TEST_NLATTR(fd, nlh0, hdrlen, 180 init_inet_diag_req_v2, print_inet_diag_req_v2, 181 INET_DIAG_REQ_BYTECODE, 182 plen, buf, plen, 183 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 184 print_inet_diag_hostcond("AF_INET"); 185 printf("addr="); 186 print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond)); 187 printf("}}")); 188 189 TEST_NLATTR(fd, nlh0, hdrlen, 190 init_inet_diag_req_v2, print_inet_diag_req_v2, 191 INET_DIAG_REQ_BYTECODE, 192 sizeof(buf), buf, sizeof(buf) - 1, 193 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 194 print_inet_diag_hostcond("AF_INET"); 195 printf("addr=%p}}", 196 RTA_DATA(TEST_NLATTR_nla) 197 + sizeof(op) + sizeof(cond))); 198 199 memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr)); 200 TEST_NLATTR(fd, nlh0, hdrlen, 201 init_inet_diag_req_v2, print_inet_diag_req_v2, 202 INET_DIAG_REQ_BYTECODE, 203 sizeof(buf), buf, sizeof(buf), 204 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 205 print_inet_diag_hostcond("AF_INET"); 206 printf("addr=inet_addr(\"%s\")}}", address)); 207 } 208 209 static void 210 test_in6_addr(const int fd) 211 { 212 const char address6[] = "12:34:56:78:90:ab:cd:ef"; 213 static const struct inet_diag_bc_op op = { 214 .code = INET_DIAG_BC_S_COND, 215 }; 216 static const struct inet_diag_hostcond cond = { 217 .family = AF_INET6, 218 }; 219 struct in6_addr addr; 220 if (!inet_pton(AF_INET6, address6, &addr)) 221 perror_msg_and_skip("inet_pton"); 222 223 char buf[sizeof(op) + sizeof(cond) + sizeof(addr)]; 224 memcpy(buf, &op, sizeof(op)); 225 memcpy(buf + sizeof(op), &cond, sizeof(cond)); 226 227 const unsigned int plen = sizeof(addr) - 1 > DEFAULT_STRLEN ? 228 sizeof(cond) + sizeof(cond) + DEFAULT_STRLEN : sizeof(buf) - 1; 229 memcpy(buf + sizeof(op) + sizeof(cond), &pattern, sizeof(addr)); 230 TEST_NLATTR(fd, nlh0, hdrlen, 231 init_inet_diag_req_v2, print_inet_diag_req_v2, 232 INET_DIAG_REQ_BYTECODE, 233 plen, buf, plen, 234 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 235 print_inet_diag_hostcond("AF_INET6"); 236 printf("addr="); 237 print_quoted_hex(pattern, plen - sizeof(op) - sizeof(cond)); 238 printf("}}")); 239 240 TEST_NLATTR(fd, nlh0, hdrlen, 241 init_inet_diag_req_v2, print_inet_diag_req_v2, 242 INET_DIAG_REQ_BYTECODE, 243 sizeof(buf), buf, sizeof(buf) - 1, 244 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 245 print_inet_diag_hostcond("AF_INET6"); 246 printf("addr=%p}}", 247 RTA_DATA(TEST_NLATTR_nla) 248 + sizeof(op) + sizeof(cond))); 249 250 memcpy(buf + sizeof(op) + sizeof(cond), &addr, sizeof(addr)); 251 TEST_NLATTR(fd, nlh0, hdrlen, 252 init_inet_diag_req_v2, print_inet_diag_req_v2, 253 INET_DIAG_REQ_BYTECODE, 254 sizeof(buf), buf, sizeof(buf), 255 print_inet_diag_bc_op("INET_DIAG_BC_S_COND"); 256 print_inet_diag_hostcond("AF_INET6"); 257 printf("inet_pton(AF_INET6, \"%s\", &addr)}}", address6)); 258 } 259 260 static void 261 test_inet_diag_bc_dev_cond(const int fd) 262 { 263 static const struct inet_diag_bc_op op = { 264 .code = INET_DIAG_BC_DEV_COND, 265 }; 266 const uint32_t ifindex = ifindex_lo(); 267 char buf[sizeof(op) + sizeof(ifindex)]; 268 memcpy(buf, &op, sizeof(op)); 269 memcpy(buf + sizeof(op), pattern, sizeof(ifindex)); 270 271 TEST_NLATTR(fd, nlh0, hdrlen, 272 init_inet_diag_req_v2, print_inet_diag_req_v2, 273 INET_DIAG_REQ_BYTECODE, 274 sizeof(buf) - 1, buf, sizeof(buf) - 1, 275 print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND"); 276 print_quoted_hex(pattern, sizeof(ifindex) - 1); 277 printf("}")); 278 279 TEST_NLATTR(fd, nlh0, hdrlen, 280 init_inet_diag_req_v2, print_inet_diag_req_v2, 281 INET_DIAG_REQ_BYTECODE, 282 sizeof(buf), buf, sizeof(buf) - 1, 283 print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND"); 284 printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op))); 285 286 memcpy(buf + sizeof(op), &ifindex, sizeof(ifindex)); 287 TEST_NLATTR(fd, nlh0, hdrlen, 288 init_inet_diag_req_v2, print_inet_diag_req_v2, 289 INET_DIAG_REQ_BYTECODE, 290 sizeof(buf), buf, sizeof(buf), 291 print_inet_diag_bc_op("INET_DIAG_BC_DEV_COND"); 292 printf(IFINDEX_LO_STR "}")); 293 } 294 295 static void 296 test_inet_diag_bc_s_le(const int fd) 297 { 298 static const struct inet_diag_bc_op op[] = { 299 { 300 .code = INET_DIAG_BC_S_LE, 301 }, 302 { 303 .code = INET_DIAG_BC_DEV_COND, 304 .yes = 0xaf, 305 .no = 0xafcd 306 } 307 }; 308 309 char buf[sizeof(op)]; 310 memcpy(buf, op, sizeof(op[0])); 311 memcpy(buf + sizeof(op[0]), pattern, sizeof(op[1])); 312 313 const unsigned int plen = sizeof(op[1]) - 1 > DEFAULT_STRLEN ? 314 sizeof(op[0]) + DEFAULT_STRLEN : sizeof(buf) - 1; 315 TEST_NLATTR(fd, nlh0, hdrlen, 316 init_inet_diag_req_v2, print_inet_diag_req_v2, 317 INET_DIAG_REQ_BYTECODE, 318 plen, buf, plen, 319 print_inet_diag_bc_op("INET_DIAG_BC_S_LE"); 320 print_quoted_hex(buf + sizeof(op[0]), plen - sizeof(op[0])); 321 printf("}")); 322 323 TEST_NLATTR(fd, nlh0, hdrlen, 324 init_inet_diag_req_v2, print_inet_diag_req_v2, 325 INET_DIAG_REQ_BYTECODE, 326 sizeof(buf), buf, sizeof(buf) - 1, 327 print_inet_diag_bc_op("INET_DIAG_BC_S_LE"); 328 printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op[0]))); 329 330 memcpy(buf + sizeof(op[0]), &op[1], sizeof(op[1])); 331 TEST_NLATTR(fd, nlh0, hdrlen, 332 init_inet_diag_req_v2, print_inet_diag_req_v2, 333 INET_DIAG_REQ_BYTECODE, 334 sizeof(buf), buf, sizeof(buf), 335 print_inet_diag_bc_op("INET_DIAG_BC_S_LE"); 336 printf("{code=INET_DIAG_BC_DEV_COND"); 337 PRINT_FIELD_U(", ", op[1], yes); 338 PRINT_FIELD_U(", ", op[1], no); 339 printf("}}")); 340 }; 341 342 static void 343 test_inet_diag_bc_mark_cond(const int fd) 344 { 345 static const struct inet_diag_bc_op op = { 346 .code = INET_DIAG_BC_MARK_COND, 347 }; 348 static const struct inet_diag_markcond markcond = { 349 .mark = 0xafbcafcd, 350 .mask = 0xbafaacda 351 }; 352 char buf[sizeof(op) + sizeof(markcond)]; 353 memcpy(buf, &op, sizeof(op)); 354 memcpy(buf + sizeof(op), pattern, sizeof(markcond)); 355 356 const unsigned int plen = sizeof(markcond) - 1 > DEFAULT_STRLEN ? 357 sizeof(markcond) + DEFAULT_STRLEN : sizeof(buf) - 1; 358 TEST_NLATTR(fd, nlh0, hdrlen, 359 init_inet_diag_req_v2, print_inet_diag_req_v2, 360 INET_DIAG_REQ_BYTECODE, 361 plen, buf, plen, 362 print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND"); 363 print_quoted_hex(buf + sizeof(op), plen - sizeof(op)); 364 printf("}")); 365 366 TEST_NLATTR(fd, nlh0, hdrlen, 367 init_inet_diag_req_v2, print_inet_diag_req_v2, 368 INET_DIAG_REQ_BYTECODE, 369 sizeof(buf), buf, sizeof(buf) - 1, 370 print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND"); 371 printf("%p}", RTA_DATA(TEST_NLATTR_nla) + sizeof(op))); 372 373 memcpy(buf + sizeof(op), &markcond, sizeof(markcond)); 374 TEST_NLATTR(fd, nlh0, hdrlen, 375 init_inet_diag_req_v2, print_inet_diag_req_v2, 376 INET_DIAG_REQ_BYTECODE, 377 sizeof(buf), buf, sizeof(buf), 378 print_inet_diag_bc_op("INET_DIAG_BC_MARK_COND"); 379 PRINT_FIELD_U("{", markcond, mark); 380 PRINT_FIELD_U(", ", markcond, mask); 381 printf("}}")); 382 } 383 384 static void 385 test_inet_diag_bc_nop(const int fd) 386 { 387 static const struct inet_diag_bc_op op = { 388 .code = INET_DIAG_BC_AUTO, 389 }; 390 char buf[sizeof(op) + 4]; 391 memcpy(buf, &op, sizeof(op)); 392 memcpy(buf + sizeof(op), pattern, 4); 393 394 TEST_NLATTR(fd, nlh0, hdrlen, 395 init_inet_diag_req_v2, print_inet_diag_req_v2, 396 INET_DIAG_REQ_BYTECODE, 397 sizeof(buf), buf, sizeof(buf), 398 print_inet_diag_bc_op("INET_DIAG_BC_AUTO"); 399 print_quoted_hex(buf + sizeof(op), 400 sizeof(buf) - sizeof(op)); 401 printf("}")); 402 } 403 404 int 405 main(void) 406 { 407 skip_if_unavailable("/proc/self/fd/"); 408 409 int fd = create_nl_socket(NETLINK_SOCK_DIAG); 410 nlh0 = midtail_alloc(NLMSG_SPACE(hdrlen), NLA_HDRLEN + 411 sizeof(struct inet_diag_bc_op) + 412 sizeof(struct inet_diag_hostcond) + 413 sizeof(struct in6_addr) + DEFAULT_STRLEN); 414 fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1); 415 416 test_inet_diag_bc_op(fd); 417 test_inet_diag_bc_s_cond(fd); 418 test_in_addr(fd); 419 test_in6_addr(fd); 420 test_inet_diag_bc_dev_cond(fd); 421 test_inet_diag_bc_s_le(fd); 422 test_inet_diag_bc_mark_cond(fd); 423 test_inet_diag_bc_nop(fd); 424 425 printf("+++ exited with 0 +++\n"); 426 return 0; 427 } 428