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