1 /*
2 * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
3 * Copyright (c) 2017-2021 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: GPL-2.0-or-later
7 */
8
9 #include "tests.h"
10 #include <string.h>
11 #include <stdio.h>
12 #include <sys/socket.h>
13 #include <arpa/inet.h>
14 #include "netlink.h"
15 #include "netlink_kobject_uevent.h"
16
17 static const char *errstr;
18
19 static ssize_t
20 sys_send(const int fd, const void *const buf, const size_t len)
21 {
22 const ssize_t rc = sendto(fd, buf, len, MSG_DONTWAIT, NULL, 0);
23 errstr = sprintrc(rc);
24 return rc;
25 }
26
27 static void
28 test_nlmsg_type_udev(const int fd)
29 {
30 static const char extra[] = "12345678";
31 struct udev_monitor_netlink_header uh = {
32 .prefix = "libudev",
33 .magic = htonl(0xfeedcafe),
34 .header_size = sizeof(uh),
35 .properties_off = 40,
36 .properties_len = 299,
37 .filter_subsystem_hash = htonl(0xc370b302),
38 .filter_devtype_hash = htonl(0x10800000),
39 .filter_tag_bloom_hi = htonl(0x2000400),
40 .filter_tag_bloom_lo = htonl(0x10800000),
41 };
42 const unsigned int extra_len = LENGTH_OF(extra);
43 const unsigned int uh_len = sizeof(uh);
44
45 char *const buf = tail_alloc(uh_len + extra_len);
46 memcpy(buf + extra_len, &uh, uh_len);
47
48 sys_send(fd, buf + extra_len, uh_len);
49 printf("sendto(%d, {prefix=\"%s\", magic=htonl(%#x)"
50 ", header_size=%u, properties_off=%u, properties_len=%u"
51 ", filter_subsystem_hash=htonl(%#x)"
52 ", filter_devtype_hash=htonl(%#x)"
53 ", filter_tag_bloom_hi=htonl(%#x)"
54 ", filter_tag_bloom_lo=htonl(%#x)}, %u, MSG_DONTWAIT, NULL, "
55 "0) = %s\n"
56 , fd, uh.prefix,
57 ntohl(uh.magic), uh.header_size, uh.properties_off,
58 uh.properties_len, ntohl(uh.filter_subsystem_hash),
59 ntohl(uh.filter_devtype_hash), ntohl(uh.filter_tag_bloom_hi),
60 ntohl(uh.filter_tag_bloom_lo), uh_len, errstr);
61
62 memcpy(buf, &uh, uh_len);
63 memcpy(buf + uh_len, extra, extra_len);
64 sys_send(fd, buf, uh_len + extra_len);
65 printf("sendto(%d, [{prefix=\"%s\", magic=htonl(%#x)"
66 ", header_size=%u, properties_off=%u, properties_len=%u"
67 ", filter_subsystem_hash=htonl(%#x)"
68 ", filter_devtype_hash=htonl(%#x)"
69 ", filter_tag_bloom_hi=htonl(%#x)"
70 ", filter_tag_bloom_lo=htonl(%#x)}, "
71 , fd, uh.prefix,
72 ntohl(uh.magic), uh.header_size, uh.properties_off,
73 uh.properties_len, ntohl(uh.filter_subsystem_hash),
74 ntohl(uh.filter_devtype_hash), ntohl(uh.filter_tag_bloom_hi),
75 ntohl(uh.filter_tag_bloom_lo));
76 print_quoted_memory(buf + uh_len, extra_len);
77 printf("], %u, MSG_DONTWAIT, NULL, 0) = %s\n",
78 uh_len + extra_len, errstr);
79
80 memcpy(buf + extra_len + 1, &uh, uh_len - 1);
81 sys_send(fd, buf + extra_len + 1, uh_len);
82 printf("sendto(%d, ", fd);
83 print_quoted_memory(&uh, MIN(uh_len - 1, DEFAULT_STRLEN));
84 printf("%s, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
85 (uh_len - 1 > DEFAULT_STRLEN ? "..." : ""),
86 uh_len, errstr);
87 }
88
89 static void
90 test_nlmsg_type_kernel(const int fd)
91 {
92 struct udev_monitor_netlink_header uh = {
93 .prefix = "change@",
94 .magic = htonl(0xfeedcafe),
95 .header_size = sizeof(uh),
96 .properties_off = 10,
97 .properties_len = 299,
98 .filter_subsystem_hash = htonl(0xfffffff),
99 .filter_devtype_hash = htonl(0x10000000),
100 .filter_tag_bloom_hi = htonl(0x2000400),
101 };
102 const unsigned int uh_len = sizeof(uh);
103
104 TAIL_ALLOC_OBJECT_CONST_PTR(struct udev_monitor_netlink_header, p);
105 memcpy(p, &uh, uh_len);
106
107 sys_send(fd, p, uh_len);
108 printf("sendto(%d, ", fd);
109 print_quoted_memory(&uh, MIN(uh_len, DEFAULT_STRLEN));
110 printf("%s, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
111 (uh_len > DEFAULT_STRLEN ? "..." : ""),
112 uh_len, errstr);
113 }
114
115 int
116 main(void)
117 {
118 skip_if_unavailable("/proc/self/fd/");
119
120 int fd = create_nl_socket(NETLINK_KOBJECT_UEVENT);
121
122 test_nlmsg_type_udev(fd);
123 test_nlmsg_type_kernel(fd);
124 /* test using data that looks like a zero-length C string */
125 char *const buf = tail_alloc(DEFAULT_STRLEN + 1);
126 buf[0] = '=';
127 fill_memory_ex(buf + 1, DEFAULT_STRLEN, 0, DEFAULT_STRLEN);
128
129 sys_send(fd, buf + 1, DEFAULT_STRLEN);
130 printf("sendto(%d, ", fd);
131 print_quoted_memory(buf + 1, DEFAULT_STRLEN);
132 printf(", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
133 DEFAULT_STRLEN, errstr);
134
135 sys_send(fd, buf, DEFAULT_STRLEN + 1);
136 printf("sendto(%d, ", fd);
137 print_quoted_memory(buf, DEFAULT_STRLEN);
138 printf("..., %u, MSG_DONTWAIT, NULL, 0) = %s\n",
139 DEFAULT_STRLEN + 1, errstr);
140
141 puts("+++ exited with 0 +++");
142 return 0;
143 }