New match extension, similar to iptables --packet
"Daniele Gozzi" <[email protected]>
| Newsgroups | gmane.linux.network.bridge.ebtables.devel |
|---|---|
| Message-ID | <[email protected]> |
I have developed a new match extension which matches every 'n'th frame. This
may be useful for research purposes or for load balancing (e.g. we are using
it to scatter frames to several IDS sensors using DNAT in a round-robin
fashion).
$ diff -r ebtables-v2.0.8-rc2 ebtables-v2.0.8-rc2_DanieleGozzi
Only in ebtables-v2.0.8-rc2_DanieleGozzi/extensions: ebt_nth.c
diff -r ebtables-v2.0.8-rc2/extensions/Makefile
ebtables-v2.0.8-rc2_DanieleGozzi/extensions/Makefile
4c4
< pkttype stp among limit ulog
---
> pkttype stp among limit ulog nth
Only in ebtables-v2.0.8-rc2_DanieleGozzi/include/linux/netfilter_bridge:ebt_nth.h
The code of the two new files (following) should compile without warning
against ebtables v2.0.8-rc2 (I'm using gcc v4.0.3).
---***--- ebt_nth.h ---***---
#ifndef __LINUX_BRIDGE_EBT_NTH_H
#define __LINUX_BRIDGE_EBT_NTH_H
#define EBT_NTH_MATCH "nth"
struct ebt_nth_info {
unsigned long int every; // match every /every/ frames.
unsigned long int frame; // match phase shift. match on /frame-th/
frame every /every/ frames.
/* Used internally by the kernel module*/
unsigned long int counter;
};
#endif
---***---***---***---
---***--- ebt_nth.c ---***---
/* Shared library add-on to ebtables to add "nth" match support.
* Daniele Gozzi <[email protected]>
* based on:
* Shared library add-on to ebtables to add limit support. (part of
ebtables package)
* (Swipted from iptables' limit match.)
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <netinet/ether.h>
#include "../include/ebtables_u.h"
#include <linux/netfilter_bridge/ebt_nth.h>
/* from iptables.c */
#include <errno.h>
int
string_to_number_lu(const char *s, unsigned long int min, unsigned long int
max,
unsigned long int *ret)
{
unsigned long int number;
char *end;
/* Handle hex, octal, etc. */
errno = 0;
number = strtoul(s, &end, 0);
if (*end == '\0' && end != s) {
/* we parsed a number, let's see if we want this */
if (errno != ERANGE && min <= number && number <= max) {
*ret = number;
return 0;
}
}
return -1;
}
#define FLAG_EVERY 0x01
#define FLAG_FRAME 0x02
#define ARG_EVERY '1'
#define ARG_FRAME '2'
static struct option opts[] =
{
{ "every", required_argument, 0, ARG_EVERY },
{ "frame", required_argument, 0, ARG_FRAME },
{ 0 }
};
static void print_help(void)
{
printf(
"limit options:\n"
"--every number match rate\n"
"--frame number frame number to match, 0 <= number < every_number"
" (default = 0)\n"
"\n");
}
/* Initialize the match. */
static void init(struct ebt_entry_match *m)
{
struct ebt_nth_info *r = (struct ebt_nth_info *)m->data;
r->counter = 0;
r->frame = 0; // default
r->every = 0; // default
}
static int parse(int c, char **argv, int argc,
const struct ebt_u_entry *entry,
unsigned int *flags,
struct ebt_entry_match **match)
{
struct ebt_nth_info *r = (struct ebt_nth_info *)(*match)->data;
switch(c) {
case ARG_EVERY:
ebt_check_option2(flags, FLAG_EVERY);
if (ebt_check_inverse2(optarg))
ebt_print_error2("Unexpected `!' after --every");
if (string_to_number_lu(optarg, 1, ULONG_MAX,&r->every) == -1)
ebt_print_error2("bad --every `%s' (must be between 1 and %u)",
optarg, ULONG_MAX);
break;
case ARG_FRAME:
ebt_check_option2(flags, FLAG_FRAME);
if (ebt_check_inverse2(optarg))
ebt_print_error2("Unexpected `!' after --frame");
if (string_to_number_lu(optarg, 0, ULONG_MAX-1, &r->frame) == -1)
ebt_print_error2("bad --frame `%s' (must be between 1 and %u)",
optarg, ULONG_MAX-1);
break;
default:
return 0;
}
return 1;
}
static void final_check(const struct ebt_u_entry *entry,
const struct ebt_entry_match *match, const char *name,
unsigned int hookmask, unsigned int time)
{
struct ebt_nth_info *r = (struct ebt_nth_info *)match->data;
if (r->every==0 || r->frame >= r->every)
ebt_print_error("--frame argument must be lower than --every");
}
/* Prints out the matchinfo. */
static void
print(const struct ebt_u_entry *entry, const struct ebt_entry_match *match)
{
struct ebt_nth_info *r = (struct ebt_nth_info *)match->data;
printf("--every %lu ",r->every);
printf("--frame %lu ",r->frame);
}
static int compare(const struct ebt_entry_match* m1, const struct
ebt_entry_match *m2)
{
struct ebt_nth_info* li1 = (struct ebt_nth_info*)m1->data;
struct ebt_nth_info* li2 = (struct ebt_nth_info*)m2->data;
if (li1->every != li2->every)
return 0;
if (li1->frame != li2->frame)
return 0;
return 1;
}
static struct ebt_u_match nth_match =
{
.name = EBT_NTH_MATCH,
.size = sizeof(struct ebt_nth_info),
.help = print_help,
.init = init,
.parse = parse,
.final_check = final_check,
.print = print,
.compare = compare,
.extra_ops = opts,
};
//static _init(void) __attribute((constructor));
void _init(void)
{
ebt_register_match(&nth_match);
}
---***---***---***---
Of course a matching kernel module is needed. Module code follows (it uses
the same ebt_nth.h header file as the previous ebtables code):
---***--- ebt_nth.c ---***---
/*
* ebt_nth
*
* Authors:
* Daniele Gozzi <[email protected]>
*
* Nth frame match module for ebtables / linux netfilter-bridge
* Based on ebt_limit.c by Tom Marshall and bt_802_3.c by Chris Vitale
*/
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/netfilter_bridge/ebtables.h>
#include "ebt_nth.h"
MODULE_AUTHOR("Daniele Gozzi");
static int ebt_nth_match(const struct sk_buff *skb,
const struct net_device *in,
const struct net_device *out, const void *data,
unsigned int datalen)
{
struct ebt_nth_info *info = (struct ebt_nth_info *) data;
/* update counter value (modulo /every/) */
info->counter = (info->counter + 1) % info->every;
/* is this frame supposed to match? */
if (info->counter == info->frame)
return EBT_MATCH;
return EBT_NOMATCH;
}
static int ebt_nth_check(const char *tablename, unsigned int hookmask,
const struct ebt_entry *e, void *data, unsigned int datalen)
{
struct ebt_nth_info *info = (struct ebt_nth_info *) data;
if (datalen < sizeof(struct ebt_nth_info))
return -EINVAL;
if (info->every == 0 || info->frame >= info->every)
return -EINVAL;
return 0;
}
static struct ebt_match ebt_nth_reg = {
.name = EBT_NTH_MATCH,
.match = ebt_nth_match,
.check = ebt_nth_check,
.me = THIS_MODULE,
};
static int __init nth_match_init(void)
{
printk(KERN_INFO "Initializing nth match for ebtables\n");
return ebt_register_match(&ebt_nth_reg);
}
static void __exit nth_match_exit(void)
{
printk(KERN_INFO "Unloading nth match for ebtables\n");
ebt_unregister_match(&ebt_nth_reg);
}
module_init(nth_match_init);
module_exit(nth_match_exit);
---***---***---***---
---***--- Makefile ---***---
obj-m += ebt_nth.o
all:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
---***---***---***---
Thank you for your consideration.
Daniele Gozzi
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Ebtables-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/ebtables-devel