Correct PPTP server firewall rules chain.
[tomato/davidwu.git] / release / src / router / ebtables / examples / ulog / test_ulog.c
blobfbbd909baf8dd8f371056734d336206112a3eabd
2 /*
3 * Simple example program to log packets received with the ulog
4 * watcher of ebtables.
6 * usage:
7 * Add the appropriate ebtables ulog rule, e.g. (0 < NLGROUP < 33):
8 * ebtables -A FORWARD --ulog-nlgroup NLGROUP
9 * Start this application somewhere:
10 * test_ulog NLGROUP
12 * compile with make test_ulog KERNEL_INCLUDES=<path_to_kernel_include_dir>
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 * General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
30 #include <asm/types.h>
31 #include <sys/socket.h>
32 #include <sys/time.h>
33 #include <time.h>
34 #include <linux/netlink.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <netdb.h>
39 #include <errno.h>
40 #include <netinet/if_ether.h>
41 #include <netinet/ether.h>
42 #include <netinet/ip.h>
43 #include <netinet/ip_icmp.h>
44 #include "../../include/ebtables_u.h"
45 #include "../../include/ethernetdb.h"
46 #include <linux/netfilter_bridge/ebt_ulog.h>
48 /* <linux/if_vlan.h> doesn't hand this to userspace :-( */
49 #define VLAN_HLEN 4
50 struct vlan_hdr {
51 unsigned short TCI;
52 unsigned short encap;
55 static struct sockaddr_nl sa_local =
57 .nl_family = AF_NETLINK,
58 .nl_groups = 1,
61 static struct sockaddr_nl sa_kernel =
63 .nl_family = AF_NETLINK,
64 .nl_pid = 0,
65 .nl_groups = 1,
68 static const char *hookstr[NF_BR_NUMHOOKS] =
70 [NF_BR_POST_ROUTING] "POSTROUTING",
71 [NF_BR_PRE_ROUTING] "PREROUTING",
72 [NF_BR_LOCAL_OUT] "OUTPUT",
73 [NF_BR_LOCAL_IN] "INPUT",
74 [NF_BR_BROUTING] "BROUTING",
75 [NF_BR_FORWARD] "FORWARD"
78 #define DEBUG_QUEUE 0
79 #define BUFLEN 65536
80 static char buf[BUFLEN];
81 static int sfd;
83 /* Get the next ebt_ulog packet, talk to the kernel if necessary */
84 ebt_ulog_packet_msg_t *ulog_get_packet()
86 static struct nlmsghdr *nlh = NULL;
87 static int len, remain_len;
88 static int pkts_per_msg = 0;
89 ebt_ulog_packet_msg_t *msg;
90 socklen_t addrlen = sizeof(sa_kernel);
92 if (!nlh) {
93 recv_new:
94 if (pkts_per_msg && DEBUG_QUEUE)
95 printf("PACKETS IN LAST MSG: %d\n", pkts_per_msg);
96 pkts_per_msg = 0;
97 len = recvfrom(sfd, buf, BUFLEN, 0,
98 (struct sockaddr *)&sa_kernel, &addrlen);
99 if (addrlen != sizeof(sa_kernel)) {
100 printf("addrlen %u != %u\n", addrlen,
101 (uint32_t)sizeof(sa_kernel));
102 exit(-1);
104 if (len == -1) {
105 perror("recvmsg");
106 if (errno == EINTR)
107 goto recv_new;
108 exit(-1);
110 nlh = (struct nlmsghdr *)buf;
111 if (nlh->nlmsg_flags & MSG_TRUNC || len > BUFLEN) {
112 printf("Packet truncated");
113 exit(-1);
115 if (!NLMSG_OK(nlh, BUFLEN)) {
116 perror("Netlink message parse error\n");
117 return NULL;
121 msg = NLMSG_DATA(nlh);
123 remain_len = (len - ((char *)nlh - buf));
124 if (nlh->nlmsg_flags & NLM_F_MULTI && nlh->nlmsg_type != NLMSG_DONE)
125 nlh = NLMSG_NEXT(nlh, remain_len);
126 else
127 nlh = NULL;
129 pkts_per_msg++;
130 return msg;
133 int main(int argc, char **argv)
135 int i, curr_len, pktcnt = 0;
136 int rcvbufsize = BUFLEN;
137 ebt_ulog_packet_msg_t *msg;
138 struct ethhdr *ehdr;
139 struct ethertypeent *etype;
140 struct protoent *prototype;
141 struct iphdr *iph;
142 struct icmphdr *icmph;
143 struct tm* ptm;
144 char time_str[40], *ctmp;
146 if (argc == 2) {
147 i = strtoul(argv[1], &ctmp, 10);
148 if (*ctmp != '\0' || i < 1 || i > 32) {
149 printf("Usage: %s <group number>\nWith 0 < group "
150 "number < 33\n", argv[0]);
151 exit(0);
153 sa_local.nl_groups = sa_kernel.nl_groups = 1 << (i - 1);
156 sa_local.nl_pid = getpid();
157 sfd = socket(PF_NETLINK, SOCK_RAW, NETLINK_NFLOG);
158 if (!sfd) {
159 perror("socket");
160 exit(-1);
163 if (bind(sfd, (struct sockaddr *)(&sa_local), sizeof(sa_local)) ==
164 -1) {
165 perror("bind");
166 exit(-1);
168 i = setsockopt(sfd, SOL_SOCKET, SO_RCVBUF, &rcvbufsize,
169 sizeof(rcvbufsize));
171 while (1) {
172 if (!(msg = ulog_get_packet()))
173 continue;
175 if (msg->version != EBT_ULOG_VERSION) {
176 printf("WRONG VERSION: %d INSTEAD OF %d\n",
177 msg->version, EBT_ULOG_VERSION);
178 continue;
180 printf("PACKET NR: %d\n", ++pktcnt);
181 iph = NULL;
182 curr_len = ETH_HLEN;
184 printf("INDEV=%s\nOUTDEV=%s\nPHYSINDEV=%s\nPHYSOUTDEV=%s\n"
185 "PREFIX='%s'", msg->indev, msg->outdev, msg->physindev,
186 msg->physoutdev, msg->prefix);
188 ptm = localtime(&msg->stamp.tv_sec);
189 strftime (time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", ptm);
190 printf("\nARRIVAL TIME: %s\nMARK=%lu\nHOOK=%s\n", time_str,
191 msg->mark, hookstr[msg->hook]);
193 if (msg->data_len < curr_len) {
194 printf("====>Packet smaller than Ethernet header "
195 "length<====\n");
196 goto letscontinue;
199 printf("::::::::ETHERNET:HEADER::::::::\n");
201 ehdr = (struct ethhdr *)msg->data;
202 printf("MAC SRC=%s\n", ether_ntoa((const struct ether_addr *)
203 ehdr->h_source));
204 printf("MAC DST=%s\nETHERNET PROTOCOL=", ether_ntoa(
205 (const struct ether_addr *)ehdr->h_dest));
206 etype = getethertypebynumber(ntohs(ehdr->h_proto));
207 if (!etype)
208 printf("0x%x\n", ntohs(ehdr->h_proto));
209 else
210 printf("%s\n", etype->e_name);
212 if (ehdr->h_proto == htons(ETH_P_8021Q)) {
213 struct vlan_hdr *vlanh = (struct vlan_hdr *)
214 (((char *)ehdr) + curr_len);
215 printf("::::::::::VLAN:HEADER::::::::::\n");
216 curr_len += VLAN_HLEN;
217 if (msg->data_len < curr_len) {
218 printf("====>Packet only contains partial "
219 "VLAN header<====\n");
220 goto letscontinue;
223 printf("VLAN TCI=%d\n", ntohs(vlanh->TCI));
224 printf("VLAN ENCAPS PROTOCOL=");
225 etype = getethertypebynumber(ntohs(vlanh->encap));
226 if (!etype)
227 printf("0x%x\n", ntohs(vlanh->encap));
228 else
229 printf("%s\n", etype->e_name);
230 if (ehdr->h_proto == htons(ETH_P_IP))
231 iph = (struct iphdr *)(vlanh + 1);
232 } else if (ehdr->h_proto == htons(ETH_P_IP))
233 iph = (struct iphdr *)(((char *)ehdr) + curr_len);
234 if (!iph)
235 goto letscontinue;
237 curr_len += sizeof(struct iphdr);
238 if (msg->data_len < curr_len || msg->data_len <
239 (curr_len += iph->ihl * 4 - sizeof(struct iphdr))) {
240 printf("====>Packet only contains partial IP "
241 "header<====\n");
242 goto letscontinue;
245 printf(":::::::::::IP:HEADER:::::::::::\n");
246 printf("IP SRC ADDR=");
247 for (i = 0; i < 4; i++)
248 printf("%d%s", ((unsigned char *)&iph->saddr)[i],
249 (i == 3) ? "" : ".");
250 printf("\nIP DEST ADDR=");
251 for (i = 0; i < 4; i++)
252 printf("%d%s", ((unsigned char *)&iph->daddr)[i],
253 (i == 3) ? "" : ".");
254 printf("\nIP PROTOCOL=");
255 if (!(prototype = getprotobynumber(iph->protocol)))
256 printf("%d\n", iph->protocol);
257 else
258 printf("%s\n", prototype->p_name);
260 if (iph->protocol != IPPROTO_ICMP)
261 goto letscontinue;
263 icmph = (struct icmphdr *)(((char *)ehdr) + curr_len);
264 curr_len += 4;
265 if (msg->data_len < curr_len) {
266 truncated_icmp:
267 printf("====>Packet only contains partial ICMP "
268 "header<====\n");
269 goto letscontinue;
271 if (icmph->type != ICMP_ECHO && icmph->type != ICMP_ECHOREPLY)
272 goto letscontinue;
274 curr_len += 4;
275 if (msg->data_len < curr_len)
276 goto truncated_icmp;
277 /* Normally the process id, it's sent out in machine
278 * byte order */
280 printf("ICMP_ECHO IDENTIFIER=%u\n", icmph->un.echo.id);
281 printf("ICMP_ECHO SEQ NR=%u\n", ntohs(icmph->un.echo.sequence));
283 letscontinue:
284 printf("===>Total Packet length: %ld, of which we examined "
285 "%d bytes\n", msg->data_len, curr_len);
286 printf("###############################\n"
287 "######END#OF##PACKET#DUMP######\n"
288 "###############################\n");
291 return 0;