---
 include/linux/netfilter_ipv4/ipt_IFWLOG.h |   26 +++
 net/ipv4/netfilter/Kconfig                |   11 +
 net/ipv4/netfilter/Makefile               |    1 
 net/ipv4/netfilter/ipt_IFWLOG.c           |  200 ++++++++++++++++++++++++++++++
 4 files changed, 238 insertions(+)

--- /dev/null
+++ b/net/ipv4/netfilter/ipt_IFWLOG.c
@@ -0,0 +1,200 @@
+/* Interactive Firewall for Mandriva
+ * Samir Bellabes <sbellabes@mandriva.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <asm/types.h>
+#include <linux/jiffies.h>
+#include <linux/skbuff.h>
+#include <linux/ip.h>
+#include <net/icmp.h>
+#include <net/udp.h>
+#include <net/tcp.h>
+#include <net/sock.h>
+#include <linux/netlink.h>
+#include <linux/string.h>
+
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4/ip_tables.h>
+#include <linux/netfilter_ipv4/ipt_IFWLOG.h>
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Samir Bellabes <sbellabes@mandriva.com>");
+MODULE_DESCRIPTION("Interactive firewall logging and module");
+
+#if 0
+#define DEBUGP PRINTR
+#else
+#define DEBUGP(format, args...)
+#endif
+
+#define PRINTR(format, args...) do { if(net_ratelimit()) printk(format, ##args); } while(0)
+
+static struct sock *nl;
+
+#define GROUP 10
+
+/* send struct to userspace */
+static void send_packet(struct nl_msg msg)
+{
+	struct sk_buff *skb = NULL;
+	struct nlmsghdr *nlh;
+
+	skb = alloc_skb(NLMSG_SPACE(sizeof(struct nl_msg)), GFP_ATOMIC);
+	if (!skb) {
+		PRINTR(KERN_WARNING "IFWLOG: OOM can't allocate skb\n");
+		return ;
+	}
+
+	nlh = NLMSG_PUT(skb, 0, 0, 0, sizeof(struct nl_msg) - sizeof(*nlh));
+
+	memcpy(NLMSG_DATA(nlh), (const void*)&msg, sizeof(struct nl_msg));
+
+	NETLINK_CB(skb).pid = 0;  /* from kernel */
+	NETLINK_CB(skb).dst_pid = 0;  /* multicast */
+	NETLINK_CB(skb).dst_group = 10;
+
+	if (nl) {
+		DEBUGP(KERN_WARNING
+		       "IFWLOG: nlmsg_len=%ld\nnlmsg_type=%d nlmsg_flags=%d\nnlmsg_seq=%ld nlmsg_pid = %ld\n",
+		       (long)nlh->nlmsg_len,  nlh->nlmsg_type, nlh->nlmsg_flags,
+		       (long)nlh->nlmsg_seq, (long)nlh->nlmsg_pid);
+		DEBUGP(KERN_WARNING "prefix : %s\n", msg.prefix);
+
+		netlink_broadcast(nl, skb, 0, 10, GFP_ATOMIC);
+		return ;
+	}
+
+ nlmsg_failure:
+        if (skb)
+                kfree_skb(skb);
+        PRINTR(KERN_WARNING "IFWLOG: Error sending netlink packet\n");
+        return ;
+}
+
+/* fill struct for userspace */
+static void ipt_IFWLOG_packet(const struct sk_buff *skb,
+			      const struct net_device *in,
+			      const struct net_device *out,
+			      const struct ipt_IFWLOG_info *info)
+{
+	struct iphdr iph;
+	struct tcphdr tcph;
+	struct udphdr udph;
+	struct nl_msg msg;
+	struct iphdr _iph, *ih;
+	struct timeval tv;
+
+	memset(&msg, 0, sizeof(struct nl_msg));
+
+	ih = skb_header_pointer(skb, 0, sizeof(_iph), &_iph);
+	if (ih == NULL) {
+		PRINTR(KERN_WARNING "IFWLOG: skb truncated");
+		return;
+	}
+
+	/* save interface name */
+	if (in)
+		strcpy(msg.indev_name, in->name);
+	if (out)
+		strcpy(msg.outdev_name, out->name);
+
+	/* save log-prefix */
+	strcpy(msg.prefix, info->prefix);
+
+	/* save ip header */
+	skb_copy_bits(skb, 0, &iph, sizeof(iph));
+	memcpy(&msg.ip, &iph, sizeof(struct iphdr));
+
+	/* save transport header */
+	switch (iph.protocol){
+	case IPPROTO_TCP:
+		skb_copy_bits(skb, iph.ihl*4 , &tcph, sizeof(tcph));
+		memcpy(&msg.h.th, &tcph, sizeof(struct tcphdr));
+		break;
+	case IPPROTO_UDP:
+		skb_copy_bits(skb, iph.ihl*4 , &udph, sizeof(udph));
+		memcpy(&msg.h.uh, &udph, sizeof(struct udphdr));
+		break;
+	default:
+		break;
+	}
+
+	/* save timetamp */
+	do_gettimeofday((struct timeval *)&tv);
+        msg.timestamp_sec = tv.tv_sec;
+
+	send_packet(msg);
+}
+
+static unsigned int ipt_IFWLOG_target(struct sk_buff **pskb,
+				      const struct net_device *in,
+				      const struct net_device *out,
+				      unsigned int hooknum,
+				      const void *targinfo,
+				      void *userinfo)
+{
+	const struct ipt_IFWLOG_info *info = targinfo;
+
+	ipt_IFWLOG_packet(*pskb, in, out, info);
+
+	return IPT_CONTINUE;
+}
+
+static int ipt_IFWLOG_checkentry(const char *tablename,
+				 const struct ipt_entry *e,
+				 void *targinfo,
+				 unsigned int targinfosize,
+				 unsigned int hook_mask)
+{
+	const struct ipt_IFWLOG_info *info = targinfo;
+
+	if (info->prefix[sizeof(info->prefix)-1] != '\0') {
+		DEBUGP("IFWLOG: prefix term %i\n",
+		       info->prefix[sizeof(info->prefix)-1]);
+		return 0;
+	}
+
+	return 1;
+}
+
+static struct ipt_target ipt_IFWLOG = {
+	.name		= "IFWLOG",
+	.target		= ipt_IFWLOG_target,
+	.targetsize	= sizeof(struct ipt_IFWLOG_info),
+	.checkentry	= ipt_IFWLOG_checkentry,
+	.me		= THIS_MODULE,
+};
+
+static int __init init(void)
+{
+	nl = (struct sock*) netlink_kernel_create(NETLINK_IFWLOG, GROUP, NULL, THIS_MODULE);
+        if (!nl) {
+                PRINTR(KERN_WARNING "IFWLOG: cannot create netlink socket\n");
+                return -EINVAL;
+        }
+
+	if (ipt_register_target(&ipt_IFWLOG)) {
+		if (nl && nl->sk_socket)
+			sock_release(nl->sk_socket);
+		return -EINVAL;
+	}
+
+	PRINTR(KERN_INFO "IFWLOG: register target\n");
+	return 0;
+}
+
+static void __exit fini(void)
+{
+	if (nl && nl->sk_socket)
+                sock_release(nl->sk_socket);
+	PRINTR(KERN_INFO "IFWLOG: unregister target\n");
+	ipt_unregister_target(&ipt_IFWLOG);
+}
+
+module_init(init);
+module_exit(fini);
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -331,6 +331,17 @@ config IP_NF_TARGET_TTL
 	(e.g. when running oldconfig). It selects
 	CONFIG_NETFILTER_XT_TARGET_HL.
 
+config IP_NF_TARGET_IFWLOG
+	tristate  'IFWLOG target support'
+	depends on IP_NF_IPTABLES
+	help
+	  This option adds a `IFWLOG' target, which is used by
+	  Interactive Firewall for sending informations to a userspace
+	  daemon
+
+	  If you want to compile it as a module, say M here and read
+	  Documentation/modules.txt.  If unsure, say `N'.
+
 # raw + specific targets
 config IP_NF_RAW
 	tristate  'raw table support (required for NOTRACK/TRACE)'
--- /dev/null
+++ b/include/linux/netfilter_ipv4/ipt_IFWLOG.h
@@ -0,0 +1,26 @@
+#ifndef _IPT_IFWLOG_H
+#define _IPT_IFWLOG_H
+
+#ifndef NETLINK_IFWLOG
+#define NETLINK_IFWLOG  19
+#endif
+
+#define PREFSIZ         32
+
+struct nl_msg {				/* Netlink message */
+	long timestamp_sec;             /* time packet */
+	char indev_name[IFNAMSIZ];      /* name of the ingoing interface */
+	char outdev_name[IFNAMSIZ];     /* name of the outgoing interface */
+	unsigned char prefix[PREFSIZ];  /* informations on the logging reason */
+	struct iphdr ip;
+	union {
+		struct tcphdr th;
+		struct udphdr uh;
+	} h;
+};
+
+struct ipt_IFWLOG_info {
+	char prefix[PREFSIZ];
+};
+
+#endif /* _IPT_IFWLOG_H */
--- linux/net/ipv4/netfilter/Makefile.net-netfilter-IFWLOG.orig	2013-10-13 11:29:08.799136037 +0300
+++ linux/net/ipv4/netfilter/Makefile	2013-10-13 11:30:28.085842333 +0300
@@ -44,6 +44,7 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ip
 # targets
 obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o
 obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o
+obj-$(CONFIG_IP_NF_TARGET_IFWLOG) += ipt_IFWLOG.o
 obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o
 obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o
 obj-$(CONFIG_IP_NF_TARGET_SYNPROXY) += ipt_SYNPROXY.o
