Commit 62c12ea9 authored by Harald Welte's avatar Harald Welte Committed by Linus Torvalds

[NETFILTER]: Add nf_log handler, from Jozsef Kadlecsik.

parent f7e36893
...@@ -99,6 +99,24 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg); ...@@ -99,6 +99,24 @@ void nf_unregister_sockopt(struct nf_sockopt_ops *reg);
extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS]; extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
typedef void nf_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix);
/* Function to register/unregister log function. */
int nf_log_register(int pf, nf_logfn *logfn);
void nf_log_unregister(int pf, nf_logfn *logfn);
/* Calls the registered backend logging function */
void nf_log_packet(int pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *fmt, ...);
/* Activate hook; either okfn or kfree_skb called, unless a hook /* Activate hook; either okfn or kfree_skb called, unless a hook
returns NF_STOLEN (in which case, it's up to the hook to deal with returns NF_STOLEN (in which case, it's up to the hook to deal with
the consequences). the consequences).
......
...@@ -11,6 +11,9 @@ ...@@ -11,6 +11,9 @@
#define NETLINK_NFLOG 5 #define NETLINK_NFLOG 5
#endif #endif
#define ULOG_DEFAULT_NLGROUP 1
#define ULOG_DEFAULT_QTHRESHOLD 1
#define ULOG_MAC_LEN 80 #define ULOG_MAC_LEN 80
#define ULOG_PREFIX_LEN 32 #define ULOG_PREFIX_LEN 32
......
...@@ -8,8 +8,10 @@ ...@@ -8,8 +8,10 @@
* *
* February 2000: Modified by James Morris to have 1 queue per protocol. * February 2000: Modified by James Morris to have 1 queue per protocol.
* 15-Mar-2000: Added NF_REPEAT --RR. * 15-Mar-2000: Added NF_REPEAT --RR.
* 08-May-2003: Internal logging interface added by Jozsef Kadlecsik.
*/ */
#include <linux/config.h> #include <linux/config.h>
#include <linux/kernel.h>
#include <linux/netfilter.h> #include <linux/netfilter.h>
#include <net/protocol.h> #include <net/protocol.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -741,6 +743,72 @@ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len) ...@@ -741,6 +743,72 @@ int skb_ip_make_writable(struct sk_buff **pskb, unsigned int writable_len)
EXPORT_SYMBOL(skb_ip_make_writable); EXPORT_SYMBOL(skb_ip_make_writable);
#endif /*CONFIG_INET*/ #endif /*CONFIG_INET*/
/* Internal logging interface, which relies on the real
LOG target modules */
#define NF_LOG_PREFIXLEN 128
static nf_logfn *nf_logging[NPROTO]; /* = NULL */
static int reported = 0;
static spinlock_t nf_log_lock = SPIN_LOCK_UNLOCKED;
int nf_log_register(int pf, nf_logfn *logfn)
{
int ret = -EBUSY;
/* Any setup of logging members must be done before
* substituting pointer. */
smp_wmb();
spin_lock(&nf_log_lock);
if (!nf_logging[pf]) {
nf_logging[pf] = logfn;
ret = 0;
}
spin_unlock(&nf_log_lock);
return ret;
}
void nf_log_unregister(int pf, nf_logfn *logfn)
{
spin_lock(&nf_log_lock);
if (nf_logging[pf] == logfn)
nf_logging[pf] = NULL;
spin_unlock(&nf_log_lock);
/* Give time to concurrent readers. */
synchronize_net();
}
void nf_log_packet(int pf,
unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *fmt, ...)
{
va_list args;
char prefix[NF_LOG_PREFIXLEN];
nf_logfn *logfn;
rcu_read_lock();
logfn = nf_logging[pf];
if (logfn) {
va_start(args, fmt);
vsnprintf(prefix, sizeof(prefix), fmt, args);
va_end(args);
/* We must read logging before nf_logfn[pf] */
smp_read_barrier_depends();
logfn(hooknum, skb, in, out, prefix);
} else if (!reported) {
printk(KERN_WARNING "nf_log_packet: can\'t log yet, "
"no backend logging module loaded in!\n");
reported++;
}
rcu_read_unlock();
}
EXPORT_SYMBOL(nf_log_register);
EXPORT_SYMBOL(nf_log_unregister);
EXPORT_SYMBOL(nf_log_packet);
/* This does not belong here, but ipt_REJECT needs it if connection /* This does not belong here, but ipt_REJECT needs it if connection
tracking in use: without this, connection may not be in hash table, tracking in use: without this, connection may not be in hash table,
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
#include <net/tcp.h> #include <net/tcp.h>
#include <net/route.h> #include <net/route.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_LOG.h> #include <linux/netfilter_ipv4/ipt_LOG.h>
...@@ -26,6 +27,10 @@ MODULE_LICENSE("GPL"); ...@@ -26,6 +27,10 @@ MODULE_LICENSE("GPL");
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
MODULE_DESCRIPTION("iptables syslog logging module"); MODULE_DESCRIPTION("iptables syslog logging module");
static unsigned int nflog = 1;
MODULE_PARM(nflog, "i");
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
#if 0 #if 0
#define DEBUGP printk #define DEBUGP printk
#else #else
...@@ -324,28 +329,25 @@ static void dump_packet(const struct ipt_log_info *info, ...@@ -324,28 +329,25 @@ static void dump_packet(const struct ipt_log_info *info,
/* maxlen = 230+ 91 + 230 + 252 = 803 */ /* maxlen = 230+ 91 + 230 + 252 = 803 */
} }
static unsigned int static void
ipt_log_target(struct sk_buff **pskb, ipt_log_packet(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
unsigned int hooknum, const struct ipt_log_info *loginfo,
const void *targinfo, const char *level_string,
void *userinfo) const char *prefix)
{ {
const struct ipt_log_info *loginfo = targinfo;
char level_string[4] = "< >";
level_string[1] = '0' + (loginfo->level % 8);
spin_lock_bh(&log_lock); spin_lock_bh(&log_lock);
printk(level_string); printk(level_string);
printk("%sIN=%s OUT=%s ", printk("%sIN=%s OUT=%s ",
loginfo->prefix, prefix == NULL ? loginfo->prefix : prefix,
in ? in->name : "", in ? in->name : "",
out ? out->name : ""); out ? out->name : "");
#ifdef CONFIG_BRIDGE_NETFILTER #ifdef CONFIG_BRIDGE_NETFILTER
if ((*pskb)->nf_bridge) { if (skb->nf_bridge) {
struct net_device *physindev = (*pskb)->nf_bridge->physindev; struct net_device *physindev = skb->nf_bridge->physindev;
struct net_device *physoutdev = (*pskb)->nf_bridge->physoutdev; struct net_device *physoutdev = skb->nf_bridge->physoutdev;
if (physindev && in != physindev) if (physindev && in != physindev)
printk("PHYSIN=%s ", physindev->name); printk("PHYSIN=%s ", physindev->name);
...@@ -357,25 +359,56 @@ ipt_log_target(struct sk_buff **pskb, ...@@ -357,25 +359,56 @@ ipt_log_target(struct sk_buff **pskb,
if (in && !out) { if (in && !out) {
/* MAC logging for input chain only. */ /* MAC logging for input chain only. */
printk("MAC="); printk("MAC=");
if ((*pskb)->dev && (*pskb)->dev->hard_header_len if (skb->dev && skb->dev->hard_header_len
&& (*pskb)->mac.raw != (void*)(*pskb)->nh.iph) { && skb->mac.raw != (void*)skb->nh.iph) {
int i; int i;
unsigned char *p = (*pskb)->mac.raw; unsigned char *p = skb->mac.raw;
for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++) for (i = 0; i < skb->dev->hard_header_len; i++,p++)
printk("%02x%c", *p, printk("%02x%c", *p,
i==(*pskb)->dev->hard_header_len - 1 i==skb->dev->hard_header_len - 1
? ' ':':'); ? ' ':':');
} else } else
printk(" "); printk(" ");
} }
dump_packet(loginfo, *pskb, 0); dump_packet(loginfo, skb, 0);
printk("\n"); printk("\n");
spin_unlock_bh(&log_lock); spin_unlock_bh(&log_lock);
}
static unsigned int
ipt_log_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_log_info *loginfo = targinfo;
char level_string[4] = "< >";
level_string[1] = '0' + (loginfo->level % 8);
ipt_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
return IPT_CONTINUE; return IPT_CONTINUE;
} }
static void
ipt_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix)
{
struct ipt_log_info loginfo = {
.level = 0,
.logflags = IPT_LOG_MASK,
.prefix = ""
};
ipt_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
}
static int ipt_log_checkentry(const char *tablename, static int ipt_log_checkentry(const char *tablename,
const struct ipt_entry *e, const struct ipt_entry *e,
void *targinfo, void *targinfo,
...@@ -413,11 +446,18 @@ static struct ipt_target ipt_log_reg = { ...@@ -413,11 +446,18 @@ static struct ipt_target ipt_log_reg = {
static int __init init(void) static int __init init(void)
{ {
return ipt_register_target(&ipt_log_reg); if (ipt_register_target(&ipt_log_reg))
return -EINVAL;
if (nflog)
nf_log_register(PF_INET, &ipt_logfn);
return 0;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
if (nflog)
nf_log_unregister(PF_INET, &ipt_logfn);
ipt_unregister_target(&ipt_log_reg); ipt_unregister_target(&ipt_log_reg);
} }
......
...@@ -50,6 +50,7 @@ ...@@ -50,6 +50,7 @@
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4/ip_tables.h> #include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_ipv4/ipt_ULOG.h> #include <linux/netfilter_ipv4/ipt_ULOG.h>
#include <linux/netfilter_ipv4/lockhelp.h> #include <linux/netfilter_ipv4/lockhelp.h>
...@@ -80,6 +81,10 @@ static unsigned int flushtimeout = 10 * HZ; ...@@ -80,6 +81,10 @@ static unsigned int flushtimeout = 10 * HZ;
MODULE_PARM(flushtimeout, "i"); MODULE_PARM(flushtimeout, "i");
MODULE_PARM_DESC(flushtimeout, "buffer flush timeout"); MODULE_PARM_DESC(flushtimeout, "buffer flush timeout");
static unsigned int nflog = 1;
MODULE_PARM(nflog, "i");
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
/* global data structures */ /* global data structures */
typedef struct { typedef struct {
...@@ -157,17 +162,17 @@ struct sk_buff *ulog_alloc_skb(unsigned int size) ...@@ -157,17 +162,17 @@ struct sk_buff *ulog_alloc_skb(unsigned int size)
return skb; return skb;
} }
static unsigned int ipt_ulog_target(struct sk_buff **pskb, static void ipt_ulog_packet(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
unsigned int hooknum, const struct ipt_ulog_info *loginfo,
const void *targinfo, void *userinfo) const char *prefix)
{ {
ulog_buff_t *ub; ulog_buff_t *ub;
ulog_packet_msg_t *pm; ulog_packet_msg_t *pm;
size_t size, copy_len; size_t size, copy_len;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
/* ffs == find first bit set, necessary because userspace /* ffs == find first bit set, necessary because userspace
* is already shifting groupnumber, but we need unshifted. * is already shifting groupnumber, but we need unshifted.
...@@ -176,8 +181,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -176,8 +181,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
/* calculate the size of the skb needed */ /* calculate the size of the skb needed */
if ((loginfo->copy_range == 0) || if ((loginfo->copy_range == 0) ||
(loginfo->copy_range > (*pskb)->len)) { (loginfo->copy_range > skb->len)) {
copy_len = (*pskb)->len; copy_len = skb->len;
} else { } else {
copy_len = loginfo->copy_range; copy_len = loginfo->copy_range;
} }
...@@ -214,19 +219,21 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -214,19 +219,21 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
/* copy hook, prefix, timestamp, payload, etc. */ /* copy hook, prefix, timestamp, payload, etc. */
pm->data_len = copy_len; pm->data_len = copy_len;
pm->timestamp_sec = (*pskb)->stamp.tv_sec; pm->timestamp_sec = skb->stamp.tv_sec;
pm->timestamp_usec = (*pskb)->stamp.tv_usec; pm->timestamp_usec = skb->stamp.tv_usec;
pm->mark = (*pskb)->nfmark; pm->mark = skb->nfmark;
pm->hook = hooknum; pm->hook = hooknum;
if (loginfo->prefix[0] != '\0') if (prefix != NULL)
strncpy(pm->prefix, prefix, sizeof(pm->prefix));
else if (loginfo->prefix[0] != '\0')
strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix));
else else
*(pm->prefix) = '\0'; *(pm->prefix) = '\0';
if (in && in->hard_header_len > 0 if (in && in->hard_header_len > 0
&& (*pskb)->mac.raw != (void *) (*pskb)->nh.iph && skb->mac.raw != (void *) skb->nh.iph
&& in->hard_header_len <= ULOG_MAC_LEN) { && in->hard_header_len <= ULOG_MAC_LEN) {
memcpy(pm->mac, (*pskb)->mac.raw, in->hard_header_len); memcpy(pm->mac, skb->mac.raw, in->hard_header_len);
pm->mac_len = in->hard_header_len; pm->mac_len = in->hard_header_len;
} else } else
pm->mac_len = 0; pm->mac_len = 0;
...@@ -241,8 +248,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -241,8 +248,8 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
else else
pm->outdev_name[0] = '\0'; pm->outdev_name[0] = '\0';
/* copy_len <= (*pskb)->len, so can't fail. */ /* copy_len <= skb->len, so can't fail. */
if (skb_copy_bits(*pskb, 0, pm->payload, copy_len) < 0) if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0)
BUG(); BUG();
/* check if we are building multi-part messages */ /* check if we are building multi-part messages */
...@@ -266,8 +273,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -266,8 +273,7 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
UNLOCK_BH(&ulog_lock); UNLOCK_BH(&ulog_lock);
return IPT_CONTINUE; return;
nlmsg_failure: nlmsg_failure:
PRINTR("ipt_ULOG: error during NLMSG_PUT\n"); PRINTR("ipt_ULOG: error during NLMSG_PUT\n");
...@@ -276,10 +282,37 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb, ...@@ -276,10 +282,37 @@ static unsigned int ipt_ulog_target(struct sk_buff **pskb,
PRINTR("ipt_ULOG: Error building netlink message\n"); PRINTR("ipt_ULOG: Error building netlink message\n");
UNLOCK_BH(&ulog_lock); UNLOCK_BH(&ulog_lock);
}
static unsigned int ipt_ulog_target(struct sk_buff **pskb,
const struct net_device *in,
const struct net_device *out,
unsigned int hooknum,
const void *targinfo, void *userinfo)
{
struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) targinfo;
ipt_ulog_packet(hooknum, *pskb, in, out, loginfo, NULL);
return IPT_CONTINUE; return IPT_CONTINUE;
} }
static void ipt_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix)
{
struct ipt_ulog_info loginfo = {
.nl_group = ULOG_DEFAULT_NLGROUP,
.copy_range = 0,
.qthreshold = ULOG_DEFAULT_QTHRESHOLD,
.prefix = ""
};
ipt_ulog_packet(hooknum, skb, in, out, &loginfo, prefix);
}
static int ipt_ulog_checkentry(const char *tablename, static int ipt_ulog_checkentry(const char *tablename,
const struct ipt_entry *e, const struct ipt_entry *e,
void *targinfo, void *targinfo,
...@@ -341,6 +374,8 @@ static int __init init(void) ...@@ -341,6 +374,8 @@ static int __init init(void)
sock_release(nflognl->sk_socket); sock_release(nflognl->sk_socket);
return -EINVAL; return -EINVAL;
} }
if (nflog)
nf_log_register(PF_INET, &ipt_logfn);
return 0; return 0;
} }
...@@ -352,6 +387,8 @@ static void __exit fini(void) ...@@ -352,6 +387,8 @@ static void __exit fini(void)
DEBUGP("ipt_ULOG: cleanup_module\n"); DEBUGP("ipt_ULOG: cleanup_module\n");
if (nflog)
nf_log_unregister(PF_INET, &ipt_logfn);
ipt_unregister_target(&ipt_ulog_reg); ipt_unregister_target(&ipt_ulog_reg);
sock_release(nflognl->sk_socket); sock_release(nflognl->sk_socket);
......
...@@ -18,12 +18,17 @@ ...@@ -18,12 +18,17 @@
#include <net/udp.h> #include <net/udp.h>
#include <net/tcp.h> #include <net/tcp.h>
#include <net/ipv6.h> #include <net/ipv6.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv6/ip6_tables.h> #include <linux/netfilter_ipv6/ip6_tables.h>
MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>"); MODULE_AUTHOR("Jan Rekorajski <baggins@pld.org.pl>");
MODULE_DESCRIPTION("IP6 tables LOG target module"); MODULE_DESCRIPTION("IP6 tables LOG target module");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
static unsigned int nflog = 1;
MODULE_PARM(nflog, "i");
MODULE_PARM_DESC(nflog, "register as internal netfilter logging module");
struct in_device; struct in_device;
#include <net/route.h> #include <net/route.h>
#include <linux/netfilter_ipv6/ip6t_LOG.h> #include <linux/netfilter_ipv6/ip6t_LOG.h>
...@@ -265,40 +270,38 @@ static void dump_packet(const struct ip6t_log_info *info, ...@@ -265,40 +270,38 @@ static void dump_packet(const struct ip6t_log_info *info,
} }
} }
static unsigned int static void
ip6t_log_target(struct sk_buff **pskb, ip6t_log_packet(unsigned int hooknum,
unsigned int hooknum, const struct sk_buff *skb,
const struct net_device *in, const struct net_device *in,
const struct net_device *out, const struct net_device *out,
const void *targinfo, const struct ip6t_log_info *loginfo,
void *userinfo) const char *level_string,
const char *prefix)
{ {
struct ipv6hdr *ipv6h = (*pskb)->nh.ipv6h; struct ipv6hdr *ipv6h = skb->nh.ipv6h;
const struct ip6t_log_info *loginfo = targinfo;
char level_string[4] = "< >";
level_string[1] = '0' + (loginfo->level % 8);
spin_lock_bh(&log_lock); spin_lock_bh(&log_lock);
printk(level_string); printk(level_string);
printk("%sIN=%s OUT=%s ", printk("%sIN=%s OUT=%s ",
loginfo->prefix, prefix == NULL ? loginfo->prefix : prefix,
in ? in->name : "", in ? in->name : "",
out ? out->name : ""); out ? out->name : "");
if (in && !out) { if (in && !out) {
/* MAC logging for input chain only. */ /* MAC logging for input chain only. */
printk("MAC="); printk("MAC=");
if ((*pskb)->dev && (*pskb)->dev->hard_header_len && (*pskb)->mac.raw != (void*)ipv6h) { if (skb->dev && skb->dev->hard_header_len && skb->mac.raw != (void*)ipv6h) {
if ((*pskb)->dev->type != ARPHRD_SIT){ if (skb->dev->type != ARPHRD_SIT){
int i; int i;
unsigned char *p = (*pskb)->mac.raw; unsigned char *p = skb->mac.raw;
for (i = 0; i < (*pskb)->dev->hard_header_len; i++,p++) for (i = 0; i < skb->dev->hard_header_len; i++,p++)
printk("%02x%c", *p, printk("%02x%c", *p,
i==(*pskb)->dev->hard_header_len - 1 i==skb->dev->hard_header_len - 1
? ' ':':'); ? ' ':':');
} else { } else {
int i; int i;
unsigned char *p = (*pskb)->mac.raw; unsigned char *p = skb->mac.raw;
if ( p - (ETH_ALEN*2+2) > (*pskb)->head ){ if ( p - (ETH_ALEN*2+2) > skb->head ){
p -= (ETH_ALEN+2); p -= (ETH_ALEN+2);
for (i = 0; i < (ETH_ALEN); i++,p++) for (i = 0; i < (ETH_ALEN); i++,p++)
printk("%02x%s", *p, printk("%02x%s", *p,
...@@ -309,10 +312,10 @@ ip6t_log_target(struct sk_buff **pskb, ...@@ -309,10 +312,10 @@ ip6t_log_target(struct sk_buff **pskb,
i == ETH_ALEN-1 ? ' ' : ':'); i == ETH_ALEN-1 ? ' ' : ':');
} }
if (((*pskb)->dev->addr_len == 4) && if ((skb->dev->addr_len == 4) &&
(*pskb)->dev->hard_header_len > 20){ skb->dev->hard_header_len > 20){
printk("TUNNEL="); printk("TUNNEL=");
p = (*pskb)->mac.raw + 12; p = skb->mac.raw + 12;
for (i = 0; i < 4; i++,p++) for (i = 0; i < 4; i++,p++)
printk("%3d%s", *p, printk("%3d%s", *p,
i == 3 ? "->" : "."); i == 3 ? "->" : ".");
...@@ -328,10 +331,41 @@ ip6t_log_target(struct sk_buff **pskb, ...@@ -328,10 +331,41 @@ ip6t_log_target(struct sk_buff **pskb,
dump_packet(loginfo, ipv6h, 1); dump_packet(loginfo, ipv6h, 1);
printk("\n"); printk("\n");
spin_unlock_bh(&log_lock); spin_unlock_bh(&log_lock);
}
static unsigned int
ip6t_log_target(struct sk_buff **pskb,
unsigned int hooknum,
const struct net_device *in,
const struct net_device *out,
const void *targinfo,
void *userinfo)
{
const struct ip6t_log_info *loginfo = targinfo;
char level_string[4] = "< >";
level_string[1] = '0' + (loginfo->level % 8);
ip6t_log_packet(hooknum, *pskb, in, out, loginfo, level_string, NULL);
return IP6T_CONTINUE; return IP6T_CONTINUE;
} }
static void
ip6t_logfn(unsigned int hooknum,
const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out,
const char *prefix)
{
struct ip6t_log_info loginfo = {
.level = 0,
.logflags = IP6T_LOG_MASK,
.prefix = ""
};
ip6t_log_packet(hooknum, skb, in, out, &loginfo, KERN_WARNING, prefix);
}
static int ip6t_log_checkentry(const char *tablename, static int ip6t_log_checkentry(const char *tablename,
const struct ip6t_entry *e, const struct ip6t_entry *e,
void *targinfo, void *targinfo,
...@@ -360,20 +394,27 @@ static int ip6t_log_checkentry(const char *tablename, ...@@ -360,20 +394,27 @@ static int ip6t_log_checkentry(const char *tablename,
return 1; return 1;
} }
static struct ip6t_target ip6t_log_reg static struct ip6t_target ip6t_log_reg = {
= { { NULL, NULL }, "LOG", ip6t_log_target, ip6t_log_checkentry, NULL, .name = "LOG",
THIS_MODULE }; .target = ip6t_log_target,
.checkentry = ip6t_log_checkentry,
.me = THIS_MODULE,
};
static int __init init(void) static int __init init(void)
{ {
if (ip6t_register_target(&ip6t_log_reg)) if (ip6t_register_target(&ip6t_log_reg))
return -EINVAL; return -EINVAL;
if (nflog)
nf_log_register(PF_INET6, &ip6t_logfn);
return 0; return 0;
} }
static void __exit fini(void) static void __exit fini(void)
{ {
if (nflog)
nf_log_unregister(PF_INET6, &ip6t_logfn);
ip6t_unregister_target(&ip6t_log_reg); ip6t_unregister_target(&ip6t_log_reg);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment