add (incomplete) support for libipq emulation API
[platform/upstream/libnetfilter_queue.git] / utils / ctnltest.c
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/socket.h>
5
6        #include <sys/socket.h>
7        #include <netinet/in.h>
8        #include <arpa/inet.h>
9
10
11 #include <linux/types.h>
12 #include <linux/netlink.h>
13 #include <linux/netfilter/nfnetlink.h>
14
15 #include "libctnetlink.h"
16
17 static struct ctnl_handle *cth;
18
19 char *display_tuple_flat(struct ip_conntrack_tuple *tuple)
20 {
21         static char buff[250];
22         char psb[20];
23         int len = 0;
24
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) {
28                 case (IPPROTO_ICMP):
29                         len += sprintf(buff + len, "Icmp (id %d)",
30                                 ntohs(tuple->src.u.icmp.id));
31                         break;
32                 case (IPPROTO_TCP):
33                         sprintf(psb, "%d", ntohs(tuple->src.u.tcp.port));
34                         len += sprintf(buff + len, "%s", psb);
35                         break;
36                 case (IPPROTO_UDP):
37                         sprintf(psb, "%d", ntohs(tuple->src.u.udp.port));
38                         len += sprintf(buff + len, "%s", psb);
39                         break;
40                 default:
41                         len += sprintf(buff + len, "Unknown");
42                         break;
43         }
44
45         len += sprintf(buff + len, "->");
46         len += sprintf(buff + len, "%s:", inet_ntoa((struct in_addr){tuple->dst.ip}));
47         switch(tuple->dst.protonum) {
48                 case (IPPROTO_ICMP):
49                         len += sprintf(buff + len, "Icmp (%d, code %d)",
50                                 tuple->dst.u.icmp.type,
51                                 tuple->dst.u.icmp.code);
52                         break;
53                 case (IPPROTO_TCP):
54                         sprintf(psb, "%d", ntohs(tuple->dst.u.tcp.port));
55                         len += sprintf(buff + len, "%s", psb);
56                         break;
57                 case (IPPROTO_UDP):
58                         sprintf(psb, "%d", ntohs(tuple->dst.u.udp.port));
59                         len += sprintf(buff + len, "%s", psb);
60                         break;
61                 default:
62                         len += sprintf(buff + len, "Unknown");
63                         break;
64         }
65
66         return (buff);
67 }
68
69 int ctnl_parse_attr(struct nfattr *tb[], int max, struct nfattr *cta, int len)
70 {
71         while(NFA_OK(cta, len)) {
72                 if(cta->nfa_type <= max)
73                         tb[cta->nfa_type] = cta;
74                 cta = NFA_NEXT(cta,len);
75         }
76         if (len)
77                 printf("ctnl_parse_attr: deficit (%d) len (%d).\n",
78                         len, cta->nfa_len);
79         return 0;
80 }
81
82 #if 0
83 int dump()
84 {
85         struct {
86                 struct nlmsghdr nlh;
87                 struct nfgenmsg nfmsg;
88         } req;
89         struct sockaddr_nl nladdr;
90
91         memset(&nladdr, 0, sizeof(nladdr));
92         nladdr.nl_family = AF_NETLINK;
93
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;
100
101         return (sendto(ctnlfd, &req, sizeof(req), 0,
102                         (struct sockaddr *) &nladdr, sizeof(nladdr)));
103
104 }
105 #endif
106
107 int print_msg(struct nfgenmsg *cm, size_t len)
108 {
109         struct nfattr *cb[CTA_MAX + 1];
110
111         printf("ctm_family=0x%x\n", cm->nfgen_family);
112
113         ctnl_parse_attr(cb, CTA_MAX, NFM_NFA(cm), len);
114
115         if (cb[CTA_ORIG]) {
116                 printf("orig: %s\n", 
117                                 display_tuple_flat(NFA_DATA(cb[CTA_ORIG])));
118                 ctnl_del_conntrack(cth, NFA_DATA(cb[CTA_ORIG]), CTA_ORIG);
119         }
120         if (cb[CTA_RPLY])
121                 printf("rply: %s\n", 
122                                 display_tuple_flat(NFA_DATA(cb[CTA_RPLY])));
123
124
125         return 0;
126 }
127
128 struct nlmsghdr *ctnl_get_packet(struct nlmsghdr **last_nlhdr, 
129                               char *buf, size_t len)
130 {
131         struct nlmsghdr *nlh;
132         size_t remain_len;
133
134         if ((char *)(*last_nlhdr) > (buf + len) ||
135             (char *)(*last_nlhdr) < buf)
136                 *last_nlhdr = NULL;
137
138         if (!*last_nlhdr) {
139                 nlh = (struct nlmsghdr *) buf;
140                 if (!NLMSG_OK(nlh, len)) {
141                         printf("error parsing nlmsg\n");
142                         return NULL;
143                 }
144         } else {
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)) {
148                         *last_nlhdr = NULL;
149                         return NULL;
150                 }
151
152                 remain_len = (len - ((char *)(*last_nlhdr) - buf));
153                 nlh = NLMSG_NEXT(*last_nlhdr, remain_len);
154         }
155
156         *last_nlhdr = nlh;
157         return nlh;
158 }
159
160 int main(int argc, char **argv)
161 {
162         char buf[20480];
163         struct nfgenmsg *last_cm = NULL, *cm;
164         struct nlmsghdr *nlh;
165         int len;
166
167         cth = malloc(sizeof(*cth));
168         if (ctnl_open(cth, 0) < 0) {
169                 exit(2);
170         }
171
172         ctnl_wilddump_request(cth, AF_INET, IPCTNL_MSG_CT_GET);
173
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);
182                         }
183                 }
184         }
185
186         return 0;
187 }
188