]> granicus.if.org Git - strace/blob - tests/netlink_inet_diag.c
tests: skip netlink based tests when resources are not available
[strace] / tests / netlink_inet_diag.c
1 #include <assert.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <netinet/in.h>
5 #include <linux/netlink.h>
6 #include <linux/sock_diag.h>
7 #include <linux/inet_diag.h>
8
9 static int
10 send_query(const int fd, const int family, const int proto)
11 {
12         struct sockaddr_nl nladdr = {
13                 .nl_family = AF_NETLINK
14         };
15         struct {
16                 struct nlmsghdr nlh;
17                 struct inet_diag_req_v2 idr;
18         } req = {
19                 .nlh = {
20                         .nlmsg_len = sizeof(req),
21                         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
22                         .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
23                 },
24                 .idr = {
25                         .sdiag_family = family,
26                         .sdiag_protocol = proto,
27                         .idiag_states = -1
28                 }
29         };
30         struct iovec iov = {
31                 .iov_base = &req,
32                 .iov_len = sizeof(req)
33         };
34         struct msghdr msg = {
35                 .msg_name = (void*)&nladdr,
36                 .msg_namelen = sizeof(nladdr),
37                 .msg_iov = &iov,
38                 .msg_iovlen = 1
39         };
40
41         return sendmsg(fd, &msg, 0) > 0;
42 }
43
44 static int
45 check_responses(const int fd)
46 {
47         static char buf[8192];
48         struct sockaddr_nl nladdr = {
49                 .nl_family = AF_NETLINK
50         };
51         struct iovec iov = {
52                 .iov_base = buf,
53                 .iov_len = sizeof(buf)
54         };
55         struct msghdr msg = {
56                 .msg_name = (void*)&nladdr,
57                 .msg_namelen = sizeof(nladdr),
58                 .msg_iov = &iov,
59                 .msg_iovlen = 1
60         };
61
62         ssize_t ret = recvmsg(fd, &msg, 0);
63         if (ret <= 0)
64                 return 0;
65
66         struct nlmsghdr *h = (struct nlmsghdr*)buf;
67         return (NLMSG_OK(h, ret) &&
68                 h->nlmsg_type != NLMSG_ERROR &&
69                 h->nlmsg_type != NLMSG_DONE) ? 1 : 0;
70 }
71
72 int main(void)
73 {
74         struct sockaddr_in addr;
75         socklen_t len = sizeof(addr);
76
77         memset(&addr, 0, sizeof(addr));
78         addr.sin_family = AF_INET;
79         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
80
81         close(0);
82         close(1);
83
84         if (socket(PF_INET, SOCK_STREAM, 0) ||
85             bind(0, (struct sockaddr *) &addr, len) ||
86             listen(0, 5) ||
87             socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG) != 1)
88                 return 77;
89
90         return (send_query(1, AF_INET, IPPROTO_TCP) &&
91                 check_responses(1)) ? 0 : 77;
92 }