]> granicus.if.org Git - strace/blob - tests/nlattr.c
netlink: print unrecognized nlattr in hex
[strace] / tests / nlattr.c
1 /*
2  * Check decoding of netlink attribute.
3  *
4  * Copyright (c) 2017 JingPiao Chen <chenjingpiao@gmail.com>
5  * Copyright (c) 2017 The strace developers.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "tests.h"
32
33 #include <stdio.h>
34 #include <stdint.h>
35 #include <string.h>
36 #include <unistd.h>
37 #include <sys/socket.h>
38 #include <netinet/tcp.h>
39 #include "netlink.h"
40 #include <linux/rtnetlink.h>
41 #include <linux/sock_diag.h>
42 #include <linux/unix_diag.h>
43
44 static void
45 test_nlattr(const int fd)
46 {
47         static const struct msg {
48                 struct nlmsghdr nlh;
49                 struct unix_diag_msg udm;
50         } c_msg = {
51                 .nlh = {
52                         .nlmsg_len = sizeof(struct msg),
53                         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
54                         .nlmsg_flags = NLM_F_DUMP
55                 },
56                 .udm = {
57                         .udiag_family = AF_UNIX,
58                         .udiag_type = SOCK_STREAM,
59                         .udiag_state = TCP_FIN_WAIT1
60                 }
61         };
62         struct msg *msg;
63         struct nlattr *nla;
64         unsigned int msg_len;
65         long rc;
66
67         /* fetch fail: len < sizeof(struct nlattr) */
68         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + 2;
69         msg = tail_memdup(&c_msg, msg_len);
70         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
71         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
72         memcpy(nla, "12", 2);
73         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
74         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
75                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
76                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
77                ", udiag_ino=0, udiag_cookie=[0, 0]}, \"\\x31\\x32\"}, %u"
78                ", MSG_DONTWAIT, NULL, 0) = %s\n",
79                fd, msg_len, msg_len, sprintrc(rc));
80
81         /* fetch fail: short read */
82         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
83         msg = tail_memdup(&c_msg, msg_len - 1);
84         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
85         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
86         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
87                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
88                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
89                ", udiag_ino=0, udiag_cookie=[0, 0]}, %p}, %u"
90                ", MSG_DONTWAIT, NULL, 0) = %s\n",
91                fd, msg_len, (void *) msg + NLMSG_SPACE(sizeof(msg->udm)),
92                msg_len, sprintrc(rc));
93
94         /* print one struct nlattr */
95         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
96         msg = tail_memdup(&c_msg, msg_len);
97         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
98         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
99         *nla = (struct nlattr) {
100                 .nla_len = sizeof(*nla),
101                 .nla_type = UNIX_DIAG_NAME
102         };
103         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
104         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
105                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
106                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
107                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
108                ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
109                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
110
111         /* print one struct nlattr with nla_len out of msg_len bounds */
112         nla->nla_len += 8;
113         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
114         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
115                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
116                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
117                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
118                ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
119                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
120
121         /* print one struct nlattr and some data */
122         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 4;
123         msg = tail_memdup(&c_msg, msg_len);
124         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
125         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
126         *nla = (struct nlattr) {
127                 .nla_len = NLA_HDRLEN + 4,
128                 .nla_type = UNIX_DIAG_SHUTDOWN + 1
129         };
130         memcpy(RTA_DATA(nla), "1234", 4);
131         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
132         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
133                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
134                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
135                ", udiag_ino=0, udiag_cookie=[0, 0]}, {{nla_len=%u"
136                ", nla_type=%#x /* UNIX_DIAG_??? */}"
137                ", \"\\x31\\x32\\x33\\x34\"}}"
138                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
139                fd, msg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
140                msg_len, sprintrc(rc));
141
142         /* print one struct nlattr and fetch fail second struct nlattr */
143         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN + 2;
144         msg = tail_memdup(&c_msg, msg_len);
145         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
146         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
147         *nla = (struct nlattr) {
148                 .nla_len = NLA_HDRLEN,
149                 .nla_type = UNIX_DIAG_NAME
150         };
151         memcpy(nla + 1, "12", 2);
152         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
153         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
154                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
155                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
156                ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
157                ", nla_type=UNIX_DIAG_NAME}, \"\\x31\\x32\"]}, %u"
158                ", MSG_DONTWAIT, NULL, 0) = %s\n",
159                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
160
161         /* print one struct nlattr and short read of second struct nlattr */
162         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
163         msg = tail_memdup(&c_msg, msg_len - 1);
164         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
165         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
166         *nla = (struct nlattr) {
167                 .nla_len = NLA_HDRLEN,
168                 .nla_type = UNIX_DIAG_NAME
169         };
170         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
171         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
172                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
173                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
174                ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
175                ", nla_type=UNIX_DIAG_NAME}, %p]}, %u"
176                ", MSG_DONTWAIT, NULL, 0) = %s\n",
177                fd, msg_len, nla->nla_len, nla + 1, msg_len, sprintrc(rc));
178
179         /* print two struct nlattr */
180         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + NLA_HDRLEN * 2;
181         msg = tail_memdup(&c_msg, msg_len);
182         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
183         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
184         *nla = (struct nlattr) {
185                 .nla_len = NLA_HDRLEN,
186                 .nla_type = UNIX_DIAG_NAME
187         };
188         *(nla + 1) = (struct nlattr) {
189                 .nla_len = NLA_HDRLEN,
190                 .nla_type = UNIX_DIAG_PEER
191         };
192         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
193         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
194                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
195                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
196                ", udiag_ino=0, udiag_cookie=[0, 0]}, [{nla_len=%u"
197                ", nla_type=UNIX_DIAG_NAME}, {nla_len=%u"
198                ", nla_type=UNIX_DIAG_PEER}]}, %u"
199                ", MSG_DONTWAIT, NULL, 0) = %s\n",
200                fd, msg_len, nla->nla_len, nla->nla_len,
201                msg_len, sprintrc(rc));
202
203         /* print first nlattr only when its nla_len is less than NLA_HDRLEN */
204         nla->nla_len = NLA_HDRLEN - 1;
205         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
206         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
207                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
208                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
209                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
210                ", nla_type=UNIX_DIAG_NAME}}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
211                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
212
213         /* abbreviated output */
214 #define ABBREV_LEN (DEFAULT_STRLEN + 1)
215         msg_len = NLA_HDRLEN * ABBREV_LEN + NLMSG_SPACE(sizeof(msg->udm));
216         msg = tail_memdup(&c_msg, msg_len);
217         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
218         unsigned int i;
219         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
220         for (i = 0; i < ABBREV_LEN; ++i)
221                 nla[i] = (struct nlattr) {
222                         .nla_len = NLA_HDRLEN,
223                         .nla_type = UNIX_DIAG_SHUTDOWN + 1 + i
224                 };
225
226         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
227         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
228                ", flags=NLM_F_DUMP, seq=0, pid=0}"
229                ", {udiag_family=AF_UNIX, udiag_type=SOCK_STREAM"
230                ", udiag_state=TCP_FIN_WAIT1, udiag_ino=0"
231                ", udiag_cookie=[0, 0]}, [",
232                fd, msg_len);
233         for (i = 0; i < DEFAULT_STRLEN; ++i) {
234                 if (i)
235                         printf(", ");
236                 printf("{nla_len=%u, nla_type=%#x /* UNIX_DIAG_??? */}",
237                        nla->nla_len, UNIX_DIAG_SHUTDOWN + 1 + i);
238         }
239         printf(", ...]}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
240                msg_len, sprintrc(rc));
241 }
242
243 static void
244 test_nla_type(const int fd)
245 {
246         static const struct msg {
247                 struct nlmsghdr nlh;
248                 struct unix_diag_msg udm;
249         } c_msg = {
250                 .nlh = {
251                         .nlmsg_len = sizeof(struct msg),
252                         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
253                         .nlmsg_flags = NLM_F_DUMP
254                 },
255                 .udm = {
256                         .udiag_family = AF_UNIX,
257                         .udiag_type = SOCK_STREAM,
258                         .udiag_state = TCP_FIN_WAIT1
259                 }
260         };
261         struct msg *msg;
262         struct nlattr *nla;
263         unsigned int msg_len;
264         long rc;
265
266         msg_len = NLMSG_SPACE(sizeof(msg->udm)) + sizeof(*nla);
267         msg = tail_memdup(&c_msg, msg_len);
268         memcpy(&msg->nlh.nlmsg_len, &msg_len, sizeof(msg_len));
269         nla = NLMSG_ATTR(msg, sizeof(msg->udm));
270         *nla = (struct nlattr) {
271                 .nla_len = sizeof(*nla),
272                 .nla_type = NLA_F_NESTED | UNIX_DIAG_NAME
273         };
274         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
275         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
276                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
277                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
278                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
279                ", nla_type=NLA_F_NESTED|UNIX_DIAG_NAME}}"
280                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
281                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
282
283         nla->nla_type = NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
284         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
285         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
286                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
287                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
288                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
289                ", nla_type=NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
290                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
291                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
292
293         nla->nla_type = NLA_F_NESTED | NLA_F_NET_BYTEORDER | UNIX_DIAG_NAME;
294         rc = sendto(fd, msg, msg_len, MSG_DONTWAIT, NULL, 0);
295         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
296                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
297                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
298                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
299                ", nla_type=NLA_F_NESTED|NLA_F_NET_BYTEORDER|UNIX_DIAG_NAME}}"
300                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
301                fd, msg_len, nla->nla_len, msg_len, sprintrc(rc));
302
303         nla->nla_type = NLA_F_NESTED | (UNIX_DIAG_SHUTDOWN + 1);
304         rc = sendto(fd, msg, msg->nlh.nlmsg_len, MSG_DONTWAIT, NULL, 0);
305         printf("sendto(%d, {{len=%u, type=SOCK_DIAG_BY_FAMILY"
306                ", flags=NLM_F_DUMP, seq=0, pid=0}, {udiag_family=AF_UNIX"
307                ", udiag_type=SOCK_STREAM, udiag_state=TCP_FIN_WAIT1"
308                ", udiag_ino=0, udiag_cookie=[0, 0]}, {nla_len=%u"
309                ", nla_type=NLA_F_NESTED|%#x /* UNIX_DIAG_??? */}}"
310                ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
311                fd, msg->nlh.nlmsg_len, nla->nla_len, UNIX_DIAG_SHUTDOWN + 1,
312                msg->nlh.nlmsg_len, sprintrc(rc));
313 }
314
315 int main(void)
316 {
317         skip_if_unavailable("/proc/self/fd/");
318
319         const int fd = create_nl_socket(NETLINK_SOCK_DIAG);
320
321         test_nlattr(fd);
322         test_nla_type(fd);
323
324         puts("+++ exited with 0 +++");
325
326         return 0;
327 }