Home | History | Annotate | Download | only in tests-m32
      1 /*
      2  * Copyright (c) 2017 JingPiao Chen <chenjingpiao (at) gmail.com>
      3  * Copyright (c) 2017 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 = tail_alloc(NLMSG_SPACE(hdrlen));
    411 	fill_memory_ex(pattern, sizeof(pattern), 'a', 'z' - 'a' + 1);
    412 
    413 	test_inet_diag_bc_op(fd);
    414 	test_inet_diag_bc_s_cond(fd);
    415 	test_in_addr(fd);
    416 	test_in6_addr(fd);
    417 	test_inet_diag_bc_dev_cond(fd);
    418 	test_inet_diag_bc_s_le(fd);
    419 	test_inet_diag_bc_mark_cond(fd);
    420 	test_inet_diag_bc_nop(fd);
    421 
    422 	printf("+++ exited with 0 +++\n");
    423 	return 0;
    424 }
    425