|
Packit |
c43939 |
|
|
Packit |
c43939 |
#include <stdio.h>
|
|
Packit |
c43939 |
#include <stdlib.h>
|
|
Packit |
c43939 |
#include <unistd.h>
|
|
Packit |
c43939 |
#include <netinet/in.h>
|
|
Packit |
c43939 |
#include <linux/types.h>
|
|
Packit |
c43939 |
#include <linux/netfilter.h> /* for NF_ACCEPT */
|
|
Packit |
c43939 |
#include <errno.h>
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
#include <libnetfilter_queue/libnetfilter_queue.h>
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
/* returns packet id */
|
|
Packit |
c43939 |
static uint32_t print_pkt (struct nfq_data *tb)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
int id = 0;
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hdr *ph;
|
|
Packit |
c43939 |
struct nfqnl_msg_packet_hw *hwph;
|
|
Packit |
c43939 |
uint32_t mark, ifi, uid, gid;
|
|
Packit |
c43939 |
int ret;
|
|
Packit |
c43939 |
unsigned char *data, *secdata;
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ph = nfq_get_msg_packet_hdr(tb);
|
|
Packit |
c43939 |
if (ph) {
|
|
Packit |
c43939 |
id = ntohl(ph->packet_id);
|
|
Packit |
c43939 |
printf("hw_protocol=0x%04x hook=%u id=%u ",
|
|
Packit |
c43939 |
ntohs(ph->hw_protocol), ph->hook, id);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
hwph = nfq_get_packet_hw(tb);
|
|
Packit |
c43939 |
if (hwph) {
|
|
Packit |
c43939 |
int i, hlen = ntohs(hwph->hw_addrlen);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("hw_src_addr=");
|
|
Packit |
c43939 |
for (i = 0; i < hlen-1; i++)
|
|
Packit |
c43939 |
printf("%02x:", hwph->hw_addr[i]);
|
|
Packit |
c43939 |
printf("%02x ", hwph->hw_addr[hlen-1]);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
mark = nfq_get_nfmark(tb);
|
|
Packit |
c43939 |
if (mark)
|
|
Packit |
c43939 |
printf("mark=%u ", mark);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_indev(tb);
|
|
Packit |
c43939 |
if (ifi)
|
|
Packit |
c43939 |
printf("indev=%u ", ifi);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_outdev(tb);
|
|
Packit |
c43939 |
if (ifi)
|
|
Packit |
c43939 |
printf("outdev=%u ", ifi);
|
|
Packit |
c43939 |
ifi = nfq_get_physindev(tb);
|
|
Packit |
c43939 |
if (ifi)
|
|
Packit |
c43939 |
printf("physindev=%u ", ifi);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ifi = nfq_get_physoutdev(tb);
|
|
Packit |
c43939 |
if (ifi)
|
|
Packit |
c43939 |
printf("physoutdev=%u ", ifi);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (nfq_get_uid(tb, &uid))
|
|
Packit |
c43939 |
printf("uid=%u ", uid);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (nfq_get_gid(tb, &gid))
|
|
Packit |
c43939 |
printf("gid=%u ", gid);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ret = nfq_get_secctx(tb, &secdata);
|
|
Packit |
c43939 |
if (ret > 0)
|
|
Packit |
c43939 |
printf("secctx=\"%.*s\" ", ret, secdata);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
ret = nfq_get_payload(tb, &data);
|
|
Packit |
c43939 |
if (ret >= 0)
|
|
Packit |
c43939 |
printf("payload_len=%d ", ret);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
fputc('\n', stdout);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
return id;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,
|
|
Packit |
c43939 |
struct nfq_data *nfa, void *data)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
uint32_t id = print_pkt(nfa);
|
|
Packit |
c43939 |
printf("entering callback\n");
|
|
Packit |
c43939 |
return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
int main(int argc, char **argv)
|
|
Packit |
c43939 |
{
|
|
Packit |
c43939 |
struct nfq_handle *h;
|
|
Packit |
c43939 |
struct nfq_q_handle *qh;
|
|
Packit |
c43939 |
int fd;
|
|
Packit |
c43939 |
int rv;
|
|
Packit |
c43939 |
uint32_t queue = 0;
|
|
Packit |
c43939 |
char buf[4096] __attribute__ ((aligned));
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
if (argc == 2) {
|
|
Packit |
c43939 |
queue = atoi(argv[1]);
|
|
Packit |
c43939 |
if (queue > 65535) {
|
|
Packit |
c43939 |
fprintf(stderr, "Usage: %s [<0-65535>]\n", argv[0]);
|
|
Packit |
c43939 |
exit(EXIT_FAILURE);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("opening library handle\n");
|
|
Packit |
c43939 |
h = nfq_open();
|
|
Packit |
c43939 |
if (!h) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_open()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
|
|
Packit |
c43939 |
if (nfq_unbind_pf(h, AF_INET) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_unbind_pf()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
|
|
Packit |
c43939 |
if (nfq_bind_pf(h, AF_INET) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_bind_pf()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("binding this socket to queue '%d'\n", queue);
|
|
Packit |
c43939 |
qh = nfq_create_queue(h, queue, &cb, NULL);
|
|
Packit |
c43939 |
if (!qh) {
|
|
Packit |
c43939 |
fprintf(stderr, "error during nfq_create_queue()\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("setting copy_packet mode\n");
|
|
Packit |
c43939 |
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
|
|
Packit |
c43939 |
fprintf(stderr, "can't set packet_copy mode\n");
|
|
Packit |
c43939 |
exit(1);
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("setting flags to request UID and GID\n");
|
|
Packit |
c43939 |
if (nfq_set_queue_flags(qh, NFQA_CFG_F_UID_GID, NFQA_CFG_F_UID_GID)) {
|
|
Packit |
c43939 |
fprintf(stderr, "This kernel version does not allow to "
|
|
Packit |
c43939 |
"retrieve process UID/GID.\n");
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("setting flags to request security context\n");
|
|
Packit |
c43939 |
if (nfq_set_queue_flags(qh, NFQA_CFG_F_SECCTX, NFQA_CFG_F_SECCTX)) {
|
|
Packit |
c43939 |
fprintf(stderr, "This kernel version does not allow to "
|
|
Packit |
c43939 |
"retrieve security context.\n");
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("Waiting for packets...\n");
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
fd = nfq_fd(h);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
for (;;) {
|
|
Packit |
c43939 |
if ((rv = recv(fd, buf, sizeof(buf), 0)) >= 0) {
|
|
Packit |
c43939 |
printf("pkt received\n");
|
|
Packit |
c43939 |
nfq_handle_packet(h, buf, rv);
|
|
Packit |
c43939 |
continue;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
/* if your application is too slow to digest the packets that
|
|
Packit |
c43939 |
* are sent from kernel-space, the socket buffer that we use
|
|
Packit |
c43939 |
* to enqueue packets may fill up returning ENOBUFS. Depending
|
|
Packit |
c43939 |
* on your application, this error may be ignored. Please, see
|
|
Packit |
c43939 |
* the doxygen documentation of this library on how to improve
|
|
Packit |
c43939 |
* this situation.
|
|
Packit |
c43939 |
*/
|
|
Packit |
c43939 |
if (rv < 0 && errno == ENOBUFS) {
|
|
Packit |
c43939 |
printf("losing packets!\n");
|
|
Packit |
c43939 |
continue;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
perror("recv failed");
|
|
Packit |
c43939 |
break;
|
|
Packit |
c43939 |
}
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("unbinding from queue 0\n");
|
|
Packit |
c43939 |
nfq_destroy_queue(qh);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
#ifdef INSANE
|
|
Packit |
c43939 |
/* normally, applications SHOULD NOT issue this command, since
|
|
Packit |
c43939 |
* it detaches other programs/sockets from AF_INET, too ! */
|
|
Packit |
c43939 |
printf("unbinding from AF_INET\n");
|
|
Packit |
c43939 |
nfq_unbind_pf(h, AF_INET);
|
|
Packit |
c43939 |
#endif
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
printf("closing library handle\n");
|
|
Packit |
c43939 |
nfq_close(h);
|
|
Packit |
c43939 |
|
|
Packit |
c43939 |
exit(0);
|
|
Packit |
c43939 |
}
|