--- 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 + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Samir Bellabes "); +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 2012-05-21 01:29:13.000000000 +0300 +++ linux/net/ipv4/netfilter/Makefile 2012-05-26 01:23:57.511514194 +0300 @@ -53,6 +53,7 @@ obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ip # targets obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o +obj-$(CONFIG_IP_NF_TARGET_IFWLOG) += ipt_IFWLOG.o obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o obj-$(CONFIG_IP_NF_TARGET_NETMAP) += ipt_NETMAP.o