1 // SPDX-License-Identifier: GPL-2.0
8 #include <sys/socket.h>
10 #include <sys/syscall.h>
11 #include <sys/types.h>
14 #include <linux/genetlink.h>
15 #include <linux/neighbour.h>
16 #include <linux/netdevice.h>
17 #include <linux/netlink.h>
18 #include <linux/mqueue.h>
19 #include <linux/rtnetlink.h>
21 #include "../kselftest_harness.h"
34 /* 0: no done, 1: done found, 2: extack found, -1: error */
35 static int nl_get_extack(char *buf
, size_t n
, struct ext_ack
*ea
)
37 const struct nlmsghdr
*nlh
;
38 const struct nlattr
*attr
;
41 for (rem
= n
; rem
> 0; NLMSG_NEXT(nlh
, rem
)) {
42 nlh
= (struct nlmsghdr
*)&buf
[n
- rem
];
43 if (!NLMSG_OK(nlh
, rem
))
46 if (nlh
->nlmsg_type
!= NLMSG_DONE
)
49 ea
->err
= -*(int *)NLMSG_DATA(nlh
);
51 if (!(nlh
->nlmsg_flags
& NLM_F_ACK_TLVS
))
54 ynl_attr_for_each(attr
, nlh
, sizeof(int)) {
55 switch (ynl_attr_type(attr
)) {
56 case NLMSGERR_ATTR_OFFS
:
57 ea
->attr_offs
= ynl_attr_get_u32(attr
);
59 case NLMSGERR_ATTR_MISS_TYPE
:
60 ea
->miss_type
= ynl_attr_get_u32(attr
);
62 case NLMSGERR_ATTR_MISS_NEST
:
63 ea
->miss_nest
= ynl_attr_get_u32(attr
);
65 case NLMSGERR_ATTR_MSG
:
66 ea
->str
= ynl_attr_get_str(attr
);
78 struct nlmsghdr nlhdr
;
84 .nlmsg_len
= sizeof(dump_neigh_bad
),
85 .nlmsg_type
= RTM_GETNEIGH
,
86 .nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
,
94 .nla_type
= NDA_FLAGS_EXT
,
96 .val
= -1, // should fail MASK validation
107 netlink_sock
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_ROUTE
);
108 ASSERT_GE(netlink_sock
, 0);
110 n
= setsockopt(netlink_sock
, SOL_NETLINK
, NETLINK_CAP_ACK
,
113 n
= setsockopt(netlink_sock
, SOL_NETLINK
, NETLINK_EXT_ACK
,
116 n
= setsockopt(netlink_sock
, SOL_NETLINK
, NETLINK_GET_STRICT_CHK
,
120 /* Dump so many times we fill up the buffer */
122 for (i
= 0; i
< cnt
; i
++) {
123 n
= send(netlink_sock
, &dump_neigh_bad
,
124 sizeof(dump_neigh_bad
), 0);
125 ASSERT_EQ(n
, sizeof(dump_neigh_bad
));
128 /* Read out the ENOBUFS */
129 n
= recv(netlink_sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
131 EXPECT_EQ(errno
, ENOBUFS
);
133 for (i
= 0; i
< cnt
; i
++) {
134 struct ext_ack ea
= {};
136 n
= recv(netlink_sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
141 ASSERT_GE(n
, (ssize_t
)sizeof(struct nlmsghdr
));
143 EXPECT_EQ(nl_get_extack(buf
, n
, &ea
), 2);
144 EXPECT_EQ(ea
.attr_offs
,
145 sizeof(struct nlmsghdr
) + sizeof(struct ndmsg
));
149 static const struct {
150 struct nlmsghdr nlhdr
;
151 struct genlmsghdr genlhdr
;
157 .nlmsg_len
= sizeof(dump_policies
),
158 .nlmsg_type
= GENL_ID_CTRL
,
159 .nlmsg_flags
= NLM_F_REQUEST
| NLM_F_ACK
| NLM_F_DUMP
,
163 .cmd
= CTRL_CMD_GETPOLICY
,
168 .nla_type
= CTRL_ATTR_FAMILY_ID
,
174 // Sanity check for the test itself, make sure the dump doesn't fit in one msg
181 netlink_sock
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_GENERIC
);
182 ASSERT_GE(netlink_sock
, 0);
184 n
= send(netlink_sock
, &dump_policies
, sizeof(dump_policies
), 0);
185 ASSERT_EQ(n
, sizeof(dump_policies
));
187 n
= recv(netlink_sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
188 ASSERT_GE(n
, (ssize_t
)sizeof(struct nlmsghdr
));
190 n
= recv(netlink_sock
, buf
, sizeof(buf
), MSG_DONTWAIT
);
191 ASSERT_GE(n
, (ssize_t
)sizeof(struct nlmsghdr
));
196 TEST(close_in_progress
)
201 netlink_sock
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_GENERIC
);
202 ASSERT_GE(netlink_sock
, 0);
204 n
= send(netlink_sock
, &dump_policies
, sizeof(dump_policies
), 0);
205 ASSERT_EQ(n
, sizeof(dump_policies
));
212 char cookie
[NOTIFY_COOKIE_LEN
] = {};
213 int netlink_sock
, mq_fd
;
214 struct sigevent sigev
;
217 netlink_sock
= socket(AF_NETLINK
, SOCK_RAW
, NETLINK_GENERIC
);
218 ASSERT_GE(netlink_sock
, 0);
220 n
= send(netlink_sock
, &dump_policies
, sizeof(dump_policies
), 0);
221 ASSERT_EQ(n
, sizeof(dump_policies
));
223 mq_fd
= syscall(__NR_mq_open
, "sed", O_CREAT
| O_WRONLY
, 0600, 0);
226 memset(&sigev
, 0, sizeof(sigev
));
227 sigev
.sigev_notify
= SIGEV_THREAD
;
228 sigev
.sigev_value
.sival_ptr
= cookie
;
229 sigev
.sigev_signo
= netlink_sock
;
231 syscall(__NR_mq_notify
, mq_fd
, &sigev
);
235 // give mqueue time to fire