kernel is 2.6.32, while ebtables is 2.0.10-4 On Thu, Oct 25, 2012 at 7:39 AM, Benjamin Beckmeyer <B.Beckmeyer@xxxxxxxxxxxxxxxxxxxx> wrote: > Thank you JieYue Ma! > > This is excellent. Out of curiousity which kernel version and ebtables > version were you working against? > > Benny > >> 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