1 /*
2 * Copyright (c) 2017, 2018 Chen Jingpiao <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 <stdio.h>
11 #include <string.h>
12 #include <unistd.h>
13 #include <netinet/in.h>
14 #include <arpa/inet.h>
15 #include <sys/socket.h>
16 #include "test_netlink.h"
17 #include <linux/netfilter/nfnetlink.h>
18 #include <linux/netfilter/nf_tables.h>
19
20 static void
21 test_nlmsg_type(const int fd)
22 {
23 long rc;
24 struct nlmsghdr nlh = {
25 .nlmsg_len = sizeof(nlh),
26 .nlmsg_flags = NLM_F_REQUEST,
27 };
28
29 nlh.nlmsg_type = NFNL_MSG_BATCH_BEGIN;
30 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
31 printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=NFNL_MSG_BATCH_BEGIN"
32 ", nlmsg_flags=NLM_F_REQUEST, nlmsg_seq=0, nlmsg_pid=0}"
33 ", %u, MSG_DONTWAIT, NULL, 0) = %s\n",
34 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
35
36 nlh.nlmsg_type = NFNL_SUBSYS_CTNETLINK << 8 | 0xff;
37 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
38 printf("sendto(%d, {nlmsg_len=%u"
39 ", nlmsg_type=NFNL_SUBSYS_CTNETLINK<<8|0xff"
40 " /* IPCTNL_MSG_CT_??? */, nlmsg_flags=NLM_F_REQUEST"
41 ", nlmsg_seq=0, nlmsg_pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
42 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
43
44 nlh.nlmsg_type = 0xffff;
45 rc = sendto(fd, &nlh, sizeof(nlh), MSG_DONTWAIT, NULL, 0);
46 printf("sendto(%d, {nlmsg_len=%u, nlmsg_type=0xff"
47 " /* NFNL_SUBSYS_??? */<<8|0xff, nlmsg_flags=NLM_F_REQUEST"
48 ", nlmsg_seq=0, nlmsg_pid=0}, %u, MSG_DONTWAIT, NULL, 0) = %s\n",
49 fd, nlh.nlmsg_len, (unsigned) sizeof(nlh), sprintrc(rc));
50 }
51
52 static void
53 test_nlmsg_done(const int fd)
54 {
55 const int num = 0xabcdefad;
56 void *const nlh0 = midtail_alloc(NLMSG_HDRLEN, sizeof(num));
57
58 TEST_NETLINK(fd, nlh0, NLMSG_DONE, NLM_F_REQUEST,
59 sizeof(num), &num, sizeof(num),
60 printf("%d", num));
61 }
62
63 static void
64 test_nfgenmsg(const int fd)
65 {
66 static const struct nlattr nla = {
67 .nla_len = sizeof(nla),
68 .nla_type = 0x0bcd
69 };
70
71 struct nfgenmsg msg = {
72 .nfgen_family = AF_UNIX,
73 .version = NFNETLINK_V0,
74 .res_id = NFNL_SUBSYS_NFTABLES
75 };
76 char str_buf[NLMSG_ALIGN(sizeof(msg)) + 4];
77 char nla_buf[NLMSG_ALIGN(sizeof(msg)) + sizeof(nla)];
78
79 void *const nlh0 = midtail_alloc(NLMSG_HDRLEN,
80 MAX(sizeof(str_buf), sizeof(nla_buf)));
81
82 TEST_NETLINK_OBJECT_EX_(fd, nlh0,
83 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE,
84 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE",
85 NLM_F_REQUEST, "NLM_F_REQUEST",
86 msg, print_quoted_hex,
87 printf("{nfgen_family=AF_UNIX");
88 printf(", version=NFNETLINK_V0");
89 printf(", res_id=");
90 if (htons(NFNL_SUBSYS_NFTABLES) == NFNL_SUBSYS_NFTABLES)
91 printf("htons(NFNL_SUBSYS_NFTABLES)");
92 else
93 printf("NFNL_SUBSYS_NFTABLES");
94 printf("}");
95 );
96
97 msg.res_id = htons(NFNL_SUBSYS_NFTABLES);
98 TEST_NETLINK_(fd, nlh0,
99 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE,
100 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE",
101 NLM_F_REQUEST, "NLM_F_REQUEST",
102 sizeof(msg), &msg, sizeof(msg),
103 printf("{nfgen_family=AF_UNIX");
104 printf(", version=NFNETLINK_V0");
105 printf(", res_id=htons(NFNL_SUBSYS_NFTABLES)}"));
106
107 msg.res_id = htons(0xabcd);
108 TEST_NETLINK_(fd, nlh0,
109 NFNL_SUBSYS_NFTABLES << 8 | NFT_MSG_NEWTABLE,
110 "NFNL_SUBSYS_NFTABLES<<8|NFT_MSG_NEWTABLE",
111 NLM_F_REQUEST, "NLM_F_REQUEST",
112 sizeof(msg), &msg, sizeof(msg),
113 printf("{nfgen_family=AF_UNIX");
114 printf(", version=NFNETLINK_V0");
115 printf(", res_id=htons(%d)}", 0xabcd));
116
117 msg.res_id = htons(NFNL_SUBSYS_NFTABLES);
118 TEST_NETLINK(fd, nlh0,
119 NFNL_MSG_BATCH_BEGIN, NLM_F_REQUEST,
120 sizeof(msg), &msg, sizeof(msg),
121 printf("{nfgen_family=AF_UNIX");
122 printf(", version=NFNETLINK_V0");
123 printf(", res_id=htons(%d)}", NFNL_SUBSYS_NFTABLES));
124
125 msg.res_id = htons(0xabcd);
126 memcpy(str_buf, &msg, sizeof(msg));
127 memcpy(str_buf + NLMSG_ALIGN(sizeof(msg)), "1234", 4);
128
129 TEST_NETLINK(fd, nlh0,
130 NFNL_MSG_BATCH_BEGIN, NLM_F_REQUEST,
131 sizeof(str_buf), str_buf, sizeof(str_buf),
132 printf("{nfgen_family=AF_UNIX");
133 printf(", version=NFNETLINK_V0");
134 printf(", res_id=htons(%d)}"
135 ", \"\\x31\\x32\\x33\\x34\"", 0xabcd));
136
137 msg.res_id = htons(NFNL_SUBSYS_NFTABLES);
138 memcpy(nla_buf, &msg, sizeof(msg));
139 memcpy(nla_buf + NLMSG_ALIGN(sizeof(msg)), &nla, sizeof(nla));
140
141 TEST_NETLINK_(fd, nlh0,
142 NFNL_SUBSYS_NFTABLES << 8 | 0xff,
143 "NFNL_SUBSYS_NFTABLES<<8|0xff /* NFT_MSG_??? */",
144 NLM_F_REQUEST, "NLM_F_REQUEST",
145 sizeof(nla_buf), nla_buf, sizeof(nla_buf),
146 printf("{nfgen_family=AF_UNIX");
147 printf(", version=NFNETLINK_V0");
148 printf(", res_id=htons(NFNL_SUBSYS_NFTABLES)}"
149 ", {nla_len=%d, nla_type=%#x}",
150 nla.nla_len, nla.nla_type));
151 }
152
153 int main(void)
154 {
155 skip_if_unavailable("/proc/self/fd/");
156
157 int fd = create_nl_socket(NETLINK_NETFILTER);
158
159 test_nlmsg_type(fd);
160 test_nlmsg_done(fd);
161 test_nfgenmsg(fd);
162
163 printf("+++ exited with 0 +++\n");
164
165 return 0;
166 }