]> granicus.if.org Git - strace/blob - tests/netlink_unix_diag.c
Fix build on systems that lack NETLINK_SOCK_DIAG definition
[strace] / tests / netlink_unix_diag.c
1 #include <assert.h>
2 #include <stddef.h>
3 #include <stdint.h>
4 #include <string.h>
5 #include <unistd.h>
6 #include <sys/socket.h>
7 #include <sys/un.h>
8 #include <linux/netlink.h>
9 #include <linux/sock_diag.h>
10 #include <linux/unix_diag.h>
11
12 #if !defined NETLINK_SOCK_DIAG && defined NETLINK_INET_DIAG
13 # define NETLINK_SOCK_DIAG NETLINK_INET_DIAG
14 #endif
15
16 static int
17 send_query(const int fd, const int family, const int proto)
18 {
19         struct sockaddr_nl nladdr = {
20                 .nl_family = AF_NETLINK
21         };
22         struct {
23                 struct nlmsghdr nlh;
24                 struct unix_diag_req udr;
25         } req = {
26                 .nlh = {
27                         .nlmsg_len = sizeof(req),
28                         .nlmsg_type = SOCK_DIAG_BY_FAMILY,
29                         .nlmsg_flags = NLM_F_DUMP | NLM_F_REQUEST
30                 },
31                 .udr = {
32                         .sdiag_family = family,
33                         .sdiag_protocol = proto,
34                         .udiag_states = -1,
35                         .udiag_show = UDIAG_SHOW_NAME | UDIAG_SHOW_PEER
36                 }
37         };
38         struct iovec iov = {
39                 .iov_base = &req,
40                 .iov_len = sizeof(req)
41         };
42         struct msghdr msg = {
43                 .msg_name = (void*)&nladdr,
44                 .msg_namelen = sizeof(nladdr),
45                 .msg_iov = &iov,
46                 .msg_iovlen = 1
47         };
48
49         return sendmsg(fd, &msg, 0) > 0;
50 }
51
52 static int
53 check_responses(const int fd)
54 {
55         static char buf[8192];
56         struct sockaddr_nl nladdr = {
57                 .nl_family = AF_NETLINK
58         };
59         struct iovec iov = {
60                 .iov_base = buf,
61                 .iov_len = sizeof(buf)
62         };
63         struct msghdr msg = {
64                 .msg_name = (void*)&nladdr,
65                 .msg_namelen = sizeof(nladdr),
66                 .msg_iov = &iov,
67                 .msg_iovlen = 1
68         };
69
70         ssize_t ret = recvmsg(fd, &msg, 0);
71         if (ret <= 0)
72                 return 0;
73
74         struct nlmsghdr *h = (struct nlmsghdr*)buf;
75         return (NLMSG_OK(h, ret) &&
76                 h->nlmsg_type != NLMSG_ERROR &&
77                 h->nlmsg_type != NLMSG_DONE) ? 1 : 0;
78 }
79
80 #define SUN_PATH "netlink_unix_diag_socket"
81 int main(void)
82 {
83         struct sockaddr_un addr = {
84                 .sun_family = AF_UNIX,
85                 .sun_path = SUN_PATH
86         };
87         socklen_t len = offsetof(struct sockaddr_un, sun_path) + sizeof(SUN_PATH);
88
89         close(0);
90         close(1);
91
92         (void) unlink(SUN_PATH);
93         assert(socket(PF_LOCAL, SOCK_STREAM, 0) == 0);
94         assert(bind(0, (struct sockaddr *) &addr, len) == 0);
95         assert(listen(0, 5) == 0);
96         assert(unlink(SUN_PATH) == 0);
97
98         if (socket(AF_NETLINK, SOCK_RAW, NETLINK_SOCK_DIAG) != 1)
99                 return 77;
100
101         return (send_query(1, AF_UNIX, 0) &&
102                 check_responses(1)) ? 0 : 77;
103 }