blob: bacb938c4ae76b7aac500228286909b1bbde7e84 [file] [log] [blame]
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +00001#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
9static int
10send_query(const int fd, const int family, const int proto)
11{
Dmitry V. Levinaf534b82014-11-21 19:59:16 +000012 struct sockaddr_nl nladdr = {
13 .nl_family = AF_NETLINK
14 };
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000015 struct {
16 struct nlmsghdr nlh;
17 struct inet_diag_req_v2 idr;
Dmitry V. Levinaf534b82014-11-21 19:59:16 +000018 } 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 };
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000030 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
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000041 return sendmsg(fd, &msg, 0) > 0;
42}
43
44static int
45check_responses(const int fd)
46{
47 static char buf[8192];
Dmitry V. Levinaf534b82014-11-21 19:59:16 +000048 struct sockaddr_nl nladdr = {
49 .nl_family = AF_NETLINK
50 };
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000051 struct iovec iov = {
52 .iov_base = buf,
53 .iov_len = sizeof(buf)
54 };
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000055 struct msghdr msg = {
56 .msg_name = (void*)&nladdr,
57 .msg_namelen = sizeof(nladdr),
58 .msg_iov = &iov,
Dmitry V. Levinaf534b82014-11-21 19:59:16 +000059 .msg_iovlen = 1
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000060 };
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
72int 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
Dmitry V. Levin6add1b02015-03-18 20:18:27 +000084 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)
Dmitry V. Levinfdfa7222014-09-23 00:14:04 +000088 return 77;
89
90 return (send_query(1, AF_INET, IPPROTO_TCP) &&
91 check_responses(1)) ? 0 : 77;
92}