summaryrefslogtreecommitdiffstats
path: root/userspace/patches
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/patches')
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre2.001.diff121
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre2.002.diff2204
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre2.003.diff40
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre2.004.diff50
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre3.001.diff245
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre3.002.diff194
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre3.003.diff66
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre3.004.diff483
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre4.001.diff522
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre5.001.diff50
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre5.002.diff61
-rw-r--r--userspace/patches/incremental-patches/ebtables-v2.0pre6.001.diff314
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre1.tar.gzbin0 -> 32529 bytes
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre2.tar.gzbin0 -> 49417 bytes
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre3.tar.gzbin0 -> 51235 bytes
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre4.tar.gzbin0 -> 52135 bytes
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre5.tar.gzbin0 -> 35558 bytes
-rw-r--r--userspace/patches/zipped/ebtables-v2.0pre6.tar.gzbin0 -> 36908 bytes
18 files changed, 4350 insertions, 0 deletions
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre2.001.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre2.001.diff
new file mode 100644
index 0000000..80cc94b
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre2.001.diff
@@ -0,0 +1,121 @@
+Changed the Makefile hacking to initialize things (taken from iptables)
+to using __attribute__ ((constructor)). Makes things cleaner.
+
+--- ebtables-v2.0pre1/Makefile Wed Apr 3 18:24:15 2002
++++ ebtables-v2.0pre2/Makefile Sat Apr 6 21:53:00 2002
+@@ -26,7 +26,7 @@
+ $(CC) $(CFLAGS) -DPROGVERSION=\"$(PROGVERSION)\" \
+ -DPROGNAME=\"$(PROGNAME)\" -c -o $@ $<
+
+-ebtables: ebtables.o communication.o initext.o $(EXT_OBJS)
++ebtables: ebtables.o communication.o $(EXT_OBJS)
+ $(CC) $(CFLAGS) -o $@ $^
+
+ $(MANDIR)/man8/ebtables.8: ebtables.8
+--- ebtables-v2.0pre1/ebtables.c Wed Apr 3 20:06:18 2002
++++ ebtables-v2.0pre2/ebtables.c Sat Apr 6 21:57:05 2002
+@@ -1051,7 +1051,6 @@
+ replace.selected_hook = -1;
+ replace.command = 'h';
+ // execute the _init functions of the extensions
+- init_extensions();
+
+ new_entry = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
+ if (!new_entry)
+--- ebtables-v2.0pre1/extensions/ebt_nat.c Wed Apr 3 12:27:59 2002
++++ ebtables-v2.0pre2/extensions/ebt_nat.c Sat Apr 6 21:59:43 2002
+@@ -160,7 +160,8 @@
+ opts_d,
+ };
+
+-void _init(void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_target(&snat_target);
+ register_target(&dnat_target);
+--- ebtables-v2.0pre1/extensions/ebt_ip.c Wed Apr 3 12:28:44 2002
++++ ebtables-v2.0pre2/extensions/ebt_ip.c Sat Apr 6 21:58:23 2002
+@@ -301,7 +301,8 @@
+ opts,
+ };
+
+-void _init(void)
++static void _init(void) __attribute((constructor));
++static void _init(void)
+ {
+ register_match(&ip_match);
+ }
+--- ebtables-v2.0pre1/extensions/ebt_arp.c Wed Apr 3 12:29:17 2002
++++ ebtables-v2.0pre2/extensions/ebt_arp.c Sat Apr 6 21:58:05 2002
+@@ -271,7 +271,8 @@
+ opts,
+ };
+
+-void _init(void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_match(&arp_match);
+ }
+--- ebtables-v2.0pre1/extensions/ebt_log.c Wed Apr 3 16:23:56 2002
++++ ebtables-v2.0pre2/extensions/ebt_log.c Sat Apr 6 21:59:34 2002
+@@ -182,7 +182,9 @@
+ opts,
+ };
+
+-void _init(void)
++#undef _init
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_watcher(&log_watcher);
+ }
+--- ebtables-v2.0pre1/extensions/ebt_standard.c Mon Apr 1 12:49:59 2002
++++ ebtables-v2.0pre2/extensions/ebt_standard.c Sat Apr 6 22:01:29 2002
+@@ -59,7 +59,8 @@
+ opts
+ };
+
+-void _init(void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_target(&standard);
+ }
+--- ebtables-v2.0pre1/extensions/ebtable_filter.c Mon Apr 1 21:25:57 2002
++++ ebtables-v2.0pre2/extensions/ebtable_filter.c Sat Apr 6 22:00:02 2002
+@@ -24,7 +24,8 @@
+ NULL
+ };
+
+-void _init(void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_table(&table);
+ }
+--- ebtables-v2.0pre1/extensions/ebtable_nat.c Wed Apr 3 10:16:46 2002
++++ ebtables-v2.0pre2/extensions/ebtable_nat.c Sat Apr 6 21:59:53 2002
+@@ -24,7 +24,8 @@
+ NULL
+ };
+
+-void _init(void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+ register_table(&table);
+ }
+--- ebtables-v2.0pre1/include/ebtables_u.h Wed Apr 3 17:20:17 2002
++++ ebtables-v2.0pre2/include/ebtables_u.h Sat Apr 6 21:56:16 2002
+@@ -25,9 +25,6 @@
+ #define EBTABLES_U_H
+ #include <linux/netfilter_bridge/ebtables.h>
+ #include <linux/br_db.h>
+-#ifdef _INIT
+-#define _init _INIT
+-#endif
+
+ struct ebt_u_entries
+ {
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre2.002.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre2.002.diff
new file mode 100644
index 0000000..c638367
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre2.002.diff
@@ -0,0 +1,2204 @@
+This is a big patch.
+Hope I didn't break anything.
+
+--- ebtables-v2.0pre2.001/Makefile Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/Makefile Thu Apr 11 18:38:47 2002
+@@ -2,8 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre1 (April 2002)"
+-
++PROGVERSION:="2.0pre2.001 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+--- ebtables-v2.0pre2.001/ebtables.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/ebtables.c Wed Apr 10 22:46:27 2002
+@@ -34,7 +34,8 @@
+ #include <asm/types.h>
+ #include "include/ebtables_u.h"
+
+-// here are the number-name correspondences kept for the ethernet frame type field
++// here are the number-name correspondences kept for the ethernet
++// frame type field
+ #define PROTOCOLFILE "/etc/etherproto"
+
+ #define DATABASEHOOKNR NF_BR_NUMHOOKS
+@@ -81,27 +82,28 @@
+
+ // yup, all the possible target names
+ char* standard_targets[NUM_STANDARD_TARGETS] = {
+- "ACCEPT" ,
++ "ACCEPT",
+ "DROP",
+ "CONTINUE",
+ };
+
+ // tells what happened to the old rules
+-unsigned short *counterchanges;
++static unsigned short *counterchanges;
+ // holds all the data
+-struct ebt_u_replace replace;
++static struct ebt_u_replace replace;
+
+ // the chosen table
+-struct ebt_u_table *table = NULL;
++static struct ebt_u_table *table = NULL;
+ // the lists of supported tables, matches, watchers and targets
+-struct ebt_u_table *tables = NULL;
+-struct ebt_u_match *matches = NULL;
+-struct ebt_u_watcher *watchers = NULL;
+-struct ebt_u_target *targets = NULL;
++static struct ebt_u_table *tables = NULL;
++static struct ebt_u_match *matches = NULL;
++static struct ebt_u_watcher *watchers = NULL;
++static struct ebt_u_target *targets = NULL;
+
+ struct ebt_u_target *find_target(const char *name)
+ {
+ struct ebt_u_target *t = targets;
++
+ while(t && strcmp(t->name, name))
+ t = t->next;
+ return t;
+@@ -110,6 +112,7 @@
+ struct ebt_u_match *find_match(const char *name)
+ {
+ struct ebt_u_match *m = matches;
++
+ while(m && strcmp(m->name, name))
+ m = m->next;
+ return m;
+@@ -118,6 +121,7 @@
+ struct ebt_u_watcher *find_watcher(const char *name)
+ {
+ struct ebt_u_watcher *w = watchers;
++
+ while(w && strcmp(w->name, name))
+ w = w->next;
+ return w;
+@@ -126,17 +130,18 @@
+ struct ebt_u_table *find_table(char *name)
+ {
+ struct ebt_u_table *t = tables;
++
+ while (t && strcmp(t->name, name))
+ t = t->next;
+ return t;
+ }
+
+-// the pointers in here are special:
+-// the struct ebt_target * pointer is actually a struct ebt_u_target * pointer
+-// instead of making yet a few other structs, we just do a cast
+-// we need a struct ebt_u_target pointer because we know the address of the data they
+-// point to won't change. We want to allow that the struct ebt_u_target.t member can
+-// change.
++// The pointers in here are special:
++// The struct ebt_target * pointer is actually a struct ebt_u_target * pointer.
++// instead of making yet a few other structs, we just do a cast.
++// We need a struct ebt_u_target pointer because we know the address of the data
++// they point to won't change. We want to allow that the struct ebt_u_target.t
++// member can change.
+ // Same holds for the struct ebt_match and struct ebt_watcher pointers
+ struct ebt_u_entry *new_entry;
+
+@@ -149,13 +154,14 @@
+ strcpy(e->out, "");
+ e->m_list = NULL;
+ e->w_list = NULL;
+- // the init function of the standard target should have put the verdict on CONTINUE
++ // the init function of the standard target should have put the verdict
++ // on CONTINUE
+ e->t = (struct ebt_entry_target *)find_target(EBT_STANDARD_TARGET);
+ if (!e->t)
+ print_bug("Couldn't load standard target\n");
+ }
+
+-// this doesn't free e, basically becoz it's lazy
++// this doesn't free e, becoz the calling function might need e->next
+ void free_u_entry(struct ebt_u_entry *e)
+ {
+ struct ebt_u_match_list *m_l, *m_l2;
+@@ -178,6 +184,40 @@
+ free(e->t);
+ }
+
++// the user will use the match, so put it in new_entry
++static void add_match(struct ebt_u_match *m)
++{
++ struct ebt_u_match_list **m_list, *new;
++
++ m->used = 1;
++ for (m_list = &new_entry->m_list;
++ *m_list; m_list = &(*m_list)->next);
++ new = (struct ebt_u_match_list *)
++ malloc(sizeof(struct ebt_u_match_list));
++ if (!new)
++ print_memory();
++ *m_list = new;
++ new->next = NULL;
++ new->m = (struct ebt_entry_match *)m;
++}
++
++static void add_watcher(struct ebt_u_watcher *w)
++{
++ struct ebt_u_watcher_list **w_list;
++ struct ebt_u_watcher_list *new;
++
++ w->used = 1;
++ for (w_list = &new_entry->w_list;
++ *w_list; w_list = &(*w_list)->next);
++ new = (struct ebt_u_watcher_list *)
++ malloc(sizeof(struct ebt_u_watcher_list));
++ if (!new)
++ print_memory();
++ *w_list = new;
++ new->next = NULL;
++ new->w = (struct ebt_entry_watcher *)w;
++}
++
+ static int global_option_offset = 0;
+ #define OPTION_OFFSET 256
+ static struct option *
+@@ -196,6 +236,8 @@
+ *options_offset = global_option_offset;
+
+ merge = malloc(sizeof(struct option) * (num_new + num_old + 1));
++ if (!merge)
++ print_memory();
+ memcpy(merge, oldopts, num_old * sizeof(struct option));
+ for (i = 0; i < num_new; i++) {
+ merge[num_old + i] = newopts[i];
+@@ -219,7 +261,8 @@
+ print_memory();
+ strcpy(m->m->u.name, m->name);
+ m->m->match_size = size;
+- ebt_options = merge_options(ebt_options, m->extra_ops, &(m->option_offset));
++ ebt_options = merge_options
++ (ebt_options, m->extra_ops, &(m->option_offset));
+ m->init(m->m);
+
+ for (i = &matches; *i; i = &((*i)->next));
+@@ -237,7 +280,8 @@
+ print_memory();
+ strcpy(w->w->u.name, w->name);
+ w->w->watcher_size = size;
+- ebt_options = merge_options(ebt_options, w->extra_ops, &(w->option_offset));
++ ebt_options = merge_options
++ (ebt_options, w->extra_ops, &(w->option_offset));
+ w->init(w->w);
+
+ for (i = &watchers; *i; i = &((*i)->next));
+@@ -255,7 +299,8 @@
+ print_memory();
+ strcpy(t->t->u.name, t->name);
+ t->t->target_size = size;
+- ebt_options = merge_options(ebt_options, t->extra_ops, &(t->option_offset));
++ ebt_options = merge_options
++ (ebt_options, t->extra_ops, &(t->option_offset));
+ t->init(t->t);
+ for (i = &targets; *i; i = &((*i)->next));
+ t->next = NULL;
+@@ -292,7 +337,7 @@
+ return 0;
+ }
+
+-/* helper function: processes a line of data from the file brebt_protocolnames */
++// helper function: processes a line of data from the file /etc/etherproto
+ int get_a_line(char *buffer, char *value, FILE *ifp)
+ {
+ int i, hlp;
+@@ -314,7 +359,7 @@
+
+ // buffer[0] already contains the first letter
+ for (i = 1; i < 21; i++) {
+- hlp = fscanf(ifp, "%c", buffer+i);
++ hlp = fscanf(ifp, "%c", buffer + i);
+ if (hlp == EOF || hlp == 0) return -1;
+ if (buffer[i] == '\t' || buffer[i] == ' ')
+ break;
+@@ -327,7 +372,8 @@
+ // buffer[0] already contains the first letter
+ for (i = 1; i < 5; i++) {
+ hlp = fscanf(ifp, "%c", value+i);
+- if (value[i] == '\n' || value[i] == '\t' || value[i] == ' ' || hlp == EOF)
++ if (value[i] == '\n' || value[i] == '\t' ||
++ value[i] == ' ' || hlp == EOF)
+ break;
+ }
+ if (i == 5) return -1;
+@@ -342,7 +388,7 @@
+ return 0;
+ }
+
+-/* helper function for list_em() */
++// helper function for list_em()
+ int number_to_name(unsigned short proto, char *name)
+ {
+ FILE *ifp;
+@@ -363,13 +409,12 @@
+ fclose(ifp);
+ return 0;
+ }
+- return -1;
+ }
+
+-/* helper function for list_rules() */
++// helper function for list_rules()
+ static void list_em(int hooknr)
+ {
+- int i, space = 0;
++ int i, j, space = 0, digits;
+ struct ebt_u_entry *hlp;
+ struct ebt_u_match_list *m_l;
+ struct ebt_u_watcher_list *w_l;
+@@ -379,7 +424,8 @@
+ char name[21];
+
+ hlp = replace.hook_entry[hooknr]->entries;
+- printf("\nBridge chain: %s\nPolicy: %s\n", hooknames[hooknr], standard_targets[(int)(replace.hook_entry[hooknr]->policy)]);
++ printf("\nBridge chain: %s\nPolicy: %s\n", hooknames[hooknr],
++ standard_targets[replace.hook_entry[hooknr]->policy]);
+ printf("nr. of entries: %d \n", replace.hook_entry[hooknr]->nentries);
+
+ i = replace.hook_entry[hooknr]->nentries;
+@@ -389,19 +435,18 @@
+ }
+
+ for (i = 0; i < replace.hook_entry[hooknr]->nentries; i++) {
+- int j = i + 1, space2 = 0;
+- // a little work to get nice rule numbers
+- // this can probably be done easier - so what
++ digits = 0;
++ // A little work to get nice rule numbers.
+ while (j > 9) {
+- space2++;
++ digits++;
+ j /= 10;
+ }
+- for (j = 0; j < space - space2; j++)
++ for (j = 0; j < space - digits; j++)
+ printf(" ");
+ printf("%d. ", i + 1);
+
+- // don't print anything about the protocol if no protocol was specified
+- // obviously this means any protocol will do
++ // Don't print anything about the protocol if no protocol was
++ // specified, obviously this means any protocol will do.
+ if (!(hlp->bitmask & EBT_NOPROTO)) {
+ printf("eth proto: ");
+ if (hlp->invflags & EBT_IPROTO)
+@@ -416,20 +461,20 @@
+ }
+ }
+ if (hlp->bitmask & EBT_SOURCEMAC) {
+- int j;
+ printf("source mac: ");
+ if (hlp->invflags & EBT_ISOURCE)
+ printf("! ");
+ for (j = 0; j < ETH_ALEN; j++)
+- printf("%02x%s", hlp->sourcemac[j], (j == ETH_ALEN - 1) ? ", " : ":");
++ printf("%02x%s", hlp->sourcemac[j],
++ (j == ETH_ALEN - 1) ? ", " : ":");
+ }
+ if (hlp->bitmask & EBT_DESTMAC) {
+- int j;
+ printf("dest mac: ");
+ if (hlp->invflags & EBT_IDEST)
+ printf("! ");
+ for (j = 0; j < ETH_ALEN; j++)
+- printf("%02x%s", hlp->destmac[j], (j == ETH_ALEN - 1) ? ", " : ":");
++ printf("%02x%s", hlp->destmac[j],
++ (j == ETH_ALEN - 1) ? ", " : ":");
+ }
+ if (hlp->in[0] != '\0') {
+ if (hlp->invflags & EBT_IIN)
+@@ -462,9 +507,10 @@
+ printf("target: ");
+ t = find_target(hlp->t->u.name);
+ if (!t)
+- print_error("Target not found.");
++ print_bug("Target not found");
+ t->print(hlp, hlp->t);
+- printf(", count = %llu", replace.counters[replace.counter_entry[hooknr] + i].pcnt);
++ printf(", count = %llu",
++ replace.counters[replace.counter_entry[hooknr] + i].pcnt);
+ printf("\n");
+ hlp = hlp->next;
+ }
+@@ -492,30 +538,30 @@
+ struct ebt_u_watcher_list *w_l;
+
+ printf(
+- "%s v%s\n"
+- "Usage:\n"
+- "ebtables -[ADI] chain rule-specification [options]\n"
+- "ebtables -P chain target\n"
+- "ebtables -[LFZ] [chain]\n"
+- "ebtables -[b] [y,n]\n"
+- "Commands:\n"
+- "--append -A chain : Append to chain\n"
+- "--delete -D chain : Delete matching rule from chain\n"
+- "--delete -D chain rulenum : Delete rule at position rulenum from chain\n"
+- "--insert -I chain rulenum : insert rule at position rulenum in chain\n"
+- "--list -L [chain] : List the rules in a chain or in all chains\n"
+- "--list -L "DATABASEHOOKNAME" : List the database (if present)\n"
+- "--flush -F [chain] : Delete all rules in chain or in all chains\n"
+- "--zero -Z [chain] : Put counters on zero in chain or in all chains\n"
+- "--policy -P chain target : Change policy on chain to target\n"
+- "Options:\n"
+- "--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
+- "--src -s [!] address : source mac address\n"
+- "--dst -d [!] address : destination mac address\n"
+- "--in-if -i [!] name : network input interface name\n"
+- "--out-if -o [!] name : network output interface name\n"
+- "--version -V : print package version\n"
+- "\n" ,
++"%s v%s\n"
++"Usage:\n"
++"ebtables -[ADI] chain rule-specification [options]\n"
++"ebtables -P chain target\n"
++"ebtables -[LFZ] [chain]\n"
++"ebtables -[b] [y,n]\n"
++"Commands:\n"
++"--append -A chain : Append to chain\n"
++"--delete -D chain : Delete matching rule from chain\n"
++"--delete -D chain rulenum : Delete rule at position rulenum from chain\n"
++"--insert -I chain rulenum : insert rule at position rulenum in chain\n"
++"--list -L [chain] : List the rules in a chain or in all chains\n"
++"--list -L "DATABASEHOOKNAME" : List the database (if present)\n"
++"--flush -F [chain] : Delete all rules in chain or in all chains\n"
++"--zero -Z [chain] : Put counters on zero in chain or in all chains\n"
++"--policy -P chain target : Change policy on chain to target\n"
++"Options:\n"
++"--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
++"--src -s [!] address : source mac address\n"
++"--dst -d [!] address : destination mac address\n"
++"--in-if -i [!] name : network input interface name\n"
++"--out-if -o [!] name : network output interface name\n"
++"--version -V : print package version\n"
++"\n" ,
+ prog_name,
+ prog_version);
+
+@@ -538,7 +584,7 @@
+ exit(0);
+ }
+
+-/* execute command L */
++// execute command L
+ static void list_rules()
+ {
+ int i;
+@@ -563,7 +609,8 @@
+ replace.num_counters = replace.nentries;
+ if (replace.nentries) {
+ // '+ 1' for the CNT_END
+- if ( !(counterchanges = (unsigned short *)malloc((replace.nentries + 1) * sizeof(unsigned short))) )
++ if (!(counterchanges = (unsigned short *) malloc(
++ (replace.nentries + 1) * sizeof(unsigned short))))
+ print_memory();
+ // done nothing special to the rules
+ for (i = 0; i < replace.nentries; i++)
+@@ -611,12 +658,14 @@
+ if (replace.hook_entry[replace.selected_hook]->nentries == 0)
+ exit(0);
+ oldnentries = replace.nentries;
+- replace.nentries = replace.nentries - replace.hook_entry[replace.selected_hook]->nentries;
++ replace.nentries = replace.nentries -
++ replace.hook_entry[replace.selected_hook]->nentries;
+
+ // delete the counters belonging to the specified chain
+ if (replace.nentries) {
+ // +1 for CNT_END
+- if ( !(counterchanges = (unsigned short *)malloc((oldnentries + 1) * sizeof(unsigned short))) )
++ if ( !(counterchanges = (unsigned short *)
++ malloc((oldnentries + 1) * sizeof(unsigned short))) )
+ print_memory();
+ cnt = counterchanges;
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+@@ -660,23 +709,31 @@
+
+ // handle '-D chain rulenr' command
+ if (rule_nr != -1) {
+- if (rule_nr > replace.hook_entry[replace.selected_hook]->nentries)
++ if (rule_nr >
++ replace.hook_entry[replace.selected_hook]->nentries)
+ return 0;
++ // user starts counting from 1
+ return rule_nr - 1;
+ }
+ u_e = replace.hook_entry[replace.selected_hook]->entries;
+- // check for an existing rule (if there are duplicate rules, take the first occurance)
+- for (i = 0; i < replace.hook_entry[replace.selected_hook]->nentries; i++, u_e = u_e->next) {
++ // check for an existing rule (if there are duplicate rules,
++ // take the first occurance)
++ for (i = 0; i < replace.hook_entry[replace.selected_hook]->nentries;
++ i++, u_e = u_e->next) {
+ if (!u_e)
+ print_bug("Hmm, trouble");
+ if ( u_e->ethproto == new_entry->ethproto
+- && !strncmp(u_e->in, new_entry->in, IFNAMSIZ)
+- && !strncmp(u_e->out, new_entry->out, IFNAMSIZ) && u_e->bitmask == new_entry->bitmask) {
+- if (new_entry->bitmask & EBT_SOURCEMAC && strncmp(u_e->sourcemac, new_entry->sourcemac, ETH_ALEN))
++ && !strcmp(u_e->in, new_entry->in)
++ && !strcmp(u_e->out, new_entry->out)
++ && u_e->bitmask == new_entry->bitmask) {
++ if (new_entry->bitmask & EBT_SOURCEMAC &&
++ strcmp(u_e->sourcemac, new_entry->sourcemac))
+ continue;
+- if (new_entry->bitmask & EBT_DESTMAC && strncmp(u_e->destmac, new_entry->destmac, ETH_ALEN))
++ if (new_entry->bitmask & EBT_DESTMAC &&
++ strcmp(u_e->destmac, new_entry->destmac))
+ continue;
+- if (new_entry->bitmask != u_e->bitmask || new_entry->invflags != u_e->invflags)
++ if (new_entry->bitmask != u_e->bitmask ||
++ new_entry->invflags != u_e->invflags)
+ continue;
+ // compare all matches
+ m_l = new_entry->m_list;
+@@ -684,7 +741,8 @@
+ while (m_l) {
+ m = (struct ebt_u_match *)(m_l->m);
+ m_l2 = u_e->m_list;
+- while (m_l2 && strcmp(m_l2->m->u.name, m->m->u.name))
++ while (m_l2 &&
++ strcmp(m_l2->m->u.name, m->m->u.name))
+ m_l2 = m_l2->next;
+ if (!m_l2 || !m->compare(m->m, m_l2->m))
+ goto letscontinue;
+@@ -707,7 +765,8 @@
+ while (w_l) {
+ w = (struct ebt_u_watcher *)(w_l->w);
+ w_l2 = u_e->w_list;
+- while (w_l2 && strcmp(w_l2->w->u.name, w->w->u.name))
++ while (w_l2 &&
++ strcmp(w_l2->w->u.name, w->w->u.name))
+ w_l2 = w_l2->next;
+ if (!w_l2 || !w->compare(w->w, w_l2->w))
+ goto letscontinue;
+@@ -743,8 +802,10 @@
+ struct ebt_u_watcher_list *w_l;
+
+ if (rule_nr != -1) { // command -I
+- if (--rule_nr > replace.hook_entry[replace.selected_hook]->nentries)
+- print_error("rule nr too high: %d > %d.", rule_nr, replace.hook_entry[replace.selected_hook]->nentries);
++ if (--rule_nr >
++ replace.hook_entry[replace.selected_hook]->nentries)
++ print_error("rule nr too high: %d > %d", rule_nr,
++ replace.hook_entry[replace.selected_hook]->nentries);
+ } else
+ rule_nr = replace.hook_entry[replace.selected_hook]->nentries;
+ // we're adding one rule
+@@ -754,7 +815,8 @@
+
+ // handle counter stuff
+ // +1 for CNT_END
+- if ( !(counterchanges = (unsigned short *)malloc((replace.nentries + 1) * sizeof(unsigned short))) )
++ if ( !(counterchanges = (unsigned short *)
++ malloc((replace.nentries + 1) * sizeof(unsigned short))) )
+ print_memory();
+ cnt = counterchanges;
+ for (i = 0; i < replace.selected_hook; i++) {
+@@ -813,7 +875,7 @@
+ struct ebt_u_entry *u_e, *u_e2;
+
+ if ( (i = check_rule_exists(rule_nr)) == -1 )
+- print_error("Sorry, rule does not exists.");
++ print_error("Sorry, rule does not exists");
+
+ // we're deleting a rule
+ replace.num_counters = replace.nentries;
+@@ -827,7 +889,8 @@
+ }
+ lentmp += i;
+ // +1 for CNT_END
+- if ( !(counterchanges = (unsigned short *)malloc((replace.num_counters + 1) * sizeof(unsigned short))) )
++ if ( !(counterchanges = (unsigned short *)malloc(
++ (replace.num_counters + 1) * sizeof(unsigned short))) )
+ print_memory();
+ cnt = counterchanges;
+ for (j = 0; j < lentmp; j++) {
+@@ -871,8 +934,8 @@
+
+ if (zerochain == -1) {
+ // tell main() we don't update the counters
+- // this results in tricking the kernel to zero his counters, naively expecting
+- // userspace to update its counters. Muahahaha
++ // this results in tricking the kernel to zero his counters,
++ // naively expecting userspace to update its counters. Muahahaha
+ counterchanges = NULL;
+ replace.num_counters = 0;
+ } else {
+@@ -881,7 +944,10 @@
+
+ if (replace.hook_entry[zerochain]->nentries == 0)
+ exit(0);
+- counterchanges = (unsigned short *)malloc((replace.nentries + 1) * sizeof(unsigned short));
++ counterchanges = (unsigned short *)
++ malloc((replace.nentries + 1) * sizeof(unsigned short));
++ if (!counterchanges)
++ print_memory();
+ cnt = counterchanges;
+ for (i = 0; i < zerochain; i++) {
+ if (!(replace.valid_hooks & (1 << i)))
+@@ -915,10 +981,12 @@
+
+ // 0 : database disabled (-db n)
+ if (!(nr.nentries))
+- print_error("Database not present (disabled), try ebtables --db y.");
+- (nr.nentries)--;
+- if (!nr.nentries) print_error("Database empty.");
+- if ( !(db = (struct brdb_dbentry *) malloc(nr.nentries * sizeof(struct brdb_dbentry))) )
++ print_error("Database not present"
++ " (disabled), try ebtables --db y");
++ nr.nentries--;
++ if (!nr.nentries) print_error("Database empty");
++ if ( !(db = (struct brdb_dbentry *)
++ malloc(nr.nentries * sizeof(struct brdb_dbentry))) )
+ print_memory();
+
+ get_db(nr.nentries, db);
+@@ -931,7 +999,7 @@
+ "out-if : %s\n"
+ "protocol: ", i + 1, hooknames[db->hook], db->in, db->out);
+ if (db->ethproto == IDENTIFY802_3)
+- printf("NO PROTO, OLD 802.3 STYLE LENGTH FIELD\n");
++ printf("802.2/802.3 STYLE LENGTH FIELD\n");
+ else {
+ if (number_to_name(ntohs(db->ethproto), name))
+ printf("%x\n",ntohs(db->ethproto));
+@@ -943,13 +1011,13 @@
+ exit(0);
+ }
+
+-// handle counter and db disabling and enabling
++// handle db [dis,en]abling
+ static void allowdb(char yorn)
+ {
+ __u16 decision;
+
+ if (yorn != 'y' && yorn != 'n')
+- print_error("Option [y] or [n] needed.");
++ print_error("Option [y] or [n] needed");
+
+ if (yorn == 'y')
+ decision = BRDB_DB;
+@@ -980,7 +1048,8 @@
+ if (strcasecmp(buffer, name))
+ continue;
+ i = (unsigned short) strtol(value, &bfr, 16);
+- if (*bfr != '\0') return -1;
++ if (*bfr != '\0')
++ return -1;
+ new_entry->ethproto = i;
+ fclose(ifp);
+ return 0;
+@@ -1022,7 +1091,7 @@
+ void check_option(unsigned int *flags, unsigned int mask)
+ {
+ if (*flags & mask)
+- print_error("Multiple use of same option not allowed.");
++ print_error("Multiple use of same option not allowed");
+ *flags |= mask;
+ }
+
+@@ -1040,17 +1109,21 @@
+ {
+ char *buffer, allowbc = 'n';
+ int c, i;
+- int zerochain = -1; // this special one for the -Z option (we can have -Z <this> -L <that>)
++ // this special one for the -Z option (we can have -Z <this> -L <that>)
++ int zerochain = -1;
+ int policy = -1;
+ int rule_nr = -1;// used for -D chain number
+ struct ebt_u_target *t;
++ struct ebt_u_match *m;
++ struct ebt_u_watcher *w;
++ struct ebt_u_match_list *m_l;
++ struct ebt_u_watcher_list *w_l;
+
+- // initialize the table name, OPT_ flags and selected hook
++ // initialize the table name, OPT_ flags, selected hook and command
+ strcpy(replace.name, "filter");
+ replace.flags = 0;
+ replace.selected_hook = -1;
+ replace.command = 'h';
+- // execute the _init functions of the extensions
+
+ new_entry = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
+ if (!new_entry)
+@@ -1059,7 +1132,8 @@
+ initialize_entry(new_entry);
+
+ // getopt saves the day
+- while ((c = getopt_long(argc, argv, "-A:D:I:L::Z::F::P:Vhi:o:j:p:b:s:d:t:", ebt_options, NULL)) != -1) {
++ while ((c = getopt_long(argc, argv,
++ "-A:D:I:L::Z::F::P:Vhi:o:j:p:b:s:d:t:", ebt_options, NULL)) != -1) {
+ switch (c) {
+
+ case 'A': // add a rule
+@@ -1068,33 +1142,39 @@
+ case 'I': // insert a rule
+ replace.command = c;
+ if (replace.flags & OPT_COMMAND)
+- print_error("Multiple commands not allowed.");
++ print_error("Multiple commands not allowed");
+ replace.flags |= OPT_COMMAND;
+ if ((replace.selected_hook = get_hooknr(optarg)) == -1)
+- print_error("Bad chain.");
+- // '-' denotes another option, if no other option it must be the (optional) rule number
+- if (c == 'D' && optind < argc && argv[optind][0] != '-') {
++ print_error("Bad chain");
++ if (c == 'D' && optind < argc &&
++ argv[optind][0] != '-') {
+ rule_nr = strtol(argv[optind], &buffer, 10);
+ if (*buffer != '\0' || rule_nr < 0)
+- print_error("Problem with the specified rule number.");
++ print_error("Problem with the "
++ "specified rule number");
+ optind++;
+ }
+ if (c == 'P') {
+ if (optind >= argc)
+- print_error("No policy specified.");
++ print_error("No policy specified");
+ for (i = 0; i < 2; i++)
+- if (!strcmp(argv[optind], standard_targets[i]))
++ if (!strcmp(argv[optind],
++ standard_targets[i])) {
+ policy = i;
++ break;
++ }
+ if (policy == -1)
+- print_error("Wrong policy.");
++ print_error("Wrong policy");
+ optind++;
+ }
+ if (c == 'I') {
+ if (optind >= argc)
+- print_error("No rulenr for -I specified.");
++ print_error("No rulenr for -I"
++ " specified");
+ rule_nr = strtol(argv[optind], &buffer, 10);
+ if (*buffer != '\0' || rule_nr < 0)
+- print_error("Problem with the specified rule number.");
++ print_error("Problem with the specified"
++ " rule number");
+ optind++;
+ }
+ break;
+@@ -1104,24 +1184,29 @@
+ case 'Z': // zero counters
+ if (c == 'Z') {
+ if (replace.flags & OPT_ZERO)
+- print_error("Multiple commands not allowed.");
+- if ( (replace.flags & OPT_COMMAND && replace.command != 'L'))
+- print_error("command -Z only allowed together with command -L.");
++ print_error("Multiple commands"
++ " not allowed");
++ if ( (replace.flags & OPT_COMMAND &&
++ replace.command != 'L'))
++ print_error("command -Z only allowed "
++ "together with command -L");
+ replace.flags |= OPT_ZERO;
+ } else {
+ replace.command = c;
+ if (replace.flags & OPT_COMMAND)
+- print_error("Multiple commands not allowed.");
++ print_error("Multiple commands"
++ " not allowed");
+ replace.flags |= OPT_COMMAND;
+ }
+ i = -1;
+ if (optarg) {
+ if ( (i = get_hooknr(optarg)) == -1 )
+- print_error("Bad chain.");
++ print_error("Bad chain");
+ } else
+ if (optind < argc && argv[optind][0] != '-') {
+- if ( (i = get_hooknr(argv[optind])) == -1 )
+- print_error("Bad chain.");
++ if ((i = get_hooknr(argv[optind]))
++ == -1)
++ print_error("Bad chain");
+ optind++;
+ }
+ if (i != -1) {
+@@ -1135,47 +1220,34 @@
+ case 'V': // version
+ replace.command = 'V';
+ if (replace.flags & OPT_COMMAND)
+- print_error("Multiple commands not allowed.");
++ print_error("Multiple commands not allowed");
+ printf("%s, %s\n", prog_name, prog_version);
+ exit(0);
+
+ case 'h': // help
+ if (replace.flags & OPT_COMMAND)
+- print_error("Multiple commands not allowed.");
++ print_error("Multiple commands not allowed");
+ replace.command = 'h';
+ // All other arguments should be extension names
+ while (optind < argc) {
+ struct ebt_u_match *m;
+ struct ebt_u_watcher *w;
+
+- if ((m = find_match(argv[optind]))) {
+- struct ebt_u_match_list **m_list, *new;
+-
+- m->used = 1;
+- for (m_list = &new_entry->m_list; *m_list; m_list = &(*m_list)->next);
+- new = (struct ebt_u_match_list *)malloc(sizeof(struct ebt_u_match_list));
+- if (!new)
+- print_memory();
+- *m_list = new;
+- new->next = NULL;
+- new->m = (struct ebt_entry_match *)m;
+- } else if ((w = find_watcher(argv[optind]))) {
+- struct ebt_u_watcher_list **w_list, *new;
+- w->used = 1;
+- for (w_list = &new_entry->w_list; *w_list; w_list = &(*w_list)->next);
+- new = (struct ebt_u_watcher_list *)malloc(sizeof(struct ebt_u_watcher_list));
+- if (!new)
+- print_memory();
+- *w_list = new;
+- new->next = NULL;
+- new->w = (struct ebt_entry_watcher *)w;
+- } else {
++ if ((m = find_match(argv[optind])))
++ add_match(m);
++ else if ((w = find_watcher(argv[optind])))
++ add_watcher(w);
++ else {
+ if (!(t = find_target(argv[optind])))
+- print_error("Extension %s not found.", argv[optind]);
++ print_error("Extension %s "
++ "not found", argv[optind]);
+ if (replace.flags & OPT_JUMP)
+- print_error("Sorry, you can only see help for one target extension each time.");
++ print_error("Sorry, you can "
++ "only see help for one "
++ "target extension each time");
+ replace.flags |= OPT_JUMP;
+- new_entry->t = (struct ebt_entry_target *)t;
++ new_entry->t =
++ (struct ebt_entry_target *)t;
+ }
+ optind++;
+ }
+@@ -1184,7 +1256,7 @@
+ case 't': // table
+ check_option(&replace.flags, OPT_TABLE);
+ if (strlen(optarg) > EBT_TABLE_MAXNAMELEN)
+- print_error("Table name too long.");
++ print_error("Table name too long");
+ strcpy(replace.name, optarg);
+ break;
+
+@@ -1195,56 +1267,69 @@
+ case 's': // source mac
+ case 'd': // destination mac
+ if ((replace.flags & OPT_COMMAND) == 0)
+- print_error("No command specified.");
+- if ( replace.command != 'A' && replace.command != 'D' && replace.command != 'I')
+- print_error("Command and option do not match.");
++ print_error("No command specified");
++ if ( replace.command != 'A' &&
++ replace.command != 'D' && replace.command != 'I')
++ print_error("Command and option do not match");
+ if (c == 'i') {
+ check_option(&replace.flags, OPT_IN);
+- if (replace.selected_hook == 2)
+- print_error("Use in-interface only in INPUT, FORWARD and PREROUTING chains.");
++ if (replace.selected_hook > 2)
++ print_error("Use in-interface only in "
++ "INPUT, FORWARD and PREROUTING chains");
+ if (check_inverse(optarg))
+ new_entry->invflags |= EBT_IIN;
+
+ if (optind > argc)
+- print_error("Missing interface argument.");
++ print_error("No in-interface "
++ "specified");
+ if (strlen(argv[optind - 1]) >= IFNAMSIZ)
+- print_error("Illegal interfacelength.");
+- strncpy(new_entry->in, argv[optind - 1], IFNAMSIZ);
++ print_error("Illegal interfacelength");
++ strcpy(new_entry->in, argv[optind - 1]);
+ break;
+ }
+ if (c == 'o') {
+ check_option(&replace.flags, OPT_OUT);
+- if (replace.selected_hook == 0)
+- print_error("Use out-interface only in OUTPUT, FORWARD and POSTROUTING chains.");
++ if (replace.selected_hook < 2)
++ print_error("Use out-interface only"
++ " in OUTPUT, FORWARD and "
++ "POSTROUTING chains");
+ if (check_inverse(optarg))
+ new_entry->invflags |= EBT_IOUT;
+
+ if (optind > argc)
+- print_error("Missing interface argument.");
++ print_error("No out-interface "
++ "specified");
++
+ if (strlen(argv[optind - 1]) >= IFNAMSIZ)
+- print_error("Illegal interface length.");
+- strncpy(new_entry->out, argv[optind - 1], IFNAMSIZ);
++ print_error("Illegal interface "
++ "length");
++ strcpy(new_entry->out, argv[optind - 1]);
+ break;
+ }
+ if (c == 'j') {
+
+ check_option(&replace.flags, OPT_JUMP);
+ for (i = 0; i < NUM_STANDARD_TARGETS; i++)
+- if (!strcmp(optarg, standard_targets[i])) {
+- t = find_target(EBT_STANDARD_TARGET);
+- ((struct ebt_standard_target *)t->t)->verdict = i;
++ if (!strcmp(optarg,
++ standard_targets[i])) {
++ t = find_target(
++ EBT_STANDARD_TARGET);
++ ((struct ebt_standard_target *)
++ t->t)->verdict = i;
+ break;
+ }
+ // must be an extension then
+ if (i == NUM_STANDARD_TARGETS) {
+ struct ebt_u_target *t;
+ t = find_target(optarg);
+- if (!t)
+- print_error("Illegal target name.");
+- new_entry->t = (struct ebt_entry_target *)t;
+- } else
+- ((struct ebt_standard_target *)(((struct ebt_u_target *)new_entry->t)->t))->verdict = i;
+-
++ // -j standard not allowed either
++ if (!t || t ==
++ (struct ebt_u_target *)new_entry->t)
++ print_error("Illegal target "
++ "name");
++ new_entry->t =
++ (struct ebt_entry_target *)t;
++ }
+ break;
+ }
+ if (c == 's') {
+@@ -1253,9 +1338,12 @@
+ new_entry->invflags |= EBT_ISOURCE;
+
+ if (optind > argc)
+- print_error("Missing source mac argument.");
+- if (getmac(argv[optind - 1], new_entry->sourcemac))
+- print_error("Problem with specified source mac.");
++ print_error("No source mac "
++ "specified");
++ if (getmac(argv[optind - 1],
++ new_entry->sourcemac))
++ print_error("Problem with specified "
++ "source mac");
+ new_entry->bitmask |= EBT_SOURCEMAC;
+ break;
+ }
+@@ -1265,9 +1353,12 @@
+ new_entry->invflags |= EBT_IDEST;
+
+ if (optind > argc)
+- print_error("Missing destination mac argument.");
+- if (getmac(argv[optind - 1], new_entry->destmac))
+- print_error("Problem with specified destination mac.");
++ print_error("No destination mac "
++ "specified");
++ if (getmac(argv[optind - 1],
++ new_entry->destmac))
++ print_error("Problem with specified "
++ "destination mac");
+ new_entry->bitmask |= EBT_DESTMAC;
+ break;
+ }
+@@ -1276,22 +1367,26 @@
+ new_entry->invflags |= EBT_IPROTO;
+
+ if (optind > argc)
+- print_error("Missing protocol argument.");
++ print_error("No protocol specified");
+ new_entry->bitmask &= ~((unsigned int)EBT_NOPROTO);
+ i = strtol(argv[optind - 1], &buffer, 16);
+ if (*buffer == '\0' && (i < 0 || i > 0xFFFF))
+- print_error("Problem with the specified protocol.");
++ print_error("Problem with the specified "
++ "protocol");
+ new_entry->ethproto = i;
+ if (*buffer != '\0')
+ if (name_to_protocol(argv[optind - 1]) == -1)
+- print_error("Problem with the specified protocol.");
+- if (new_entry->ethproto < 1536 && !(new_entry->bitmask & EBT_802_3))
+- print_error("Sorry, protocols have values above or equal to 1536 (0x0600).");
++ print_error("Problem with the specified"
++ " protocol");
++ if (new_entry->ethproto < 1536 &&
++ !(new_entry->bitmask & EBT_802_3))
++ print_error("Sorry, protocols have values above"
++ " or equal to 1536 (0x0600)");
+ break;
+
+ case 'b': // allow database?
+ if (replace.flags & OPT_COMMAND)
+- print_error("Multiple commands not allowed.");
++ print_error("Multiple commands not allowed");
+ replace.command = c;
+ allowbc = *optarg;
+ break;
+@@ -1300,49 +1395,32 @@
+
+ // is it a target option?
+ t = (struct ebt_u_target *)new_entry->t;
+- if (!(t->parse(c - t->option_offset, argv, argc, new_entry, &t->flags, &t->t))) {
+- struct ebt_u_match *m;
+-
+- // is it a match_option?
+- for (m = matches; m; m = m->next)
+- if (m->parse(c - m->option_offset, argv, argc, new_entry, &m->flags, &m->m))
+- break;
++ if ((t->parse(c - t->option_offset, argv, argc,
++ new_entry, &t->flags, &t->t)))
++ continue;
+
+- if (m == NULL) {
+- struct ebt_u_watcher *w;
++ // is it a match_option?
++ for (m = matches; m; m = m->next)
++ if (m->parse(c - m->option_offset, argv,
++ argc, new_entry, &m->flags, &m->m))
++ break;
+
+- // is it a watcher option?
+- for (w = watchers; w; w = w->next)
+- if (w->parse(c - w->option_offset, argv, argc, new_entry, &w->flags, &w->w))
+- break;
+-
+- if (w == NULL)
+- print_error("Unknown argument.");
+- if (w->used == 0) {
+- struct ebt_u_watcher_list **w_list, *new;
+- w->used = 1;
+- for (w_list = &new_entry->w_list; *w_list; w_list = &(*w_list)->next);
+- new = (struct ebt_u_watcher_list *)malloc(sizeof(struct ebt_u_watcher_list));
+- if (!new)
+- print_memory();
+- *w_list = new;
+- new->next = NULL;
+- new->w = (struct ebt_entry_watcher *)w;
+- }
+- } else {
+- if (m->used == 0) {
+- struct ebt_u_match_list **m_list, *new;
+- m->used = 1;
+- for (m_list = &new_entry->m_list; *m_list; m_list = &(*m_list)->next);
+- new = (struct ebt_u_match_list *)malloc(sizeof(struct ebt_u_match_list));
+- if (!new)
+- print_memory();
+- *m_list = new;
+- new->next = NULL;
+- new->m = (struct ebt_entry_match *)m;
+- }
+- }
++ if (m != NULL) {
++ if (m->used == 0)
++ add_match(m);
++ continue;
+ }
++
++ // is it a watcher option?
++ for (w = watchers; w; w = w->next)
++ if (w->parse(c-w->option_offset, argv,
++ argc, new_entry, &w->flags, &w->w))
++ break;
++
++ if (w == NULL)
++ print_error("Unknown argument");
++ if (w->used == 0)
++ add_watcher(w);
+ }
+ }
+
+@@ -1352,43 +1430,40 @@
+ if (replace.command == 'L' && replace.selected_hook == DATABASEHOOKNR)
+ list_db();
+
+- if ( (replace.flags & OPT_COMMAND) && replace.command != 'L' && replace.flags & OPT_ZERO )
+- print_error("Command -Z only allowed together with command -L.");
++ if ( (replace.flags & OPT_COMMAND) && replace.command != 'L' &&
++ replace.flags & OPT_ZERO )
++ print_error("Command -Z only allowed together with command -L");
+
+- if (replace.command == 'A' || replace.command == 'I' || replace.command == 'D') {
++ if (replace.command == 'A' || replace.command == 'I' ||
++ replace.command == 'D') {
+ if (replace.selected_hook == -1)
+- print_error("Not enough information.");
++ print_error("Not enough information");
+ }
+
+ if ( !(table = find_table(replace.name)) )
+- print_error("Bad table name.");
++ print_error("Bad table name");
+
+ // do this after parsing everything, so we can print specific info
+ if (replace.command == 'h' && !(replace.flags & OPT_ZERO))
+ print_help();
+
+ // do the final checks
+- {
+- struct ebt_u_match_list *m_l = new_entry->m_list;
+- struct ebt_u_match *m;
+- struct ebt_u_watcher_list *w_l = new_entry->w_list;
+- struct ebt_u_watcher *w;
+- struct ebt_u_target *t = (struct ebt_u_target *)new_entry->t;
+-
++ m_l = new_entry->m_list;
++ w_l = new_entry->w_list;
++ t = (struct ebt_u_target *)new_entry->t;
+ while (m_l) {
+ m = (struct ebt_u_match *)(m_l->m);
+- m->final_check(new_entry, m->m, replace.name, replace.selected_hook);
++ m->final_check(new_entry, m->m, replace.name,
++ replace.selected_hook);
+ m_l = m_l->next;
+ }
+-
+ while (w_l) {
+ w = (struct ebt_u_watcher *)(w_l->w);
+- w->final_check(new_entry, w->w, replace.name, replace.selected_hook);
++ w->final_check(new_entry, w->w, replace.name,
++ replace.selected_hook);
+ w_l = w_l->next;
+ }
+-
+ t->final_check(new_entry, t->t, replace.name, replace.selected_hook);
+- }
+
+ // so, the extensions can work with the host endian
+ // the kernel does not have to do this ofcourse
+@@ -1396,10 +1471,10 @@
+
+ // get the kernel's information
+ get_table(&replace);
+- replace.nentries = replace.nentries;
+ // check if selected_hook is a valid_hook
+- if (replace.selected_hook >= 0 && !(replace.valid_hooks & (1 << replace.selected_hook)))
+- print_error("Bad chain name.");
++ if (replace.selected_hook >= 0 &&
++ !(replace.valid_hooks & (1 << replace.selected_hook)))
++ print_error("Bad chain name");
+ if (replace.command == 'P')
+ change_policy(policy);
+ else if (replace.command == 'L') {
+--- ebtables-v2.0pre2.001/communication.c Wed Apr 3 17:22:39 2002
++++ ebtables-v2.0pre2.002/communication.c Wed Apr 10 22:10:49 2002
+@@ -25,12 +25,6 @@
+
+ extern char* hooknames[NF_BR_NUMHOOKS];
+
+-void print_memory()
+-{
+- printf("Out of memory\n");
+- exit(0);
+-}
+-
+ int sockfd = -1;
+
+ void get_sockfd()
+@@ -38,7 +32,7 @@
+ if (sockfd == -1) {
+ sockfd = socket(AF_INET, SOCK_RAW, PF_INET);
+ if (sockfd < 0)
+- print_error("Problem getting a socket.");
++ print_error("Problem getting a socket");
+ }
+ }
+
+@@ -60,7 +54,8 @@
+ new->nentries = u_repl->nentries;
+ new->num_counters = u_repl->num_counters;
+ new->counters = u_repl->counters;
+- memcpy(new->counter_entry, u_repl->counter_entry, sizeof(new->counter_entry));
++ memcpy(new->counter_entry, u_repl->counter_entry,
++ sizeof(new->counter_entry));
+ // determine size
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+ if (!(new->valid_hooks & (1 << i)))
+@@ -86,7 +81,8 @@
+ }
+ // a little sanity check
+ if (j != u_repl->hook_entry[i]->nentries)
+- print_bug("Wrong nentries: %d != %d, hook = %s", j, u_repl->hook_entry[i]->nentries, hooknames[i]);
++ print_bug("Wrong nentries: %d != %d, hook = %s", j,
++ u_repl->hook_entry[i]->nentries, hooknames[i]);
+ }
+
+ new->entries_size = entries_size;
+@@ -116,7 +112,8 @@
+ tmp->ethproto = e->ethproto;
+ memcpy(tmp->in, e->in, sizeof(tmp->in));
+ memcpy(tmp->out, e->out, sizeof(tmp->out));
+- memcpy(tmp->sourcemac, e->sourcemac, sizeof(tmp->sourcemac));
++ memcpy(tmp->sourcemac, e->sourcemac,
++ sizeof(tmp->sourcemac));
+ memcpy(tmp->destmac, e->destmac, sizeof(tmp->destmac));
+
+ base = p;
+@@ -159,11 +156,13 @@
+ // give the data to the kernel
+ optlen = sizeof(struct ebt_replace) + repl->entries_size;
+ if (setsockopt(sockfd, IPPROTO_IP, EBT_SO_SET_ENTRIES, repl, optlen))
+- print_error("Couldn't update kernel chains, you probably need to insmod an extension.");
++ print_error("Couldn't update kernel chains, you probably need "
++ "to insmod an extension");
+ }
+
+ // gets executed after deliver_table
+-void deliver_counters(struct ebt_u_replace *u_repl, unsigned short *counterchanges)
++void
++deliver_counters(struct ebt_u_replace *u_repl, unsigned short *counterchanges)
+ {
+ unsigned short *point;
+ struct ebt_counter *old, *new, *newcounters;
+@@ -173,7 +172,8 @@
+ if (u_repl->nentries == 0)
+ return;
+
+- newcounters = (struct ebt_counter *)malloc(u_repl->nentries * sizeof(struct ebt_counter));
++ newcounters = (struct ebt_counter *)
++ malloc(u_repl->nentries * sizeof(struct ebt_counter));
+ if (!newcounters)
+ print_memory();
+ memset(newcounters, 0, u_repl->nentries * sizeof(struct ebt_counter));
+@@ -208,7 +208,8 @@
+ free(u_repl->counters);
+ u_repl->counters = newcounters;
+ u_repl->num_counters = u_repl->nentries;
+- optlen = u_repl->nentries * sizeof(struct ebt_counter) + sizeof(struct ebt_replace);
++ optlen = u_repl->nentries * sizeof(struct ebt_counter) +
++ sizeof(struct ebt_replace);
+ // now put the stuff in the kernel's struct ebt_replace
+ repl.counters = u_repl->counters;
+ repl.num_counters = u_repl->num_counters;
+@@ -224,7 +225,8 @@
+ {
+ struct ebt_u_match_list *new;
+
+- new = (struct ebt_u_match_list *)malloc(sizeof(struct ebt_u_match_list));
++ new = (struct ebt_u_match_list *)
++ malloc(sizeof(struct ebt_u_match_list));
+ if (!new)
+ print_memory();
+ new->m = (struct ebt_entry_match *)malloc(m->match_size);
+@@ -235,12 +237,14 @@
+ **l = new;
+ *l = &new->next;
+ if (find_match(new->m->u.name) == NULL)
+- print_error("Kernel match %s unsupported by userspace tool.", new->m->u.name);
++ print_error("Kernel match %s unsupported by userspace tool",
++ new->m->u.name);
+ return 0;
+ }
+
+ static int
+-ebt_translate_watcher(struct ebt_entry_watcher *w, struct ebt_u_watcher_list ***l)
++ebt_translate_watcher(struct ebt_entry_watcher *w,
++ struct ebt_u_watcher_list ***l)
+ {
+ struct ebt_u_watcher_list *new;
+
+@@ -255,13 +259,15 @@
+ **l = new;
+ *l = &new->next;
+ if (find_watcher(new->w->u.name) == NULL)
+- print_error("Kernel watcher %s unsupported by userspace tool.", new->w->u.name);
++ print_error("Kernel watcher %s unsupported by userspace tool",
++ new->w->u.name);
+ return 0;
+ }
+
+ static int
+-ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt, int *totalcnt,
+- struct ebt_u_entry ***u_e, struct ebt_u_replace *u_repl, unsigned int valid_hooks)
++ebt_translate_entry(struct ebt_entry *e, unsigned int *hook, int *n, int *cnt,
++ int *totalcnt, struct ebt_u_entry ***u_e, struct ebt_u_replace *u_repl,
++ unsigned int valid_hooks)
+ {
+ // an entry
+ if (e->bitmask & EBT_ENTRY_OR_ENTRIES) {
+@@ -295,7 +301,8 @@
+ if (!new->t)
+ print_memory();
+ if (find_target(t->u.name) == NULL)
+- print_error("Kernel target %s unsupported by userspace tool.", t->u.name);
++ print_error("Kernel target %s unsupported by "
++ "userspace tool", t->u.name);
+ memcpy(new->t, t, t->target_size);
+
+ // I love pointers
+@@ -304,7 +311,7 @@
+ (*cnt)++;
+ (*totalcnt)++;
+ return 0;
+- } else {// a new chain
++ } else { // a new chain
+ int i;
+ struct ebt_entries *entries = (struct ebt_entries *)e;
+ struct ebt_u_entries *new;
+@@ -319,7 +326,8 @@
+ print_bug("Nr of entries in the chain is wrong");
+ *n = entries->nentries;
+ *cnt = 0;
+- new = (struct ebt_u_entries *)malloc(sizeof(struct ebt_u_entries));
++ new = (struct ebt_u_entries *)
++ malloc(sizeof(struct ebt_u_entries));
+ if (!new)
+ print_memory();
+ new->nentries = entries->nentries;
+@@ -344,12 +352,14 @@
+ optlen = sizeof(struct ebt_replace);
+ strcpy(repl.name, u_repl->name);
+ if (getsockopt(sockfd, IPPROTO_IP, EBT_SO_GET_INFO, &repl, &optlen))
+- print_bug("hmm, what is wrong??? bug#3");
++ print_error("A kernel module needed by your command is probably"
++ " not loaded. Try insmod ebtables or the like");
+
+ if ( !(repl.entries = (char *) malloc(repl.entries_size)) )
+ print_memory();
+ if (repl.nentries) {
+- if (!(repl.counters = (struct ebt_counter *) malloc(repl.nentries * sizeof(struct ebt_counter))) )
++ if (!(repl.counters = (struct ebt_counter *)
++ malloc(repl.nentries * sizeof(struct ebt_counter))) )
+ print_memory();
+ }
+ else
+@@ -357,7 +367,8 @@
+
+ // we want to receive the counters
+ repl.num_counters = repl.nentries;
+- optlen += repl.entries_size + repl.num_counters * sizeof(struct ebt_counter);
++ optlen += repl.entries_size + repl.num_counters *
++ sizeof(struct ebt_counter);
+ if (getsockopt(sockfd, IPPROTO_IP, EBT_SO_GET_ENTRIES, &repl, &optlen))
+ print_bug("hmm, what is wrong??? bug#1");
+
+@@ -367,12 +378,15 @@
+ u_repl->nentries = repl.nentries;
+ u_repl->num_counters = repl.num_counters;
+ u_repl->counters = repl.counters;
+- memcpy(u_repl->counter_entry, repl.counter_entry, sizeof(repl.counter_entry));
++ memcpy(u_repl->counter_entry, repl.counter_entry,
++ sizeof(repl.counter_entry));
+ hook = -1;
+ i = 0; // holds the expected nr. of entries for the chain
+ j = 0; // holds the up to now counted entries for the chain
+- k = 0; // holds the total nr. of entries, should equal u_repl->nentries afterwards
+- EBT_ENTRY_ITERATE(repl.entries, repl.entries_size, ebt_translate_entry, &hook, &i, &j, &k, &u_e, u_repl, u_repl->valid_hooks);
++ k = 0; // holds the total nr. of entries,
++ // should equal u_repl->nentries afterwards
++ EBT_ENTRY_ITERATE(repl.entries, repl.entries_size, ebt_translate_entry,
++ &hook, &i, &j, &k, &u_e, u_repl, u_repl->valid_hooks);
+ if (k != u_repl->nentries)
+ print_bug("Wrong total nentries");
+ }
+@@ -384,7 +398,8 @@
+ get_sockfd();
+
+ if (getsockopt(sockfd, IPPROTO_IP, BRDB_SO_GET_DBINFO, nr, &optlen))
+- print_error("Sorry, br_db code probably not in kernel, try insmod br_db.");
++ print_error("Sorry, br_db code probably not in kernel, "
++ "try insmod br_db");
+ }
+
+ void get_db(int len, struct brdb_dbentry *db)
+@@ -405,5 +420,6 @@
+ get_sockfd();
+
+ if (setsockopt(sockfd, IPPROTO_IP, BRDB_SO_SET_ALLOWDB, decision, optlen))
+- print_error("Sorry, br_db code probably not in kernel, try insmod br_db.");
++ print_error("Sorry, br_db code probably not in kernel, "
++ "try insmod br_db");
+ }
+--- ebtables-v2.0pre2.001/extensions/ebt_nat.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebt_nat.c Thu Apr 11 18:12:55 2002
+@@ -52,8 +52,9 @@
+ }
+
+ #define OPT_SNAT 0x01
+-static int parse_s(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_target **target)
++static int parse_s(int c, char **argv, int argc,
++ const struct ebt_u_entry *entry, unsigned int *flags,
++ struct ebt_entry_target **target)
+ {
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
+
+@@ -62,7 +63,7 @@
+ check_option(flags, OPT_SNAT);
+ to_source_supplied = 1;
+ if (getmac(optarg, natinfo->mac))
+- print_error("Problem with specified to-source mac.");
++ print_error("Problem with specified to-source mac");
+ break;
+ default:
+ return 0;
+@@ -71,8 +72,9 @@
+ }
+
+ #define OPT_DNAT 0x01
+-static int parse_d(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_target **target)
++static int parse_d(int c, char **argv, int argc,
++ const struct ebt_u_entry *entry, unsigned int *flags,
++ struct ebt_entry_target **target)
+ {
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
+
+@@ -81,7 +83,8 @@
+ check_option(flags, OPT_DNAT);
+ to_dest_supplied = 1;
+ if (getmac(optarg, natinfo->mac))
+- print_error("Problem with specified to-destination mac.");
++ print_error("Problem with specified "
++ "to-destination mac");
+ break;
+ default:
+ return 0;
+@@ -89,44 +92,52 @@
+ return 1;
+ }
+
+-static void final_check_s(const struct ebt_u_entry *entry, const struct ebt_entry_target *target, const char *name, unsigned int hook)
++static void final_check_s(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target, const char *name, unsigned int hook)
+ {
+ if (hook != NF_BR_POST_ROUTING || strcmp(name, "nat"))
+- print_error("Wrong chain for SNAT.");
++ print_error("Wrong chain for SNAT");
+ if (to_source_supplied == 0)
+- print_error("No snat address supplied.");
++ print_error("No snat address supplied");
+
+ }
+
+-static void final_check_d(const struct ebt_u_entry *entry, const struct ebt_entry_target *target, const char *name, unsigned int hook)
++static void final_check_d(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target, const char *name, unsigned int hook)
+ {
+- if ( (hook != NF_BR_PRE_ROUTING && hook != NF_BR_LOCAL_OUT) || strcmp(name, "nat") )
+- print_error("Wrong chain for DNAT.");
++ if ( (hook != NF_BR_PRE_ROUTING && hook != NF_BR_LOCAL_OUT) ||
++ strcmp(name, "nat") )
++ print_error("Wrong chain for DNAT");
+ if (to_dest_supplied == 0)
+- print_error("No dnat address supplied.");
++ print_error("No dnat address supplied");
+ }
+
+-static void print_s(const struct ebt_u_entry *entry, const struct ebt_entry_target *target)
++static void print_s(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target)
+ {
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
+ int i;
+
+ printf("snat - to: ");
+ for (i = 0; i < ETH_ALEN; i++)
+- printf("%02x%s", natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
++ printf("%02x%s",
++ natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
+ }
+
+-static void print_d(const struct ebt_u_entry *entry, const struct ebt_entry_target *target)
++static void print_d(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target)
+ {
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
+ int i;
+
+ printf("dnat - to: ");
+ for (i = 0; i < ETH_ALEN; i++)
+- printf("%02x%s", natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
++ printf("%02x%s",
++ natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
+ }
+
+-static int compare(const struct ebt_entry_target *t1, const struct ebt_entry_target *t2)
++static int compare(const struct ebt_entry_target *t1,
++ const struct ebt_entry_target *t2)
+ {
+ struct ebt_nat_info *natinfo1 = (struct ebt_nat_info *)t1->data;
+ struct ebt_nat_info *natinfo2 = (struct ebt_nat_info *)t2->data;
+--- ebtables-v2.0pre2.001/extensions/ebt_ip.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebt_ip.c Wed Apr 10 23:28:40 2002
+@@ -40,16 +40,16 @@
+ return -1;
+ *q = '\0';
+ onebyte = strtol(p, &end, 10);
+- if (*end != '\0' || onebyte >255 || onebyte < 0)
++ if (*end != '\0' || onebyte > 255 || onebyte < 0)
+ return -1;
+- ip2[i] = (unsigned char) onebyte;
++ ip2[i] = (unsigned char)onebyte;
+ p = q + 1;
+ }
+
+ onebyte = strtol(p, &end, 10);
+ if (*end != '\0' || onebyte >255 || onebyte < 0)
+ return -1;
+- ip2[3] = (unsigned char) onebyte;
++ ip2[3] = (unsigned char)onebyte;
+
+ return 0;
+ }
+@@ -88,15 +88,15 @@
+ *p = '\0';
+ i = ip_mask(p + 1, (unsigned char *)msk);
+ if (i)
+- print_error("Problem with the ip mask.");
++ print_error("Problem with the ip mask");
+ }
+ else
+ *msk = 0xFFFFFFFF;
+
+ i = undot_ip(address, (unsigned char *)addr);
+- *addr = *addr & *msk;
+ if (i)
+- print_error("Problem with the ip address.");
++ print_error("Problem with the ip address");
++ *addr = *addr & *msk;
+ }
+
+ // transform the ip mask into a string ready for output
+@@ -106,7 +106,6 @@
+ static char buf[20];
+ __u32 maskaddr, bits;
+
+- // cool hack I copied from iptables.c ... Think about it :-)
+ maskaddr = ntohl(mask);
+
+ // don't print /32
+@@ -114,7 +113,7 @@
+ return "";
+
+ i = 32;
+- bits = 0xFFFFFFFEL;// case 0xFFFFFFFF has just been dealt with
++ bits = 0xFFFFFFFEL; // case 0xFFFFFFFF has just been dealt with
+ while (--i >= 0 && maskaddr != bits)
+ bits <<= 1;
+
+@@ -123,9 +122,10 @@
+ else if (!i)
+ *buf = '\0';
+ else
+- /* mask was not a decent combination of 1's and 0's */
+- sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0], ((unsigned char *)&mask)[1],
+- ((unsigned char *)&mask)[2], ((unsigned char *)&mask)[3]);
++ // mask was not a decent combination of 1's and 0's
++ sprintf(buf, "/%d.%d.%d.%d", ((unsigned char *)&mask)[0],
++ ((unsigned char *)&mask)[1], ((unsigned char *)&mask)[2],
++ ((unsigned char *)&mask)[3]);
+
+ return buf;
+ }
+@@ -133,11 +133,11 @@
+ static void print_help()
+ {
+ printf(
+- "ip options:\n"
+- "--ip-src [!] address[/mask]: ip source specification\n"
+- "--ip-dst [!] address[/mask]: ip destination specification\n"
+- "--ip-tos [!] tos : ip tos specification\n"
+- "--ip-proto [!] protocol : ip protocol specification\n");
++"ip options:\n"
++"--ip-src [!] address[/mask]: ip source specification\n"
++"--ip-dst [!] address[/mask]: ip destination specification\n"
++"--ip-tos [!] tos : ip tos specification\n"
++"--ip-proto [!] protocol : ip protocol specification\n");
+ }
+
+ static void init(struct ebt_entry_match *match)
+@@ -152,9 +152,8 @@
+ #define OPT_DEST 0x02
+ #define OPT_TOS 0x04
+ #define OPT_PROTO 0x08
+-static int parse(int c, char **argv, int argc,
+- const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_match **match)
++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_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data;
+ char *end, *buffer;
+@@ -163,13 +162,13 @@
+ switch (c) {
+ case IP_SOURCE:
+ check_option(flags, OPT_SOURCE);
++ ipinfo->bitmask |= EBT_IP_SOURCE;
++
+ case IP_DEST:
+- if (c == IP_DEST)
++ if (c == IP_DEST) {
+ check_option(flags, OPT_DEST);
+- if (c == IP_SOURCE)
+- ipinfo->bitmask |= EBT_IP_SOURCE;
+- else
+ ipinfo->bitmask |= EBT_IP_DEST;
++ }
+ if (check_inverse(optarg)) {
+ if (c == IP_SOURCE)
+ ipinfo->invflags |= EBT_IP_SOURCE;
+@@ -178,34 +177,38 @@
+ }
+
+ if (optind > argc)
+- print_error("Missing ip address argument.");
++ print_error("Missing ip address argument");
+ if (c == IP_SOURCE)
+- parse_ip_address(argv[optind - 1], &ipinfo->saddr, &ipinfo->smsk);
++ parse_ip_address(argv[optind - 1], &ipinfo->saddr,
++ &ipinfo->smsk);
+ else
+- parse_ip_address(argv[optind - 1], &ipinfo->daddr, &ipinfo->dmsk);
++ parse_ip_address(argv[optind - 1], &ipinfo->daddr,
++ &ipinfo->dmsk);
+ break;
++
+ case IP_myTOS:
+ check_option(flags, OPT_TOS);
+ if (check_inverse(optarg))
+ ipinfo->invflags |= EBT_IP_TOS;
+
+ if (optind > argc)
+- print_error("Missing ip tos argument.");
++ print_error("Missing ip tos argument");
+ i = strtol(argv[optind - 1], &end, 16);
+ if (i < 0 || i > 255 || *buffer != '\0')
+- print_error("Problem with specified ip tos.");
++ print_error("Problem with specified ip tos");
+ ipinfo->tos = i;
+ ipinfo->bitmask |= EBT_IP_TOS;
+ break;
++
+ case IP_PROTO:
+ check_option(flags, OPT_PROTO);
+ if (check_inverse(optarg))
+ ipinfo->invflags |= EBT_IP_PROTO;
+ if (optind > argc)
+- print_error("Missing ip protocol argument.");
++ print_error("Missing ip protocol argument");
+ i = strtol(argv[optind - 1], &end, 10);
+ if (i < 0 || i > 255 || *end != '\0')
+- print_error("Problem with specified ip protocol.");
++ print_error("Problem with specified ip protocol");
+ ipinfo->protocol = i;
+ ipinfo->bitmask |= EBT_IP_PROTO;
+ break;
+@@ -215,13 +218,17 @@
+ return 1;
+ }
+
+-static void final_check(const struct ebt_u_entry *entry, const struct ebt_entry_match *match, const char *name, unsigned int hook)
++static void final_check(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match, const char *name, unsigned int hook)
+ {
+- if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 || entry->ethproto != ETH_P_IP)
+- print_error("For IP filtering the protocol must be specified as IPV4.");
++ if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 ||
++ entry->ethproto != ETH_P_IP)
++ print_error("For IP filtering the protocol must be "
++ "specified as IPv4");
+ }
+
+-static void print(const struct ebt_u_entry *entry, const struct ebt_entry_match *match)
++static void print(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match)
+ {
+ struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
+ int j;
+@@ -231,7 +238,8 @@
+ if (ipinfo->invflags & EBT_IP_SOURCE)
+ printf("! ");
+ for (j = 0; j < 4; j++)
+- printf("%d%s", ((unsigned char *)&ipinfo->saddr)[j], (j == 3) ? "" : ".");
++ printf("%d%s",((unsigned char *)&ipinfo->saddr)[j],
++ (j == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(ipinfo->smsk));
+ }
+ if (ipinfo->bitmask & EBT_IP_DEST) {
+@@ -239,7 +247,8 @@
+ if (ipinfo->invflags & EBT_IP_DEST)
+ printf("! ");
+ for (j = 0; j < 4; j++)
+- printf("%d%s", ((unsigned char *)&ipinfo->daddr)[j], (j == 3) ? "" : ".");
++ printf("%d%s", ((unsigned char *)&ipinfo->daddr)[j],
++ (j == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(ipinfo->dmsk));
+ }
+ if (ipinfo->bitmask & EBT_IP_TOS) {
+@@ -256,7 +265,8 @@
+ }
+ }
+
+-static int compare(const struct ebt_entry_match *m1, const struct ebt_entry_match *m2)
++static int compare(const struct ebt_entry_match *m1,
++ const struct ebt_entry_match *m2)
+ {
+ struct ebt_ip_info *ipinfo1 = (struct ebt_ip_info *)m1->data;
+ struct ebt_ip_info *ipinfo2 = (struct ebt_ip_info *)m2->data;
+--- ebtables-v2.0pre2.001/extensions/ebt_arp.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebt_arp.c Wed Apr 10 23:05:29 2002
+@@ -44,20 +44,20 @@
+ int i = 0;
+
+ printf(
+- "arp options:\n"
+- "--arp-opcode opcode : ARP opcode (integer or string)\n"
+- "--arp-htype type : ARP hardware type (integer or string)\n"
+- "--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
+- "--arp-ip-src [!] address[/mask]: ARP ip source specification\n"
+- "--arp-ip-dst [!] address[/mask]: ARP ip target specification\n"
+- " opcode strings: \n");
++"arp options:\n"
++"--arp-opcode opcode : ARP opcode (integer or string)\n"
++"--arp-htype type : ARP hardware type (integer or string)\n"
++"--arp-ptype type : ARP protocol type (hexadecimal or string)\n"
++"--arp-ip-src [!] address[/mask]: ARP ip source specification\n"
++"--arp-ip-dst [!] address[/mask]: ARP ip target specification\n"
++" opcode strings: \n");
+ while (strcmp(opcodes[i], "")) {
+ printf("%d = %s\n", i + 1, opcodes[i]);
+ i++;
+ }
+ printf(
+- " hardware type string: \n 1 = Ethernet\n"
+- " protocol type string: \n 0x0800 = IPv4\n");
++" hardware type string: \n 1 = Ethernet\n"
++" protocol type string: \n 0x0800 = IPv4\n");
+ }
+
+ static void init(struct ebt_entry_match *match)
+@@ -68,7 +68,8 @@
+ arpinfo->bitmask = 0;
+ }
+
+-void parse_ip_address(char *address, __u32 *addr, __u32 *msk); // defined in ebt_ip.c
++// defined in ebt_ip.c
++void parse_ip_address(char *address, __u32 *addr, __u32 *msk);
+
+ #define OPT_OPCODE 0x01
+ #define OPT_HTYPE 0x02
+@@ -87,15 +88,14 @@
+
+ switch (c) {
+ case ARP_OPCODE:
+-
+ check_option(flags, OPT_OPCODE);
+ if (check_inverse(optarg))
+ arpinfo->invflags |= EBT_ARP_OPCODE;
+
+ if (optind > argc)
+- print_error("Missing arp opcode argument.");
++ print_error("Missing arp opcode argument");
+ i = strtol(argv[optind - 1], &end, 10);
+- if (i < 0 || i > (0x1 << 16) || *end !='\0') {
++ if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
+ i = 0;
+ while (strcmp(opcodes[i], "")) {
+ if (!strcasecmp(opcodes[i], optarg))
+@@ -103,7 +103,8 @@
+ i++;
+ }
+ if (!strcmp(opcodes[i], ""))
+- print_error("Problem with specified arp opcode.");
++ print_error("Problem with specified "
++ "arp opcode");
+ }
+ arpinfo->opcode = htons(i);
+ arpinfo->bitmask |= EBT_ARP_OPCODE;
+@@ -115,13 +116,14 @@
+ arpinfo->invflags |= EBT_ARP_HTYPE;
+
+ if (optind > argc)
+- print_error("Missing arp hardware type argument.");
++ print_error("Missing arp hardware type argument");
+ i = strtol(argv[optind - 1], &end, 10);
+- if (i < 0 || i > (0x1 << 16) || *end !='\0') {
++ if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
+ if (!strcasecmp("Ethernet", argv[optind - 1]))
+ i = 1;
+ else
+- print_error("Problem with specified arp hardware type.");
++ print_error("Problem with specified arp "
++ "hardware type");
+ }
+ arpinfo->htype = htons(i);
+ arpinfo->bitmask |= EBT_ARP_HTYPE;
+@@ -133,13 +135,14 @@
+ arpinfo->invflags |= EBT_ARP_PTYPE;
+
+ if (optind > argc)
+- print_error("Missing arp protocol type argument.");
++ print_error("Missing arp protocol type argument");
+ i = strtol(argv[optind - 1], &end, 16);
+- if (i < 0 || i > (0x1 << 16) || *end !='\0') {
++ if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
+ if (!strcasecmp("IPv4", argv[optind - 1]))
+ i = 0x0800;
+ else
+- print_error("Problem with specified arp protocol type.");
++ print_error("Problem with specified arp "
++ "protocol type");
+ }
+ arpinfo->ptype = htons(i);
+ arpinfo->bitmask |= EBT_ARP_PTYPE;
+@@ -165,7 +168,7 @@
+ arpinfo->invflags |= EBT_ARP_DST_IP;
+ }
+ if (optind > argc)
+- print_error("Missing ip address argument.");
++ print_error("Missing ip address argument");
+ parse_ip_address(argv[optind - 1], addr, mask);
+ break;
+ default:
+@@ -174,14 +177,19 @@
+ return 1;
+ }
+
+-static void final_check(const struct ebt_u_entry *entry, const struct ebt_entry_match *match, const char *name, unsigned int hook)
++static void final_check(const struct ebt_u_entry *entry,
++const struct ebt_entry_match *match, const char *name, unsigned int hook)
+ {
+- if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 || (entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP))
+- print_error("For (R)ARP filtering the protocol must be specified as ARP or RARP.");
++ if (entry->bitmask & EBT_NOPROTO || entry->bitmask & EBT_802_3 ||
++ (entry->ethproto != ETH_P_ARP && entry->ethproto != ETH_P_RARP))
++ print_error("For (R)ARP filtering the protocol must be "
++ "specified as ARP or RARP");
+ }
+
+-char *mask_to_dotted(__u32 mask); // defined in the ebt_ip.c
+-static void print(const struct ebt_u_entry *entry, const struct ebt_entry_match *match)
++// defined in the ebt_ip.c
++char *mask_to_dotted(__u32 mask);
++static void print(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match)
+ {
+ struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
+ int i;
+@@ -209,7 +217,8 @@
+ if (arpinfo->invflags & EBT_ARP_SRC_IP)
+ printf("! ");
+ for (i = 0; i < 4; i++)
+- printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i], (i == 3) ? "" : ".");
++ printf("%d%s", ((unsigned char *)&arpinfo->saddr)[i],
++ (i == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(arpinfo->smsk));
+ }
+ if (arpinfo->bitmask & EBT_ARP_DST_IP) {
+@@ -217,12 +226,14 @@
+ if (arpinfo->invflags & EBT_ARP_DST_IP)
+ printf("! ");
+ for (i = 0; i < 4; i++)
+- printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i], (i == 3) ? "" : ".");
++ printf("%d%s", ((unsigned char *)&arpinfo->daddr)[i],
++ (i == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(arpinfo->dmsk));
+ }
+ }
+
+-static int compare(const struct ebt_entry_match *m1, const struct ebt_entry_match *m2)
++static int compare(const struct ebt_entry_match *m1,
++ const struct ebt_entry_match *m2)
+ {
+ struct ebt_arp_info *arpinfo1 = (struct ebt_arp_info *)m1->data;
+ struct ebt_arp_info *arpinfo2 = (struct ebt_arp_info *)m2->data;
+--- ebtables-v2.0pre2.001/extensions/ebt_log.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebt_log.c Wed Apr 10 23:51:18 2002
+@@ -9,14 +9,14 @@
+
+ // copied from syslog.h
+ // used for the LOG target
+-#define LOG_EMERG 0 /* system is unusable */
+-#define LOG_ALERT 1 /* action must be taken immediately */
+-#define LOG_CRIT 2 /* critical conditions */
+-#define LOG_ERR 3 /* error conditions */
+-#define LOG_WARNING 4 /* warning conditions */
+-#define LOG_NOTICE 5 /* normal but significant condition */
+-#define LOG_INFO 6 /* informational */
+-#define LOG_DEBUG 7 /* debug-level messages */
++#define LOG_EMERG 0 // system is unusable
++#define LOG_ALERT 1 // action must be taken immediately
++#define LOG_CRIT 2 // critical conditions
++#define LOG_ERR 3 // error conditions
++#define LOG_WARNING 4 // warning conditions
++#define LOG_NOTICE 5 // normal but significant condition
++#define LOG_INFO 6 // informational
++#define LOG_DEBUG 7 // debug-level messages
+ #define LOG_DEFAULT_LEVEL LOG_INFO
+
+ typedef struct _code {
+@@ -70,16 +70,17 @@
+ int i;
+
+ printf(
+- "log options:\n"
+- "--log : use this if you're not specifying anything\n"
+- "--log-level level : level = [1-8] or a string\n"
+- "--log-prefix prefix : max. %d chars.\n"
+- "--log-ip : put ip info. in the log for ip packets\n"
+- "--log-arp : put (r)arp info. in the log for (r)arp packets\n"
++"log options:\n"
++"--log : use this if you're not specifying anything\n"
++"--log-level level : level = [1-8] or a string\n"
++"--log-prefix prefix : max. %d chars.\n"
++"--log-ip : put ip info. in the log for ip packets\n"
++"--log-arp : put (r)arp info. in the log for (r)arp packets\n"
+ , EBT_LOG_PREFIX_SIZE - 1);
+ printf("levels:\n");
+ for (i = 0; i < 8; i++)
+- printf("%d = %s\n", eight_priority[i].c_val, eight_priority[i].c_name);
++ printf("%d = %s\n", eight_priority[i].c_val,
++ eight_priority[i].c_name);
+ }
+
+ static void init(struct ebt_entry_watcher *watcher)
+@@ -88,7 +89,7 @@
+
+ loginfo->bitmask = 0;
+ loginfo->prefix[0] = '\0';
+- loginfo->loglevel = 6;
++ loginfo->loglevel = LOG_NOTICE;
+ }
+
+ #define OPT_PREFIX 0x01
+@@ -96,9 +97,8 @@
+ #define OPT_ARP 0x04
+ #define OPT_IP 0x08
+ #define OPT_LOG 0x10
+-static int parse(int c, char **argv, int argc,
+- const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_watcher **watcher)
++static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
++ unsigned int *flags, struct ebt_entry_watcher **watcher)
+ {
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)(*watcher)->data;
+ int i;
+@@ -108,9 +108,10 @@
+ case LOG_PREFIX:
+ check_option(flags, OPT_PREFIX);
+ if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
+- print_error("Prefix too long.");
++ print_error("Prefix too long");
+ strcpy(loginfo->prefix, optarg);
+ break;
++
+ case LOG_LEVEL:
+ check_option(flags, OPT_LEVEL);
+ i = strtol(optarg, &end, 16);
+@@ -119,16 +120,19 @@
+ else
+ loginfo->loglevel = i;
+ if (loginfo->loglevel == 9)
+- print_error("Problem with the log-level.");
++ print_error("Problem with the log-level");
+ break;
++
+ case LOG_IP:
+ check_option(flags, OPT_IP);
+ loginfo->bitmask |= EBT_LOG_IP;
+ break;
++
+ case LOG_ARP:
+ check_option(flags, OPT_ARP);
+ loginfo->bitmask |= EBT_LOG_ARP;
+ break;
++
+ case LOG_LOG:
+ check_option(flags, OPT_LOG);
+ break;
+@@ -138,16 +142,18 @@
+ return 1;
+ }
+
+-static void final_check(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watcher, const char *name, unsigned int hook)
++static void final_check(const struct ebt_u_entry *entry,
++ const struct ebt_entry_watcher *watcher, const char *name, unsigned int hook)
+ {
+ return;
+ }
+
+-static void print(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watcher)
++static void print(const struct ebt_u_entry *entry,
++ const struct ebt_entry_watcher *watcher)
+ {
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)watcher->data;
+
+- printf("log: log-level = %s - log-prefix = '%s'",
++ printf("log: log-level = %s - log-prefix = \"%s\"",
+ eight_priority[loginfo->loglevel].c_name,
+ loginfo->prefix);
+ if (loginfo->bitmask & EBT_LOG_IP)
+@@ -157,7 +163,8 @@
+ printf(" ");
+ }
+
+-static int compare(const struct ebt_entry_watcher *w1, const struct ebt_entry_watcher *w2)
++static int compare(const struct ebt_entry_watcher *w1,
++ const struct ebt_entry_watcher *w2)
+ {
+ struct ebt_log_info *loginfo1 = (struct ebt_log_info *)w1->data;
+ struct ebt_log_info *loginfo2 = (struct ebt_log_info *)w2->data;
+--- ebtables-v2.0pre2.001/extensions/ebt_standard.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebt_standard.c Thu Apr 11 18:14:07 2002
+@@ -19,17 +19,19 @@
+ ((struct ebt_standard_target *)t)->verdict = EBT_CONTINUE;
+ }
+
+-static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_target **target)
++static int parse(int c, char **argv, int argc, const struct ebt_u_entry *entry,
++ unsigned int *flags, struct ebt_entry_target **target)
+ {
+ return 0;
+ }
+
+-static void final_check(const struct ebt_u_entry *entry, const struct ebt_entry_target *target, const char *name, unsigned int hook)
++static void final_check(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target, const char *name, unsigned int hook)
+ {
+ }
+
+-static void print(const struct ebt_u_entry *entry, const struct ebt_entry_target *target)
++static void print(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target)
+ {
+ __u8 verdict = ((struct ebt_standard_target *)target)->verdict;
+
+@@ -41,9 +43,11 @@
+ printf("Drop ");
+ }
+
+-static int compare(const struct ebt_entry_target *t1, const struct ebt_entry_target *t2)
++static int compare(const struct ebt_entry_target *t1,
++ const struct ebt_entry_target *t2)
+ {
+- return ((struct ebt_standard_target *)t1)->verdict == ((struct ebt_standard_target *)t2)->verdict;
++ return ((struct ebt_standard_target *)t1)->verdict ==
++ ((struct ebt_standard_target *)t2)->verdict;
+ }
+
+ static struct ebt_u_target standard =
+--- ebtables-v2.0pre2.001/extensions/ebtable_filter.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebtable_filter.c Thu Apr 11 18:14:40 2002
+@@ -3,7 +3,8 @@
+ #include <linux/netfilter_bridge/ebtables.h>
+ #include "../include/ebtables_u.h"
+
+-#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | (1 << NF_BR_LOCAL_OUT))
++#define FILTER_VALID_HOOKS ((1 << NF_BR_LOCAL_IN) | (1 << NF_BR_FORWARD) | \
++ (1 << NF_BR_LOCAL_OUT))
+
+ static void print_help(char **hn)
+ {
+--- ebtables-v2.0pre2.001/extensions/ebtable_nat.c Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/extensions/ebtable_nat.c Thu Apr 11 18:14:57 2002
+@@ -2,7 +2,8 @@
+ #include <sys/socket.h>
+ #include "../include/ebtables_u.h"
+
+-#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_POST_ROUTING))
++#define NAT_VALID_HOOKS ((1 << NF_BR_PRE_ROUTING) | (1 << NF_BR_LOCAL_OUT) | \
++ (1 << NF_BR_POST_ROUTING))
+
+ static void print_help(char **hn)
+ {
+--- ebtables-v2.0pre2.001/ChangeLog Wed Apr 3 16:56:37 2002
++++ ebtables-v2.0pre2.002/ChangeLog Thu Apr 11 18:26:21 2002
+@@ -1,3 +1,12 @@
++20020411
++ * -j standard no longer works, is this cryptic? good :)
++ * lots of beautification.
++ - made some code smaller
++ - made everything fit within 80 columns
++ * fix problems with -i and -o option
++ * print_memory now prints useful info
++ * trying to see the tables when ebtables is not loaded in kernel
++ no longer makes this be seen as a bug.
+ 20020403
+ ebtables v2.0 released, changes:
+ * A complete rewrite, made everything modular.
+--- ebtables-v2.0pre2.001/include/ebtables_u.h Thu Apr 11 18:27:45 2002
++++ ebtables-v2.0pre2.002/include/ebtables_u.h Wed Apr 10 22:29:01 2002
+@@ -38,20 +38,28 @@
+ {
+ char name[EBT_TABLE_MAXNAMELEN];
+ unsigned int valid_hooks;
+- unsigned int nentries; // nr of rules in the table
++ // nr of rules in the table
++ unsigned int nentries;
+ struct ebt_u_entries *hook_entry[NF_BR_NUMHOOKS];
+- unsigned int counter_entry[NF_BR_NUMHOOKS]; // how many counters in front of it?
+- unsigned int num_counters; // nr of counters the userspace expects back
+- struct ebt_counter *counters; // where the kernel will put the old counters
+- unsigned int flags; // can be used e.g. to know if a standard option has been specified twice
+- char command; // we stick the specified command (e.g. -A) in here
+- int selected_hook; // here we stick the hook to do our thing on (can be -1 if unspecified)
++ // how many counters in front of it?
++ unsigned int counter_entry[NF_BR_NUMHOOKS];
++ // nr of counters userspace expects back
++ unsigned int num_counters;
++ // where the kernel will put the old counters
++ struct ebt_counter *counters;
++ // can be used e.g. to know if a standard option
++ // has been specified twice
++ unsigned int flags;
++ // we stick the specified command (e.g. -A) in here
++ char command;
++ // here we stick the hook to do our thing on (can be -1 if unspecified)
++ int selected_hook;
+ };
+
+ struct ebt_u_table
+ {
+ char name[EBT_TABLE_MAXNAMELEN];
+- int (*check) (struct ebt_u_replace *repl);
++ int (*check)(struct ebt_u_replace *repl);
+ void (*help)(char **);
+ struct ebt_u_table *next;
+ };
+@@ -70,9 +78,9 @@
+
+ struct ebt_u_entry
+ {
+- __u32 bitmask; // this needs to be the first field
++ __u32 bitmask;
+ __u32 invflags;
+- __u16 ethproto; /* packet type ID field */
++ __u16 ethproto;
+ __u8 in[IFNAMSIZ];
+ __u8 out[IFNAMSIZ];
+ __u8 sourcemac[ETH_ALEN];
+@@ -86,35 +94,47 @@
+ struct ebt_u_match
+ {
+ char name[EBT_FUNCTION_MAXNAMELEN];
+- unsigned int size;// size of the real match data
++ // size of the real match data + sizeof struct ebt_match
++ unsigned int size;
+ void (*help)(void);
+ void (*init)(struct ebt_entry_match *m);
+ int (*parse)(int c, char **argv, int argc,
+ const struct ebt_u_entry *entry, unsigned int *flags,
+ struct ebt_entry_match **match);
+- void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_match *match, const char *name, unsigned int hook);
+- void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_match *match);
+- int (*compare)(const struct ebt_entry_match *m1, const struct ebt_entry_match *m2);
++ void (*final_check)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match,
++ const char *name, unsigned int hook);
++ void (*print)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match);
++ int (*compare)(const struct ebt_entry_match *m1,
++ const struct ebt_entry_match *m2);
+ const struct option *extra_ops;
+- unsigned int flags;// can be used e.g. to check for multiple occurance of the same option
++ // can be used e.g. to check for multiple occurance of the same option
++ unsigned int flags;
+ unsigned int option_offset;
+ struct ebt_entry_match *m;
+- unsigned int used;// if used == 1 we no longer have to add it to the match chain of the new entry
++ // if used == 1 we no longer have to add it to
++ // the match chain of the new entry
++ unsigned int used;
+ struct ebt_u_match *next;
+ };
+
+ struct ebt_u_watcher
+ {
+ char name[EBT_FUNCTION_MAXNAMELEN];
+- unsigned int size;// size of the real match data
++ unsigned int size;
+ void (*help)(void);
+ void (*init)(struct ebt_entry_watcher *w);
+ int (*parse)(int c, char **argv, int argc,
+- const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_watcher **watcher);
+- void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watch, const char *name, unsigned int hook);
+- void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_watcher *watcher);
+- int (*compare)(const struct ebt_entry_watcher *w1, const struct ebt_entry_watcher *w2);
++ const struct ebt_u_entry *entry, unsigned int *flags,
++ struct ebt_entry_watcher **watcher);
++ void (*final_check)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_watcher *watch, const char *name,
++ unsigned int hook);
++ void (*print)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_watcher *watcher);
++ int (*compare)(const struct ebt_entry_watcher *w1,
++ const struct ebt_entry_watcher *w2);
+ const struct option *extra_ops;
+ unsigned int flags;
+ unsigned int option_offset;
+@@ -126,14 +146,19 @@
+ struct ebt_u_target
+ {
+ char name[EBT_FUNCTION_MAXNAMELEN];
+- unsigned int size;// size of the real match data
++ unsigned int size;
+ void (*help)(void);
+ void (*init)(struct ebt_entry_target *t);
+- int (*parse)(int c, char **argv, int argc, const struct ebt_u_entry *entry, unsigned int *flags,
+- struct ebt_entry_target **target);
+- void (*final_check)(const struct ebt_u_entry *entry, const struct ebt_entry_target *target, const char *name, unsigned int hook);
+- void (*print)(const struct ebt_u_entry *entry, const struct ebt_entry_target *target);
+- int (*compare)(const struct ebt_entry_target *t1, const struct ebt_entry_target *t2);
++ int (*parse)(int c, char **argv, int argc,
++ const struct ebt_u_entry *entry, unsigned int *flags,
++ struct ebt_entry_target **target);
++ void (*final_check)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target, const char *name,
++ unsigned int hook);
++ void (*print)(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target);
++ int (*compare)(const struct ebt_entry_target *t1,
++ const struct ebt_entry_target *t2);
+ const struct option *extra_ops;
+ unsigned int option_offset;
+ unsigned int flags;
+@@ -150,19 +175,21 @@
+ struct ebt_u_target *find_target(const char *name);
+ struct ebt_u_match *find_match(const char *name);
+ struct ebt_u_watcher *find_watcher(const char *name);
+-void deliver_counters(struct ebt_u_replace *repl, unsigned short * counterchanges);
++void deliver_counters(struct ebt_u_replace *repl,
++ unsigned short * counterchanges);
+ void deliver_table(struct ebt_u_replace *repl);
+-void get_sockfd();
+ void get_dbinfo(struct brdb_dbinfo *nr);
+ void get_db(int len, struct brdb_dbentry *db);
+ void deliver_allowdb(__u16 *decision);
+-void print_memory();
+-void init_extensions();
+ int getmac(char *from, char *to);
+ void check_option(unsigned int *flags, unsigned int mask);
+ int check_inverse(const char option[]);
+-#define print_bug(format, args...) {printf("BUG: "format"\n", ##args); exit(-1);}
+-#define print_error(format, args...) {printf(format"\n", ##args); exit(-1);}
++#define print_bug(format, args...) \
++ {printf("BUG: "format".\n", ##args); exit(-1);}
++#define print_error(format, args...) {printf(format".\n", ##args); exit(-1);}
++#define print_memory() {printf("Ebtables: " __FILE__ " " __FUNCTION__ \
++ " %d :Out of memory.\n", __LINE__); exit(-1);}
++
+
+
+ // used for keeping the rule counters right during rule adds or deletes
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre2.003.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre2.003.diff
new file mode 100644
index 0000000..aac6a6f
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre2.003.diff
@@ -0,0 +1,40 @@
+--- ebtables-v2.0pre2.002/Makefile Sat Apr 13 17:39:08 2002
++++ ebtables-v2.0pre2.003/Makefile Sat Apr 13 17:43:09 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre2.001 (April 2002)"
++PROGVERSION:="2.0pre2.003 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+--- ebtables-v2.0pre2.002/ebtables.c Sat Apr 13 17:39:08 2002
++++ ebtables-v2.0pre2.003/ebtables.c Sat Apr 13 17:37:00 2002
+@@ -1490,7 +1490,7 @@
+ flush_chains();
+ else if (replace.command == 'A' || replace.command == 'I')
+ add_rule(rule_nr);
+- else
++ else if (replace.command == 'D')
+ delete_rule(rule_nr);
+
+ if (table->check)
+--- ebtables-v2.0pre2.002/THANKS Wed Apr 3 17:44:44 2002
++++ ebtables-v2.0pre2.003/THANKS Sat Apr 13 17:40:35 2002
+@@ -5,3 +5,5 @@
+ Harald Welte
+ Jason Lunz
+ Tim Gardner
++Loïc Minier
++
+--- ebtables-v2.0pre2.002/ebtables.8 Wed Apr 3 16:29:11 2002
++++ ebtables-v2.0pre2.003/ebtables.8 Sat Apr 13 17:32:23 2002
+@@ -128,6 +128,7 @@
+ Put the counters of the selected chain on zero. If no chain is selected, all the counters
+ are put on zero. This can be used in conjunction with the -L command (see above).
+ This will cause the rule counters to be printed on the screen before they are put on zero.
++.TP
+ .B "-P, --policy"
+ Set the policy for the chain to the given target. The policy is either
+ .B ACCEPT
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre2.004.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre2.004.diff
new file mode 100644
index 0000000..87ed4dc
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre2.004.diff
@@ -0,0 +1,50 @@
+--- ebtables-v2.0pre2.003/Makefile Sun Apr 14 15:01:46 2002
++++ ebtables-v2.0pre2.004/Makefile Sun Apr 14 15:03:11 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre2.003 (April 2002)"
++PROGVERSION:="2.0pre2 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+--- ebtables-v2.0pre2.003/ChangeLog Sat Apr 13 17:39:08 2002
++++ ebtables-v2.0pre2.004/ChangeLog Sun Apr 14 14:15:59 2002
+@@ -1,3 +1,6 @@
++20020414
++ * fixed some things in the manual.
++ * fixed -P problem.
+ 20020411
+ * -j standard no longer works, is this cryptic? good :)
+ * lots of beautification.
+--- ebtables-v2.0pre2.003/ebtables.8 Sun Apr 14 15:01:46 2002
++++ ebtables-v2.0pre2.004/ebtables.8 Sun Apr 14 14:58:15 2002
+@@ -1,4 +1,4 @@
+-.TH EBTABLES 8 "03 April 2002"
++.TH EBTABLES 8 "14 April 2002"
+ .\"
+ .\" Man page written by Bart De Schuymer <bart.de.schuymer@pandora.be>
+ .\" It is based on the iptables man page.
+@@ -21,7 +21,7 @@
+ .\"
+ .\"
+ .SH NAME
+-ebtables(v.2) \- ethernet bridge packet table administration
++ebtables(v.2.0) \- ethernet bridge packet table administration
+ .SH SYNOPSIS
+ .BR "ebtables -[ADI] " "chain rule-specification [options]"
+ .br
+@@ -263,6 +263,12 @@
+ .BR "--arp-ptype " "[!] \fIprotocol type\fP"
+ The protocol type for which the (r)arp is used (hexadecimal or the string "IPv4").
+ This is normally IPv4 (0x0800).
++.TP
++.BR "--arp-ip-src " "[!] \fIaddress\fP[/\fImask\fP]"
++The ARP IP source address specification.
++.TP
++.BR "--arp-ip-dst " "[!] \fIaddress\fP[/\fImask\fP]"
++The ARP IP destination address specification.
+ .SH WATCHER EXTENSION(S)
+ Watchers are things that only look at frames passing by. These watchers only see the
+ frame if the frame passes all the matches of the rule.
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre3.001.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre3.001.diff
new file mode 100644
index 0000000..12c7a2b
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre3.001.diff
@@ -0,0 +1,245 @@
+Adjust to the kernel's wish that the size members represent the size
+of the actual data.
+
+Make a little note in the man page about the chain naming.
+
+--- ebtables-v2.0pre2/ebtables.c Sat Apr 13 17:37:00 2002
++++ ebtables-v2.0pre3.001/ebtables.c Fri Apr 19 19:44:33 2002
+@@ -253,14 +253,14 @@
+
+ void register_match(struct ebt_u_match *m)
+ {
+- int size = m->size;
++ int size = m->size + sizeof(struct ebt_entry_match);
+ struct ebt_u_match **i;
+
+ m->m = (struct ebt_entry_match *)malloc(size);
+ if (!m->m)
+ print_memory();
+ strcpy(m->m->u.name, m->name);
+- m->m->match_size = size;
++ m->m->match_size = m->size;
+ ebt_options = merge_options
+ (ebt_options, m->extra_ops, &(m->option_offset));
+ m->init(m->m);
+@@ -272,14 +272,14 @@
+
+ void register_watcher(struct ebt_u_watcher *w)
+ {
+- int size = w->size;
++ int size = w->size + sizeof(struct ebt_entry_watcher);
+ struct ebt_u_watcher **i;
+
+ w->w = (struct ebt_entry_watcher *)malloc(size);
+ if (!w->w)
+ print_memory();
+ strcpy(w->w->u.name, w->name);
+- w->w->watcher_size = size;
++ w->w->watcher_size = w->size;
+ ebt_options = merge_options
+ (ebt_options, w->extra_ops, &(w->option_offset));
+ w->init(w->w);
+@@ -291,14 +291,14 @@
+
+ void register_target(struct ebt_u_target *t)
+ {
+- int size = t->size;
++ int size = t->size + sizeof(struct ebt_entry_target);
+ struct ebt_u_target **i;
+
+ t->t = (struct ebt_entry_target *)malloc(size);
+ if (!t->t)
+ print_memory();
+ strcpy(t->t->u.name, t->name);
+- t->t->target_size = size;
++ t->t->target_size = t->size;
+ ebt_options = merge_options
+ (ebt_options, t->extra_ops, &(t->option_offset));
+ t->init(t->t);
+--- ebtables-v2.0pre2/communication.c Wed Apr 10 22:10:49 2002
++++ ebtables-v2.0pre3.001/communication.c Fri Apr 19 22:02:45 2002
+@@ -68,15 +68,18 @@
+ entries_size += sizeof(struct ebt_entry);
+ m_l = e->m_list;
+ while (m_l) {
+- entries_size += m_l->m->match_size;
++ entries_size += m_l->m->match_size +
++ sizeof(struct ebt_entry_match);
+ m_l = m_l->next;
+ }
+ w_l = e->w_list;
+ while (w_l) {
+- entries_size += w_l->w->watcher_size;
++ entries_size += w_l->w->watcher_size +
++ sizeof(struct ebt_entry_watcher);
+ w_l = w_l->next;
+ }
+- entries_size += e->t->target_size;
++ entries_size += e->t->target_size +
++ sizeof(struct ebt_entry_target);
+ e = e->next;
+ }
+ // a little sanity check
+@@ -120,20 +123,26 @@
+ p += sizeof(struct ebt_entry);
+ m_l = e->m_list;
+ while (m_l) {
+- memcpy(p, m_l->m, m_l->m->match_size);
+- p += m_l->m->match_size;
++ memcpy(p, m_l->m, m_l->m->match_size +
++ sizeof(struct ebt_entry_match));
++ p += m_l->m->match_size +
++ sizeof(struct ebt_entry_match);
+ m_l = m_l->next;
+ }
+ tmp->watchers_offset = p - base;
+ w_l = e->w_list;
+ while (w_l) {
+- memcpy(p, w_l->w, w_l->w->watcher_size);
+- p += w_l->w->watcher_size;
++ memcpy(p, w_l->w, w_l->w->watcher_size +
++ sizeof(struct ebt_entry_watcher));
++ p += w_l->w->watcher_size +
++ sizeof(struct ebt_entry_watcher);
+ w_l = w_l->next;
+ }
+ tmp->target_offset = p - base;
+- memcpy(p, e->t, e->t->target_size);
+- p += e->t->target_size;
++ memcpy(p, e->t, e->t->target_size +
++ sizeof(struct ebt_entry_target));
++ p += e->t->target_size +
++ sizeof(struct ebt_entry_target);
+ tmp->next_offset = p - base;
+ e = e->next;
+ }
+@@ -229,10 +238,11 @@
+ malloc(sizeof(struct ebt_u_match_list));
+ if (!new)
+ print_memory();
+- new->m = (struct ebt_entry_match *)malloc(m->match_size);
++ new->m = (struct ebt_entry_match *)
++ malloc(m->match_size + sizeof(struct ebt_entry_match));
+ if (!new->m)
+ print_memory();
+- memcpy(new->m, m, m->match_size);
++ memcpy(new->m, m, m->match_size + sizeof(struct ebt_entry_match));
+ new->next = NULL;
+ **l = new;
+ *l = &new->next;
+@@ -248,13 +258,15 @@
+ {
+ struct ebt_u_watcher_list *new;
+
+- new = (struct ebt_u_watcher_list *)malloc(sizeof(struct ebt_u_watcher_list));
++ new = (struct ebt_u_watcher_list *)
++ malloc(sizeof(struct ebt_u_watcher_list));
+ if (!new)
+ print_memory();
+- new->w = (struct ebt_entry_watcher *)malloc(w->watcher_size);
++ new->w = (struct ebt_entry_watcher *)
++ malloc(w->watcher_size + sizeof(struct ebt_entry_watcher));
+ if (!new->w)
+ print_memory();
+- memcpy(new->w, w, w->watcher_size);
++ memcpy(new->w, w, w->watcher_size + sizeof(struct ebt_entry_watcher));
+ new->next = NULL;
+ **l = new;
+ *l = &new->next;
+@@ -297,13 +309,15 @@
+ EBT_WATCHER_ITERATE(e, ebt_translate_watcher, &w_l);
+
+ t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
+- new->t = (struct ebt_entry_target *)malloc(t->target_size);
++ new->t = (struct ebt_entry_target *)
++ malloc(t->target_size + sizeof(struct ebt_entry_target));
+ if (!new->t)
+ print_memory();
+ if (find_target(t->u.name) == NULL)
+ print_error("Kernel target %s unsupported by "
+ "userspace tool", t->u.name);
+- memcpy(new->t, t, t->target_size);
++ memcpy(new->t, t, t->target_size +
++ sizeof(struct ebt_entry_target));
+
+ // I love pointers
+ **u_e = new;
+@@ -419,7 +433,8 @@
+
+ get_sockfd();
+
+- if (setsockopt(sockfd, IPPROTO_IP, BRDB_SO_SET_ALLOWDB, decision, optlen))
++ if (setsockopt(sockfd, IPPROTO_IP, BRDB_SO_SET_ALLOWDB,
++ decision, optlen))
+ print_error("Sorry, br_db code probably not in kernel, "
+ "try insmod br_db");
+ }
+--- ebtables-v2.0pre2/extensions/ebt_nat.c Thu Apr 11 18:12:55 2002
++++ ebtables-v2.0pre3.001/extensions/ebt_nat.c Fri Apr 19 19:41:04 2002
+@@ -161,7 +161,7 @@
+ static struct ebt_u_target dnat_target =
+ {
+ EBT_DNAT_TARGET,
+- sizeof(struct ebt_nat_info) + sizeof(struct ebt_entry_target),
++ sizeof(struct ebt_nat_info),
+ print_help_d,
+ init_d,
+ parse_d,
+--- ebtables-v2.0pre2/extensions/ebt_ip.c Wed Apr 10 23:28:40 2002
++++ ebtables-v2.0pre3.001/extensions/ebt_ip.c Fri Apr 19 19:40:18 2002
+@@ -301,7 +301,7 @@
+ static struct ebt_u_match ip_match =
+ {
+ EBT_IP_MATCH,
+- sizeof(struct ebt_ip_info) + sizeof(struct ebt_entry_match),
++ sizeof(struct ebt_ip_info),
+ print_help,
+ init,
+ parse,
+--- ebtables-v2.0pre2/extensions/ebt_arp.c Wed Apr 10 23:05:29 2002
++++ ebtables-v2.0pre3.001/extensions/ebt_arp.c Fri Apr 19 19:40:40 2002
+@@ -272,7 +272,7 @@
+ static struct ebt_u_match arp_match =
+ {
+ EBT_ARP_MATCH,
+- sizeof(struct ebt_arp_info) + sizeof(struct ebt_entry_match),
++ sizeof(struct ebt_arp_info),
+ print_help,
+ init,
+ parse,
+--- ebtables-v2.0pre2/extensions/ebt_log.c Wed Apr 10 23:51:18 2002
++++ ebtables-v2.0pre3.001/extensions/ebt_log.c Fri Apr 19 19:40:52 2002
+@@ -179,7 +179,7 @@
+ static struct ebt_u_watcher log_watcher =
+ {
+ EBT_LOG_WATCHER,
+- sizeof(struct ebt_log_info) + sizeof(struct ebt_entry_watcher),
++ sizeof(struct ebt_log_info),
+ print_help,
+ init,
+ parse,
+--- ebtables-v2.0pre2/extensions/ebt_standard.c Thu Apr 11 18:14:07 2002
++++ ebtables-v2.0pre3.001/extensions/ebt_standard.c Fri Apr 19 19:44:54 2002
+@@ -53,7 +53,7 @@
+ static struct ebt_u_target standard =
+ {
+ EBT_STANDARD_TARGET,
+- sizeof(struct ebt_standard_target),
++ sizeof(struct ebt_standard_target) - sizeof(struct ebt_entry_target),
+ print_help,
+ init,
+ parse,
+--- ebtables-v2.0pre2/ebtables.8 Sun Apr 14 14:58:15 2002
++++ ebtables-v2.0pre3.001/ebtables.8 Thu Apr 18 18:44:40 2002
+@@ -86,7 +86,10 @@
+ .B OUTPUT
+ (for altering locally generated frames before they are bridged) and
+ .B POSTROUTING
+-(for altering frames as they are about to go out).
++(for altering frames as they are about to go out). A small note on the naming
++of chains POSTROUTING and PREROUTING: it would be more accurate to call them
++PREFORWARDING and POSTFORWARDING, but for all those who come from the iptables
++world to ebtables it is easier to have the same names.
+ .SH OPTIONS
+ The options can be divided into several different groups.
+ .SS COMMANDS
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre3.002.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre3.002.diff
new file mode 100644
index 0000000..175f9df
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre3.002.diff
@@ -0,0 +1,194 @@
+--- ebtables-v2.0pre3.001/ebtables.c Fri Apr 19 22:07:46 2002
++++ ebtables-v2.0pre3.002/ebtables.c Fri Apr 19 23:43:05 2002
+@@ -62,6 +62,8 @@
+ { "policy" , required_argument, 0, 'P' },
+ { "in-interface" , required_argument, 0, 'i' },
+ { "in-if" , required_argument, 0, 'i' },
++ { "logical-in" , required_argument, 0, 1 },
++ { "logical-out" , required_argument, 0, 2 },
+ { "out-interface" , required_argument, 0, 'o' },
+ { "out-if" , required_argument, 0, 'o' },
+ { "version" , no_argument , 0, 'V' },
+@@ -481,6 +483,16 @@
+ printf("! ");
+ printf("in-if: %s, ", hlp->in);
+ }
++ if (hlp->logical_in[0] != '\0') {
++ if (hlp->invflags & EBT_ILOGICALIN)
++ printf("! ");
++ printf("logical in-if: %s, ", hlp->logical_in);
++ }
++ if (hlp->logical_out[0] != '\0') {
++ if (hlp->invflags & EBT_ILOGICALOUT)
++ printf("! ");
++ printf("logical out-if: %s, ", hlp->logical_out);
++ }
+ if (hlp->out[0] != '\0') {
+ if (hlp->invflags & EBT_IOUT)
+ printf("! ");
+@@ -560,6 +572,8 @@
+ "--dst -d [!] address : destination mac address\n"
+ "--in-if -i [!] name : network input interface name\n"
+ "--out-if -o [!] name : network output interface name\n"
++"--logical-in [!] name : logical bridge input interface name\n"
++"--logical-out [!] name : logical bridge output interface name\n"
+ "--version -V : print package version\n"
+ "\n" ,
+ prog_name,
+@@ -1095,15 +1109,17 @@
+ *flags |= mask;
+ }
+
+-#define OPT_COMMAND 0x01
+-#define OPT_TABLE 0x02
+-#define OPT_IN 0x04
+-#define OPT_OUT 0x08
+-#define OPT_JUMP 0x10
+-#define OPT_PROTOCOL 0x20
+-#define OPT_SOURCE 0x40
+-#define OPT_DEST 0x80
+-#define OPT_ZERO 0x100
++#define OPT_COMMAND 0x01
++#define OPT_TABLE 0x02
++#define OPT_IN 0x04
++#define OPT_OUT 0x08
++#define OPT_JUMP 0x10
++#define OPT_PROTOCOL 0x20
++#define OPT_SOURCE 0x40
++#define OPT_DEST 0x80
++#define OPT_ZERO 0x100
++#define OPT_LOGICALIN 0x200
++#define OPT_LOGICALOUT 0x400
+ // the main thing
+ int main(int argc, char *argv[])
+ {
+@@ -1261,7 +1277,9 @@
+ break;
+
+ case 'i': // input interface
++ case 1 : // logical input interface
+ case 'o': // output interface
++ case 2 : // logical output interface
+ case 'j': // target
+ case 'p': // net family protocol
+ case 's': // source mac
+@@ -1287,6 +1305,23 @@
+ strcpy(new_entry->in, argv[optind - 1]);
+ break;
+ }
++ if (c == 1) {
++ check_option(&replace.flags, OPT_LOGICALIN);
++ if (replace.selected_hook > 2)
++ print_error("Use logical in-interface "
++ "only in INPUT, FORWARD and "
++ "PREROUTING chains");
++ if (check_inverse(optarg))
++ new_entry->invflags |= EBT_ILOGICALIN;
++
++ if (optind > argc)
++ print_error("No logical in-interface "
++ "specified");
++ if (strlen(argv[optind - 1]) >= IFNAMSIZ)
++ print_error("Illegal interfacelength");
++ strcpy(new_entry->logical_in, argv[optind - 1]);
++ break;
++ }
+ if (c == 'o') {
+ check_option(&replace.flags, OPT_OUT);
+ if (replace.selected_hook < 2)
+@@ -1304,6 +1339,26 @@
+ print_error("Illegal interface "
+ "length");
+ strcpy(new_entry->out, argv[optind - 1]);
++ break;
++ }
++ if (c == 2) {
++ check_option(&replace.flags, OPT_LOGICALOUT);
++ if (replace.selected_hook < 2)
++ print_error("Use logical out-interface "
++ "only in OUTPUT, FORWARD and "
++ "POSTROUTING chains");
++ if (check_inverse(optarg))
++ new_entry->invflags |= EBT_ILOGICALOUT;
++
++ if (optind > argc)
++ print_error("No logical out-interface "
++ "specified");
++
++ if (strlen(argv[optind - 1]) >= IFNAMSIZ)
++ print_error("Illegal interface "
++ "length");
++ strcpy(new_entry->logical_out,
++ argv[optind - 1]);
+ break;
+ }
+ if (c == 'j') {
+--- ebtables-v2.0pre3.001/communication.c Fri Apr 19 22:07:46 2002
++++ ebtables-v2.0pre3.002/communication.c Fri Apr 19 22:57:13 2002
+@@ -115,6 +115,10 @@
+ tmp->ethproto = e->ethproto;
+ memcpy(tmp->in, e->in, sizeof(tmp->in));
+ memcpy(tmp->out, e->out, sizeof(tmp->out));
++ memcpy(tmp->logical_in, e->logical_in,
++ sizeof(tmp->logical_in));
++ memcpy(tmp->logical_out, e->logical_out,
++ sizeof(tmp->logical_out));
+ memcpy(tmp->sourcemac, e->sourcemac,
+ sizeof(tmp->sourcemac));
+ memcpy(tmp->destmac, e->destmac, sizeof(tmp->destmac));
+@@ -298,6 +302,10 @@
+ new->ethproto = e->ethproto;
+ memcpy(new->in, e->in, sizeof(new->in));
+ memcpy(new->out, e->out, sizeof(new->out));
++ memcpy(new->logical_in, e->logical_in,
++ sizeof(new->logical_in));
++ memcpy(new->logical_out, e->logical_out,
++ sizeof(new->logical_out));
+ memcpy(new->sourcemac, e->sourcemac, sizeof(new->sourcemac));
+ memcpy(new->destmac, e->destmac, sizeof(new->destmac));
+ new->m_list = NULL;
+--- ebtables-v2.0pre3.001/ebtables.8 Fri Apr 19 22:07:46 2002
++++ ebtables-v2.0pre3.002/ebtables.8 Fri Apr 19 23:28:06 2002
+@@ -184,6 +184,14 @@
+ .B --in-if
+ is an alias for this option.
+ .TP
++.BR "--logical-in " "[!] \fIname\fP"
++The (logical) bridge interface via which a frame is received (for the
++.BR INPUT ,
++.B FORWARD
++and
++.B PREROUTING
++chains).
++.TP
+ .BR "-o, --out-interface " "[!] \fIname\fP"
+ The interface via which a frame is going to be sent (for the
+ .BR OUTPUT ,
+@@ -193,6 +201,15 @@
+ chains). The flag
+ .B --out-if
+ is an alias for this option.
++.TP
++.BR "--logical-out " "[!] \fIname\fP"
++The (logical) bridge interface via which a frame is going to be sent (for
++the
++.BR OUTPUT ,
++.B FORWARD
++and
++.B POSTROUTING
++chains).
+ .TP
+ .BR "-s, --source " "[!] \fIaddress\fP"
+ The source mac address. The flag
+--- ebtables-v2.0pre3.001/include/ebtables_u.h Wed Apr 10 22:29:01 2002
++++ ebtables-v2.0pre3.002/include/ebtables_u.h Fri Apr 19 22:55:15 2002
+@@ -82,7 +82,9 @@
+ __u32 invflags;
+ __u16 ethproto;
+ __u8 in[IFNAMSIZ];
++ __u8 logical_in[IFNAMSIZ];
+ __u8 out[IFNAMSIZ];
++ __u8 logical_out[IFNAMSIZ];
+ __u8 sourcemac[ETH_ALEN];
+ __u8 destmac[ETH_ALEN];
+ struct ebt_u_match_list *m_list;
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre3.003.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre3.003.diff
new file mode 100644
index 0000000..1a80a01
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre3.003.diff
@@ -0,0 +1,66 @@
+* Add brouter support
+* Give better advice when a table is not found by the kernel
+
+--- ebtables-v2.0pre3.002/Makefile Sun Apr 14 15:03:11 2002
++++ ebtables-v2.0pre3.003/Makefile Mon Apr 22 20:05:21 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre2 (April 2002)"
++PROGVERSION:="2.0pre3 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+--- ebtables-v2.0pre3.002/ebtables.c Mon Apr 22 20:08:03 2002
++++ ebtables-v2.0pre3.003/ebtables.c Sat Apr 20 20:07:42 2002
+@@ -48,7 +48,8 @@
+ [NF_BR_LOCAL_IN]"INPUT",
+ [NF_BR_FORWARD]"FORWARD",
+ [NF_BR_LOCAL_OUT]"OUTPUT",
+- [NF_BR_POST_ROUTING]"POSTROUTING"
++ [NF_BR_POST_ROUTING]"POSTROUTING",
++ [NF_BR_BROUTING]"BROUTING"
+ };
+
+ // default command line options
+--- ebtables-v2.0pre3.002/communication.c Mon Apr 22 20:08:03 2002
++++ ebtables-v2.0pre3.003/communication.c Sun Apr 21 15:38:38 2002
+@@ -375,7 +375,8 @@
+ strcpy(repl.name, u_repl->name);
+ if (getsockopt(sockfd, IPPROTO_IP, EBT_SO_GET_INFO, &repl, &optlen))
+ print_error("A kernel module needed by your command is probably"
+- " not loaded. Try insmod ebtables or the like");
++ " not loaded. Try insmod ebtables or"
++ " insmod ebtable_%s", repl.name);
+
+ if ( !(repl.entries = (char *) malloc(repl.entries_size)) )
+ print_memory();
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0pre3.003/extensions/ebtable_broute.c Sat Apr 20 20:12:26 2002
+@@ -0,0 +1,25 @@
++#include <stdio.h>
++#include <sys/socket.h>
++#include "../include/ebtables_u.h"
++
++
++static void print_help(char **hn)
++{
++ printf("Supported chain for the nat table:\n");
++ printf("%s\n",hn[NF_BR_BROUTING]);
++}
++
++static struct
++ebt_u_table table =
++{
++ "broute",
++ NULL,
++ print_help,
++ NULL
++};
++
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
++{
++ register_table(&table);
++}
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre3.004.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre3.004.diff
new file mode 100644
index 0000000..9a3bc67
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre3.004.diff
@@ -0,0 +1,483 @@
+--- ebtables-v2.0pre3.003/ebtables.c Sat Apr 27 16:57:47 2002
++++ ebtables-v2.0pre3.004/ebtables.c Wed Apr 24 19:47:02 2002
+@@ -63,8 +63,8 @@
+ { "policy" , required_argument, 0, 'P' },
+ { "in-interface" , required_argument, 0, 'i' },
+ { "in-if" , required_argument, 0, 'i' },
+- { "logical-in" , required_argument, 0, 1 },
+- { "logical-out" , required_argument, 0, 2 },
++ { "logical-in" , required_argument, 0, 2 },
++ { "logical-out" , required_argument, 0, 3 },
+ { "out-interface" , required_argument, 0, 'o' },
+ { "out-if" , required_argument, 0, 'o' },
+ { "version" , no_argument , 0, 'V' },
+@@ -155,6 +155,8 @@
+ e->ethproto = 0;
+ strcpy(e->in, "");
+ strcpy(e->out, "");
++ strcpy(e->logical_in, "");
++ strcpy(e->logical_out, "");
+ e->m_list = NULL;
+ e->w_list = NULL;
+ // the init function of the standard target should have put the verdict
+@@ -1278,9 +1280,9 @@
+ break;
+
+ case 'i': // input interface
+- case 1 : // logical input interface
++ case 2 : // logical input interface
+ case 'o': // output interface
+- case 2 : // logical output interface
++ case 3 : // logical output interface
+ case 'j': // target
+ case 'p': // net family protocol
+ case 's': // source mac
+@@ -1306,7 +1308,7 @@
+ strcpy(new_entry->in, argv[optind - 1]);
+ break;
+ }
+- if (c == 1) {
++ if (c == 2) {
+ check_option(&replace.flags, OPT_LOGICALIN);
+ if (replace.selected_hook > 2)
+ print_error("Use logical in-interface "
+@@ -1342,7 +1344,7 @@
+ strcpy(new_entry->out, argv[optind - 1]);
+ break;
+ }
+- if (c == 2) {
++ if (c == 3) {
+ check_option(&replace.flags, OPT_LOGICALOUT);
+ if (replace.selected_hook < 2)
+ print_error("Use logical out-interface "
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0pre3.004/extensions/ebt_redirect.c Sat Apr 27 17:18:16 2002
+@@ -0,0 +1,109 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <linux/netfilter_bridge/ebtables.h>
++#include <getopt.h>
++#include "../include/ebtables_u.h"
++#include <linux/netfilter_bridge/ebt_redirect.h>
++
++extern char *standard_targets[NUM_STANDARD_TARGETS];
++
++#define REDIRECT_TARGET '1'
++static struct option opts[] =
++{
++ { "redirect-target" , required_argument, 0, REDIRECT_TARGET },
++ { 0 }
++};
++
++static void print_help()
++{
++ printf(
++ "redirect option:\n"
++ " --redirect-target target : ACCEPT, DROP or CONTINUE\n");
++}
++
++static void init(struct ebt_entry_target *target)
++{
++ struct ebt_redirect_info *redirectinfo =
++ (struct ebt_redirect_info *)target->data;
++
++ redirectinfo->target = EBT_ACCEPT;
++ return;
++}
++
++
++#define OPT_REDIRECT_TARGET 0x01
++static int parse(int c, char **argv, int argc,
++ const struct ebt_u_entry *entry, unsigned int *flags,
++ struct ebt_entry_target **target)
++{
++ int i;
++ struct ebt_redirect_info *redirectinfo =
++ (struct ebt_redirect_info *)(*target)->data;
++
++ switch (c) {
++ case REDIRECT_TARGET:
++ check_option(flags, OPT_REDIRECT_TARGET);
++ for (i = 0; i < NUM_STANDARD_TARGETS; i++)
++ if (!strcmp(optarg, standard_targets[i])) {
++ redirectinfo->target = i;
++ break;
++ }
++ if (i == NUM_STANDARD_TARGETS)
++ print_error("Illegal --redirect-target target");
++ break;
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++static void final_check(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target, const char *name, unsigned int hook)
++{
++ if ( (hook != NF_BR_PRE_ROUTING || strcmp(name, "nat")) &&
++ (hook != NF_BR_BROUTING || strcmp(name, "broute")) )
++ print_error("Wrong chain for redirect");
++}
++
++static void print(const struct ebt_u_entry *entry,
++ const struct ebt_entry_target *target)
++{
++ struct ebt_redirect_info *redirectinfo =
++ (struct ebt_redirect_info *)target->data;
++
++ printf("redirect");
++ printf(" --redirect-target %s", standard_targets[redirectinfo->target]);
++}
++
++static int compare(const struct ebt_entry_target *t1,
++ const struct ebt_entry_target *t2)
++{
++ struct ebt_redirect_info *redirectinfo1 =
++ (struct ebt_redirect_info *)t1->data;
++ struct ebt_redirect_info *redirectinfo2 =
++ (struct ebt_redirect_info *)t2->data;
++
++ return redirectinfo1->target == redirectinfo2->target;
++}
++
++static struct ebt_u_target redirect_target =
++{
++ EBT_REDIRECT_TARGET,
++ sizeof(struct ebt_redirect_info),
++ print_help,
++ init,
++ parse,
++ final_check,
++ print,
++ compare,
++ opts,
++};
++
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
++{
++ register_target(&redirect_target);
++}
+--- ebtables-v2.0pre3.003/extensions/ebt_nat.c Sat Apr 27 16:57:41 2002
++++ ebtables-v2.0pre3.004/extensions/ebt_nat.c Sat Apr 27 17:16:19 2002
+@@ -8,54 +8,71 @@
+ #include "../include/ebtables_u.h"
+ #include <linux/netfilter_bridge/ebt_nat.h>
+
++extern char *standard_targets[NUM_STANDARD_TARGETS];
++
+ int to_source_supplied, to_dest_supplied;
+
+ #define NAT_S '1'
+ #define NAT_D '1'
++#define NAT_S_TARGET '2'
++#define NAT_D_TARGET '2'
+ static struct option opts_s[] =
+ {
+ { "to-source" , required_argument, 0, NAT_S },
+ { "to-src" , required_argument, 0, NAT_S },
+- { 0 },
++ { "snat-target" , required_argument, 0, NAT_S_TARGET },
++ { 0 }
+ };
+
+ static struct option opts_d[] =
+ {
+ { "to-destination", required_argument, 0, NAT_D },
+ { "to-dst" , required_argument, 0, NAT_D },
++ { "dnat-target" , required_argument, 0, NAT_D_TARGET },
+ { 0 }
+ };
+
+ static void print_help_s()
+ {
+ printf(
+- "snat option:\n"
+- " --to-src address : MAC address to map source to\n");
++ "snat options:\n"
++ " --to-src address : MAC address to map source to\n"
++ " --snat-target target : ACCEPT, DROP or CONTINUE\n");
+ }
+
+ static void print_help_d()
+ {
+ printf(
+- "dnat option:\n"
+- " --to-dst address : MAC address to map destination to\n");
++ "dnat options:\n"
++ " --to-dst address : MAC address to map destination to\n"
++ " --dnat-target target : ACCEPT, DROP or CONTINUE\n");
+ }
+
+ static void init_s(struct ebt_entry_target *target)
+ {
++ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
++
+ to_source_supplied = 0;
++ natinfo->target = EBT_ACCEPT;
+ return;
+ }
+
+ static void init_d(struct ebt_entry_target *target)
+ {
++ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)target->data;
++
+ to_dest_supplied = 0;
++ natinfo->target = EBT_ACCEPT;
++ return;
+ }
+
+-#define OPT_SNAT 0x01
++#define OPT_SNAT 0x01
++#define OPT_SNAT_TARGET 0x02
+ static int parse_s(int c, char **argv, int argc,
+ const struct ebt_u_entry *entry, unsigned int *flags,
+ struct ebt_entry_target **target)
+ {
++ int i;
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
+
+ switch (c) {
+@@ -65,17 +82,29 @@
+ if (getmac(optarg, natinfo->mac))
+ print_error("Problem with specified to-source mac");
+ break;
++ case NAT_S_TARGET:
++ check_option(flags, OPT_SNAT_TARGET);
++ for (i = 0; i < NUM_STANDARD_TARGETS; i++)
++ if (!strcmp(optarg, standard_targets[i])) {
++ natinfo->target = i;
++ break;
++ }
++ if (i == NUM_STANDARD_TARGETS)
++ print_error("Illegal --snat-target target");
++ break;
+ default:
+- return 0;
++ return 0;
+ }
+ return 1;
+ }
+
+-#define OPT_DNAT 0x01
++#define OPT_DNAT 0x01
++#define OPT_DNAT_TARGET 0x02
+ static int parse_d(int c, char **argv, int argc,
+ const struct ebt_u_entry *entry, unsigned int *flags,
+ struct ebt_entry_target **target)
+ {
++ int i;
+ struct ebt_nat_info *natinfo = (struct ebt_nat_info *)(*target)->data;
+
+ switch (c) {
+@@ -86,8 +115,18 @@
+ print_error("Problem with specified "
+ "to-destination mac");
+ break;
++ case NAT_D_TARGET:
++ check_option(flags, OPT_DNAT_TARGET);
++ for (i = 0; i < NUM_STANDARD_TARGETS; i++)
++ if (!strcmp(optarg, standard_targets[i])) {
++ natinfo->target = i;
++ break;
++ }
++ if (i == NUM_STANDARD_TARGETS)
++ print_error("Illegal --dnat-target target");
++ break;
+ default:
+- return 0;
++ return 0;
+ }
+ return 1;
+ }
+@@ -96,18 +135,18 @@
+ const struct ebt_entry_target *target, const char *name, unsigned int hook)
+ {
+ if (hook != NF_BR_POST_ROUTING || strcmp(name, "nat"))
+- print_error("Wrong chain for SNAT");
++ print_error("Wrong chain for snat");
+ if (to_source_supplied == 0)
+ print_error("No snat address supplied");
+-
+ }
+
+ static void final_check_d(const struct ebt_u_entry *entry,
+ const struct ebt_entry_target *target, const char *name, unsigned int hook)
+ {
+- if ( (hook != NF_BR_PRE_ROUTING && hook != NF_BR_LOCAL_OUT) ||
+- strcmp(name, "nat") )
+- print_error("Wrong chain for DNAT");
++ if ( ((hook != NF_BR_PRE_ROUTING && hook != NF_BR_LOCAL_OUT) ||
++ strcmp(name, "nat")) &&
++ (hook != NF_BR_BROUTING || strcmp(name, "broute")) )
++ print_error("Wrong chain for dnat");
+ if (to_dest_supplied == 0)
+ print_error("No dnat address supplied");
+ }
+@@ -122,6 +161,7 @@
+ for (i = 0; i < ETH_ALEN; i++)
+ printf("%02x%s",
+ natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
++ printf(" --snat-target %s", standard_targets[natinfo->target]);
+ }
+
+ static void print_d(const struct ebt_u_entry *entry,
+@@ -134,6 +174,7 @@
+ for (i = 0; i < ETH_ALEN; i++)
+ printf("%02x%s",
+ natinfo->mac[i], (i == ETH_ALEN - 1) ? "" : ":");
++ printf(" --dnat-target %s", standard_targets[natinfo->target]);
+ }
+
+ static int compare(const struct ebt_entry_target *t1,
+@@ -142,13 +183,15 @@
+ struct ebt_nat_info *natinfo1 = (struct ebt_nat_info *)t1->data;
+ struct ebt_nat_info *natinfo2 = (struct ebt_nat_info *)t2->data;
+
+- return !memcmp(natinfo1->mac, natinfo2->mac, sizeof(natinfo1->mac));
++
++ return !memcmp(natinfo1->mac, natinfo2->mac, sizeof(natinfo1->mac)) &&
++ natinfo1->target == natinfo2->target;
+ }
+
+ static struct ebt_u_target snat_target =
+ {
+ EBT_SNAT_TARGET,
+- sizeof(struct ebt_nat_info) + sizeof(struct ebt_entry_target),
++ sizeof(struct ebt_nat_info),
+ print_help_s,
+ init_s,
+ parse_s,
+--- ebtables-v2.0pre3.003/extensions/Makefile Sat Apr 6 21:56:53 2002
++++ ebtables-v2.0pre3.004/extensions/Makefile Tue Apr 23 22:46:21 2002
+@@ -1,7 +1,7 @@
+ #! /usr/bin/make
+
+-EXT_FUNC+=nat arp ip standard log
+-EXT_TABLES+=filter nat
++EXT_FUNC+=nat arp ip standard log redirect
++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)
+
+--- ebtables-v2.0pre3.003/ChangeLog Sun Apr 14 14:15:59 2002
++++ ebtables-v2.0pre3.004/ChangeLog Sat Apr 27 17:24:26 2002
+@@ -1,3 +1,9 @@
++20020427
++ * added broute table.
++ * added redirect target.
++ * added --redirect-target, --snat-target and --dnat-target options.
++ * added logical_out and logical_in
++ * snat bugfix (->size)
+ 20020414
+ * fixed some things in the manual.
+ * fixed -P problem.
+--- ebtables-v2.0pre3.003/ebtables.8 Sat Apr 27 16:57:44 2002
++++ ebtables-v2.0pre3.004/ebtables.8 Sat Apr 27 13:33:37 2002
+@@ -1,4 +1,4 @@
+-.TH EBTABLES 8 "14 April 2002"
++.TH EBTABLES 8 "27 April 2002"
+ .\"
+ .\" Man page written by Bart De Schuymer <bart.de.schuymer@pandora.be>
+ .\" It is based on the iptables man page.
+@@ -40,7 +40,7 @@
+ complicated. This man page is written with the man page of iptables
+ next to it, so don't be surprised to see copied sentences and structure.
+
+-There are two tables with each three built-in chains. Each chain is a list
++There are three tables with built-in chains. Each chain is a list
+ of rules which can match frames: each rule specifies what to do with a
+ frame which matches. This is called a 'target'. The tables are used to
+ divide functionality into different sets of chains.
+@@ -66,7 +66,7 @@
+ .B "TARGET EXTENSIONS"
+ section.
+ .SS TABLES
+-There are two tables.
++There are three tables.
+ .TP
+ .B "-t, --table"
+ This option specifies the frame matching table which the command should
+@@ -90,6 +90,22 @@
+ of chains POSTROUTING and PREROUTING: it would be more accurate to call them
+ PREFORWARDING and POSTFORWARDING, but for all those who come from the iptables
+ world to ebtables it is easier to have the same names.
++.BR broute ,
++this table is used to make a brouter, it has one chain:
++.BR BROUTING .
++The targets
++.BR DROP and ACCEPT
++have special meaning in this table.
++.B DROP
++actually means the frame has to be routed, while
++.B ACCEPT
++means the frame has to be bridged. The
++.B BROUTING
++chain is traversed very early. It is only traversed by frames entering on
++a bridge enslaved nic that is in forwarding state. Normally those frames
++would be bridged, but you can decide otherwise here. The
++.B redirect
++target is very handy here.
+ .SH OPTIONS
+ The options can be divided into several different groups.
+ .SS COMMANDS
+@@ -334,13 +350,21 @@
+ The flag
+ .B --to-src
+ is an alias for this option.
++.br
++.BR "--snat-target " "\fItarget\fP"
++.br
++Specifies the standard target. After doing the snat, the rule still has
++to give a standard target so ebtables knows what to do.
++The default target is ACCEPT. Making it CONTINUE could let you use
++multiple target extensions on the same frame. Making it DROP doesn't
++make sense, but you could do that too.
+ .TP
+ .B dnat
+ The
+ .B dnat
+ target can only be used in the
+-.BR PREROUTING " and the
+-.BR OUTPUT " chains of the " nat " table."
++.BR BROUTING " chain of the " broute " table and the "
++.BR PREROUTING " and " OUTPUT " chains of the " nat " table."
+ It specifies that the destination mac address has to be changed.
+ .br
+ .BR "--to-destination " "\fIaddress\fP"
+@@ -348,6 +372,31 @@
+ The flag
+ .B --to-dst
+ is an alias for this option.
++.br
++.BR "--dnat-target " "\fItarget\fP"
++.br
++Specifies the standard target. After doing the dnat, the rule still has to
++give a standard target so ebtables knows what to do.
++The default target is ACCEPT. Making it CONTINUE could let you use
++multiple target extensions on the same frame. Making it DROP only makes
++sense in the BROUTING chain but using the redirect target is more logical
++there.
++.TP
++.B redirect
++The
++.B redirect
++target will change the MAC target address to that of the physical nic the
++frame arrived on. This target can only be used in the
++.BR BROUTING " chain of the " broute " table and the "
++.BR PREROUTING " chain of the " nat " table."
++.br
++.BR "--redirect-target " "\fItarget\fP"
++.br
++Specifies the standard target. After doing the MAC redirect, the rule
++still has to give a standard target so ebtables knows what to do.
++The default target is ACCEPT. Making it CONTINUE could let you use
++multiple target extensions on the same frame. Making it DROP in the
++BROUTING chain will let the frames be routed.
+ .SH FILES
+ .I /etc/etherproto
+ .SH BUGS
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre4.001.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre4.001.diff
new file mode 100644
index 0000000..c4a9e39
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre4.001.diff
@@ -0,0 +1,522 @@
+--- ebtables-v2.0pre3/Makefile Sat Apr 27 22:31:19 2002
++++ ebtables-v2.0pre4.001/Makefile Thu May 2 19:02:44 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre3 (April 2002)"
++PROGVERSION:="2.0pre4 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+@@ -32,12 +32,12 @@
+ mkdir -p $(@D)
+ install -m 0644 -o root -g root $< $@
+
+-/etc/etherproto: etherproto
++/etc/ethertypes: ethertypes
+ mkdir -p $(@D)
+ install -m 0644 -o root -g root $< $@
+
+ install: $(MANDIR)/man8/ebtables.8 headers \
+- ebtables /etc/etherproto
++ ebtables /etc/ethertypes
+
+ clean:
+ -rm -f ebtables
+--- ebtables-v2.0pre3/ebtables.c Sat Apr 27 22:31:21 2002
++++ ebtables-v2.0pre4.001/ebtables.c Fri May 3 20:56:14 2002
+@@ -36,7 +36,7 @@
+
+ // here are the number-name correspondences kept for the ethernet
+ // frame type field
+-#define PROTOCOLFILE "/etc/etherproto"
++#define PROTOCOLFILE "/etc/ethertypes"
+
+ #define DATABASEHOOKNR NF_BR_NUMHOOKS
+ #define DATABASEHOOKNAME "DB"
+@@ -90,6 +90,13 @@
+ "CONTINUE",
+ };
+
++unsigned char mac_type_unicast[ETH_ALEN] = {0,0,0,0,0,0};
++unsigned char msk_type_unicast[ETH_ALEN] = {1,0,0,0,0,0};
++unsigned char mac_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
++unsigned char msk_type_multicast[ETH_ALEN] = {1,0,0,0,0,0};
++unsigned char mac_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
++unsigned char msk_type_broadcast[ETH_ALEN] = {255,255,255,255,255,255};
++
+ // tells what happened to the old rules
+ static unsigned short *counterchanges;
+ // holds all the data
+@@ -466,20 +473,70 @@
+ }
+ }
+ if (hlp->bitmask & EBT_SOURCEMAC) {
++ char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
++
+ printf("source mac: ");
+ if (hlp->invflags & EBT_ISOURCE)
+ printf("! ");
++ if (!memcmp(hlp->sourcemac, mac_type_unicast, 6) &&
++ !memcmp(hlp->sourcemsk, msk_type_unicast, 6)) {
++ printf("Unicast");
++ goto endsrc;
++ }
++ if (!memcmp(hlp->sourcemac, mac_type_multicast, 6) &&
++ !memcmp(hlp->sourcemsk, msk_type_multicast, 6)) {
++ printf("Multicast");
++ goto endsrc;
++ }
++ if (!memcmp(hlp->sourcemac, mac_type_broadcast, 6) &&
++ !memcmp(hlp->sourcemsk, msk_type_broadcast, 6)) {
++ printf("Broadcast");
++ goto endsrc;
++ }
+ for (j = 0; j < ETH_ALEN; j++)
+ printf("%02x%s", hlp->sourcemac[j],
+- (j == ETH_ALEN - 1) ? ", " : ":");
++ (j == ETH_ALEN - 1) ? "" : ":");
++ if (memcmp(hlp->sourcemsk, hlpmsk, 6)) {
++ printf("/");
++ for (j = 0; j < ETH_ALEN; j++)
++ printf("%02x%s", hlp->sourcemsk[j],
++ (j == ETH_ALEN - 1) ? "" : ":");
++ }
++endsrc:
++ printf(", ");
+ }
+ if (hlp->bitmask & EBT_DESTMAC) {
++ char hlpmsk[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
++
+ printf("dest mac: ");
+ if (hlp->invflags & EBT_IDEST)
+ printf("! ");
++ if (!memcmp(hlp->destmac, mac_type_unicast, 6) &&
++ !memcmp(hlp->destmsk, msk_type_unicast, 6)) {
++ printf("Unicast");
++ goto enddst;
++ }
++ if (!memcmp(hlp->destmac, mac_type_multicast, 6) &&
++ !memcmp(hlp->destmsk, msk_type_multicast, 6)) {
++ printf("Multicast");
++ goto enddst;
++ }
++ if (!memcmp(hlp->destmac, mac_type_broadcast, 6) &&
++ !memcmp(hlp->destmsk, msk_type_broadcast, 6)) {
++ printf("Broadcast");
++ goto enddst;
++ }
+ for (j = 0; j < ETH_ALEN; j++)
+ printf("%02x%s", hlp->destmac[j],
+- (j == ETH_ALEN - 1) ? ", " : ":");
++ (j == ETH_ALEN - 1) ? "" : ":");
++ if (memcmp(hlp->destmsk, hlpmsk, 6)) {
++ printf("/");
++ for (j = 0; j < ETH_ALEN; j++)
++ printf("%02x%s", hlp->destmsk[j],
++ (j == ETH_ALEN - 1) ? "" : ":");
++ }
++enddst:
++ printf(", ");
+ }
+ if (hlp->in[0] != '\0') {
+ if (hlp->invflags & EBT_IIN)
+@@ -1096,6 +1153,39 @@
+ return 0;
+ }
+
++int getmac_and_mask(char *from, char *to, char *mask)
++{
++ char *p;
++ int i;
++
++ if (strcasecmp(from, "Unicast") == 0) {
++ memcpy(to, mac_type_unicast, ETH_ALEN);
++ memcpy(mask, msk_type_unicast, ETH_ALEN);
++ return 0;
++ }
++ if (strcasecmp(from, "Multicast") == 0) {
++ memcpy(to, mac_type_multicast, ETH_ALEN);
++ memcpy(mask, msk_type_multicast, ETH_ALEN);
++ return 0;
++ }
++ if (strcasecmp(from, "Broadcast") == 0) {
++ memcpy(to, mac_type_broadcast, ETH_ALEN);
++ memcpy(mask, msk_type_broadcast, ETH_ALEN);
++ return 0;
++ }
++ if ( (p = strrchr(from, '/')) != NULL) {
++ *p = '\0';
++ if (getmac(p + 1, mask))
++ return -1;
++ } else
++ memset(mask, 0xff, ETH_ALEN);
++ if (getmac(from, to))
++ return -1;
++ for (i = 0; i < ETH_ALEN; i++)
++ to[i] &= mask[i];
++ return 0;
++}
++
+ int check_inverse(const char option[])
+ {
+ if (strcmp(option, "!") == 0) {
+@@ -1294,9 +1384,11 @@
+ print_error("Command and option do not match");
+ if (c == 'i') {
+ check_option(&replace.flags, OPT_IN);
+- if (replace.selected_hook > 2)
++ if (replace.selected_hook > 2 &&
++ replace.selected_hook < NF_BR_BROUTING)
+ print_error("Use in-interface only in "
+- "INPUT, FORWARD and PREROUTING chains");
++ "INPUT, FORWARD, PREROUTING and"
++ "BROUTING chains");
+ if (check_inverse(optarg))
+ new_entry->invflags |= EBT_IIN;
+
+@@ -1310,10 +1402,11 @@
+ }
+ if (c == 2) {
+ check_option(&replace.flags, OPT_LOGICALIN);
+- if (replace.selected_hook > 2)
++ if (replace.selected_hook > 2 &&
++ replace.selected_hook < NF_BR_BROUTING)
+ print_error("Use logical in-interface "
+- "only in INPUT, FORWARD and "
+- "PREROUTING chains");
++ "only in INPUT, FORWARD, "
++ "PREROUTING and BROUTING chains");
+ if (check_inverse(optarg))
+ new_entry->invflags |= EBT_ILOGICALIN;
+
+@@ -1398,8 +1491,8 @@
+ if (optind > argc)
+ print_error("No source mac "
+ "specified");
+- if (getmac(argv[optind - 1],
+- new_entry->sourcemac))
++ if (getmac_and_mask(argv[optind - 1],
++ new_entry->sourcemac, new_entry->sourcemsk))
+ print_error("Problem with specified "
+ "source mac");
+ new_entry->bitmask |= EBT_SOURCEMAC;
+@@ -1413,8 +1506,8 @@
+ if (optind > argc)
+ print_error("No destination mac "
+ "specified");
+- if (getmac(argv[optind - 1],
+- new_entry->destmac))
++ if (getmac_and_mask(argv[optind - 1],
++ new_entry->destmac, new_entry->destmsk))
+ print_error("Problem with specified "
+ "destination mac");
+ new_entry->bitmask |= EBT_DESTMAC;
+--- ebtables-v2.0pre3/communication.c Sat Apr 27 22:31:19 2002
++++ ebtables-v2.0pre4.001/communication.c Thu May 2 19:02:44 2002
+@@ -121,7 +121,10 @@
+ sizeof(tmp->logical_out));
+ memcpy(tmp->sourcemac, e->sourcemac,
+ sizeof(tmp->sourcemac));
++ memcpy(tmp->sourcemsk, e->sourcemsk,
++ sizeof(tmp->sourcemsk));
+ memcpy(tmp->destmac, e->destmac, sizeof(tmp->destmac));
++ memcpy(tmp->destmsk, e->destmsk, sizeof(tmp->destmsk));
+
+ base = p;
+ p += sizeof(struct ebt_entry);
+@@ -307,7 +310,9 @@
+ memcpy(new->logical_out, e->logical_out,
+ sizeof(new->logical_out));
+ memcpy(new->sourcemac, e->sourcemac, sizeof(new->sourcemac));
++ memcpy(new->sourcemsk, e->sourcemsk, sizeof(new->sourcemsk));
+ memcpy(new->destmac, e->destmac, sizeof(new->destmac));
++ memcpy(new->destmsk, e->destmsk, sizeof(new->destmsk));
+ new->m_list = NULL;
+ new->w_list = NULL;
+ new->next = NULL;
+--- ebtables-v2.0pre3/ChangeLog Sat Apr 27 22:31:21 2002
++++ ebtables-v2.0pre4.001/ChangeLog Thu May 2 19:02:44 2002
+@@ -1,3 +1,11 @@
++20020501
++ * allow -i and --logical-in in BROUTING
++ * update the manual page
++ * rename /etc/etherproto into /etc/ethertypes (seems to be a more
++ standard name)
++ * add MAC mask for -s and -d, also added Unicast, Multicast and
++ Broadcast specification for specifying a (family of) MAC
++ addresses.
+ 20020427
+ * added broute table.
+ * added redirect target.
+--- ebtables-v2.0pre3/ebtables.8 Sat Apr 27 22:31:21 2002
++++ ebtables-v2.0pre4.001/ebtables.8 Thu May 2 19:02:44 2002
+@@ -1,4 +1,4 @@
+-.TH EBTABLES 8 "27 April 2002"
++.TH EBTABLES 8 "01 May 2002"
+ .\"
+ .\" Man page written by Bart De Schuymer <bart.de.schuymer@pandora.be>
+ .\" It is based on the iptables man page.
+@@ -31,7 +31,7 @@
+ .br
+ .B "ebtables -L DB"
+ .br
+-.BR "ebtables -[cb] [" "y/n" "]"
++.BR "ebtables -[b] [" "y/n" "]"
+ .br
+ .SH DESCRIPTION
+ .B ebtables
+@@ -88,13 +88,14 @@
+ .B POSTROUTING
+ (for altering frames as they are about to go out). A small note on the naming
+ of chains POSTROUTING and PREROUTING: it would be more accurate to call them
+-PREFORWARDING and POSTFORWARDING, but for all those who come from the iptables
+-world to ebtables it is easier to have the same names.
++PREFORWARDING and POSTFORWARDING, but for all those who come from the
++.BR iptables " world to " ebtables
++it is easier to have the same names.
+ .BR broute ,
+ this table is used to make a brouter, it has one chain:
+ .BR BROUTING .
+ The targets
+-.BR DROP and ACCEPT
++.BR DROP " and " ACCEPT
+ have special meaning in this table.
+ .B DROP
+ actually means the frame has to be routed, while
+@@ -178,8 +179,9 @@
+ .B ebtables
+ for these frames is
+ .BR LENGTH .
++.br
+ The file
+-.B /etc/etherproto
++.B /etc/ethertypes
+ can be used to show readable
+ characters instead of hexadecimal numbers for the protocols. For example,
+ .I 0x0800
+@@ -193,9 +195,8 @@
+ .BR "-i, --in-interface " "[!] \fIname\fP"
+ The interface via which a frame is received (for the
+ .BR INPUT ,
+-.B FORWARD
+-and
+-.B PREROUTING
++.BR FORWARD ,
++.BR PREROUTING " and " BROUTING
+ chains). The flag
+ .B --in-if
+ is an alias for this option.
+@@ -203,9 +204,8 @@
+ .BR "--logical-in " "[!] \fIname\fP"
+ The (logical) bridge interface via which a frame is received (for the
+ .BR INPUT ,
+-.B FORWARD
+-and
+-.B PREROUTING
++.BR FORWARD ,
++.BR PREROUTING " and " BROUTING
+ chains).
+ .TP
+ .BR "-o, --out-interface " "[!] \fIname\fP"
+@@ -227,23 +227,31 @@
+ .B POSTROUTING
+ chains).
+ .TP
+-.BR "-s, --source " "[!] \fIaddress\fP"
+-The source mac address. The flag
++.BR "-s, --source " "[!] \fIaddress\fP[/\fImask\fP]"
++The source mac address. Both mask and address are written as 6 hexadecimal
++numbers seperated by colons. Alternatively one can specify Unicast,
++Multicast or Broadcast.
++.br
++Unicast=00:00:00:00:00:00/01:00:00:00:00:00,
++Multicast=01:00:00:00:00:00/01:00:00:00:00:00 and
++Broadcast=ff:ff:ff:ff:ff:ff/ff:ff:ff:ff:ff:ff. Note that a broadcast
++address will also match the multicast specification. The flag
+ .B --src
+ is an alias for this option.
+ .TP
+-.BR "-d, --destination " "[!] \fIaddress\fP"
+-The destination mac address. The flag
++.BR "-d, --destination " "[!] \fIaddress\fP[/\fImask\fP]"
++The destination mac address. See -s (above) for more details. The flag
+ .B --dst
+ is an alias for this option.
+
+ .SS OTHER OPTIONS
++.TP
+ .B "-V, --version"
+ Show the version of the userprogram.
+ .TP
+ .B "-h, --help"
+-Give a brief description of the command syntax. Here you can specify names of
+-extensions and
++Give a brief description of the command syntax. Here you can also specify
++names of extensions and
+ .B ebtables
+ will try to write help about those extensions. E.g. ebtables -h snat log ip arp.
+ .TP
+@@ -258,7 +266,8 @@
+ or a target extension, see
+ .BR "TARGET EXTENSIONS" .
+ .SH MATCH EXTENSIONS
+-ebtables extensions are precompiled into the userspace tool. So there is no need
++.B ebtables
++extensions are precompiled into the userspace tool. So there is no need
+ to explicitly load them with a -m option like in iptables. However, these
+ extensions deal with functionality supported by supplemental kernel modules.
+ .SS ip
+@@ -291,10 +300,11 @@
+ .BR ARP " or " RARP .
+ .TP
+ .BR "--arp-opcode " "[!] \fIopcode\fP"
+-The (r)arp opcode (decimal or a string, see ebtables help).
++The (r)arp opcode (decimal or a string, for more details see ebtables -h arp).
+ .TP
+ .BR "--arp-htype " "[!] \fIhardware type\fP"
+-The hardware type (decimal or the string "Ethernet"). This is normally Ethernet (value 1).
++The hardware type, this can be a decimal or the string "Ethernet". This
++is normally Ethernet (value 1).
+ .TP
+ .BR "--arp-ptype " "[!] \fIprotocol type\fP"
+ The protocol type for which the (r)arp is used (hexadecimal or the string "IPv4").
+@@ -354,7 +364,9 @@
+ .BR "--snat-target " "\fItarget\fP"
+ .br
+ Specifies the standard target. After doing the snat, the rule still has
+-to give a standard target so ebtables knows what to do.
++to give a standard target so
++.B ebtables
++knows what to do.
+ The default target is ACCEPT. Making it CONTINUE could let you use
+ multiple target extensions on the same frame. Making it DROP doesn't
+ make sense, but you could do that too.
+@@ -376,7 +388,9 @@
+ .BR "--dnat-target " "\fItarget\fP"
+ .br
+ Specifies the standard target. After doing the dnat, the rule still has to
+-give a standard target so ebtables knows what to do.
++give a standard target so
++.B ebtables
++knows what to do.
+ The default target is ACCEPT. Making it CONTINUE could let you use
+ multiple target extensions on the same frame. Making it DROP only makes
+ sense in the BROUTING chain but using the redirect target is more logical
+@@ -385,7 +399,7 @@
+ .B redirect
+ The
+ .B redirect
+-target will change the MAC target address to that of the physical nic the
++target will change the MAC target address to that of the bridge device the
+ frame arrived on. This target can only be used in the
+ .BR BROUTING " chain of the " broute " table and the "
+ .BR PREROUTING " chain of the " nat " table."
+@@ -393,12 +407,14 @@
+ .BR "--redirect-target " "\fItarget\fP"
+ .br
+ Specifies the standard target. After doing the MAC redirect, the rule
+-still has to give a standard target so ebtables knows what to do.
++still has to give a standard target so
++.B ebtables
++knows what to do.
+ The default target is ACCEPT. Making it CONTINUE could let you use
+ multiple target extensions on the same frame. Making it DROP in the
+ BROUTING chain will let the frames be routed.
+ .SH FILES
+-.I /etc/etherproto
++.I /etc/ethertypes
+ .SH BUGS
+ This won't work on an architecture with a user32/kernel64 situation like the Sparc64.
+ .SH AUTHOR
+--- ebtables-v2.0pre3/etherproto Wed Apr 3 13:16:59 2002
++++ /dev/null Thu Aug 24 11:00:32 2000
+@@ -1,36 +0,0 @@
+- # all whitespace is ignored
+- # comment lines must have a '#' as the first character
+- # all protocol numbers are in hexadecimal form
+- # maximum namesize = 20 characters
+- # always put tabs or spaces between the name and the protocol number
+-# don't use more than 4 digits for the protocol number
+-# programs using this file should not be case sensitive
+-# that's all :-))
+-IPV4 0800 put your comments behind, on the same line, after a tab
+-X25 0800 or whitespace
+-ARP 0806
+-IPX 8137
+-IPV6 86DD
+-NetBEUI 8191
+-
+-# some definitions from the kernel (/include/linux/if_ether.h)
+-
+-BPQ 08FF G8BPQ AX.25 Ethernet Packet
+-DEC 6000 DEC Assigned proto
+-DNA_DL 6001 DEC DNA Dump/Load
+-DNA_RC 6002 DEC DNA Remote Console
+-DNA_RT 6003 DEC DNA Routing
+-LAT 6004 DEC LAT
+-DIAG 6005 DEC Diagnostics
+-CUST 6006 DEC Customer use
+-SCA 6007 DEC Systems Comms Arch
+-RARP 8035 Reverse Addr Res packet
+-ATALK 809B Appletalk DDP
+-AARP 80F3 Appletalk AARP
+-IPX 8137 IPX over DIX
+-PPP_DISC 8863 PPPoE discovery messages
+-PPP_SES 8864 PPPoE session messages
+-ATMMPOA 884C MultiProtocol over ATM
+-ATMFATE 8884 Frame-based ATM Transport over Ethernet
+-
+-
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0pre4.001/ethertypes Thu May 2 19:02:44 2002
+@@ -0,0 +1,36 @@
++ # all whitespace is ignored
++ # comment lines must have a '#' as the first character
++ # all protocol numbers are in hexadecimal form
++ # maximum namesize = 20 characters
++ # always put tabs or spaces between the name and the protocol number
++# don't use more than 4 digits for the protocol number
++# programs using this file should not be case sensitive
++# that's all :-))
++IPV4 0800 put your comments behind, on the same line, after a tab
++X25 0800 or whitespace
++ARP 0806
++IPX 8137
++IPV6 86DD
++NetBEUI 8191
++
++# some definitions from the kernel (/include/linux/if_ether.h)
++
++BPQ 08FF G8BPQ AX.25 Ethernet Packet
++DEC 6000 DEC Assigned proto
++DNA_DL 6001 DEC DNA Dump/Load
++DNA_RC 6002 DEC DNA Remote Console
++DNA_RT 6003 DEC DNA Routing
++LAT 6004 DEC LAT
++DIAG 6005 DEC Diagnostics
++CUST 6006 DEC Customer use
++SCA 6007 DEC Systems Comms Arch
++RARP 8035 Reverse Addr Res packet
++ATALK 809B Appletalk DDP
++AARP 80F3 Appletalk AARP
++IPX 8137 IPX over DIX
++PPP_DISC 8863 PPPoE discovery messages
++PPP_SES 8864 PPPoE session messages
++ATMMPOA 884C MultiProtocol over ATM
++ATMFATE 8884 Frame-based ATM Transport over Ethernet
++
++
+--- ebtables-v2.0pre3/include/ebtables_u.h Sat Apr 27 22:31:16 2002
++++ ebtables-v2.0pre4.001/include/ebtables_u.h Thu May 2 19:02:44 2002
+@@ -86,7 +86,9 @@
+ __u8 out[IFNAMSIZ];
+ __u8 logical_out[IFNAMSIZ];
+ __u8 sourcemac[ETH_ALEN];
++ __u8 sourcemsk[ETH_ALEN];
+ __u8 destmac[ETH_ALEN];
++ __u8 destmsk[ETH_ALEN];
+ struct ebt_u_match_list *m_list;
+ struct ebt_u_watcher_list *w_list;
+ struct ebt_entry_target *t;
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre5.001.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre5.001.diff
new file mode 100644
index 0000000..42202a4
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre5.001.diff
@@ -0,0 +1,50 @@
+update help and VLAN ethertype in /etc/ethertypes
+
+--- ebtables-v2.0pre4/Makefile Fri May 3 21:08:24 2002
++++ ebtables-v2.0pre5.001/Makefile Fri May 3 21:34:23 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre4 (April 2002)"
++PROGVERSION:="2.0pre5 (April 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+--- ebtables-v2.0pre4/ebtables.c Fri May 3 21:08:24 2002
++++ ebtables-v2.0pre5.001/ebtables.c Fri May 3 21:33:55 2002
+@@ -628,8 +628,8 @@
+ "--policy -P chain target : Change policy on chain to target\n"
+ "Options:\n"
+ "--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
+-"--src -s [!] address : source mac address\n"
+-"--dst -d [!] address : destination mac address\n"
++"--src -s [!] address[/mask]: source mac address\n"
++"--dst -d [!] address[/mask]: destination mac address\n"
+ "--in-if -i [!] name : network input interface name\n"
+ "--out-if -o [!] name : network output interface name\n"
+ "--logical-in [!] name : logical bridge input interface name\n"
+--- ebtables-v2.0pre4/ChangeLog Fri May 3 21:08:25 2002
++++ ebtables-v2.0pre5.001/ChangeLog Sat May 18 10:30:44 2002
+@@ -1,3 +1,5 @@
++ * update help for -s and -d
++ * add VLAN in ethertypes
+ 20020501
+ * allow -i and --logical-in in BROUTING
+ * update the manual page
+--- ebtables-v2.0pre4/ethertypes Fri May 3 21:08:25 2002
++++ ebtables-v2.0pre5.001/ethertypes Sat May 18 10:30:10 2002
+@@ -9,12 +9,10 @@
+ IPV4 0800 put your comments behind, on the same line, after a tab
+ X25 0800 or whitespace
+ ARP 0806
++VLAN 8100
+ IPX 8137
+ IPV6 86DD
+ NetBEUI 8191
+-
+-# some definitions from the kernel (/include/linux/if_ether.h)
+-
+ BPQ 08FF G8BPQ AX.25 Ethernet Packet
+ DEC 6000 DEC Assigned proto
+ DNA_DL 6001 DEC DNA Dump/Load
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre5.002.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre5.002.diff
new file mode 100644
index 0000000..5b2d037
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre5.002.diff
@@ -0,0 +1,61 @@
+--- ebtables-v2.0pre5.001/Makefile Mon May 20 13:59:48 2002
++++ ebtables-v2.0pre5.002/Makefile Mon May 20 14:06:38 2002
+@@ -2,12 +2,19 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre5 (April 2002)"
++PROGVERSION:="2.0pre5 (May 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+ include extensions/Makefile
+
++# Some kernel testers prefer to use a symlink for /usr/include/linux
++ifeq ($(SYMLINK), y)
++KERNEL_INCLUDES=symlink
++else
++KERNEL_INCLUDES=headers
++endif
++
+ .PHONY: headers
+ headers:
+ mkdir -p /usr/include/linux/netfilter_bridge
+@@ -18,6 +25,10 @@
+ cp -f $(KERNEL_DIR)/include/linux/netfilter_bridge.h \
+ /usr/include/linux/netfilter_bridge.h
+
++.PHONY: symlink
++symlink:
++ ln -fs $(KERNEL_DIR)/include/linux /usr/include/linux
++
+ communication.o: communication.c include/ebtables_u.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+
+@@ -36,7 +47,7 @@
+ mkdir -p $(@D)
+ install -m 0644 -o root -g root $< $@
+
+-install: $(MANDIR)/man8/ebtables.8 headers \
++install: $(MANDIR)/man8/ebtables.8 $(KERNEL_INCLUDES) \
+ ebtables /etc/ethertypes
+
+ clean:
+--- ebtables-v2.0pre5.001/THANKS Sat Apr 13 17:40:35 2002
++++ ebtables-v2.0pre5.002/THANKS Mon May 20 13:49:50 2002
+@@ -6,4 +6,4 @@
+ Jason Lunz
+ Tim Gardner
+ Loïc Minier
+-
++Nick Fedchik
+--- ebtables-v2.0pre5.001/ChangeLog Mon May 20 13:59:48 2002
++++ ebtables-v2.0pre5.002/ChangeLog Mon May 20 13:49:27 2002
+@@ -1,5 +1,7 @@
++20020520
+ * update help for -s and -d
+ * add VLAN in ethertypes
++ * add SYMLINK option for compiling
+ 20020501
+ * allow -i and --logical-in in BROUTING
+ * update the manual page
diff --git a/userspace/patches/incremental-patches/ebtables-v2.0pre6.001.diff b/userspace/patches/incremental-patches/ebtables-v2.0pre6.001.diff
new file mode 100644
index 0000000..a143d62
--- /dev/null
+++ b/userspace/patches/incremental-patches/ebtables-v2.0pre6.001.diff
@@ -0,0 +1,314 @@
+--- ebtables-v2.0pre5/Makefile Mon May 20 14:06:38 2002
++++ ebtables-v2.0pre6.001/Makefile Thu May 30 18:39:04 2002
+@@ -2,7 +2,7 @@
+
+ KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0pre5 (May 2002)"
++PROGVERSION:="2.0pre6 (May 2002)"
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+@@ -15,6 +15,8 @@
+ KERNEL_INCLUDES=headers
+ endif
+
++all: ebtables
++
+ .PHONY: headers
+ headers:
+ mkdir -p /usr/include/linux/netfilter_bridge
+@@ -52,3 +54,5 @@
+
+ clean:
+ -rm -f ebtables
++ rm -f *.o *.c~
++ rm -f extensions/*.o extensions/*.c~
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0pre6.001/extensions/ebt_vlan.c Thu May 30 18:38:44 2002
+@@ -0,0 +1,231 @@
++/*
++ * Summary: ebt_vlan userspace module
++ *
++ * Description: 802.1Q Virtual LAN match support module for ebtables project.
++ * Enable to match 802.1Q VLAN tagged frames by VLAN numeric
++ * identifier (12-bites field) and frame priority (3-bites field)
++ *
++ * Authors:
++ * Bart De Schuymer <bart.de.schuymer@pandora.be>
++ * Nick Fedchik <nick@fedchik.org.ua>
++ *
++ * May, 2002
++ */
++
++#include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
++#include <sys/socket.h>
++#include <netinet/in.h>
++#include <linux/netfilter_bridge/ebtables.h>
++#include <getopt.h>
++#include "../include/ebtables_u.h"
++#include <linux/netfilter_bridge/ebt_vlan.h>
++
++#define VLAN_ID '1'
++#define VLAN_PRIO '2'
++
++static struct option opts[] = {
++ {"vlan-id", required_argument, 0, VLAN_ID},
++ {"vlan-prio", required_argument, 0, VLAN_PRIO},
++ {0}
++};
++
++/*
++ * Print out help for ebtables -h vlan
++ */
++static void print_help ()
++{
++ printf ("802.1Q VLAN options:\n"
++ "--vlan-id [!] id : VLAN ID 1-4095 (integer)\n"
++ "--vlan-prio [!] prio : VLAN Priority 0-7 (integer)\n");
++}
++
++/*
++ * Initialization function
++ */
++static void init (struct ebt_entry_match *match)
++{
++ struct ebt_vlan_info *vlaninfo =
++ (struct ebt_vlan_info *) match->data;
++ /*
++ * Just clean initial values
++ */
++ vlaninfo->id = 0;
++ vlaninfo->prio = 0;
++ vlaninfo->invflags = 0;
++ vlaninfo->bitmask = 0;
++}
++
++#define OPT_VLAN_ID 0x01
++#define OPT_VLAN_PRIO 0x02
++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_vlan_info *vlaninfo =
++ (struct ebt_vlan_info *) (*match)->data;
++ unsigned short i;
++ char *end;
++
++ switch (c) {
++ case VLAN_ID:
++ check_option (flags, OPT_VLAN_ID);
++ /*
++ * Check If we got inversed arg for VID,
++ * otherwise unset inversion flag
++ */
++ if (check_inverse (optarg))
++ vlaninfo->invflags |= EBT_VLAN_ID;
++ /*
++ * Check arg value presense
++ */
++ if (optind > argc)
++ print_error ("Missing VLAN ID argument\n");
++ /*
++ * Convert argv to long int,
++ * set *end to end of argv string,
++ * base set 10 for decimal only
++ */
++ (unsigned short) i = strtol (argv[optind - 1], &end, 10);
++ /*
++ * Check arg val range
++ */
++ if (i < 1 || i >= 4096 || *end != '\0') {
++ i = 0;
++ print_error
++ ("Problem with specified VLAN ID range\n");
++ }
++ vlaninfo->id = i;
++ vlaninfo->bitmask|=EBT_VLAN_ID;
++ break;
++
++ case VLAN_PRIO:
++ check_option (flags, OPT_VLAN_PRIO);
++ if (check_inverse (optarg))
++ vlaninfo->invflags |= EBT_VLAN_PRIO;
++ if (optind > argc)
++ print_error
++ ("Missing VLAN Priority level argument\n");
++ /*
++ * Convert argv to long int,
++ * set *end to end of argv string,
++ * base set 10 for decimal only
++ */
++ (unsigned short) i = strtol (argv[optind - 1], &end, 10);
++ /*
++ * Check arg val range
++ */
++ if (i >= 8 || *end != '\0') {
++ i = 0;
++ print_error
++ ("Problem with specified VLAN Priority range\n");
++ }
++ vlaninfo->prio = i;
++ vlaninfo->bitmask|=EBT_VLAN_PRIO;
++ break;
++
++ default:
++ return 0;
++ }
++ return 1;
++}
++
++/*
++ * Final check
++ */
++static void
++final_check (const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match,
++ const char *name, unsigned int hook)
++{
++ /*
++ * Is any proto supplied there? Or specified proto isn't 802.1Q?
++ */
++ if (entry->bitmask & EBT_NOPROTO || entry->ethproto != ETH_P_8021Q)
++ print_error
++ ("For matching 802.1Q VLAN the protocol must be specified as 802_1Q\n");
++}
++
++/*
++ * Print line when listing rules by ebtables -L
++ */
++static void
++print (const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match)
++{
++ struct ebt_vlan_info *vlaninfo =
++ (struct ebt_vlan_info *) match->data;
++
++ /*
++ * Print VLAN ID if they are specified
++ */
++ if (vlaninfo->bitmask & EBT_VLAN_ID) {
++ printf ("vlan id: %s%d, ",
++ vlaninfo->invflags & EBT_VLAN_ID ? "!" : "",
++ vlaninfo->id);
++ }
++ /*
++ * Print VLAN priority if they are specified
++ */
++ if (vlaninfo->bitmask & EBT_VLAN_PRIO) {
++ printf ("vlan prio: %s%d, ",
++ vlaninfo->invflags & EBT_VLAN_PRIO ? "!" : "",
++ vlaninfo->prio);
++ }
++}
++
++
++static int
++compare (const struct ebt_entry_match *vlan1,
++ const struct ebt_entry_match *vlan2)
++{
++ struct ebt_vlan_info *vlaninfo1 =
++ (struct ebt_vlan_info *) vlan1->data;
++ struct ebt_vlan_info *vlaninfo2 =
++ (struct ebt_vlan_info *) vlan2->data;
++ /*
++ * Compare argc
++ */
++ if (vlaninfo1->bitmask != vlaninfo2->bitmask)
++ return 0;
++ /*
++ * Compare inv flags
++ */
++ if (vlaninfo1->invflags != vlaninfo2->invflags)
++ return 0;
++ /*
++ * Compare VLAN ID if they are present
++ */
++ if (vlaninfo1->bitmask & EBT_VLAN_ID) {
++ if (vlaninfo1->id != vlaninfo2->id)
++ return 0;
++ };
++ /*
++ * Compare VLAN Prio if they are present
++ */
++ if (vlaninfo1->bitmask & EBT_VLAN_PRIO) {
++ if (vlaninfo1->prio != vlaninfo2->prio)
++ return 0;
++ };
++ return 1;
++}
++
++static struct ebt_u_match vlan_match = {
++ EBT_VLAN_MATCH,
++ sizeof (struct ebt_vlan_info),
++ print_help,
++ init,
++ parse,
++ final_check,
++ print,
++ compare,
++ opts,
++};
++
++static void _init (void) __attribute__ ((constructor));
++static void _init (void)
++{
++ register_match (&vlan_match);
++}
+--- ebtables-v2.0pre5/extensions/Makefile Sat Apr 27 22:31:21 2002
++++ ebtables-v2.0pre6.001/extensions/Makefile Thu May 30 18:38:44 2002
+@@ -1,6 +1,6 @@
+ #! /usr/bin/make
+
+-EXT_FUNC+=nat arp ip standard log redirect
++EXT_FUNC+=nat arp ip standard log redirect vlan
+ 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)
+--- ebtables-v2.0pre5/ebtables.8 Fri May 3 21:08:25 2002
++++ ebtables-v2.0pre6.001/ebtables.8 Thu May 30 18:43:19 2002
+@@ -315,6 +315,17 @@
+ .TP
+ .BR "--arp-ip-dst " "[!] \fIaddress\fP[/\fImask\fP]"
+ The ARP IP destination address specification.
++.SS vlan
++Specify 802.1Q VLAN specific fields. These will only work if the protocol equals
++.BR 802_1Q .
++For more details see
++.BR "ebtables -h vlan" .
++.TP
++.BR "--vlan-id " "[!] \fIid\fP"
++The VLAN identifier (decimal number from 0 to 4095).
++.TP
++.BR "--vlan-prio " "[!] \fIprio\fP"
++The VLAN priority type, this can be a decimal number from 0 to 7. The default value is 0.
+ .SH WATCHER EXTENSION(S)
+ Watchers are things that only look at frames passing by. These watchers only see the
+ frame if the frame passes all the matches of the rule.
+--- ebtables-v2.0pre5/ethertypes Sat May 18 10:30:10 2002
++++ ebtables-v2.0pre6.001/ethertypes Thu May 30 18:38:44 2002
+@@ -1,15 +1,15 @@
+- # all whitespace is ignored
+- # comment lines must have a '#' as the first character
+- # all protocol numbers are in hexadecimal form
+- # maximum namesize = 20 characters
+- # always put tabs or spaces between the name and the protocol number
++# all whitespace is ignored
++# comment lines must have a '#' as the first character
++# all protocol numbers are in hexadecimal form
++# maximum namesize = 20 characters
++# always put tabs or spaces between the name and the protocol number
+ # don't use more than 4 digits for the protocol number
+ # programs using this file should not be case sensitive
+ # that's all :-))
+ IPV4 0800 put your comments behind, on the same line, after a tab
+ X25 0800 or whitespace
+ ARP 0806
+-VLAN 8100
++802_1Q 8100 802.1Q Virtual LAN tagged frame
+ IPX 8137
+ IPV6 86DD
+ NetBEUI 8191
diff --git a/userspace/patches/zipped/ebtables-v2.0pre1.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre1.tar.gz
new file mode 100644
index 0000000..52322df
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre1.tar.gz
Binary files differ
diff --git a/userspace/patches/zipped/ebtables-v2.0pre2.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre2.tar.gz
new file mode 100644
index 0000000..e398d7c
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre2.tar.gz
Binary files differ
diff --git a/userspace/patches/zipped/ebtables-v2.0pre3.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre3.tar.gz
new file mode 100644
index 0000000..d27fac2
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre3.tar.gz
Binary files differ
diff --git a/userspace/patches/zipped/ebtables-v2.0pre4.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre4.tar.gz
new file mode 100644
index 0000000..7fc57ce
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre4.tar.gz
Binary files differ
diff --git a/userspace/patches/zipped/ebtables-v2.0pre5.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre5.tar.gz
new file mode 100644
index 0000000..c09e318
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre5.tar.gz
Binary files differ
diff --git a/userspace/patches/zipped/ebtables-v2.0pre6.tar.gz b/userspace/patches/zipped/ebtables-v2.0pre6.tar.gz
new file mode 100644
index 0000000..dd0fedc
--- /dev/null
+++ b/userspace/patches/zipped/ebtables-v2.0pre6.tar.gz
Binary files differ