#include <asm/types.h> #include <sys/types.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4/ip_queue.h> #include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <time.h> #include <signal.h>
static int done = 0;
void sigint(int signum) { done = 1; }
int main(int argc, char *argv[]) { int fd; struct sockaddr_nl a; size_t alen; struct sockaddr_nl ra; size_t ralen; struct nlmsghdr *h; struct ipq_mode_msg *m; struct ipq_packet_msg *p; struct ipq_verdict_msg *v; char dbuf[20]; unsigned char obuf[128]; unsigned char ibuf[128]; size_t nsent, nrecv; int seq = 0;
/* Create the socket */ fd = socket(AF_NETLINK, SOCK_DGRAM, NETLINK_FIREWALL); if (fd == -1) { perror("socket"); return EXIT_FAILURE; }
/* Bind local end of the socket to the pid of current process */
memset(&a, 0, sizeof(struct sockaddr_nl));
a.nl_family = AF_NETLINK;
a.nl_pid = getpid();
a.nl_groups = 0;
if (bind(fd, (struct sockaddr *)&a, sizeof(struct sockaddr_nl)) == -1) {
perror("bind");
return EXIT_FAILURE;
}
/* Remote end of the socket is in kernel */ memset(&a, 0, sizeof(struct sockaddr_nl)); a.nl_family = AF_NETLINK; a.nl_pid = 0; a.nl_groups = 0;
/* Send a mode message to register for packet messages */ h = (struct nlmsghdr *)obuf; h->nlmsg_type = IPQM_MODE; h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_mode_msg)); h->nlmsg_flags = 0; /* NLM_F_REQUEST; */ h->nlmsg_pid = getpid(); h->nlmsg_seq = seq++;
m = NLMSG_DATA(h); m->value = IPQ_COPY_META; m->range = 0;
nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0, (struct sockaddr *)&a, sizeof(struct sockaddr_nl)); if (nsent == -1) { perror("sendto(IPQM_MODE)"); return EXIT_FAILURE; }
/* we're ready to filter packets */ signal(SIGINT, sigint); while (!done) { alen = sizeof(struct sockaddr_nl); nrecv = recvfrom(fd, (void *)ibuf, 128, 0, (struct sockaddr *)&ra, &ralen); if (nrecv == -1) { perror("recvfrom(IPQM_PACKET)"); done = 1; continue; }
h = (struct nlmsghdr *)ibuf; p = NLMSG_DATA(h);
strftime(dbuf, 20, "%Y-%m-%d %H:%M:%S", localtime(&p->timestamp_sec));
printf(
"-----\n"
"remote_pid: %d\n"
"packet_id: %lu\n"
"mark: %lu\n"
"timestamp: %s.%06ld\n"
"hook: %u\n"
"indev: %s\n"
"outdev: %s\n"
"hw_protocol: %u\n"
"hw_type: %u\n"
"hw_addrlen: %u\n"
"hw_addr: %s\n"
"data_len: %u\n",
ra.nl_pid,
p->packet_id, p->mark,
dbuf, p->timestamp_usec,
p->hook, p->indev_name, p->outdev_name,
p->hw_protocol, p->hw_type, p->hw_addrlen, (char *)NULL,
p->data_len);
/* Sent ACCEPT verdict message */ h = (struct nlmsghdr *)obuf; h->nlmsg_type = IPQM_VERDICT; h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_verdict_msg)); h->nlmsg_flags = 0; /*NLM_F_REQUEST;*/ h->nlmsg_pid = getpid(); h->nlmsg_seq = seq++;
v = (struct ipq_verdict_msg *)NLMSG_DATA(h); v->value = NF_ACCEPT; v->id = p->packet_id;
nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0, (struct sockaddr *)&a, sizeof(struct sockaddr_nl)); if (nsent == -1) { perror("sendto(IPQM_VERDICT)"); done = 1; continue; } }
/* Send a mode message to unregister from packet messages */ h = (struct nlmsghdr *)obuf; h->nlmsg_type = IPQM_MODE; h->nlmsg_len = NLMSG_LENGTH(sizeof(struct ipq_mode_msg)); h->nlmsg_flags = NLM_F_REQUEST; h->nlmsg_pid = getpid(); h->nlmsg_seq = seq++;
m = NLMSG_DATA(h); m->value = IPQ_COPY_NONE; m->range = 0;
nsent = sendto(fd, (void *)obuf, h->nlmsg_len, 0, (struct sockaddr *)&a, sizeof(struct sockaddr_nl)); if (nsent == -1) { perror("sendto(IPQM_MODE)"); return EXIT_FAILURE; }
close(fd);
return 0; }