/*
 * This code is GPL.
 * 2012-11-17 (1391-08-27)
 *
 * Compile : gcc libipq-pipe.c -o libipq-pipe -lipq
 *
 */

#include <netinet/in.h>
#include <linux/netfilter.h>
#include <libipq.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define BUFSIZE 65536

static void die(struct ipq_handle *h)
{
	ipq_perror("passer");
	ipq_destroy_handle(h);
	exit(1);
}

void show_buffer(unsigned char *buf, int len)
{
	int i;

	/* Show packet length at first 5 characters */
	fprintf(stdout, "%05d", len);

	/* Show packet payload */
	for (i = 0; i < len; i++) {
		fprintf(stdout, "%c", buf[i]);
		fflush(stdout);
	}
	fflush(stdout);
}

int main()
{
	int status;
	unsigned char buf[BUFSIZE];
	struct ipq_handle *h;
	size_t pack_len;

	/*
	 * Initialisation:
	 * IPV4 protocol only
	 */
	h = ipq_create_handle(0, NFPROTO_IPV4);
	if (!h)
		die(h);

	/*
	 * Setting the Queue Mode:
	 * Get packet metadata and packet payloads
	 */
	status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
	if (status < 0)
		die(h);

	/* Receiving Packets from the Queue */
	do {
		status = ipq_read(h, buf, BUFSIZE, 0);
		if (status < 0)
			die(h);

		switch (ipq_message_type(buf)) {
		case NLMSG_ERROR:
			fprintf(stderr, "Received error message %d\n",
				ipq_get_msgerr(buf));
			break;
		case IPQM_PACKET:{
				ipq_packet_msg_t *m = ipq_get_packet(buf);

				/* get packet length */
				pack_len = m->data_len;

				/* Show packet */
				show_buffer(m->payload, pack_len);

				/* Drop original packet in netfilter */
				status =
				    ipq_set_verdict(h, m->packet_id, NF_DROP, 0,
						    NULL);
				if (status < 0)
					die(h);

				break;
			}
		default:
			fprintf(stderr, "Unknown message type!\n");
			break;
		}
	} while (1);

	ipq_destroy_handle(h);
	return 0;
}