4 #include <sys/socket.h>
6 #include <sys/socket.h>
7 #include <netinet/in.h>
11 #include <linux/types.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter/nfnetlink.h>
15 #include "libctnetlink.h"
17 static struct ctnl_handle *cth;
19 char *display_tuple_flat(struct ip_conntrack_tuple *tuple)
21 static char buff[250];
25 memset(buff, '\0', sizeof(buff));
26 len += sprintf(buff + len, "%s:", inet_ntoa((struct in_addr){tuple->src.ip}));
27 switch(tuple->dst.protonum) {
29 len += sprintf(buff + len, "Icmp (id %d)",
30 ntohs(tuple->src.u.icmp.id));
33 sprintf(psb, "%d", ntohs(tuple->src.u.tcp.port));
34 len += sprintf(buff + len, "%s", psb);
37 sprintf(psb, "%d", ntohs(tuple->src.u.udp.port));
38 len += sprintf(buff + len, "%s", psb);
41 len += sprintf(buff + len, "Unknown");
45 len += sprintf(buff + len, "->");
46 len += sprintf(buff + len, "%s:", inet_ntoa((struct in_addr){tuple->dst.ip}));
47 switch(tuple->dst.protonum) {
49 len += sprintf(buff + len, "Icmp (%d, code %d)",
50 tuple->dst.u.icmp.type,
51 tuple->dst.u.icmp.code);
54 sprintf(psb, "%d", ntohs(tuple->dst.u.tcp.port));
55 len += sprintf(buff + len, "%s", psb);
58 sprintf(psb, "%d", ntohs(tuple->dst.u.udp.port));
59 len += sprintf(buff + len, "%s", psb);
62 len += sprintf(buff + len, "Unknown");
69 int ctnl_parse_attr(struct nfattr *tb[], int max, struct nfattr *cta, int len)
71 while(NFA_OK(cta, len)) {
72 if(cta->nfa_type <= max)
73 tb[cta->nfa_type] = cta;
74 cta = NFA_NEXT(cta,len);
77 printf("ctnl_parse_attr: deficit (%d) len (%d).\n",
87 struct nfgenmsg nfmsg;
89 struct sockaddr_nl nladdr;
91 memset(&nladdr, 0, sizeof(nladdr));
92 nladdr.nl_family = AF_NETLINK;
94 req.nlh.nlmsg_len = sizeof(req);
95 req.nlh.nlmsg_type = (NFNL_SUBSYS_CTNETLINK << 8)|CTNL_MSG_CT_GET;
96 req.nlh.nlmsg_flags = NLM_F_ROOT|NLM_F_DUMP|NLM_F_REQUEST;
97 req.nlh.nlmsg_pid = 0;
98 req.nlh.nlmsg_seq = 1;
99 req.nfmsg.nfgen_family = AF_INET;
101 return (sendto(ctnlfd, &req, sizeof(req), 0,
102 (struct sockaddr *) &nladdr, sizeof(nladdr)));
107 int print_msg(struct nfgenmsg *cm, size_t len)
109 struct nfattr *cb[CTA_MAX + 1];
111 printf("ctm_family=0x%x\n", cm->nfgen_family);
113 ctnl_parse_attr(cb, CTA_MAX, NFM_NFA(cm), len);
117 display_tuple_flat(NFA_DATA(cb[CTA_ORIG])));
118 ctnl_del_conntrack(cth, NFA_DATA(cb[CTA_ORIG]), CTA_ORIG);
122 display_tuple_flat(NFA_DATA(cb[CTA_RPLY])));
128 struct nlmsghdr *ctnl_get_packet(struct nlmsghdr **last_nlhdr,
129 char *buf, size_t len)
131 struct nlmsghdr *nlh;
134 if ((char *)(*last_nlhdr) > (buf + len) ||
135 (char *)(*last_nlhdr) < buf)
139 nlh = (struct nlmsghdr *) buf;
140 if (!NLMSG_OK(nlh, len)) {
141 printf("error parsing nlmsg\n");
145 /* we are n-th part of multipart mesasge */
146 if ((*last_nlhdr)->nlmsg_type == NLMSG_DONE ||
147 !((*last_nlhdr)->nlmsg_flags & NLM_F_MULTI)) {
152 remain_len = (len - ((char *)(*last_nlhdr) - buf));
153 nlh = NLMSG_NEXT(*last_nlhdr, remain_len);
160 int main(int argc, char **argv)
163 struct nfgenmsg *last_cm = NULL, *cm;
164 struct nlmsghdr *nlh;
167 cth = malloc(sizeof(*cth));
168 if (ctnl_open(cth, 0) < 0) {
172 ctnl_wilddump_request(cth, AF_INET, IPCTNL_MSG_CT_GET);
174 while (len = recv(cth->nfnlh.fd, &buf, sizeof(buf), 0)) {
175 printf("pkt received\n");
176 while (nlh = ctnl_get_packet(&last_cm, (char *)&buf, len)) {
177 printf(" decoding msg type 0x%04x\n", nlh->nlmsg_type);
178 if (NFNL_SUBSYS_ID(nlh->nlmsg_type) ==
179 NFNL_SUBSYS_CTNETLINK) {
180 cm = NLMSG_DATA(nlh);
181 print_msg(cm, nlh->nlmsg_len);