7 #include <libmnl/libmnl.h>
8 #include <linux/netfilter/nfnetlink.h>
9 #include <linux/netfilter/nfnetlink_conntrack.h>
11 static int parse_ip_cb(
const struct nlattr *attr,
void *data)
13 const struct nlattr **tb = data;
14 int type = mnl_attr_get_type(attr);
16 if (mnl_attr_type_valid(attr, CTA_IP_MAX) < 0)
22 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
23 perror(
"mnl_attr_validate");
32 static void print_ip(
const struct nlattr *nest)
34 struct nlattr *tb[CTA_IP_MAX+1] = {};
36 mnl_attr_parse_nested(nest, parse_ip_cb, tb);
37 if (tb[CTA_IP_V4_SRC]) {
38 struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_SRC]);
39 printf(
"src=%s ", inet_ntoa(*in));
41 if (tb[CTA_IP_V4_DST]) {
42 struct in_addr *in = mnl_attr_get_payload(tb[CTA_IP_V4_DST]);
43 printf(
"dst=%s ", inet_ntoa(*in));
47 static int parse_proto_cb(
const struct nlattr *attr,
void *data)
49 const struct nlattr **tb = data;
50 int type = mnl_attr_get_type(attr);
52 if (mnl_attr_type_valid(attr, CTA_PROTO_MAX) < 0)
57 case CTA_PROTO_ICMP_TYPE:
58 case CTA_PROTO_ICMP_CODE:
59 if (mnl_attr_validate(attr, MNL_TYPE_U8) < 0) {
60 perror(
"mnl_attr_validate");
64 case CTA_PROTO_SRC_PORT:
65 case CTA_PROTO_DST_PORT:
66 case CTA_PROTO_ICMP_ID:
67 if (mnl_attr_validate(attr, MNL_TYPE_U16) < 0) {
68 perror(
"mnl_attr_validate");
77 static void print_proto(
const struct nlattr *nest)
79 struct nlattr *tb[CTA_PROTO_MAX+1] = {};
81 mnl_attr_parse_nested(nest, parse_proto_cb, tb);
82 if (tb[CTA_PROTO_NUM]) {
83 printf(
"proto=%u ", mnl_attr_get_u8(tb[CTA_PROTO_NUM]));
85 if (tb[CTA_PROTO_SRC_PORT]) {
87 ntohs(mnl_attr_get_u16(tb[CTA_PROTO_SRC_PORT])));
89 if (tb[CTA_PROTO_DST_PORT]) {
91 ntohs(mnl_attr_get_u16(tb[CTA_PROTO_DST_PORT])));
93 if (tb[CTA_PROTO_ICMP_ID]) {
95 ntohs(mnl_attr_get_u16(tb[CTA_PROTO_ICMP_ID])));
97 if (tb[CTA_PROTO_ICMP_TYPE]) {
98 printf(
"type=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_TYPE]));
100 if (tb[CTA_PROTO_ICMP_CODE]) {
101 printf(
"code=%u ", mnl_attr_get_u8(tb[CTA_PROTO_ICMP_CODE]));
105 static int parse_tuple_cb(
const struct nlattr *attr,
void *data)
107 const struct nlattr **tb = data;
108 int type = mnl_attr_get_type(attr);
110 if (mnl_attr_type_valid(attr, CTA_TUPLE_MAX) < 0)
115 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
116 perror(
"mnl_attr_validate");
120 case CTA_TUPLE_PROTO:
121 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
122 perror(
"mnl_attr_validate");
131 static void print_tuple(
const struct nlattr *nest)
133 struct nlattr *tb[CTA_TUPLE_MAX+1] = {};
135 mnl_attr_parse_nested(nest, parse_tuple_cb, tb);
136 if (tb[CTA_TUPLE_IP]) {
137 print_ip(tb[CTA_TUPLE_IP]);
139 if (tb[CTA_TUPLE_PROTO]) {
140 print_proto(tb[CTA_TUPLE_PROTO]);
144 static int data_attr_cb(
const struct nlattr *attr,
void *data)
146 const struct nlattr **tb = data;
147 int type = mnl_attr_get_type(attr);
149 if (mnl_attr_type_valid(attr, CTA_MAX) < 0)
154 if (mnl_attr_validate(attr, MNL_TYPE_NESTED) < 0) {
155 perror(
"mnl_attr_validate");
162 if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0) {
163 perror(
"mnl_attr_validate");
172 static int data_cb(
const struct nlmsghdr *nlh,
void *data)
174 struct nlattr *tb[CTA_MAX+1] = {};
175 struct nfgenmsg *nfg = mnl_nlmsg_get_payload(nlh);
177 switch(nlh->nlmsg_type & 0xFF) {
178 case IPCTNL_MSG_CT_NEW:
179 if (nlh->nlmsg_flags & (NLM_F_CREATE|NLM_F_EXCL))
180 printf(
"%9s ",
"[NEW] ");
182 printf(
"%9s ",
"[UPDATE] ");
184 case IPCTNL_MSG_CT_DELETE:
185 printf(
"%9s ",
"[DESTROY] ");
189 mnl_attr_parse(nlh,
sizeof(*nfg), data_attr_cb, tb);
190 if (tb[CTA_TUPLE_ORIG]) {
191 print_tuple(tb[CTA_TUPLE_ORIG]);
194 printf(
"mark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_MARK])));
196 if (tb[CTA_SECMARK]) {
197 printf(
"secmark=%u ", ntohl(mnl_attr_get_u32(tb[CTA_SECMARK])));
206 char buf[MNL_SOCKET_BUFFER_SIZE];
209 nl = mnl_socket_open(NETLINK_NETFILTER);
211 perror(
"mnl_socket_open");
215 if (mnl_socket_bind(nl, NF_NETLINK_CONNTRACK_NEW |
216 NF_NETLINK_CONNTRACK_UPDATE |
217 NF_NETLINK_CONNTRACK_DESTROY,
218 MNL_SOCKET_AUTOPID) < 0) {
219 perror(
"mnl_socket_bind");
224 ret = mnl_socket_recvfrom(nl, buf,
sizeof(buf));
226 perror(
"mnl_socket_recvfrom");
230 ret = mnl_cb_run(buf, ret, 0, 0, data_cb, NULL);
232 perror(
"mnl_cb_run");
237 mnl_socket_close(nl);