I forgot the ebtables command patch, here it is.. diff -upNr old/extensions/ebt_nfqueue.c new/extensions/ebt_nfqueue.c --- old/extensions/ebt_nfqueue.c 1970-01-01 08:00:00.000000000 +0800 +++ new/extensions/ebt_nfqueue.c 2012-10-24 14:35:40.000000000 +0800 @@ -0,0 +1,127 @@ +/* + * Shared library add-on to ebtables for NFQ + * + * (C) 2012 by Ma Jie Yue <jieyue.majy@xxxxxxxxxxxxxx> + * + * This program is distributed under the terms of GNU GPLv2, 1991 + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include <errno.h> + +#include "../include/ebtables_u.h" +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter_bridge/ebt_nfqueue.h> + +#define NFQUEUE_QUEUENUM 0x1 +#define NFQUEUE_QUEUEBALANCE 0x2 + +static int string_to_number(const char *s, unsigned int min, unsigned int max, unsigned int *ret) +{ + long number; + char *end; + errno = 0; + number = strtol(s, &end, 0); + + if (*end == '\0' && end != s) { + if (errno != ERANGE && min <= number && number <= max) { + *ret = number; + return 0; + } + } + return -1; +} + +static void nfqueue_help(void) +{ + printf("NFQUEUE target options\n" + " --queue-num value Send packet to QUEUE number <value>.\n" + " Valid queue numbers are 0-65535\n"); +} + +static void nfqueue_init(struct ebt_entry_target* target) { + struct xt_NFQ_info* info = (struct xt_NFQ_info *)target->data; + + info->queuenum = 0; +} + +static const struct option nfqueue_opts[] = { + { "queue-num", 1, NULL, 'F' }, + { "queue-balance", 1, NULL, 'B' }, + { .name = NULL } +}; + +static void parse_num(const char *s, struct xt_NFQ_info *tinfo) +{ + unsigned int num = 0; + if (string_to_number(s, 0, 65535, &num) < 0) { + ebt_print_error("Invalid queue number %s\n", s); + } + + tinfo->queuenum = num; +} + +static int nfqueue_parse(int c, char **argv, int argc, + const struct ebt_u_entry *entry, unsigned int *flags, + struct ebt_entry_target **target) +{ + struct xt_NFQ_info *tinfo = (struct xt_NFQ_info *)(*target)->data; + tinfo->queuenum = 0; + + switch (c) { + case 'F': + if (*flags) + ebt_print_error2("NFQUEUE target: " + "Only use --queue-num ONCE!"); + *flags |= NFQUEUE_QUEUENUM; + parse_num(optarg, tinfo); + break; + + case 'B': + ebt_print_error2("NFQUEUE target: " + "--queue-balance not supported (kernel too old?)"); + + default: + break; + } + return 1; +} + +static void nfqueue_print(const struct ebt_u_entry* entry, const struct ebt_entry_target *target) { + struct xt_NFQ_info *tinfo = (struct xt_NFQ_info *)target->data; + + printf("--queue-num %u ", tinfo->queuenum); +} + +static void nfqueue_check(const struct ebt_u_entry *entry, + const struct ebt_entry_target *target, const char *name, + unsigned int hookmask, unsigned int time) { + +} + +static int nfqueue_compare(const struct ebt_entry_target *t1, const struct ebt_entry_target *t2) { + struct xt_NFQ_info *info1 = (struct xt_NFQ_info *)t1->data; + struct xt_NFQ_info *info2 = (struct xt_NFQ_info *)t2->data; + + return (info1->queuenum == info2->queuenum); +} + +static struct ebt_u_target nfqueue_target = { + .name = "nfqueue", + .init = nfqueue_init, + .size = sizeof(struct xt_NFQ_info), + .help = nfqueue_help, + .parse = nfqueue_parse, + .print = nfqueue_print, + .final_check = nfqueue_check, + .compare = nfqueue_compare, + .extra_ops = nfqueue_opts, +}; + +void _init(void) { + ebt_register_target(&nfqueue_target); +} + diff -upNr old/extensions/Makefile new/extensions/Makefile --- old/extensions/Makefile 2011-12-16 04:02:47.000000000 +0800 +++ new/extensions/Makefile 2012-10-24 14:18:50.000000000 +0800 @@ -1,7 +1,7 @@ #! /usr/bin/make EXT_FUNC+=802_3 nat arp arpreply ip ip6 standard log redirect vlan mark_m mark \ - pkttype stp among limit ulog nflog + pkttype stp among limit ulog nflog nfqueue EXT_TABLES+=filter nat broute EXT_OBJS+=$(foreach T,$(EXT_FUNC), extensions/ebt_$(T).o) EXT_OBJS+=$(foreach T,$(EXT_TABLES), extensions/ebtable_$(T).o) diff -upNr old/include/linux/netfilter_bridge/ebt_nfqueue.h new/include/linux/netfilter_bridge/ebt_nfqueue.h --- old/include/linux/netfilter_bridge/ebt_nfqueue.h 1970-01-01 08:00:00.000000000 +0800 +++ new/include/linux/netfilter_bridge/ebt_nfqueue.h 2012-10-24 14:17:02.000000000 +0800 @@ -0,0 +1,11 @@ +#ifndef __LINUX_BRIDGE_EBT_NFQUEUE_H +#define __LINUX_BRIDGE_EBT_NFQUEUE_H + +#include <linux/types.h> + +struct xt_NFQ_info { + __u16 queuenum; + int target; +}; + +#endif On Wed, Oct 24, 2012 at 1:16 PM, JieYue Ma <xiaoma80.dev@xxxxxxxxx> wrote: > Well, I wrote the nfqueue patch for both ebtables and arptables a few > months ago, it did work well, so I think it is appropriate to release > these patches. Hope it will help you. > > I am not sure if I understand the problem you raised correctly. I > guess it might be the netfilter sus-subsystem currently not supporting > queue verdict for bridge very well. As you can see, you need a > nf_afinfo structure to be registered before using netfilter queue > verdict for this protocol. Unfortunately, during initialization of > netfilter, it did register such nf_afinfo for ipv4, ipv6, maybe arp as > well.. but not for bridge. So in order to enable queue verdict to work > under bridge, you need to register it by yourself, maybe during > initialization of ebtables nfqueue target module > > here is my patch for ebtables: > > > diff -upNr old/include/linux/netfilter_bridge/ebt_nfqueue.h > new/include/linux/netfilter_bridge/ebt_nfqueue.h > --- old/include/linux/netfilter_bridge/ebt_nfqueue.h 1969-12-31 > 19:00:00.000000000 -0500 > +++ new/include/linux/netfilter_bridge/ebt_nfqueue.h 2012-05-29 > 23:59:06.940194206 -0400 > @@ -0,0 +1,10 @@ > +#ifndef __LINUX_BRIDGE_EBT_NFQUEUE_H > +#define __LINUX_BRIDGE_EBT_NFQUEUE_H > +#include <linux/types.h> > + > +struct xt_NFQ_info { > + __u16 queuenum; > + int target; > +}; > + > +#endif > diff -upNr old/net/bridge/netfilter/ebtables.c > new/net/bridge/netfilter/ebtables.c > --- old/net/bridge/netfilter/ebtables.c 2012-05-27 08:48:00.095617214 -0400 > +++ new/net/bridge/netfilter/ebtables.c 2012-05-27 08:57:27.644193954 -0400 > @@ -252,6 +252,17 @@ letsreturn: > return NF_DROP; > } > #endif > + /* > + * We add NFQUEUE support in ebtables here: > + * > + * If verdict is NF_QUEUE type, pass it to Netfilter. Netfilter will > + * call nf_queue to handle this. > + */ > + if (verdict > 0 && (verdict & NF_VERDICT_MASK) == NF_QUEUE) { > + read_unlock_bh(&table->lock); > + return verdict; > + } > + > /* jump to a udc */ > cs[sp].n = i + 1; > cs[sp].chaininfo = chaininfo; > > diff -upNr old/net/bridge/netfilter/ebt_nfqueue.c > new/net/bridge/netfilter/ebt_nfqueue.c > --- old/net/bridge/netfilter/ebt_nfqueue.c 1969-12-31 19:00:00.000000000 -0500 > +++ new/net/bridge/netfilter/ebt_nfqueue.c 2012-05-27 08:58:58.511193378 -0400 > @@ -0,0 +1,117 @@ > +/* > + * 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 <linux/skbuff.h> > +#include <linux/kernel.h> > +#include <linux/types.h> > +#include <linux/netfilter.h> > +#include <linux/netfilter/x_tables.h> > +#include <linux/netfilter_bridge/ebtables.h> > +#include <linux/netfilter_bridge/ebt_nfqueue.h> > + > +MODULE_AUTHOR("alibaba"); > +MODULE_DESCRIPTION("ebtables: forwarding to netlink"); > +MODULE_LICENSE("GPL"); > + > +static unsigned int ebt_nfqueue_tg(struct sk_buff *skb, const struct > xt_target_param *par) { > + const struct xt_NFQ_info *info = par->targinfo; > + > + return NF_QUEUE_NR(info->queuenum); > +} > + > +static bool ebt_nfqueue_tg_check(const struct xt_tgchk_param* par) { > + const struct xt_NFQ_info *info = par->targinfo; > + > + if (BASE_CHAIN && info->target == EBT_RETURN) { > + printk(KERN_INFO"ebt_nfqueue: ebt_nfqueue_tg_check failed\n"); > + return false; > + } > + > + return true; > +} > + > +void dummy_from_user(void *dst, void *src) { > +} > + > +int dummy_to_user(void __user *dst, void *src) { > + return 0; > +} > + > +static struct xt_target nfqueue_tg_reg __read_mostly = { > + .name = "nfqueue", > + .revision = 0, > + .family = NFPROTO_BRIDGE, > + .table = "filter", > + .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_LOCAL_IN) | (1 > << NF_BR_LOCAL_OUT) | (1 << NF_BR_FORWARD), > + .target = ebt_nfqueue_tg, > + .checkentry = ebt_nfqueue_tg_check, > + .targetsize = XT_ALIGN(sizeof(struct xt_NFQ_info)), > + .compat_from_user = dummy_from_user, > + .compat_to_user = dummy_to_user, > + .me = THIS_MODULE, > +}; > + > + > +__sum16 nf_br_checksum(struct sk_buff* skb, unsigned int hook, > unsigned int dataoff, u_int8_t protocol) { > + return 0; > +} > + > +static __sum16 nf_br_checksum_partial(struct sk_buff* skb, unsigned int hook, > + unsigned int dataoff, unsigned int len, > + u_int8_t protocol) { > + return 0; > +} > + > +static int nf_br_route(struct dst_entry **dst, struct flowi *fl) { > + return 0; > +} > + > +static void nf_br_saveroute(const struct sk_buff *skb, struct > nf_queue_entry *entry) { > + > +} > + > +static int nf_br_reroute(struct sk_buff *skb, const struct > nf_queue_entry *entry) { > + return 0; > +} > + > +static const struct nf_afinfo nf_br_afinfo = { > + .family = NFPROTO_BRIDGE, > + .checksum = nf_br_checksum, > + .checksum_partial = nf_br_checksum_partial, > + .route = nf_br_route, > + .saveroute = nf_br_saveroute, > + .reroute = nf_br_reroute, > + .route_key_size = 0, > +}; > + > + > +static int __init nfqueue_tg_init(void) > +{ > + int ret; > + /* > + * a tricky hack here, we forge a bridge nf_afinfo struct and register it > + * > + * We have to do this, coz currently netfilter subsystem doesn't > support bridge in nf_queue > + */ > + ret = nf_register_afinfo(&nf_br_afinfo); > + if (ret < 0) { > + printk("[ebt_nfqueue] nf_register_afinfo failed, cannot > install ebt_nfqueue.ko\n"); > + return ret; > + } > + > + return xt_register_target(&nfqueue_tg_reg); > +} > + > +static void __exit nfqueue_tg_exit(void) > +{ > + nf_unregister_afinfo(&nf_br_afinfo); > + xt_unregister_target(&nfqueue_tg_reg); > +} > + > +module_init(nfqueue_tg_init); > +module_exit(nfqueue_tg_exit); > > > > > On Sat, Oct 20, 2012 at 2:32 AM, Benjamin Beckmeyer > <B.Beckmeyer@xxxxxxxxxxxxxxxxxxxx> wrote: >> Hi all, >> >> I am trying to build an Ebtables NFQUEUE module to also move layer 2 >> traffic to the NFQUEUE system provided by IPtables. A few years ago a >> Pierre Chifflier provided 3 patches to Ebtables that appear to try and >> utilize the NFQUEUE xt_tables target within Ebtables to pass the layer 2 >> data via nfnetlink_queue. >> >> Some background, I am trying to get this working on 2.6.26.5 kernel >> version and have applied the patches listed here: >> >> http://permalink.gmane.org/gmane.comp.security.firewalls.netfilter.devel/37859 >> http://permalink.gmane.org/gmane.comp.security.firewalls.netfilter.devel/37862 >> >> I have also patched the Ebtables (2.0.8) userspace utility to produce the >> shared object ebt_NFQUEUE.so with code also from Pierre, which can be >> found here: >> >> https://www.wzdftpd.net/downloads/ebt_NFQUEUE.c >> >> To get the patches to work for the ebt_nfqueue kernel object, due to an >> older kernel, I had to modify the target and check function arguments as >> the "const struct xt_action_param" does not exist in my kernel version: >> >> static int ebt_nfqueue_tg(const struct sk_buff *skb, const struct >> net_device *in, >> const struct net_device *out, const void *data, unsigned int datalen) >> { >> const struct ebt_nfqueue_info *info = data; >> struct nf_loginfo li; >> unsigned int verdict = NF_ACCEPT; >> >> printk(KERN_NOTICE "ebt_NFQUEUE: returning EBT_QUEUE\n"); >> return EBT_QUEUE; // return -5 >> } >> >> static struct ebt_target ebt_nfqueue __read_mostly = { >> .name = "NFQUEUE", >> .target = ebt_nfqueue_tg, >> .check = ebt_nfqueue_check, >> .me = THIS_MODULE, >> }; >> >> +++++ VERSUS +++++ >> >> static struct xt_target ebt_xt_nfqueue __read_mostly = { >> .name = "NFQUEUE", >> .revision = 0, >> .family = 7, // NFPROTO_BRIDGE >> .target = ebt_nfqueue_tg, >> .checkentry = ebt_nfqueue_check, >> .targetsize = sizeof(struct ebt_nfqueue_info), >> .me = THIS_MODULE, >> }; >> >> Nevertheless, the return value from this target is just the EBT_QUEUE (-5) >> to inform the Netfilter system of the queue number. If I use the >> ebt_target rather than xt_target the kernel module will build and can be >> inserted into ebtables with no errors - the problem is that queuing does >> not work. If I use the xt_target rather than the ebt_target then Ebtables >> userspace complains that it is not supported from this kernel version >> (error in communication.c in userspace and appears to fail on the >> "setsockopt" calls). >> >> I have printed out the entire contents of using the xt_target vs >> ebt_target and all data going into this call is identical, which boggles >> my mind as to why xt_target will trigger the error in the ebtables >> userspace program and ebt_target will not. >> >> I think that I MUST use the xt_target within ebtables to properly pass >> this data to the NFQUEUE system. This comes from an earlier discussion: >> >> +++ >> >> On 04.02.2011 14:40, Pierre Chifflier wrote: >>> On 02/04/2011 02:25 PM, Patrick McHardy wrote: >>>> On 03.02.2011 15:32, Pierre Chifflier wrote: >>>>> This adds support for sending bridge packets to userspace using >>>>> the NFQUEUE target with ebtables. >>>> >>>> I don't think we need a new target for this (and the EBT_QUEUE >>>> definition), just using xt_NFQUEUE should work fine. >>> >>> I thought ebtables did not support sending packet to xtables ? (that's >>> on the TODO list for ebtables). >> >> It can use xtables targets and matches if I'm not completely >> mistaken. >> >> +++ >> >> It appears I can 'use' xtables targets, it will compile correctly, but >> ebtables will not actually allow me to insert the rules to jump to the >> NFQUEUE target, so I am unable to actually verify if packets would be >> queue'd by the system. >> >> When using the ebt_target I can insert my NFQUEUE rules into the nat >> PREROUTING table, and the packet counter will actually increment on layer >> 2 traffic, but the packets do not appear to actually hit any of the >> nfnetlink_queue functions (I have added a printk to every function). I >> even see that my target has been hit via a printk: >> >> user.notice kernel: ebt_NFQUEUE: returning EBT_QUEUE >> >> But then it appears that is as far as the packet goes. >> >> When queueing a packet from IPtables I see a huge amount of output: >> >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> __enqueue_entry >> user.notice kernel: BB: File: nfnetlink.c Function: nfnetlink_rcv >> user.notice kernel: BB: File: nfnetlink.c Function: nfnl_lock >> user.notice kernel: BB: File: nfnetlink.c Function: nfnetlink_rcv_msg >> user.notice kernel: BB: File: nfnetlink.c Function: nfnetlink_get_subsys >> user.notice kernel: BB: File: nfnetlink.c Function: >> nfnetlink_find_client >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> nfqnl_recv_verdict >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> instance_lookup >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> find_dequeue_entry >> user.notice kernel: BB: File: nfnetlink.c Function: nfnl_unlock >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> nfqnl_enqueue_packet >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> instance_lookup >> user.notice kernel: BB: File: nfnetlink_queue.c Function: >> nfqnl_build_packet_message >> user.notice kernel: BB: File: nfnetlink.c Function: nfnetlink_unicast >> >> But from my ebtables -j NFQUEUE there are no calls to the nfnetlink.c or >> nfnetlink_queue.c functions. It is almost like the target is hit then the >> packet is just mysteriously gone...or hits other functions unrelated to >> the queueing system. >> >> In summation, the problem is if using the ebt_target struct in the kernel >> module for ebtables, it will be inserted and can be utilized by the >> userspace Ebtables - but it doesnt appear to pass the packet to the >> IPtables nfqueue correctly. If using the xt_target struct in the kernel >> module for ebtables, it will compile, but fails to be utilized by Ebtables >> userspace due to a "setsockopt error mentioned above. >> >> Any help or suggestions are greatly appreciated! >> >> Thank you, Benny >> >> >> >> >> >> >> >> -- >> To unsubscribe from this list: send the line "unsubscribe netfilter" in >> the body of a message to majordomo@xxxxxxxxxxxxxxx >> More majordomo info at http://vger.kernel.org/majordomo-info.html -- To unsubscribe from this list: send the line "unsubscribe netfilter" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html