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);

Attachment: pgpARnyS8oFG5.pgp
Description: PGP signature

Reply via email to