Hi Bart, Dave, Patrick, attached is a patch that converts ebt_ulog to use the generic logging mechanism (and thus be able to use the nfnetlink_log backend).
This patch breaks userspace compatibility, since the netlink message format of nfnetlink_log is different than the ebt_ulog one. I cannot decide whether that can be done, but at least in the past I had the feeling that nobody is really using ebt_ulog [yet], and thus it might be possible for those few users to directly use libnfnetlink_log (https://svn.netfilter.org/netfilter/trunk/libnfnetlink_log), especially considering that those uerspace apps already breaks since ebt_ulog now uses a different netlink family. How does it work? ebt_ulog.c calls nf_log_packet() which looks for a logging backend (nf_logger) for PF_BRIDGE. Userspace can attach nfnetlink_log to PF_BRIDGE by sending NFULNL_CFG_CMD_PF_BIND. libnfnetlink_log provides "nfulnl_bind_pf()" for that. The ebg_ulog "group number" is directly translated into a nfnetlink_log goup number. A userspace process can attach to a specific group by sending NFULNL_CFG_CMD_BIND (or better: calling "nfulnl_bind_group()" in libnfnetlink_log). If deleting all the old code is not feasible, I still suggest using the nf_log_packet() API (i.e. ebt_ulog calls nf_log_packet() but registers itself as default nf_logger for PF_BRIDGE). This way 'legacy' applications would work as long as some new nfnetlink_log app would register itself for PF_BRIDGE. I can prepare a patch, if it is needed. The same _should_ be done for regular "LOG" style logging of ebtables, much as ipt_LOG has been reworked by one of my recent patches. Please comment, Harald -- - Harald Welte <[EMAIL PROTECTED]> http://gnumonks.org/ ============================================================================ "Privacy in residential applications is a desirable marketing option." (ETSI EN 300 175-7 Ch. A6)
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c --- a/net/bridge/netfilter/ebt_ulog.c +++ b/net/bridge/netfilter/ebt_ulog.c @@ -3,28 +3,13 @@ * * Authors: * Bart De Schuymer <[EMAIL PROTECTED]> + * Harald Welte <[EMAIL PROTECTED]> * * November, 2004 * * Based on ipt_ULOG.c, which is * (C) 2000-2002 by Harald Welte <[EMAIL PROTECTED]> * - * This module accepts two parameters: - * - * nlbufsiz: - * The parameter specifies how big the buffer for each netlink multicast - * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will - * get accumulated in the kernel until they are sent to userspace. It is - * NOT possible to allocate more than 128kB, and it is strongly discouraged, - * because atomically allocating 128kB inside the network rx softirq is not - * reliable. Please also keep in mind that this buffer size is allocated for - * each nlgroup you are using, so the total kernel memory usage increases - * by that factor. - * - * flushtimeout: - * Specify, after how many hundredths of a second the queue should be - * flushed even if it is not full yet. - * */ #include <linux/module.h> @@ -45,175 +30,22 @@ #define PRINTR(format, args...) do { if (net_ratelimit()) \ printk(format , ## args); } while (0) -static unsigned int nlbufsiz = 4096; -module_param(nlbufsiz, uint, 0600); -MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " - "(defaults to 4096)"); - -static unsigned int flushtimeout = 10; -module_param(flushtimeout, uint, 0600); -MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) " - "(defaults to 10)"); - -typedef struct { - unsigned int qlen; /* number of nlmsgs' in the skb */ - struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ - struct sk_buff *skb; /* the pre-allocated skb */ - struct timer_list timer; /* the timer function */ - spinlock_t lock; /* the per-queue lock */ -} ebt_ulog_buff_t; - -static ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; -static struct sock *ebtulognl; - -/* send one ulog_buff_t to userspace */ -static void ulog_send(unsigned int nlgroup) -{ - ebt_ulog_buff_t *ub = &ulog_buffers[nlgroup]; - - if (timer_pending(&ub->timer)) - del_timer(&ub->timer); - - /* last nlmsg needs NLMSG_DONE */ - if (ub->qlen > 1) - ub->lastnlh->nlmsg_type = NLMSG_DONE; - - NETLINK_CB(ub->skb).dst_groups = 1 << nlgroup; - netlink_broadcast(ebtulognl, ub->skb, 0, 1 << nlgroup, GFP_ATOMIC); - - ub->qlen = 0; - ub->skb = NULL; -} - -/* timer function to flush queue in flushtimeout time */ -static void ulog_timer(unsigned long data) -{ - spin_lock_bh(&ulog_buffers[data].lock); - if (ulog_buffers[data].skb) - ulog_send(data); - spin_unlock_bh(&ulog_buffers[data].lock); -} - -static struct sk_buff *ulog_alloc_skb(unsigned int size) -{ - struct sk_buff *skb; - - skb = alloc_skb(nlbufsiz, GFP_ATOMIC); - if (!skb) { - PRINTR(KERN_ERR "ebt_ulog: can't alloc whole buffer " - "of size %ub!\n", nlbufsiz); - if (size < nlbufsiz) { - /* try to allocate only as much as we need for - * current packet */ - skb = alloc_skb(size, GFP_ATOMIC); - if (!skb) - PRINTR(KERN_ERR "ebt_ulog: can't even allocate " - "buffer of size %ub\n", size); - } - } - - return skb; -} static void ebt_ulog(const struct sk_buff *skb, unsigned int hooknr, const struct net_device *in, const struct net_device *out, const void *data, unsigned int datalen) { - ebt_ulog_packet_msg_t *pm; - size_t size, copy_len; - struct nlmsghdr *nlh; struct ebt_ulog_info *uloginfo = (struct ebt_ulog_info *)data; - unsigned int group = uloginfo->nlgroup; - ebt_ulog_buff_t *ub = &ulog_buffers[group]; - spinlock_t *lock = &ub->lock; - - if ((uloginfo->cprange == 0) || - (uloginfo->cprange > skb->len + ETH_HLEN)) - copy_len = skb->len + ETH_HLEN; - else - copy_len = uloginfo->cprange; - - size = NLMSG_SPACE(sizeof(*pm) + copy_len); - if (size > nlbufsiz) { - PRINTR("ebt_ulog: Size %Zd needed, but nlbufsiz=%d\n", - size, nlbufsiz); - return; - } - - spin_lock_bh(lock); - - if (!ub->skb) { - if (!(ub->skb = ulog_alloc_skb(size))) - goto alloc_failure; - } else if (size > skb_tailroom(ub->skb)) { - ulog_send(group); - - if (!(ub->skb = ulog_alloc_skb(size))) - goto alloc_failure; - } - - nlh = NLMSG_PUT(ub->skb, 0, ub->qlen, 0, - size - NLMSG_ALIGN(sizeof(*nlh))); - ub->qlen++; - - pm = NLMSG_DATA(nlh); - - /* Fill in the ulog data */ - pm->version = EBT_ULOG_VERSION; - do_gettimeofday(&pm->stamp); - if (ub->qlen == 1) - ub->skb->stamp = pm->stamp; - pm->data_len = copy_len; - pm->mark = skb->nfmark; - pm->hook = hooknr; - if (uloginfo->prefix != NULL) - strcpy(pm->prefix, uloginfo->prefix); - else - *(pm->prefix) = '\0'; - - if (in) { - strcpy(pm->physindev, in->name); - /* If in isn't a bridge, then physindev==indev */ - if (in->br_port) - strcpy(pm->indev, in->br_port->br->dev->name); - else - strcpy(pm->indev, in->name); - } else - pm->indev[0] = pm->physindev[0] = '\0'; - - if (out) { - /* If out exists, then out is a bridge port */ - strcpy(pm->physoutdev, out->name); - strcpy(pm->outdev, out->br_port->br->dev->name); - } else - pm->outdev[0] = pm->physoutdev[0] = '\0'; - - if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) - BUG(); - - if (ub->qlen > 1) - ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; - - ub->lastnlh = nlh; - - if (ub->qlen >= uloginfo->qthreshold) - ulog_send(group); - else if (!timer_pending(&ub->timer)) { - ub->timer.expires = jiffies + flushtimeout * HZ / 100; - add_timer(&ub->timer); - } + struct nf_loginfo li; -unlock: - spin_unlock_bh(lock); + li.type = NF_LOG_TYPE_ULOG; + li.u.ulog.copy_len = uloginfo->cprange; + li.u.ulog.qthreshold = uloginfo->qthreshold; + li.u.ulog.group = uloginfo->nlgroup; - return; + nf_log_packet(PF_BRIDGE, hooknr, skb, in, out, &li, uloginfo->prefix); -nlmsg_failure: - printk(KERN_CRIT "ebt_ulog: error during NLMSG_PUT. This should " - "not happen, please report to author.\n"); - goto unlock; -alloc_failure: - goto unlock; + return; } static int ebt_ulog_check(const char *tablename, unsigned int hookmask, @@ -242,49 +74,12 @@ static struct ebt_watcher ulog = { static int __init init(void) { - int i, ret = 0; - - if (nlbufsiz >= 128*1024) { - printk(KERN_NOTICE "ebt_ulog: Netlink buffer has to be <= 128kB," - " please try a smaller nlbufsiz parameter.\n"); - return -EINVAL; - } - - /* initialize ulog_buffers */ - for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { - init_timer(&ulog_buffers[i].timer); - ulog_buffers[i].timer.function = ulog_timer; - ulog_buffers[i].timer.data = i; - spin_lock_init(&ulog_buffers[i].lock); - } - - ebtulognl = netlink_kernel_create(NETLINK_NFLOG, NULL, THIS_MODULE); - if (!ebtulognl) - ret = -ENOMEM; - else if ((ret = ebt_register_watcher(&ulog))) - sock_release(ebtulognl->sk_socket); - - return ret; + return ebt_register_watcher(&ulog); } static void __exit fini(void) { - ebt_ulog_buff_t *ub; - int i; - ebt_unregister_watcher(&ulog); - for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { - ub = &ulog_buffers[i]; - if (timer_pending(&ub->timer)) - del_timer(&ub->timer); - spin_lock_bh(&ub->lock); - if (ub->skb) { - kfree_skb(ub->skb); - ub->skb = NULL; - } - spin_unlock_bh(&ub->lock); - } - sock_release(ebtulognl->sk_socket); } module_init(init);
pgpARnyS8oFG5.pgp
Description: PGP signature