summaryrefslogtreecommitdiffstats
path: root/userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff
diff options
context:
space:
mode:
Diffstat (limited to 'userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff')
-rw-r--r--userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff2445
1 files changed, 2445 insertions, 0 deletions
diff --git a/userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff b/userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff
new file mode 100644
index 0000000..d7b588c
--- /dev/null
+++ b/userspace/patches/incremental-patches/v2.0/ebtables-v2.0.2.001.diff
@@ -0,0 +1,2445 @@
+--- ebtables-v2.0.1/Makefile Thu Oct 17 23:27:29 2002
++++ ebtables-v2.0.2/Makefile Sat Dec 7 13:09:40 2002
+@@ -1,64 +1,86 @@
+ # ebtables Makefile
+
+-KERNEL_DIR?=/usr/src/linux
+ PROGNAME:=ebtables
+-PROGVERSION:="2.0.1"
+-PROGDATE:="October 2002"
++PROGVERSION:=2.0.2
++PROGDATE:=December\ 2002
+
+ MANDIR?=/usr/local/man
+ CFLAGS:=-Wall -Wunused
+ CC:=gcc
++
+ include extensions/Makefile
+
+-# Some kernel testers prefer to use a symlink for /usr/include/linux
+-ifeq ($(SYMLINK), y)
+-KERNEL_INCLUDES=symlink
++OBJECTS:=getethertype.o ebtables.o communication.o $(EXT_OBJS)
++
++# Use the option NONSTANDARD=y when you don't want to use the kernel includes
++# that are included in this package. You should set KERNEL_INCLUDES to
++# the right directory (eg /usr/src/linux/include).
++# You should only need this when compiling the CVS or when adding new code.
++ifeq ($(NONSTANDARD), y)
++KERNEL_INCLUDES?=/usr/include/
+ else
+-KERNEL_INCLUDES=headers
++KERNEL_INCLUDES:=include/
++endif
++
++ifeq ($(ETHERTYPESPATH),)
++ETHERTYPESPATH:=/etc/
+ endif
++ETHERTYPESFILE:=$(ETHERTYPESPATH)ethertypes
+
+-all: ebtables
++PROGSPECS:=-DPROGVERSION=\"$(PROGVERSION)\" \
++ -DPROGNAME=\"$(PROGNAME)\" \
++ -DPROGDATE=\"$(PROGDATE)\" \
++ -D_PATH_ETHERTYPES=\"$(ETHERTYPESFILE)\"
+
+-.PHONY: headers
+-headers:
+- mkdir -p /usr/include/linux/netfilter_bridge
+- cp -f $(KERNEL_DIR)/include/linux/netfilter_bridge/* \
+- /usr/include/linux/netfilter_bridge/
+- cp -f $(KERNEL_DIR)/include/linux/netfilter_bridge.h \
+- /usr/include/linux/netfilter_bridge.h
+- cp -f $(KERNEL_DIR)/include/linux/if_ether.h \
+- /usr/include/linux/if_ether.h
+-
+-.PHONY: symlink
+-symlink:
+- rm -f /usr/include/linux
+- ln -fs $(KERNEL_DIR)/include/linux /usr/include/linux
++
++all: ebtables
+
+ communication.o: communication.c include/ebtables_u.h
+- $(CC) $(CFLAGS) -DPROGVERSION=\"$(PROGVERSION)\" -c -o $@ $<
++ $(CC) $(CFLAGS) $(PROGSPECS) -c -o $@ $< -I$(KERNEL_INCLUDES)
++
++getethertype.o: getethertype.c include/ethernetdb.h
++ $(CC) $(CFLAGS) $(PROGSPECS) -c -o $@ $< -Iinclude/
+
+ ebtables.o: ebtables.c include/ebtables_u.h
+- $(CC) $(CFLAGS) -DPROGVERSION=\"$(PROGVERSION)\" \
+- -DPROGNAME=\"$(PROGNAME)\" -DPROGDATE=\"$(PROGDATE)\" -c -o $@ $<
++ $(CC) $(CFLAGS) $(PROGSPECS) -c -o $@ $< -I$(KERNEL_INCLUDES)
+
+-ebtables: ebtables.o communication.o $(EXT_OBJS)
+- $(CC) $(CFLAGS) -o $@ $^
++ebtables: $(OBJECTS)
++ $(CC) $(CFLAGS) -o $@ $^ -I$(KERNEL_INCLUDES)
+
+ $(MANDIR)/man8/ebtables.8: ebtables.8
+ mkdir -p $(@D)
+ install -m 0644 -o root -g root $< $@
+
+-/etc/ethertypes: ethertypes
++$(ETHERTYPESFILE): ethertypes
+ mkdir -p $(@D)
+ install -m 0644 -o root -g root $< $@
++
+ .PHONY: exec
+ exec: ebtables
+ install -m 0755 -o root -g root $< /sbin/ebtables
+
+-install: $(MANDIR)/man8/ebtables.8 $(KERNEL_INCLUDES) \
+- ebtables /etc/ethertypes exec
++.PHONY: install
++install: $(MANDIR)/man8/ebtables.8 ebtables $(ETHERTYPESFILE) exec
+
++.PHONY: clean
+ clean:
+ rm -f ebtables
+ rm -f *.o *.c~
+ rm -f extensions/*.o extensions/*.c~
++
++DIR:=$(PROGNAME)-v$(PROGVERSION)
++# This is used to make a new userspace release
++.PHONY: release
++release:
++ mkdir -p include/linux/netfilter_bridge
++ install -m 0644 -o root -g root \
++ $(KERNEL_INCLUDES)/linux/netfilter_bridge.h include/linux/
++# To keep possible compile error complaints about undefined ETH_P_8021Q
++# off my back
++ install -m 0644 -o root -g root \
++ $(KERNEL_INCLUDES)/linux/if_ether.h include/linux/
++ install -m 0644 -o root -g root \
++ $(KERNEL_INCLUDES)/linux/netfilter_bridge/*.h \
++ include/linux/netfilter_bridge/
++ make clean
++ cd ..;tar -c $(DIR) | gzip >$(DIR).tar.gz
+--- ebtables-v2.0.1/ebtables.c Thu Oct 17 22:51:12 2002
++++ ebtables-v2.0.2/ebtables.c Tue Dec 3 22:52:12 2002
+@@ -28,11 +28,14 @@
+ #include <stdarg.h>
+ #include <netinet/ether.h>
+ #include "include/ebtables_u.h"
++#include "include/ethernetdb.h"
+ #include <unistd.h>
+ #include <fcntl.h>
+ #include <sys/wait.h>
+
+-// Don't use this function, use print_bug()
++/*
++ * Don't use this function, use print_bug()
++ */
+ void __print_bug(char *file, int line, char *format, ...)
+ {
+ va_list l;
+@@ -45,13 +48,10 @@
+ exit (-1);
+ }
+
+-// here are the number-name correspondences kept for the Ethernet
+-// frame type field
+-#define PROTOCOLFILE "/etc/ethertypes"
+-
+ #ifndef PROC_SYS_MODPROBE
+ #define PROC_SYS_MODPROBE "/proc/sys/kernel/modprobe"
+ #endif
++#define ATOMIC_ENV_VARIABLE "EBTABLES_ATOMIC_FILE"
+
+ char *hooknames[NF_BR_NUMHOOKS] =
+ {
+@@ -63,9 +63,11 @@
+ [NF_BR_BROUTING]"BROUTING"
+ };
+
+-// default command line options
+-// do not mess around with the already assigned numbers unless
+-// you know what you are doing
++/*
++ * default command line options
++ * do not mess around with the already assigned numbers unless
++ * you know what you are doing
++ */
+ static struct option ebt_original_options[] =
+ {
+ { "append" , required_argument, 0, 'A' },
+@@ -99,17 +101,16 @@
+ { "new-chain" , required_argument, 0, 'N' },
+ { "rename-chain" , required_argument, 0, 'E' },
+ { "delete-chain" , required_argument, 0, 'X' },
+- { "atomic-init" , required_argument, 0, 7 },
+- { "atomic-commit" , required_argument, 0, 8 },
+- { "atomic" , required_argument, 0, 9 },
+- { "atomic-save" , required_argument, 0, 10 },
++ { "atomic-init" , no_argument , 0, 7 },
++ { "atomic-commit" , no_argument , 0, 8 },
++ { "atomic-file" , required_argument, 0, 9 },
++ { "atomic-save" , no_argument , 0, 10 },
+ { "init-table" , no_argument , 0, 11 },
+ { 0 }
+ };
+
+ static struct option *ebt_options = ebt_original_options;
+
+-// yup, all the possible target names
+ char* standard_targets[NUM_STANDARD_TARGETS] =
+ {
+ "ACCEPT",
+@@ -125,12 +126,18 @@
+ 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};
+
+-// holds all the data
++/*
++ * holds all the data
++ */
+ static struct ebt_u_replace replace;
+
+-// the chosen table
++/*
++ * the chosen table
++ */
+ static struct ebt_u_table *table = NULL;
+-// the lists of supported tables, matches, watchers and targets
++/*
++ * the lists of supported tables, matches, watchers and targets
++ */
+ static struct ebt_u_table *tables = NULL;
+ static struct ebt_u_match *matches = NULL;
+ static struct ebt_u_watcher *watchers = NULL;
+@@ -172,13 +179,15 @@
+ 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.
+-// Same holds for the struct ebt_match and struct ebt_watcher pointers
++/*
++ * 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;
+
+ static void initialize_entry(struct ebt_u_entry *e)
+@@ -199,7 +208,9 @@
+ print_bug("Couldn't load standard target");
+ }
+
+-// this doesn't free e, becoz the calling function might need e->next
++/*
++ * this doesn't free e, becoz the calling function might need e->next
++ */
+ static void free_u_entry(struct ebt_u_entry *e)
+ {
+ struct ebt_u_match_list *m_l, *m_l2;
+@@ -222,7 +233,9 @@
+ free(e->t);
+ }
+
+-// the user will use the match, so put it in new_entry
++/*
++ * 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;
+@@ -350,8 +363,10 @@
+ tables = t;
+ }
+
+-// blatently stolen (again) from iptables.c userspace program
+-// find out where the modprobe utility is located
++/*
++ * blatently stolen (again) from iptables.c userspace program
++ * find out where the modprobe utility is located
++ */
+ static char *get_modprobe(void)
+ {
+ int procfile;
+@@ -411,59 +426,16 @@
+ return 0;
+ }
+
+-// helper function: processes a line of data from the file /etc/ethertypes
+-static int get_a_line(char *buffer, char *value, FILE *ifp)
+-{
+- char line[80], *p;
+- const char delim[] = " \t\n";
+-
+- while (fgets(line, sizeof(line), ifp)) {
+- p = strtok(line, delim);
+- if (!p || p[0] == '#')
+- continue;
+- if (strlen(p) > 20)
+- continue;
+- strcpy(buffer, p);
+- p = strtok(NULL, delim);
+- if (!p || strlen(p) > 10)
+- continue;
+- strcpy(value, p);
+- return 0;
+- }
+- return -1;
+-}
+-
+-// translate a hexadecimal number to a protocol name, parsing /etc/ethertypes
+-// returns 0 on success
+-// this demands the name buffer to be of size at least 21
+-int number_to_name(unsigned short proto, char *name)
+-{
+- FILE *ifp;
+- char buffer[21], value[11], *bfr;
+- unsigned short i;
+-
+- if ( !(ifp = fopen(PROTOCOLFILE, "r")) )
+- return -1;
+- while (1) {
+- if (get_a_line(buffer, value, ifp)) {
+- fclose(ifp);
+- return -1;
+- }
+- i = (unsigned short) strtol(value, &bfr, 16);
+- if (*bfr != '\0' || i != proto)
+- continue;
+- strcpy(name, buffer);
+- fclose(ifp);
+- return 0;
+- }
+-}
+-
+-// we use replace.flags, so we can't use the following values:
+-// 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO
++/*
++ * we use replace.flags, so we can't use the following values:
++ * 0x01 == OPT_COMMAND, 0x02 == OPT_TABLE, 0x100 == OPT_ZERO
++ */
+ #define LIST_N 0x04
+ #define LIST_C 0x08
+ #define LIST_X 0x10
+-// helper function for list_rules()
++/*
++ * helper function for list_rules()
++ */
+ static void list_em(struct ebt_u_entries *entries)
+ {
+ int i, j, space = 0, digits;
+@@ -473,7 +445,6 @@
+ struct ebt_u_match *m;
+ struct ebt_u_watcher *w;
+ struct ebt_u_target *t;
+- char name[21];
+
+ hlp = entries->entries;
+ if (replace.flags & LIST_X && entries->policy != EBT_ACCEPT) {
+@@ -508,8 +479,10 @@
+ printf("ebtables -t %s -A %s ",
+ replace.name, entries->name);
+
+- // 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("-p ");
+ if (hlp->invflags & EBT_IPROTO)
+@@ -517,10 +490,13 @@
+ if (hlp->bitmask & EBT_802_3)
+ printf("Length ");
+ else {
+- if (number_to_name(ntohs(hlp->ethproto), name))
++ struct ethertypeent *ent;
++
++ ent = getethertypebynumber(ntohs(hlp->ethproto));
++ if (!ent)
+ printf("0x%x ", ntohs(hlp->ethproto));
+ else
+- printf("%s ", name);
++ printf("%s ", ent->e_name);
+ }
+ }
+ if (hlp->bitmask & EBT_SOURCEMAC) {
+@@ -665,7 +641,7 @@
+ }
+ }
+
+-static struct ebt_u_entries *to_chain()
++static inline struct ebt_u_entries *to_chain()
+ {
+ return nr_to_chain(replace.selected_hook);
+ }
+@@ -686,7 +662,9 @@
+ struct ebt_u_entry *e;
+
+ i = -1;
+- // initialize hook_mask to 0
++ /*
++ * initialize hook_mask to 0
++ */
+ while (1) {
+ i++;
+ if (i < NF_BR_NUMHOOKS && !(replace.valid_hooks & (1 << i)))
+@@ -703,13 +681,17 @@
+ print_memory();
+ }
+
+- // check for loops, starting from every base chain
++ /*
++ * check for loops, starting from every base chain
++ */
+ for (i = 0; i < NF_BR_NUMHOOKS; i++) {
+ if (!(replace.valid_hooks & (1 << i)))
+ continue;
+ entries = nr_to_chain(i);
+- // (1 << NF_BR_NUMHOOKS) implies it's a standard chain
+- // (usefull in the final_check() funtions)
++ /*
++ * (1 << NF_BR_NUMHOOKS) implies it's a standard chain
++ * (usefull in the final_check() funtions)
++ */
+ entries->hook_mask = (1 << i) | (1 << NF_BR_NUMHOOKS);
+ chain_nr = i;
+
+@@ -722,13 +704,17 @@
+ goto letscontinue;
+ entries2 = nr_to_chain(verdict + NF_BR_NUMHOOKS);
+ entries2->hook_mask |= entries->hook_mask;
+- // now see if we've been here before
++ /*
++ * now see if we've been here before
++ */
+ for (k = 0; k < sp; k++)
+ if (stack[k].chain_nr == verdict + NF_BR_NUMHOOKS)
+ print_error("Loop from chain %s to chain %s",
+ nr_to_chain(chain_nr)->name,
+ nr_to_chain(stack[k].chain_nr)->name);
+- // jump to the chain, make sure we know how to get back
++ /*
++ * jump to the chain, make sure we know how to get back
++ */
+ stack[sp].chain_nr = chain_nr;
+ stack[sp].n = j;
+ stack[sp].entries = entries;
+@@ -742,10 +728,14 @@
+ letscontinue:
+ e = e->next;
+ }
+- // we are at the end of a standard chain
++ /*
++ * we are at the end of a standard chain
++ */
+ if (sp == 0)
+ continue;
+- // go back to the chain one level higher
++ /*
++ * go back to the chain one level higher
++ */
+ sp--;
+ j = stack[sp].n;
+ chain_nr = stack[sp].chain_nr;
+@@ -757,8 +747,10 @@
+ return;
+ }
+
+-// parse the chain name and return the corresponding nr
+-// returns -1 on failure
++/*
++ * parse the chain name and return the corresponding nr
++ * returns -1 on failure
++ */
+ int get_hooknr(char* arg)
+ {
+ int i;
+@@ -779,7 +771,6 @@
+ return -1;
+ }
+
+-// yup, print out help
+ static void print_help()
+ {
+ struct ebt_u_match_list *m_l;
+@@ -790,7 +781,8 @@
+ "ebtables -[ADI] chain rule-specification [options]\n"
+ "ebtables -P chain target\n"
+ "ebtables -[LFZ] [chain]\n"
+-"ebtables -[b] [y,n]\n"
++"ebtables -[NX] [chain]\n"
++"ebtables -E old-chain-name new-chain-name\n\n"
+ "Commands:\n"
+ "--append -A chain : append to chain\n"
+ "--delete -D chain : delete matching rule from chain\n"
+@@ -804,10 +796,10 @@
+ "--new-chain -N chain : create a user defined chain\n"
+ "--rename-chain -E old new : rename a chain\n"
+ "--delete-chain -X chain : delete a user defined chain\n"
+-"--atomic-commit file : update the kernel w/ the table contained in file\n"
+-"--atomic-init file : put the initial kernel table into file\n"
+-"--atomic-save file : put the current kernel table into file\n"
+-"--atomic file : write changes to file instead of kernel\n"
++"--atomic-commit : update the kernel w/t table contained in <FILE>\n"
++"--atomic-init : put the initial kernel table into <FILE>\n"
++"--atomic-save : put the current kernel table into <FILE>\n"
++"--atomic file : set <FILE> to file\n\n"
+ "Options:\n"
+ "--proto -p [!] proto : protocol hexadecimal, by name or LENGTH\n"
+ "--src -s [!] address[/mask]: source mac address\n"
+@@ -817,8 +809,10 @@
+ "--logical-in [!] name : logical bridge input interface name\n"
+ "--logical-out [!] name : logical bridge output interface name\n"
+ "--modprobe -M program : try to insert modules using this program\n"
+-"--version -V : print package version\n"
+-"\n");
++"--version -V : print package version\n\n"
++"Environment variable:\n"
++ATOMIC_ENV_VARIABLE " : if set <FILE> (see above) will equal its value"
++"\n\n");
+
+ m_l = new_entry->m_list;
+ while (m_l) {
+@@ -839,7 +833,9 @@
+ exit(0);
+ }
+
+-// execute command L
++/*
++ * execute command L
++ */
+ static void list_rules()
+ {
+ int i;
+@@ -851,7 +847,9 @@
+ } else {
+ struct ebt_u_chain_list *cl = replace.udc;
+
+- // create new chains and rename standard chains when necessary
++ /*
++ * create new chains and rename standard chains when necessary
++ */
+ if (replace.flags & LIST_X) {
+ while (cl) {
+ printf("ebtables -t %s -N %s\n", replace.name,
+@@ -883,22 +881,30 @@
+ }
+ }
+
+-// execute command P
++/*
++ * execute command P
++ */
+ static void change_policy(int policy)
+ {
+ int i;
+ struct ebt_u_entries *entries = to_chain();
+
+- // don't do anything if the policy is the same
++ /*
++ * don't do anything if the policy is the same
++ */
+ if (entries->policy != policy) {
+ entries->policy = policy;
+ replace.num_counters = replace.nentries;
+ if (replace.nentries) {
+- // '+ 1' for the CNT_END
++ /*
++ * '+ 1' for the CNT_END
++ */
+ if (!(replace.counterchanges = (unsigned short *) malloc(
+ (replace.nentries + 1) * sizeof(unsigned short))))
+ print_memory();
+- // done nothing special to the rules
++ /*
++ * done nothing special to the rules
++ */
+ for (i = 0; i < replace.nentries; i++)
+ replace.counterchanges[i] = CNT_NORM;
+ replace.counterchanges[replace.nentries] = CNT_END;
+@@ -910,9 +916,11 @@
+ exit(0);
+ }
+
+-// flush one chain or the complete table
+-// -1 == nothing to do
+-// 0 == give back to kernel
++/*
++ * flush one chain or the complete table
++ * -1 == nothing to do
++ * 0 == give back to kernel
++ */
+ static int flush_chains()
+ {
+ int i, j, oldnentries, numdel;
+@@ -920,15 +928,21 @@
+ struct ebt_u_entry *u_e, *tmp;
+ struct ebt_u_entries *entries = to_chain();
+
+- // flush whole table
++ /*
++ * flush whole table
++ */
+ if (!entries) {
+ if (replace.nentries == 0)
+ return -1;
+ replace.nentries = 0;
+- // no need for the kernel to give us counters back
++ /*
++ * no need for the kernel to give us counters back
++ */
+ replace.num_counters = 0;
+
+- // free everything and zero (n)entries
++ /*
++ * free everything and zero (n)entries
++ */
+ i = -1;
+ while (1) {
+ i++;
+@@ -960,13 +974,17 @@
+ numdel = entries->nentries;
+
+ if (replace.nentries) {
+- // +1 for CNT_END
++ /*
++ * +1 for CNT_END
++ */
+ if ( !(replace.counterchanges = (unsigned short *)
+ malloc((oldnentries + 1) * sizeof(unsigned short))) )
+ print_memory();
+ }
+- // delete the counters belonging to the specified chain,
+- // update counter_offset
++ /*
++ * delete the counters belonging to the specified chain,
++ * update counter_offset
++ */
+ i = -1;
+ cnt = replace.counterchanges;
+ while (1) {
+@@ -994,8 +1012,7 @@
+ if (replace.nentries) {
+ *cnt = CNT_END;
+ replace.num_counters = oldnentries;
+- }
+- else
++ } else
+ replace.num_counters = 0;
+
+ entries = to_chain();
+@@ -1011,7 +1028,9 @@
+ return 0;
+ }
+
+-// -1 == no match
++/*
++ * -1 == no match
++ */
+ static int check_rule_exists(int rule_nr)
+ {
+ struct ebt_u_entry *u_e;
+@@ -1023,16 +1042,22 @@
+ struct ebt_u_entries *entries = to_chain();
+ int i, j, k;
+
+- // handle '-D chain rulenr' command
++ /*
++ * handle '-D chain rulenr' command
++ */
+ if (rule_nr != -1) {
+ if (rule_nr > entries->nentries)
+ return -1;
+- // user starts counting from 1
++ /*
++ * user starts counting from 1
++ */
+ return rule_nr - 1;
+ }
+ u_e = entries->entries;
+- // check for an existing rule (if there are duplicate rules,
+- // take the first occurance)
++ /*
++ * check for an existing rule (if there are duplicate rules,
++ * take the first occurance)
++ */
+ for (i = 0; i < entries->nentries; i++, u_e = u_e->next) {
+ if (!u_e)
+ print_bug("Hmm, trouble");
+@@ -1055,7 +1080,9 @@
+ if (new_entry->bitmask != u_e->bitmask ||
+ new_entry->invflags != u_e->invflags)
+ continue;
+- // compare all matches
++ /*
++ * compare all matches
++ */
+ m_l = new_entry->m_list;
+ j = 0;
+ while (m_l) {
+@@ -1068,7 +1095,9 @@
+ j++;
+ m_l = m_l->next;
+ }
+- // now be sure they have the same nr of matches
++ /*
++ * now be sure they have the same nr of matches
++ */
+ k = 0;
+ m_l = u_e->m_list;
+ while (m_l) {
+@@ -1078,7 +1107,9 @@
+ if (j != k)
+ continue;
+
+- // compare all watchers
++ /*
++ * compare all watchers
++ */
+ w_l = new_entry->w_list;
+ j = 0;
+ while (w_l) {
+@@ -1119,19 +1150,23 @@
+ struct ebt_u_watcher_list *w_l;
+ struct ebt_u_entries *entries = to_chain(), *entries2;
+
+- if (rule_nr != -1) { // command -I
++ if (rule_nr != -1) { /* command -I */
+ if (--rule_nr > entries->nentries)
+ print_error("rule nr too high: %d > %d", rule_nr + 1,
+ entries->nentries + 1);
+ } else
+ rule_nr = entries->nentries;
+- // we're adding one rule
++ /*
++ * we're adding one rule
++ */
+ replace.num_counters = replace.nentries;
+ replace.nentries++;
+ entries->nentries++;
+
+- // handle counter stuff
+- // +1 for CNT_END
++ /*
++ * handle counter stuff
++ * +1 for CNT_END
++ */
+ if ( !(replace.counterchanges = (unsigned short *)
+ malloc((replace.nentries + 1) * sizeof(unsigned short))) )
+ print_memory();
+@@ -1157,15 +1192,21 @@
+ }
+ *cnt = CNT_END;
+
+- // go to the right position in the chain
++ /*
++ * go to the right position in the chain
++ */
+ u_e = &entries->entries;
+ for (i = 0; i < rule_nr; i++)
+ u_e = &(*u_e)->next;
+- // insert the rule
++ /*
++ * insert the rule
++ */
+ new_entry->next = *u_e;
+ *u_e = new_entry;
+
+- // put the ebt_[match, watcher, target] pointers in place
++ /*
++ * put the ebt_[match, watcher, target] pointers in place
++ */
+ m_l = new_entry->m_list;
+ while (m_l) {
+ m_l->m = ((struct ebt_u_match *)m_l->m)->m;
+@@ -1178,7 +1219,9 @@
+ }
+ new_entry->t = ((struct ebt_u_target *)new_entry->t)->t;
+
+- // update the counter_offset of chains behind this one
++ /*
++ * update the counter_offset of chains behind this one
++ */
+ i = replace.selected_hook;
+ while (1) {
+ i++;
+@@ -1193,21 +1236,27 @@
+ }
+ }
+
+-// execute command D
+-static void delete_rule(int rule_nr)
++/*
++ * execute command D
++ */
++static void delete_rule(int begin, int end)
+ {
+- int i, j, lentmp = 0;
++ int j, lentmp = 0, nr_deletes;
+ unsigned short *cnt;
+ struct ebt_u_entry **u_e, *u_e2;
+ struct ebt_u_entries *entries = to_chain(), *entries2;
+
+- if ( (i = check_rule_exists(rule_nr)) == -1 )
++ if ((begin = check_rule_exists(begin)) == -1 ||
++ (end = check_rule_exists(end)) == -1)
+ print_error("Sorry, rule does not exist");
+
+- // we're deleting a rule
++ /*
++ * we're deleting rules
++ */
+ replace.num_counters = replace.nentries;
+- replace.nentries--;
+- entries->nentries--;
++ nr_deletes = end - begin + 1;
++ replace.nentries -= nr_deletes;
++ entries->nentries -= nr_deletes;
+
+ if (replace.nentries) {
+ for (j = 0; j < replace.selected_hook; j++) {
+@@ -1217,61 +1266,75 @@
+ entries2 = nr_to_chain(j);
+ lentmp += entries2->nentries;
+ }
+- lentmp += i;
+- // +1 for CNT_END
++ lentmp += begin;
++ /*
++ * +1 for CNT_END
++ */
+ if ( !(replace.counterchanges = (unsigned short *)malloc(
+ (replace.num_counters + 1) * sizeof(unsigned short))) )
+ print_memory();
+ cnt = replace.counterchanges;
+- for (j = 0; j < lentmp; j++) {
++ for (j = 0; j < lentmp; j++, cnt++)
+ *cnt = CNT_NORM;
+- cnt++;
+- }
+- *cnt = CNT_DEL;
+- cnt++;
+- for (j = 0; j < replace.num_counters - lentmp; j++) {
++ for (j = 0; j < nr_deletes; j++, cnt++)
++ *cnt = CNT_DEL;
++
++ for (j = 0; j < replace.num_counters - lentmp - nr_deletes;
++ j++, cnt++)
+ *cnt = CNT_NORM;
+- cnt++;
+- }
++
+ *cnt = CNT_END;
+ }
+ else
+ replace.num_counters = 0;
+
+- // go to the right position in the chain
++ /*
++ * go to the right position in the chain
++ */
+ u_e = &entries->entries;
+- for (j = 0; j < i; j++)
++ for (j = 0; j < begin; j++)
+ u_e = &(*u_e)->next;
+- // remove the rule
+- u_e2 = *u_e;
+- *u_e = (*u_e)->next;
+- // free everything
+- free_u_entry(u_e2);
+- free(u_e2);
+-
+- // update the counter_offset of chains behind this one
+- i = replace.selected_hook;
++ /*
++ * remove the rules
++ */
++ j = nr_deletes;
++ while(j--) {
++ u_e2 = *u_e;
++ *u_e = (*u_e)->next;
++ // free everything
++ free_u_entry(u_e2);
++ free(u_e2);
++ }
++
++ /*
++ * update the counter_offset of chains behind this one
++ */
++ j = replace.selected_hook;
+ while (1) {
+- i++;
+- entries = nr_to_chain(i);
++ j++;
++ entries = nr_to_chain(j);
+ if (!entries) {
+- if (i < NF_BR_NUMHOOKS)
++ if (j < NF_BR_NUMHOOKS)
+ continue;
+ else
+ break;
+- } else
+- entries->counter_offset--;
++ } else
++ entries->counter_offset -= nr_deletes;
+ }
+ }
+
+-// execute command Z
++/*
++ * execute command Z
++ */
+ static void zero_counters(int zerochain)
+ {
+
+ if (zerochain == -1) {
+- // tell main() we don't update the counters
+- // this results in tricking the kernel to zero its counters,
+- // naively expecting userspace to update its counters. Muahahaha
++ /*
++ * tell main() we don't update the counters
++ * this results in tricking the kernel to zero its counters,
++ * naively expecting userspace to update its counters. Muahahaha
++ */
+ replace.counterchanges = NULL;
+ replace.num_counters = 0;
+ } else {
+@@ -1308,38 +1371,21 @@
+ }
+ }
+
+-// 0 == success
+-// 1 == success, but for the special 'protocol' LENGTH
+-// -1 == failure
+-int name_to_number(char *name, __u16 *proto)
+-{
+- FILE *ifp;
+- char buffer[21], value[11], *bfr;
+- unsigned short i;
+-
+- if (!strcasecmp("LENGTH", name)) {
+- *proto = 0;
+- new_entry->bitmask |= EBT_802_3;
+- return 1;
+- }
+- if ( !(ifp = fopen(PROTOCOLFILE, "r")) )
+- return -1;
+- while (1) {
+- if (get_a_line(buffer, value, ifp))
+- return -1;
+- if (strcasecmp(buffer, name))
+- continue;
+- fclose(ifp);
+- i = (unsigned short) strtol(value, &bfr, 16);
+- if (*bfr != '\0')
+- return -1;
+- *proto = i;
+- return 0;
+- }
+- return -1;
++/*
++ * Checks the type for validity and calls getethertypebynumber()
++ */
++struct ethertypeent *parseethertypebynumber(int type)
++{
++ if (type < 1536)
++ print_error("Ethernet protocols have values >= 0x0600");
++ if (type > 0xffff)
++ print_error("Ethernet protocols have values <= 0xffff");
++ return getethertypebynumber(type);
+ }
+
+-// put the mac address into 6 (ETH_ALEN) bytes
++/*
++ * put the mac address into 6 (ETH_ALEN) bytes
++ */
+ int getmac_and_mask(char *from, char *to, char *mask)
+ {
+ char *p;
+@@ -1376,7 +1422,9 @@
+ return 0;
+ }
+
+-// executes the final_check() function for all extensions used by the rule
++/*
++ * executes the final_check() function for all extensions used by the rule
++ */
+ static void do_final_checks(struct ebt_u_entry *e, struct ebt_u_entries *entries)
+ {
+ struct ebt_u_match_list *m_l;
+@@ -1404,7 +1452,9 @@
+ entries->hook_mask, 1);
+ }
+
+-// used for the -X command
++/*
++ * used for the -X command
++ */
+ static void check_for_references(int chain_nr)
+ {
+ int i = -1, j;
+@@ -1436,13 +1486,45 @@
+ }
+ }
+
++static int parse_delete_rule(const char *argv, int *rule_nr, int *rule_nr_end)
++{
++ char *colon = strchr(argv, ':'), *buffer;
++
++ if (colon) {
++ *colon = '\0';
++ if (*(colon + 1) == '\0')
++ *rule_nr_end = -1;
++ else {
++ *rule_nr_end = strtol(colon + 1, &buffer, 10);
++ if (*buffer != '\0' || *rule_nr_end < 0)
++ return -1;
++ }
++ }
++ if (colon == argv)
++ *rule_nr = 1;
++ else {
++ *rule_nr = strtol(argv, &buffer, 10);
++ if (*buffer != '\0' || *rule_nr < 0)
++ return -1;
++ }
++ if (!colon)
++ *rule_nr_end = *rule_nr;
++ if (*rule_nr_end != -1 && *rule_nr > *rule_nr_end)
++ return -1;
++ return 0;
++}
++
++static int invert = 0;
+ int check_inverse(const char option[])
+ {
+ if (strcmp(option, "!") == 0) {
++ if (invert == 1)
++ print_error("double use of '!' not allowed");
+ optind++;
++ invert = 1;
+ return 1;
+ }
+- return 0;
++ return invert;
+ }
+
+ void check_option(unsigned int *flags, unsigned int mask)
+@@ -1456,15 +1538,19 @@
+ {
+ if ( !(table = find_table(replace.name)) )
+ print_error("Bad table name");
+- // get the kernel's information
++ /*
++ * get the kernel's information
++ */
+ if (get_table(&replace)) {
+ ebtables_insmod("ebtables", modprobe);
+ if (get_table(&replace))
+ print_error("The kernel doesn't support the ebtables "
+ "%s table", replace.name);
+ }
+- // when listing a table contained in a file, we don't expect the user
+- // to know what the table's name is
++ /*
++ * when listing a table contained in a file, we don't demand that
++ * the user knows the table's name
++ */
+ if ( !(table = find_table(replace.name)) )
+ print_error("Bad table name");
+ }
+@@ -1482,15 +1568,18 @@
+ #define OPT_ZERO 0x100
+ #define OPT_LOGICALIN 0x200
+ #define OPT_LOGICALOUT 0x400
+-// the main thing
++/* the main thing */
+ int main(int argc, char *argv[])
+ {
+ char *buffer;
+ int c, i;
+- // 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 = 0;
+- int rule_nr = -1;// used for -[D,I] chain number
++ int rule_nr = -1; /* used for -[D,I] */
++ int rule_nr_end = -1; /* used for -I */
+ struct ebt_u_target *t;
+ struct ebt_u_match *m;
+ struct ebt_u_watcher *w;
+@@ -1499,36 +1588,46 @@
+ struct ebt_u_entries *entries;
+ const char *modprobe = NULL;
+
+- // initialize the table name, OPT_ flags, selected hook and command
++ opterr = 0;
++
++ replace.filename = getenv(ATOMIC_ENV_VARIABLE);
++ /*
++ * initialize the table name, OPT_ flags, selected hook and command
++ */
+ strcpy(replace.name, "filter");
+ replace.flags = 0;
+ replace.selected_hook = -1;
+ replace.command = 'h';
+- replace.filename = NULL;
+ replace.counterchanges = NULL;
+
+ new_entry = (struct ebt_u_entry *)malloc(sizeof(struct ebt_u_entry));
+ if (!new_entry)
+ print_memory();
+- // put some sane values in our new entry
++ /*
++ * put some sane values in our new entry
++ */
+ initialize_entry(new_entry);
+
+- // The scenario induced by this loop makes that:
+- // '-t' ,'-M' and --atomic (if specified) have to come
+- // before '-A' and the like
+-
+- // getopt saves the day
++ /*
++ * The scenario induced by this loop makes that:
++ * '-t' ,'-M' and --atomic (if specified) have to come
++ * before '-A' and the like
++ */
++
++ /*
++ * getopt saves the day
++ */
+ while ((c = getopt_long(argc, argv,
+ "-A:D:I:N:E:X:L::Z::F::P:Vhi:o:j:p:s:d:t:M:", ebt_options, NULL)) != -1) {
+ switch (c) {
+
+- case 'A': // add a rule
+- case 'D': // delete a rule
+- case 'P': // define policy
+- case 'I': // insert a rule
+- case 'N': // make a user defined chain
+- case 'E': // rename chain
+- case 'X': // delete chain
++ case 'A': /* add a rule */
++ case 'D': /* delete a rule */
++ case 'P': /* define policy */
++ case 'I': /* insert a rule */
++ case 'N': /* make a user defined chain */
++ case 'E': /* rename chain */
++ case 'X': /* delete chain */
+ replace.command = c;
+ if (replace.flags & OPT_COMMAND)
+ print_error("Multiple commands not allowed");
+@@ -1564,7 +1663,9 @@
+ strcpy(cl->udc->name, optarg);
+ cl->udc->entries = NULL;
+ cl->kernel_start = NULL;
+- // put the new chain at the end
++ /*
++ * put the new chain at the end
++ */
+ cl2 = &replace.udc;
+ while (*cl2)
+ cl2 = &((*cl2)->next);
+@@ -1596,7 +1697,9 @@
+
+ if (replace.selected_hook < NF_BR_NUMHOOKS)
+ print_error("You can't remove a standard chain");
+- // if the chain is referenced, don't delete it
++ /*
++ * if the chain is referenced, don't delete it
++ */
+ check_for_references(replace.selected_hook - NF_BR_NUMHOOKS);
+ flush_chains();
+ entries = to_chain();
+@@ -1610,8 +1713,15 @@
+ break;
+ }
+
+- if ( (c == 'D' && optind < argc &&
+- argv[optind][0] != '-') || c == 'I') {
++ if (c == 'D' && optind < argc &&
++ argv[optind][0] != '-') {
++ if (parse_delete_rule(argv[optind],
++ &rule_nr, &rule_nr_end))
++ print_error("Problem with the "
++ "specified rule number(s)");
++ optind++;
++ }
++ if (c == 'I') {
+ if (optind >= argc || argv[optind][0] == '-')
+ print_error("No rulenr for -I"
+ " specified");
+@@ -1639,9 +1749,9 @@
+ }
+ break;
+
+- case 'L': // list
+- case 'F': // flush
+- case 'Z': // zero counters
++ case 'L': /* list */
++ case 'F': /* flush */
++ case 'Z': /* zero counters */
+ if (c == 'Z') {
+ if (replace.flags & OPT_ZERO)
+ print_error("Multiple commands"
+@@ -1677,24 +1787,26 @@
+ }
+ break;
+
+- case 'V': // version
++ case 'V': /* version */
+ replace.command = 'V';
+ if (replace.flags & OPT_COMMAND)
+ print_error("Multiple commands not allowed");
+ printf(PROGNAME" v"PROGVERSION" ("PROGDATE")\n");
+ exit(0);
+
+- case 'M': // modprobe
++ case 'M': /* modprobe */
+ if (replace.command != 'h')
+ print_error("Please put the -M option earlier");
+ modprobe = optarg;
+ break;
+
+- case 'h': // help
++ case 'h': /* help */
+ if (replace.flags & OPT_COMMAND)
+ print_error("Multiple commands not allowed");
+ replace.command = 'h';
+- // All other arguments should be extension names
++ /*
++ * All other arguments should be extension names
++ */
+ while (optind < argc) {
+ struct ebt_u_match *m;
+ struct ebt_u_watcher *w;
+@@ -1719,7 +1831,7 @@
+ }
+ break;
+
+- case 't': // table
++ case 't': /* table */
+ if (replace.command != 'h')
+ print_error("Please put the -t option first");
+ check_option(&replace.flags, OPT_TABLE);
+@@ -1728,14 +1840,14 @@
+ strcpy(replace.name, optarg);
+ break;
+
+- case 'i': // input interface
+- case 2 : // logical input interface
+- case 'o': // output interface
+- case 3 : // logical output interface
+- case 'j': // target
+- case 'p': // net family protocol
+- case 's': // source mac
+- case 'd': // destination mac
++ case 'i': /* input interface */
++ case 2 : /* logical input interface */
++ case 'o': /* output interface */
++ case 3 : /* logical output interface */
++ case 'j': /* target */
++ case 'p': /* net family protocol */
++ case 's': /* source mac */
++ case 'd': /* destination mac */
+ if ((replace.flags & OPT_COMMAND) == 0)
+ print_error("No command specified");
+ if ( replace.command != 'A' &&
+@@ -1843,11 +1955,15 @@
+ break;
+ }
+ else {
+- // must be an extension then
++ /*
++ * must be an extension then
++ */
+ struct ebt_u_target *t;
+
+ t = find_target(optarg);
+- // -j standard not allowed either
++ /*
++ * -j standard not allowed either
++ */
+ if (!t || t ==
+ (struct ebt_u_target *)new_entry->t)
+ print_error("Illegal target "
+@@ -1900,12 +2016,17 @@
+ "protocol");
+ new_entry->ethproto = i;
+ if (*buffer != '\0') {
+- if ((i = name_to_number(argv[optind - 1],
+- &new_entry->ethproto)) == -1)
++ struct ethertypeent *ent;
++
++ if (!strcasecmp(argv[optind - 1], "LENGTH")) {
++ new_entry->bitmask |= EBT_802_3;
++ break;
++ }
++ ent = getethertypebyname(argv[optind - 1]);
++ if (!ent)
+ print_error("Problem with the specified"
+ " protocol");
+- if (i == 1)
+- new_entry->bitmask |= EBT_802_3;
++ new_entry->ethproto = ent->e_ethertype;
+ }
+ if (new_entry->ethproto < 1536 &&
+ !(new_entry->bitmask & EBT_802_3))
+@@ -1944,12 +2065,11 @@
+ if (replace.flags & OPT_COMMAND)
+ print_error("Multiple commands not allowed");
+ replace.flags |= OPT_COMMAND;
+- if (replace.filename)
+- print_error("--atomic incompatible with "
+- "command");
+- replace.filename = (char *)malloc(strlen(optarg) + 1);
+- strcpy(replace.filename, optarg);
+- // get the information from the file
++ if (!replace.filename)
++ print_error("No atomic file specified");
++ /*
++ * get the information from the file
++ */
+ get_table(&replace);
+ if (replace.nentries) {
+ replace.counterchanges = (unsigned short *)
+@@ -1958,25 +2078,36 @@
+ replace.counterchanges[i] = CNT_NORM;
+ replace.counterchanges[i] = CNT_END;
+ }
+- // we don't want the kernel giving us its counters, they would
+- // overwrite the counters extracted from the file
++ /*
++ * we don't want the kernel giving us its counters, they would
++ * overwrite the counters extracted from the file
++ */
+ replace.num_counters = 0;
+- // make sure the table will be written to the kernel
+- free(replace.filename);
++ /*
++ * make sure the table will be written to the kernel
++ * possible memory leak here
++ */
+ replace.filename = NULL;
+ ebtables_insmod("ebtables", modprobe);
+ break;
+- case 7 : // atomic-init
+- case 10: // atomic-save
+- case 11: // init-table
++ case 7 : /* atomic-init */
++ case 10: /* atomic-save */
++ case 11: /* init-table */
+ replace.command = c;
+ if (replace.flags & OPT_COMMAND)
+ print_error("Multiple commands not allowed");
++ if (c != 11 && !replace.filename)
++ print_error("No atomic file specified");
+ replace.flags |= OPT_COMMAND;
+- if (replace.filename)
+- print_error("--atomic incompatible with "
+- "command");
+- get_kernel_table(modprobe);
++ {
++ char *tmp = replace.filename;
++
++ tmp = replace.filename;
++ /* get the kernel table */
++ replace.filename = NULL;
++ get_kernel_table(modprobe);
++ replace.filename = tmp;
++ }
+ if (replace.nentries) {
+ replace.counterchanges = (unsigned short *)
+ malloc(sizeof(unsigned short) * (replace.nentries + 1));
+@@ -1984,24 +2115,37 @@
+ replace.counterchanges[i] = CNT_NORM;
+ replace.counterchanges[i] = CNT_END;
+ }
+- if (c == 11)
+- break;
+- case 9 : // atomic
+- if (c == 9 && (replace.flags & OPT_COMMAND))
++ break;
++ case 9 : /* atomic */
++ if (replace.flags & OPT_COMMAND)
+ print_error("--atomic has to come before"
+ " the command");
++ /* another possible memory leak here */
+ replace.filename = (char *)malloc(strlen(optarg) + 1);
+ strcpy(replace.filename, optarg);
+ break;
+-
++ case 1 :
++ if (!strcmp(optarg, "!"))
++ check_inverse(optarg);
++ else
++ print_error("Bad argument : %s", optarg);
++ /*
++ * check_inverse() did optind++
++ */
++ optind--;
++ continue;
+ default:
+- // is it a target option?
++ /*
++ * 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)))
+ goto check_extension;
+
+- // is it a match_option?
++ /*
++ * 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))
+@@ -2013,7 +2157,9 @@
+ goto check_extension;
+ }
+
+- // is it a watcher option?
++ /*
++ * 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))
+@@ -2028,6 +2174,7 @@
+ replace.command != 'D')
+ print_error("Extensions only for -A, -I and -D");
+ }
++ invert = 0;
+ }
+
+ if ( !table && !(table = find_table(replace.name)) )
+@@ -2037,14 +2184,20 @@
+ replace.flags & OPT_ZERO )
+ print_error("Command -Z only allowed together with command -L");
+
+- // do this after parsing everything, so we can print specific info
++ /*
++ * 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
++ /*
++ * do the final checks
++ */
+ if (replace.command == 'A' || replace.command == 'I' ||
+ replace.command == 'D') {
+- // this will put the hook_mask right for the chains
++ /*
++ * this will put the hook_mask right for the chains
++ */
+ check_for_loops();
+ entries = to_chain();
+ m_l = new_entry->m_list;
+@@ -2065,8 +2218,10 @@
+ t->final_check(new_entry, t->t, replace.name,
+ entries->hook_mask, 0);
+ }
+- // so, the extensions can work with the host endian
+- // the kernel does not have to do this ofcourse
++ /*
++ * so, the extensions can work with the host endian
++ * the kernel does not have to do this ofcourse
++ */
+ new_entry->ethproto = htons(new_entry->ethproto);
+
+ if (replace.command == 'P') {
+@@ -2090,8 +2245,10 @@
+ } else if (replace.command == 'A' || replace.command == 'I') {
+ add_rule(rule_nr);
+ check_for_loops();
+- // do the final_check(), for all entries
+- // needed when adding a rule that has a chain target
++ /*
++ * do the final_check(), for all entries
++ * needed when adding a rule that has a chain target
++ */
+ i = -1;
+ while (1) {
+ struct ebt_u_entry *e;
+@@ -2106,17 +2263,24 @@
+ }
+ e = entries->entries;
+ while (e) {
+- // userspace extensions use host endian
++ /*
++ * userspace extensions use host endian
++ */
+ e->ethproto = ntohs(e->ethproto);
+ do_final_checks(e, entries);
+ e->ethproto = htons(e->ethproto);
+ e = e->next;
+ }
+ }
+- } else if (replace.command == 'D')
+- delete_rule(rule_nr);
+- // commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
+- // --init-table fall through
++ } else if (replace.command == 'D') {
++ if (rule_nr != -1 && rule_nr_end == -1)
++ rule_nr_end = entries->nentries;
++ delete_rule(rule_nr, rule_nr_end);
++ }
++ /*
++ * commands -N, -E, -X, --atomic-commit, --atomic-commit, --atomic-save,
++ * --init-table fall through
++ */
+
+ if (table->check)
+ table->check(&replace);
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0.2/getethertype.c Sat Dec 7 13:28:57 2002
+@@ -0,0 +1,162 @@
++/*
++* getethertype.c
++*
++* This file was part of the NYS Library.
++*
++** The NYS Library is free software; you can redistribute it and/or
++** modify it under the terms of the GNU Library General Public License as
++** published by the Free Software Foundation; either version 2 of the
++** License, or (at your option) any later version.
++*
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2 of the License, or
++* (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++/********************************************************************
++* Description: Ethertype name service switch and the ethertypes
++* database access functions
++* Author: Nick Fedchik <fnm@ukrsat.com>
++* Checker: Bart De Schuymer <bdschuym@pandora.be>
++* Origin: uClibc-0.9.16/libc/inet/getproto.c
++* Created at: Mon Nov 11 12:20:11 EET 2002
++********************************************************************/
++
++
++#include <ctype.h>
++#include <features.h>
++#include <sys/types.h>
++#include <sys/socket.h>
++#include <netdb.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <netinet/ether.h>
++#include <net/ethernet.h>
++
++#include "ethernetdb.h"
++
++#define MAXALIASES 35
++
++static FILE *etherf = NULL;
++static char line[BUFSIZ + 1];
++static struct ethertypeent et_ent;
++static char *ethertype_aliases[MAXALIASES];
++static int ethertype_stayopen;
++
++void setethertypeent(int f)
++{
++ if (etherf == NULL)
++ etherf = fopen(_PATH_ETHERTYPES, "r");
++ else
++ rewind(etherf);
++ ethertype_stayopen |= f;
++}
++
++void endethertypeent(void)
++{
++ if (etherf) {
++ fclose(etherf);
++ etherf = NULL;
++ }
++ ethertype_stayopen = 0;
++}
++
++struct ethertypeent *getethertypeent(void)
++{
++ char *e;
++ char *endptr;
++ register char *cp, **q;
++
++ if (etherf == NULL
++ && (etherf = fopen(_PATH_ETHERTYPES, "r")) == NULL) {
++ return (NULL);
++ }
++
++again:
++ if ((e = fgets(line, BUFSIZ, etherf)) == NULL) {
++ return (NULL);
++ }
++ if (*e == '#')
++ goto again;
++ cp = strpbrk(e, "#\n");
++ if (cp == NULL)
++ goto again;
++ *cp = '\0';
++ et_ent.e_name = e;
++ cp = strpbrk(e, " \t");
++ if (cp == NULL)
++ goto again;
++ *cp++ = '\0';
++ while (*cp == ' ' || *cp == '\t')
++ cp++;
++ e = strpbrk(cp, " \t");
++ if (e != NULL)
++ *e++ = '\0';
++// Check point
++ et_ent.e_ethertype = strtol(cp, &endptr, 16);
++ if (*endptr != '\0'
++ || (et_ent.e_ethertype < ETH_ZLEN
++ || et_ent.e_ethertype > 0xFFFF))
++ goto again; // Skip invalid etherproto type entry
++ q = et_ent.e_aliases = ethertype_aliases;
++ if (e != NULL) {
++ cp = e;
++ while (cp && *cp) {
++ if (*cp == ' ' || *cp == '\t') {
++ cp++;
++ continue;
++ }
++ if (q < &ethertype_aliases[MAXALIASES - 1])
++ *q++ = cp;
++ cp = strpbrk(cp, " \t");
++ if (cp != NULL)
++ *cp++ = '\0';
++ }
++ }
++ *q = NULL;
++ return (&et_ent);
++}
++
++
++struct ethertypeent *getethertypebyname(const char *name)
++{
++ register struct ethertypeent *e;
++ register char **cp;
++
++ setethertypeent(ethertype_stayopen);
++ while ((e = getethertypeent()) != NULL) {
++ if (strcasecmp(e->e_name, name) == 0)
++ break;
++ for (cp = e->e_aliases; *cp != 0; cp++)
++ if (strcasecmp(*cp, name) == 0)
++ goto found;
++ }
++found:
++ if (!ethertype_stayopen)
++ endethertypeent();
++ return (e);
++}
++
++struct ethertypeent *getethertypebynumber(int type)
++{
++ register struct ethertypeent *e;
++
++ setethertypeent(ethertype_stayopen);
++ while ((e = getethertypeent()) != NULL)
++ if (e->e_ethertype == type)
++ break;
++ if (!ethertype_stayopen)
++ endethertypeent();
++ return (e);
++}
+--- ebtables-v2.0.1/extensions/ebt_arp.c Thu Aug 29 18:48:36 2002
++++ ebtables-v2.0.2/extensions/ebt_arp.c Fri Nov 22 20:43:47 2002
+@@ -3,6 +3,7 @@
+ #include <stdlib.h>
+ #include <getopt.h>
+ #include "../include/ebtables_u.h"
++#include "../include/ethernetdb.h"
+ #include <linux/netfilter_bridge/ebt_arp.h>
+
+ #define ARP_OPCODE '1'
+@@ -52,7 +53,7 @@
+ printf("%d = %s\n", i + 1, opcodes[i]);
+ printf(
+ " hardware type string: 1 = Ethernet\n"
+-" protocol type string: see /etc/ethertypes\n");
++" protocol type string: see "_PATH_ETHERTYPES"\n");
+ }
+
+ static void init(struct ebt_entry_match *match)
+@@ -133,9 +134,14 @@
+ print_error("Missing ARP protocol type argument");
+ i = strtol(argv[optind - 1], &end, 16);
+ if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
+- if (name_to_number (argv[optind - 1], &proto) == -1)
++ struct ethertypeent *ent;
++
++ ent = getethertypebyname(argv[optind - 1]);
++ if (!ent)
+ print_error("Problem with specified ARP "
+ "protocol type");
++ proto = ent->e_ethertype;
++
+ } else
+ proto = i;
+ arpinfo->ptype = htons(proto);
+@@ -190,7 +196,6 @@
+ {
+ struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
+ int i;
+- char name[21];
+
+ if (arpinfo->bitmask & EBT_ARP_OPCODE) {
+ int opcode = ntohs(arpinfo->opcode);
+@@ -209,13 +214,16 @@
+ printf("%d ", ntohs(arpinfo->htype));
+ }
+ if (arpinfo->bitmask & EBT_ARP_PTYPE) {
++ struct ethertypeent *ent;
++
+ printf("--arp-ptype ");
+ if (arpinfo->invflags & EBT_ARP_PTYPE)
+ printf("! ");
+- if (number_to_name(ntohs(arpinfo->ptype), name))
++ ent = getethertypebynumber(ntohs(arpinfo->ptype));
++ if (!ent)
+ printf("0x%x ", ntohs(arpinfo->ptype));
+ else
+- printf("%s ", name);
++ printf("%s ", ent->e_name);
+ }
+ if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
+ printf("--arp-ip-src ");
+--- ebtables-v2.0.1/extensions/ebt_vlan.c Thu Aug 29 18:48:36 2002
++++ ebtables-v2.0.2/extensions/ebt_vlan.c Sat Dec 7 13:29:16 2002
+@@ -34,39 +34,73 @@
+ #include <stdlib.h>
+ #include <string.h>
+ #include <getopt.h>
++#include <ctype.h>
+ #include "../include/ebtables_u.h"
++#include "../include/ethernetdb.h"
+ #include <linux/netfilter_bridge/ebt_vlan.h>
++#include <linux/if_ether.h>
++
+
+ #define GET_BITMASK(_MASK_) vlaninfo->bitmask & _MASK_
+ #define SET_BITMASK(_MASK_) vlaninfo->bitmask |= _MASK_
+ #define INV_FLAG(_inv_flag_) (vlaninfo->invflags & _inv_flag_) ? "! " : ""
++#define CHECK_IF_MISSING_VALUE if (optind > argc) print_error ("Missing %s value", opts[c].name);
++#define CHECK_INV_FLAG(_INDEX_) if (check_inverse (optarg)) vlaninfo->invflags |= _INDEX_;
++#define CHECK_RANGE(_RANGE_) if (_RANGE_) print_error ("Invalid %s range", opts[c].name);
++
++#define NAME_VLAN_ID "id"
++#define NAME_VLAN_PRIO "prio"
++#define NAME_VLAN_ENCAP "encap"
+
+ #define VLAN_ID 0
+ #define VLAN_PRIO 1
+ #define VLAN_ENCAP 2
++
+ static struct option opts[] = {
+- {"vlan-id", required_argument, NULL, VLAN_ID},
+- {"vlan-prio", required_argument, NULL, VLAN_PRIO},
+- {"vlan-encap", required_argument, NULL, VLAN_ENCAP},
++ {EBT_VLAN_MATCH "-" NAME_VLAN_ID, required_argument, NULL,
++ VLAN_ID},
++ {EBT_VLAN_MATCH "-" NAME_VLAN_PRIO, required_argument, NULL,
++ VLAN_PRIO},
++ {EBT_VLAN_MATCH "-" NAME_VLAN_ENCAP, required_argument, NULL,
++ VLAN_ENCAP},
+ {NULL}
+ };
+
++/*
++ * option inverse flags definition
++ */
++#define OPT_VLAN_ID 0x01
++#define OPT_VLAN_PRIO 0x02
++#define OPT_VLAN_ENCAP 0x04
++#define OPT_VLAN_FLAGS (OPT_VLAN_ID | OPT_VLAN_PRIO | OPT_VLAN_ENCAP)
++
++struct ethertypeent *ethent;
+
+ /*
+- * Print out local help by "ebtables -h vlan"
++ * Print out local help by "ebtables -h <match name>"
+ */
+-static void print_help ()
++
++static void print_help()
+ {
+- printf ("802.1Q VLAN extension options:\n"
+- "--vlan-id [!] id : VLAN-tagged frame identifier, 0,1-4094 (integer)\n"
+- "--vlan-prio [!] prio : Priority-tagged frame user_priority, 0-7 (integer)\n"
+- "--vlan-encap [!] proto : Encapsulated protocol (hexadecimal)\n");
++#define HELP_TITLE "802.1Q VLAN extension"
++
++ printf(HELP_TITLE " options:\n");
++ printf("--" EBT_VLAN_MATCH "-" NAME_VLAN_ID " %s" NAME_VLAN_ID
++ " : VLAN-tagged frame identifier, 0,1-4096 (integer), default 1\n",
++ OPT_VLAN_FLAGS & OPT_VLAN_ID ? "[!] " : "");
++ printf("--" EBT_VLAN_MATCH "-" NAME_VLAN_PRIO " %s" NAME_VLAN_PRIO
++ " : Priority-tagged frame user_priority, 0-7 (integer), default 0\n",
++ OPT_VLAN_FLAGS & OPT_VLAN_PRIO ? "[!] " : "");
++ printf("--" EBT_VLAN_MATCH "-" NAME_VLAN_ENCAP " %s"
++ NAME_VLAN_ENCAP
++ " : Encapsulated frame type (hexadecimal), default IP (0800)\n",
++ OPT_VLAN_FLAGS & OPT_VLAN_ENCAP ? "[!] " : "");
+ }
+
+ /*
+ * Initialization function
+ */
+-static void init (struct ebt_entry_match *match)
++static void init(struct ebt_entry_match *match)
+ {
+ struct ebt_vlan_info *vlaninfo =
+ (struct ebt_vlan_info *) match->data;
+@@ -80,131 +114,72 @@
+ vlaninfo->bitmask = 0;
+ }
+
+-/*
+- * option flags definition
+- */
+-#define OPT_VLAN_ID 0x01
+-#define OPT_VLAN_PRIO 0x02
+-#define OPT_VLAN_ENCAP 0x04
+
+ /*
+ * Parse passed arguments values (ranges, flags, etc...)
+ * int c - parameter number from static struct option opts[]
+ * int argc - total amout of arguments (std argc value)
+- *
++ * int argv - arguments (std argv value)
++ * const struct ebt_u_entry *entry - default ebtables entry set
++ * 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)
++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 long i;
+ char *end;
+- uint16_t encap;
++ struct ebt_vlan_info local;
++
+ switch (c) {
+ case VLAN_ID:
+- /*
+- * ebtables.c:check_option(unsigned int *flags, unsigned int mask)
+- * checking for multiple usage of same option
+- */
+- check_option (flags, OPT_VLAN_ID);
+- /*
+- * Check If we got inversed arg for vlan-id option,
+- * otherwise unset inversion flag
+- */
+- if (check_inverse (optarg))
+- vlaninfo->invflags |= EBT_VLAN_ID;
+- /*
+- * Check arg value presence
+- */
+- if (optind > argc)
+- print_error ("Missing VLAN ID argument value");
+- /*
+- * 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 > 4094 || *end != '\0')
+- print_error
+- ("Specified VLAN ID is out of range (0-4094)");
+- /*
+- * Set up parameter value
+- */
+- vlaninfo->id = i;
+- /*
+- * Set up parameter presence flag
+- */
+- SET_BITMASK (EBT_VLAN_ID);
++ check_option(flags, OPT_VLAN_ID);
++ CHECK_INV_FLAG(EBT_VLAN_ID);
++ CHECK_IF_MISSING_VALUE;
++ (unsigned short) local.id =
++ strtoul(argv[optind - 1], &end, 10);
++ CHECK_RANGE(local.id > 4094 || *end != '\0');
++ vlaninfo->id = local.id;
++ SET_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 user_priority argument value");
+- /*
+- * Convert argv to long int,
+- * set *end to end of argv string,
+- * base set 10 for decimal only
+- */
+- (unsigned char) i = strtol (argv[optind - 1], &end, 10);
+- /*
+- * Check arg val range
+- */
+- if (i >= 8 || *end != '\0')
+- print_error
+- ("Specified user_priority is out of range (0-7)");
+- /*
+- * Set up parameter value
+- */
+- vlaninfo->prio = i;
+- /*
+- * Set up parameter presence flag
+- */
+- SET_BITMASK (EBT_VLAN_PRIO);
++ check_option(flags, OPT_VLAN_PRIO);
++ CHECK_INV_FLAG(EBT_VLAN_PRIO);
++ CHECK_IF_MISSING_VALUE;
++ (unsigned char) local.prio =
++ strtoul(argv[optind - 1], &end, 10);
++ CHECK_RANGE(local.prio >= 8 || *end != '\0');
++ vlaninfo->prio = local.prio;
++ SET_BITMASK(EBT_VLAN_PRIO);
+ break;
+
+ case VLAN_ENCAP:
+- check_option (flags, OPT_VLAN_ENCAP);
+- if (check_inverse (optarg))
+- vlaninfo->invflags |= EBT_VLAN_ENCAP;
+- if (optind > argc)
+- print_error
+- ("Missing encapsulated frame type argument value");
+- /*
+- * Parameter can be decimal, hexadecimal, or string.
+- * Check arg val range (still raw area)
+- */
+- (unsigned short) encap = strtol (argv[optind - 1], &end, 16);
+- if (*end == '\0' && (encap < ETH_ZLEN || encap > 0xFFFF))
+- print_error
+- ("Specified encapsulated frame type is out of range");
+- if (*end != '\0')
+- if (name_to_number (argv[optind - 1], &encap) == -1)
+- print_error
+- ("Problem with the specified encapsulated"
+- "protocol");
+- /*
+- * Set up parameter value (network notation)
+- */
+- vlaninfo->encap = htons (encap);
+- /*
+- * Set up parameter presence flag
+- */
+- SET_BITMASK (EBT_VLAN_ENCAP);
++ check_option(flags, OPT_VLAN_ENCAP);
++ CHECK_INV_FLAG(EBT_VLAN_ENCAP);
++ CHECK_IF_MISSING_VALUE;
++ (unsigned short) local.encap =
++ strtoul(argv[optind - 1], &end, 16);
++ if (*end != '\0') {
++ ethent = getethertypebyname(argv[optind - 1]);
++ if (ethent == NULL)
++ print_error("Unknown %s encap",
++ opts[c].name);
++ local.encap = ethent->e_ethertype;
++ }
++ CHECK_RANGE(local.encap < ETH_ZLEN);
++ vlaninfo->encap = htons(local.encap);
++ SET_BITMASK(EBT_VLAN_ENCAP);
+ break;
++
+ default:
+ return 0;
++
+ }
+ return 1;
+ }
+@@ -213,9 +188,9 @@
+ * Final check - logical conditions
+ */
+ static void
+-final_check (const struct ebt_u_entry *entry,
+- const struct ebt_entry_match *match,
+- const char *name, unsigned int hookmask, unsigned int time)
++final_check(const struct ebt_u_entry *entry,
++ const struct ebt_entry_match *match,
++ const char *name, unsigned int hookmask, unsigned int time)
+ {
+
+ struct ebt_vlan_info *vlaninfo =
+@@ -223,16 +198,25 @@
+ /*
+ * Specified proto isn't 802.1Q?
+ */
+- if (entry->ethproto != ETH_P_8021Q ||
+- entry->invflags & EBT_IPROTO)
++ if (entry->ethproto != ETH_P_8021Q || entry->invflags & EBT_IPROTO)
+ print_error
+ ("For use 802.1Q extension the protocol must be specified as 802_1Q");
+ /*
++ * Check if specified vlan-encap=0x8100 (802.1Q Frame)
++ * when vlan-encap specified.
++ */
++ if (GET_BITMASK(EBT_VLAN_ENCAP)) {
++ if (vlaninfo->encap == htons(0x8100))
++ print_error
++ ("Encapsulated frame type can not be 802.1Q (0x8100)");
++ }
++
++ /*
+ * Check if specified vlan-id=0 (priority-tagged frame condition)
+ * when vlan-prio was specified.
+ */
+- if (GET_BITMASK (EBT_VLAN_PRIO)) {
+- if (vlaninfo->id && GET_BITMASK (EBT_VLAN_ID))
++ if (GET_BITMASK(EBT_VLAN_PRIO)) {
++ if (vlaninfo->id && GET_BITMASK(EBT_VLAN_ID))
+ print_error
+ ("For use user_priority the specified vlan-id must be 0");
+ }
+@@ -242,49 +226,46 @@
+ * Print line when listing rules by ebtables -L
+ */
+ static void
+-print (const struct ebt_u_entry *entry,
+- const struct ebt_entry_match *match)
++print(const struct ebt_u_entry *entry, const struct ebt_entry_match *match)
+ {
+ struct ebt_vlan_info *vlaninfo =
+ (struct ebt_vlan_info *) match->data;
+
+- char ethertype_name[21];
+ /*
+ * Print VLAN ID if they are specified
+ */
+- if (GET_BITMASK (EBT_VLAN_ID)) {
+- printf ("--%s %s%d ",
+- opts[VLAN_ID].name,
+- INV_FLAG (EBT_VLAN_ID), vlaninfo->id);
++ if (GET_BITMASK(EBT_VLAN_ID)) {
++ printf("--%s %s%d ",
++ opts[VLAN_ID].name,
++ INV_FLAG(EBT_VLAN_ID), vlaninfo->id);
+ }
+ /*
+ * Print user priority if they are specified
+ */
+- if (GET_BITMASK (EBT_VLAN_PRIO)) {
+- printf ("--%s %s%d ",
+- opts[VLAN_PRIO].name,
+- INV_FLAG (EBT_VLAN_PRIO), vlaninfo->prio);
++ if (GET_BITMASK(EBT_VLAN_PRIO)) {
++ printf("--%s %s%d ",
++ opts[VLAN_PRIO].name,
++ INV_FLAG(EBT_VLAN_PRIO), vlaninfo->prio);
+ }
+ /*
+ * Print encapsulated frame type if they are specified
+ */
+- if (GET_BITMASK (EBT_VLAN_ENCAP)) {
+- printf ("--%s %s",
+- opts[VLAN_ENCAP].name, INV_FLAG (EBT_VLAN_ENCAP));
+- bzero (ethertype_name, 21);
+- if (!number_to_name
+- (ntohs (vlaninfo->encap), ethertype_name)) {
+- printf ("%s ", ethertype_name);
++ if (GET_BITMASK(EBT_VLAN_ENCAP)) {
++ printf("--%s %s",
++ opts[VLAN_ENCAP].name, INV_FLAG(EBT_VLAN_ENCAP));
++ ethent = getethertypebynumber(ntohs(vlaninfo->encap));
++ if (ethent != NULL) {
++ printf("%s ", ethent->e_name);
+ } else {
+- printf ("%2.4X ", ntohs (vlaninfo->encap));
++ printf("%4.4X ", ntohs(vlaninfo->encap));
+ }
+ }
+ }
+
+
+ static int
+-compare (const struct ebt_entry_match *vlan1,
+- const struct ebt_entry_match *vlan2)
++compare(const struct ebt_entry_match *vlan1,
++ const struct ebt_entry_match *vlan2)
+ {
+ struct ebt_vlan_info *vlaninfo1 =
+ (struct ebt_vlan_info *) vlan1->data;
+@@ -321,12 +302,13 @@
+ if (vlaninfo1->encap != vlaninfo2->encap)
+ return 0;
+ };
++
+ return 1;
+ }
+
+ static struct ebt_u_match vlan_match = {
+ EBT_VLAN_MATCH,
+- sizeof (struct ebt_vlan_info),
++ sizeof(struct ebt_vlan_info),
+ print_help,
+ init,
+ parse,
+@@ -336,8 +318,8 @@
+ opts
+ };
+
+-static void _init (void) __attribute__ ((constructor));
+-static void _init (void)
++static void _init(void) __attribute__ ((constructor));
++static void _init(void)
+ {
+- register_match (&vlan_match);
++ register_match(&vlan_match);
+ }
+--- ebtables-v2.0.1/extensions/Makefile Wed Jul 24 10:36:48 2002
++++ ebtables-v2.0.2/extensions/Makefile Fri Nov 22 20:44:37 2002
+@@ -6,7 +6,8 @@
+ EXT_OBJS+=$(foreach T,$(EXT_TABLES), extensions/ebtable_$(T).o)
+
+ extensions/ebt_%.o: extensions/ebt_%.c include/ebtables_u.h
+- $(CC) $(CFLAGS) -c -o $@ $<
++ $(CC) $(CFLAGS) $(PROGSPECS) -c -o $@ $< -I$(KERNEL_INCLUDES)
++
+ extensions/ebtable_%.o: extensions/ebtable_%.c
+- $(CC) $(CFLAGS) -c -o $@ $<
++ $(CC) $(CFLAGS) $(PROGSPECS) -c -o $@ $< -I$(KERNEL_INCLUDES)
+
+--- ebtables-v2.0.1/ChangeLog Fri Aug 30 22:33:36 2002
++++ ebtables-v2.0.2/ChangeLog Tue Dec 3 23:00:45 2002
+@@ -1,3 +1,20 @@
++20021203
++ * changed the way to use the atomic operations. It's now possible
++ to use the EBTABLES_ATOMIC_FILE environment variable, so it's no
++ longer necessary to explicitly state the file name. See the man.
++20021120
++ * changed the way of compiling. New releases will now contain their
++ own set of kernel includes. No more copying of kernel includes to
++ /usr/include/linux
++ * added getethertype.c (Nick) and use it. Removed name_to_number()
++ and number_to_name().
++20021106
++ * added possibility to specify a rule number interval when deleting
++ rules
++20021102
++ * added ! - option possibility, which is equivalent to - ! option
++20021102
++ * since last entry: added byte counters and udp/tcp port matching
+ 20020830
+ * updated the kernel files for 2.4.20-pre5 and 2.5.32
+ * last big cleanup of kernel and userspace code just finished
+--- ebtables-v2.0.1/ebtables.8 Thu Oct 17 23:20:57 2002
++++ ebtables-v2.0.2/ebtables.8 Sat Dec 7 13:42:58 2002
+@@ -1,6 +1,6 @@
+-.TH EBTABLES 8 "11 August 2002"
++.TH EBTABLES 8 "03 December 2002"
+ .\"
+-.\" Man page written by Bart De Schuymer <bart.de.schuymer@pandora.be>
++.\" Man page written by Bart De Schuymer <bdschuym@pandora.be>
+ .\" It is based on the iptables man page.
+ .\"
+ .\" Iptables page by Herve Eychenne March 2000.
+@@ -35,11 +35,11 @@
+ .br
+ .BR "ebtables --init-table"
+ .br
+-.BR "ebtables --atomic-init " file
++.BR "ebtables --atomic-init "
+ .br
+-.BR "ebtables --atomic-save " file
++.BR "ebtables --atomic-save "
+ .br
+-.BR "ebtables --atomic-commit " file
++.BR "ebtables --atomic-commit "
+ .br
+ .SH DESCRIPTION
+ .B ebtables
+@@ -133,9 +133,10 @@
+ Append a rule to the end of the selected chain.
+ .TP
+ .B "-D, --delete"
+-Delete the specified rule from the selected chain. There are two versions
+-of this command. A rule number (starting at 1) or the complete rule can be
+-specified.
++Delete the specified rule from the selected chain. There are two ways to
++use this command. The first is by specifying an interval of rule numbers
++to delete, syntax: start_nr[:end_nr]. The second usage is by specifying
++the complete rule as it would have been specified when it was added.
+ .TP
+ .B "-I, --insert"
+ Insert the specified rule into the selected chain at the specified rule number (1 meaning
+@@ -178,10 +179,8 @@
+ 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
+-, either
+-.BR DROP .
++Set the policy for the chain to the given target. The policy can be
++.BR ACCEPT ", " DROP " or " RETURN .
+ .TP
+ .B "-N, --new-chain"
+ Create a new user-defined chain by the given name. The number of
+@@ -202,26 +201,34 @@
+ .B "--atomic-init"
+ Copy the kernel's initial data of the table to the specified
+ file. This can be used as the first action, after which rules are added
+-to the file.
++to the file. The file can be specified using the
++.B --atomic-file
++option or through the
++.IR EBTABLES_ATOMIC_FILE " environment variable."
+ .TP
+ .B "--atomic-save"
+ Copy the kernel's current data of the table to the specified
+ file. This can be used as the first action, after which rules are added
+-to the file.
++to the file. The file can be specified using the
++.B --atomic-file
++option or through the
++.IR EBTABLES_ATOMIC_FILE " environment variable."
+ .TP
+ .B "--atomic-commit"
+ Replace the kernel table data with the data contained in the specified
+ file. This is a useful command that allows you to put all your rules of a
+ certain table into the kernel at once, saving the kernel a lot of precious
+-time. The file which contains the table data is constructed by using
+-either the
++time and allowing atomic updates of the tables. The file which contains
++the table data is constructed by using either the
+ .B "--atomic-init"
+ or the
+ .B "--atomic-save"
+ command to get a starting file. After that, using the
+-.B "--atomic"
+-option when constructing rules allows you to extend the file and build up
+-the complete wanted table.
++.B "--atomic-file"
++option when constructing rules or setting the
++.IR EBTABLES_ATOMIC_FILE " environment variable"
++allows you to extend the file and build the complete table before
++commiting it to the kernel.
+ .SS
+ PARAMETERS
+ The following parameters make up a rule specification (as used in the add
+@@ -334,11 +341,13 @@
+ .BR "TARGET EXTENSIONS" ")"
+ or a user defined chain name.
+ .TP
+-.B --atomic file
++.B --atomic-file file
+ Let the command operate on the specified file. The data of the table to
+ operate on will be extracted from the file and the result of the operation
+ will be saved back into the file. If specified, this option should come
+-before the command specification.
++before the command specification. An alternative that should be preferred,
++is setting the
++.BR EBTABLES_ATOMIC_FILE "environment variable."
+ .TP
+ .B -M, --modprobe program
+ When talking to the kernel, use this program to try to automatically load
+@@ -560,9 +569,11 @@
+ .br
+ .SH FILES
+ .I /etc/ethertypes
++.SH ENVIRONMENT VARIABLES
++.I EBTABLES_ATOMIC_FILE
+ .SH BUGS
+ This won't work on an architecture with a user32/kernel64 situation like the Sparc64.
+ .SH AUTHOR
+-.IR "" "Bart De Schuymer <" bart.de.schuymer@pandora.be >
++.IR "" "Bart De Schuymer <" bdschuym@pandora.be >
+ .SH SEE ALSO
+ .BR iptables "(8), " brctl (8)
+--- ebtables-v2.0.1/ethertypes Sun Aug 11 18:49:14 2002
++++ ebtables-v2.0.2/ethertypes Wed Nov 20 20:44:45 2002
+@@ -1,32 +1,37 @@
+-# 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
+-# anything on a line after the protocol number is ignored
+-# programs using this file should not be case sensitive
+-IPv4 0800
++#
++# Ethernet frame types
++# This file describes some of the various Ethernet
++# protocol types that are used on Ethernet networks.
++#
++# This list could be found on:
++# http://www.iana.org/assignments/ethernet-numbers
++#
++# <name> <hexnumber> <alias1>...<alias35> #Comment
++#
++IPv4 0800 ip ip4 # Internet IP (IPv4)
+ X25 0805
+-ARP 0806
+-802_1Q 8100 802.1Q Virtual LAN tagged frame
+-IPX 8137
+-IPv6 86DD
+-NetBEUI 8191
+-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
+-LOOP 9000
++ARP 0806 ether-arp #
++FR_ARP 0808 # Frame Relay ARP [RFC1701]
++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
++TEB 6558 # Trans Ether Bridging [RFC1701]
++RAW_FR 6559 # Raw Frame Relay [RFC1701]
++AARP 80F3 # Appletalk AARP
++ATALK 809B # Appletalk
++802_1Q 8100 8021q 1q 802.1q dot1q # 802.1Q Virtual LAN tagged frame
++IPX 8137 # Novell IPX
++NetBEUI 8191 # NetBEUI
++IPv6 86DD ip6 # IP version 6
++PPP 880B # PPP
++ATMMPOA 884C # MultiProtocol over ATM
++PPP_DISC 8863 # PPPoE discovery messages
++PPP_SES 8864 # PPPoE session messages
++ATMFATE 8884 # Frame-based ATM Transport over Ethernet
++LOOP 9000 loopback # loop proto
+--- ebtables-v2.0.1/include/ebtables_u.h Thu Aug 29 18:52:36 2002
++++ ebtables-v2.0.2/include/ebtables_u.h Wed Nov 20 22:05:39 2002
+@@ -198,14 +198,12 @@
+ struct ebt_u_table *find_table(char *name);
+ void deliver_counters(struct ebt_u_replace *repl);
+ void deliver_table(struct ebt_u_replace *repl);
+-int name_to_number(char *name, uint16_t *proto);
+-int number_to_name(unsigned short proto, char *name);
+ void check_option(unsigned int *flags, unsigned int mask);
+ int check_inverse(const char option[]);
+ void __print_bug(char *file, int line, char *format, ...);
+ #define print_bug(format, args...) \
+ __print_bug(__FILE__, __LINE__, format, ##args)
+-#define print_error(format, args...) {printf(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);}
+
+--- /dev/null Thu Aug 24 11:00:32 2000
++++ ebtables-v2.0.2/include/ethernetdb.h Fri Nov 22 20:44:03 2002
+@@ -0,0 +1,58 @@
++/*
++* This program is free software; you can redistribute it and/or modify
++* it under the terms of the GNU General Public License as published by
++* the Free Software Foundation; either version 2 of the License, or
++* (at your option) any later version.
++*
++* This program is distributed in the hope that it will be useful,
++* but WITHOUT ANY WARRANTY; without even the implied warranty of
++* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++* GNU General Public License for more details.
++*
++* You should have received a copy of the GNU General Public License
++* along with this program; if not, write to the Free Software
++* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
++*/
++
++/* All data returned by the network data base library are supplied in
++ host order and returned in network order (suitable for use in
++ system calls). */
++
++#ifndef _ETHERNETDB_H
++#define _ETHERNETDB_H 1
++
++#include <features.h>
++#include <netinet/in.h>
++#include <stdint.h>
++
++/* Absolute file name for network data base files. */
++#ifndef _PATH_ETHERTYPES
++#define _PATH_ETHERTYPES "/etc/ethertypes"
++#endif /* _PATH_ETHERTYPES */
++
++struct ethertypeent {
++ char *e_name; /* Official ethernet type name. */
++ char **e_aliases; /* Alias list. */
++ int e_ethertype; /* Ethernet type number. */
++};
++
++/* Open ethertype data base files and mark them as staying open even
++ after a later search if STAY_OPEN is non-zero. */
++extern void setethertypeent(int __stay_open) __THROW;
++
++/* Close ethertype data base files and clear `stay open' flag. */
++extern void endethertypeent(void) __THROW;
++
++/* Get next entry from ethertype data base file. Open data base if
++ necessary. */
++extern struct ethertypeent *getethertypeent(void) __THROW;
++
++/* Return entry from ethertype data base for network with NAME. */
++extern struct ethertypeent *getethertypebyname(__const char *__name)
++ __THROW;
++
++/* Return entry from ethertype data base which number is PROTO. */
++extern struct ethertypeent *getethertypebynumber(int __ethertype) __THROW;
++
++
++#endif /* ethernetdb.h */