summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
Diffstat (limited to 'extensions')
-rw-r--r--extensions/Makefile12
-rw-r--r--extensions/ebt_arp.c289
-rw-r--r--extensions/ebt_ip.c318
-rw-r--r--extensions/ebt_log.c197
-rw-r--r--extensions/ebt_nat.c222
-rw-r--r--extensions/ebt_redirect.c109
-rw-r--r--extensions/ebt_standard.c70
-rw-r--r--extensions/ebt_vlan.c231
-rw-r--r--extensions/ebtable_broute.c25
-rw-r--r--extensions/ebtable_filter.c32
-rw-r--r--extensions/ebtable_nat.c32
11 files changed, 1537 insertions, 0 deletions
diff --git a/extensions/Makefile b/extensions/Makefile
new file mode 100644
index 0000000..109af35
--- /dev/null
+++ b/extensions/Makefile
@@ -0,0 +1,12 @@
+#! /usr/bin/make
+
+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)
+
+extensions/ebt_%.o: extensions/ebt_%.c include/ebtables_u.h
+ $(CC) $(CFLAGS) -c -o $@ $<
+extensions/ebtable_%.o: extensions/ebtable_%.c
+ $(CC) $(CFLAGS) -c -o $@ $<
+
diff --git a/extensions/ebt_arp.c b/extensions/ebt_arp.c
new file mode 100644
index 0000000..0e22b0b
--- /dev/null
+++ b/extensions/ebt_arp.c
@@ -0,0 +1,289 @@
+#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_arp.h>
+
+#define ARP_OPCODE '1'
+#define ARP_HTYPE '2'
+#define ARP_PTYPE '3'
+#define ARP_IP_S '4'
+#define ARP_IP_D '5'
+static struct option opts[] =
+{
+ { "arp-opcode" , required_argument, 0, ARP_OPCODE },
+ { "arp-op" , required_argument, 0, ARP_OPCODE },
+ { "arp-htype" , required_argument, 0, ARP_HTYPE },
+ { "arp-ptype" , required_argument, 0, ARP_PTYPE },
+ { "arp-ip-src" , required_argument, 0, ARP_IP_S },
+ { "arp-ip-dst" , required_argument, 0, ARP_IP_D },
+ { 0 }
+};
+
+// a few names
+static char *opcodes[] =
+{
+ "Request",
+ "Reply",
+ "Request Reverse",
+ "Reply Reverse",
+ "DRARP Request",
+ "DRARP Reply",
+ "DRARP Error",
+ "InARP Request",
+ "ARP NAK",
+ ""
+};
+
+static void print_help()
+{
+ 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");
+ 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");
+}
+
+static void init(struct ebt_entry_match *match)
+{
+ struct ebt_arp_info *arpinfo = (struct ebt_arp_info *)match->data;
+
+ arpinfo->invflags = 0;
+ arpinfo->bitmask = 0;
+}
+
+// defined in ebt_ip.c
+void parse_ip_address(char *address, __u32 *addr, __u32 *msk);
+
+#define OPT_OPCODE 0x01
+#define OPT_HTYPE 0x02
+#define OPT_PTYPE 0x04
+#define OPT_IP_S 0x08
+#define OPT_IP_D 0x10
+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_arp_info *arpinfo = (struct ebt_arp_info *)(*match)->data;
+ int i;
+ char *end;
+ __u32 *addr;
+ __u32 *mask;
+
+ 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");
+ i = strtol(argv[optind - 1], &end, 10);
+ if (i < 0 || i >= (0x1 << 16) || *end !='\0') {
+ i = 0;
+ while (strcmp(opcodes[i], "")) {
+ if (!strcasecmp(opcodes[i], optarg))
+ break;
+ i++;
+ }
+ if (!strcmp(opcodes[i], ""))
+ print_error("Problem with specified "
+ "arp opcode");
+ }
+ arpinfo->opcode = htons(i);
+ arpinfo->bitmask |= EBT_ARP_OPCODE;
+ break;
+
+ case ARP_HTYPE:
+ check_option(flags, OPT_HTYPE);
+ if (check_inverse(optarg))
+ arpinfo->invflags |= EBT_ARP_HTYPE;
+
+ if (optind > argc)
+ print_error("Missing arp hardware type argument");
+ i = strtol(argv[optind - 1], &end, 10);
+ 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");
+ }
+ arpinfo->htype = htons(i);
+ arpinfo->bitmask |= EBT_ARP_HTYPE;
+ break;
+
+ case ARP_PTYPE:
+ check_option(flags, OPT_PTYPE);
+ if (check_inverse(optarg))
+ arpinfo->invflags |= EBT_ARP_PTYPE;
+
+ if (optind > argc)
+ print_error("Missing arp protocol type argument");
+ i = strtol(argv[optind - 1], &end, 16);
+ 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");
+ }
+ arpinfo->ptype = htons(i);
+ arpinfo->bitmask |= EBT_ARP_PTYPE;
+ break;
+
+ case ARP_IP_S:
+ case ARP_IP_D:
+ if (c == ARP_IP_S) {
+ check_option(flags, OPT_IP_S);
+ addr = &arpinfo->saddr;
+ mask = &arpinfo->smsk;
+ arpinfo->bitmask |= EBT_ARP_SRC_IP;
+ } else {
+ check_option(flags, OPT_IP_D);
+ addr = &arpinfo->daddr;
+ mask = &arpinfo->dmsk;
+ arpinfo->bitmask |= EBT_ARP_DST_IP;
+ }
+ if (check_inverse(optarg)) {
+ if (c == ARP_IP_S)
+ arpinfo->invflags |= EBT_ARP_SRC_IP;
+ else
+ arpinfo->invflags |= EBT_ARP_DST_IP;
+ }
+ if (optind > argc)
+ print_error("Missing ip address argument");
+ parse_ip_address(argv[optind - 1], addr, mask);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+const struct ebt_entry_match *match, const char *name, unsigned int 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");
+}
+
+// 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;
+
+ if (arpinfo->bitmask & EBT_ARP_OPCODE) {
+ printf("arp opcode: ");
+ if (arpinfo->invflags & EBT_ARP_OPCODE)
+ printf("! ");
+ printf("%d ", ntohs(arpinfo->opcode));
+ }
+ if (arpinfo->bitmask & EBT_ARP_HTYPE) {
+ printf("arp htype: ");
+ if (arpinfo->invflags & EBT_ARP_HTYPE)
+ printf("! ");
+ printf("%d ", ntohs(arpinfo->htype));
+ }
+ if (arpinfo->bitmask & EBT_ARP_PTYPE) {
+ printf("arp ptype: ");
+ if (arpinfo->invflags & EBT_ARP_PTYPE)
+ printf("! ");
+ printf("0x%x ", ntohs(arpinfo->ptype));
+ }
+ if (arpinfo->bitmask & EBT_ARP_SRC_IP) {
+ printf("arp src IP ");
+ 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("%s, ", mask_to_dotted(arpinfo->smsk));
+ }
+ if (arpinfo->bitmask & EBT_ARP_DST_IP) {
+ printf("arp dst IP ");
+ 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("%s, ", mask_to_dotted(arpinfo->dmsk));
+ }
+}
+
+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;
+
+ if (arpinfo1->bitmask != arpinfo2->bitmask)
+ return 0;
+ if (arpinfo1->invflags != arpinfo2->invflags)
+ return 0;
+ if (arpinfo1->bitmask & EBT_ARP_OPCODE) {
+ if (arpinfo1->opcode != arpinfo2->opcode)
+ return 0;
+ }
+ if (arpinfo1->bitmask & EBT_ARP_HTYPE) {
+ if (arpinfo1->htype != arpinfo2->htype)
+ return 0;
+ }
+ if (arpinfo1->bitmask & EBT_ARP_PTYPE) {
+ if (arpinfo1->ptype != arpinfo2->ptype)
+ return 0;
+ }
+ if (arpinfo1->bitmask & EBT_ARP_SRC_IP) {
+ if (arpinfo1->saddr != arpinfo2->saddr)
+ return 0;
+ if (arpinfo1->smsk != arpinfo2->smsk)
+ return 0;
+ }
+ if (arpinfo1->bitmask & EBT_ARP_DST_IP) {
+ if (arpinfo1->daddr != arpinfo2->daddr)
+ return 0;
+ if (arpinfo1->dmsk != arpinfo2->dmsk)
+ return 0;
+ }
+ return 1;
+}
+
+static struct ebt_u_match arp_match =
+{
+ EBT_ARP_MATCH,
+ sizeof(struct ebt_arp_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts,
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_match(&arp_match);
+}
diff --git a/extensions/ebt_ip.c b/extensions/ebt_ip.c
new file mode 100644
index 0000000..5d62d3a
--- /dev/null
+++ b/extensions/ebt_ip.c
@@ -0,0 +1,318 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_ip.h>
+
+#define IP_SOURCE '1'
+#define IP_DEST '2'
+#define IP_myTOS '3' // include/bits/in.h seems to already define IP_TOS
+#define IP_PROTO '4'
+
+static struct option opts[] =
+{
+ { "ip-source" , required_argument, 0, IP_SOURCE },
+ { "ip-src" , required_argument, 0, IP_SOURCE },
+ { "ip-destination", required_argument, 0, IP_DEST },
+ { "ip-dst" , required_argument, 0, IP_DEST },
+ { "ip-tos" , required_argument, 0, IP_myTOS },
+ { "ip-protocol" , required_argument, 0, IP_PROTO },
+ { "ip-proto" , required_argument, 0, IP_PROTO },
+ { 0 }
+};
+
+// put the ip string into 4 bytes
+static int undot_ip(char *ip, unsigned char *ip2)
+{
+ char *p, *q, *end;
+ int onebyte, i;
+ char buf[20];
+
+ strncpy(buf, ip, sizeof(buf) - 1);
+
+ p = buf;
+ for (i = 0; i < 3; i++) {
+ if ((q = strchr(p, '.')) == NULL)
+ return -1;
+ *q = '\0';
+ onebyte = strtol(p, &end, 10);
+ if (*end != '\0' || onebyte > 255 || onebyte < 0)
+ return -1;
+ 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;
+
+ return 0;
+}
+
+// put the mask into 4 bytes
+static int ip_mask(char *mask, unsigned char *mask2)
+{
+ char *end;
+ int bits;
+ __u32 mask22;
+
+ if (undot_ip(mask, mask2)) {
+ // not the /a.b.c.e format, maybe the /x format
+ bits = strtol(mask, &end, 10);
+ if (*end != '\0' || bits > 32 || bits < 0)
+ return -1;
+ if (bits != 0) {
+ mask22 = htonl(0xFFFFFFFF << (32 - bits));
+ memcpy(mask2, &mask22, 4);
+ } else {
+ mask22 = 0xFFFFFFFF;
+ memcpy(mask2, &mask22, 4);
+ }
+ }
+ return 0;
+}
+
+// set the ip mask and ip address
+void parse_ip_address(char *address, __u32 *addr, __u32 *msk)
+{
+ char *p;
+ int i;
+
+ // first the mask
+ if ((p = strrchr(address, '/')) != NULL) {
+ *p = '\0';
+ i = ip_mask(p + 1, (unsigned char *)msk);
+ if (i)
+ print_error("Problem with the ip mask");
+ }
+ else
+ *msk = 0xFFFFFFFF;
+
+ i = undot_ip(address, (unsigned char *)addr);
+ if (i)
+ print_error("Problem with the ip address");
+ *addr = *addr & *msk;
+}
+
+// transform the ip mask into a string ready for output
+char *mask_to_dotted(__u32 mask)
+{
+ int i;
+ static char buf[20];
+ __u32 maskaddr, bits;
+
+ maskaddr = ntohl(mask);
+
+ // don't print /32
+ if (mask == 0xFFFFFFFFL)
+ return "";
+
+ i = 32;
+ bits = 0xFFFFFFFEL; // case 0xFFFFFFFF has just been dealt with
+ while (--i >= 0 && maskaddr != bits)
+ bits <<= 1;
+
+ if (i > 0)
+ sprintf(buf, "/%d", i);
+ 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]);
+
+ return buf;
+}
+
+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");
+}
+
+static void init(struct ebt_entry_match *match)
+{
+ struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)match->data;
+
+ ipinfo->invflags = 0;
+ ipinfo->bitmask = 0;
+}
+
+#define OPT_SOURCE 0x01
+#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)
+{
+ struct ebt_ip_info *ipinfo = (struct ebt_ip_info *)(*match)->data;
+ char *end, *buffer;
+ int i;
+
+ switch (c) {
+ case IP_SOURCE:
+ check_option(flags, OPT_SOURCE);
+ ipinfo->bitmask |= EBT_IP_SOURCE;
+
+ case IP_DEST:
+ if (c == IP_DEST) {
+ check_option(flags, OPT_DEST);
+ ipinfo->bitmask |= EBT_IP_DEST;
+ }
+ if (check_inverse(optarg)) {
+ if (c == IP_SOURCE)
+ ipinfo->invflags |= EBT_IP_SOURCE;
+ else
+ ipinfo->invflags |= EBT_IP_DEST;
+ }
+
+ if (optind > argc)
+ print_error("Missing ip address argument");
+ if (c == IP_SOURCE)
+ parse_ip_address(argv[optind - 1], &ipinfo->saddr,
+ &ipinfo->smsk);
+ else
+ 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");
+ i = strtol(argv[optind - 1], &end, 16);
+ if (i < 0 || i > 255 || *buffer != '\0')
+ 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");
+ i = strtol(argv[optind - 1], &end, 10);
+ if (i < 0 || i > 255 || *end != '\0')
+ print_error("Problem with specified ip protocol");
+ ipinfo->protocol = i;
+ ipinfo->bitmask |= EBT_IP_PROTO;
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+static void final_check(const struct ebt_u_entry *entry,
+ const struct ebt_entry_match *match, const char *name, unsigned int 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");
+}
+
+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;
+
+ if (ipinfo->bitmask & EBT_IP_SOURCE) {
+ printf("source ip: ");
+ if (ipinfo->invflags & EBT_IP_SOURCE)
+ printf("! ");
+ for (j = 0; j < 4; j++)
+ printf("%d%s",((unsigned char *)&ipinfo->saddr)[j],
+ (j == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(ipinfo->smsk));
+ }
+ if (ipinfo->bitmask & EBT_IP_DEST) {
+ printf("dest ip: ");
+ if (ipinfo->invflags & EBT_IP_DEST)
+ printf("! ");
+ for (j = 0; j < 4; j++)
+ printf("%d%s", ((unsigned char *)&ipinfo->daddr)[j],
+ (j == 3) ? "" : ".");
+ printf("%s, ", mask_to_dotted(ipinfo->dmsk));
+ }
+ if (ipinfo->bitmask & EBT_IP_TOS) {
+ printf("ip TOS: ");
+ if (ipinfo->invflags & EBT_IP_TOS)
+ printf("! ");
+ printf("0x%02X, ", ipinfo->tos);
+ }
+ if (ipinfo->bitmask & EBT_IP_PROTO) {
+ printf("ip proto: ");
+ if (ipinfo->invflags & EBT_IP_DEST)
+ printf("! ");
+ printf("%d, ", ipinfo->protocol);
+ }
+}
+
+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;
+
+ if (ipinfo1->bitmask != ipinfo2->bitmask)
+ return 0;
+ if (ipinfo1->invflags != ipinfo2->invflags)
+ return 0;
+ if (ipinfo1->bitmask & EBT_IP_SOURCE) {
+ if (ipinfo1->saddr != ipinfo2->saddr)
+ return 0;
+ if (ipinfo1->smsk != ipinfo2->smsk)
+ return 0;
+ }
+ if (ipinfo1->bitmask & EBT_IP_DEST) {
+ if (ipinfo1->daddr != ipinfo2->daddr)
+ return 0;
+ if (ipinfo1->dmsk != ipinfo2->dmsk)
+ return 0;
+ }
+ if (ipinfo1->bitmask & EBT_IP_TOS) {
+ if (ipinfo1->tos != ipinfo2->tos)
+ return 0;
+ }
+ if (ipinfo1->bitmask & EBT_IP_PROTO) {
+ if (ipinfo1->protocol != ipinfo2->protocol)
+ return 0;
+ }
+ return 1;
+}
+
+static struct ebt_u_match ip_match =
+{
+ EBT_IP_MATCH,
+ sizeof(struct ebt_ip_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts,
+};
+
+static void _init(void) __attribute((constructor));
+static void _init(void)
+{
+ register_match(&ip_match);
+}
diff --git a/extensions/ebt_log.c b/extensions/ebt_log.c
new file mode 100644
index 0000000..6dff952
--- /dev/null
+++ b/extensions/ebt_log.c
@@ -0,0 +1,197 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_log.h>
+
+// 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_DEFAULT_LEVEL LOG_INFO
+
+typedef struct _code {
+ char *c_name;
+ int c_val;
+} CODE;
+
+static CODE eight_priority[] = {
+ { "emerg", LOG_EMERG },
+ { "alert", LOG_ALERT },
+ { "crit", LOG_CRIT },
+ { "error", LOG_ERR },
+ { "warning", LOG_WARNING },
+ { "notice", LOG_NOTICE },
+ { "info", LOG_INFO },
+ { "debug", LOG_DEBUG },
+ { NULL, -1 }
+};
+
+static int name_to_loglevel(char* arg)
+{
+ int i = 0, c_val = eight_priority[0].c_val;
+
+ while (c_val != -1) {
+ if (!strcmp(arg, eight_priority[i].c_name))
+ return c_val;
+ i++;
+ c_val = eight_priority[i].c_val;
+ }
+ // return bad loglevel
+ return 9;
+}
+
+#define LOG_PREFIX '1'
+#define LOG_LEVEL '2'
+#define LOG_ARP '3'
+#define LOG_IP '4'
+#define LOG_LOG '5'
+static struct option opts[] =
+{
+ { "log-prefix", required_argument, 0, LOG_PREFIX },
+ { "log-level" , required_argument, 0, LOG_LEVEL },
+ { "log-arp" , no_argument , 0, LOG_ARP },
+ { "log-ip" , no_argument , 0, LOG_IP },
+ { "log" , no_argument , 0, LOG_LOG },
+ { 0 }
+};
+
+static void print_help()
+{
+ 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"
+ , 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);
+}
+
+static void init(struct ebt_entry_watcher *watcher)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)watcher->data;
+
+ loginfo->bitmask = 0;
+ loginfo->prefix[0] = '\0';
+ loginfo->loglevel = LOG_NOTICE;
+}
+
+#define OPT_PREFIX 0x01
+#define OPT_LEVEL 0x02
+#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)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)(*watcher)->data;
+ int i;
+ char *end;
+
+ switch (c) {
+ case LOG_PREFIX:
+ check_option(flags, OPT_PREFIX);
+ if (strlen(optarg) > sizeof(loginfo->prefix) - 1)
+ print_error("Prefix too long");
+ strcpy(loginfo->prefix, optarg);
+ break;
+
+ case LOG_LEVEL:
+ check_option(flags, OPT_LEVEL);
+ i = strtol(optarg, &end, 16);
+ if (*end != '\0' || i < 0 || i > 7)
+ loginfo->loglevel = name_to_loglevel(optarg);
+ else
+ loginfo->loglevel = i;
+ if (loginfo->loglevel == 9)
+ 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;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+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)
+{
+ struct ebt_log_info *loginfo = (struct ebt_log_info *)watcher->data;
+
+ printf("log: log-level = %s - log-prefix = \"%s\"",
+ eight_priority[loginfo->loglevel].c_name,
+ loginfo->prefix);
+ if (loginfo->bitmask & EBT_LOG_IP)
+ printf(" - log-ip");
+ if (loginfo->bitmask & EBT_LOG_ARP)
+ printf(" - log-arp");
+ printf(" ");
+}
+
+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;
+
+ if (loginfo1->loglevel != loginfo2->loglevel)
+ return 0;
+ if (loginfo1->bitmask != loginfo2->bitmask)
+ return 0;
+ return !strcmp(loginfo1->prefix, loginfo2->prefix);
+}
+
+static struct ebt_u_watcher log_watcher =
+{
+ EBT_LOG_WATCHER,
+ sizeof(struct ebt_log_info),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts,
+};
+
+#undef _init
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_watcher(&log_watcher);
+}
diff --git a/extensions/ebt_nat.c b/extensions/ebt_nat.c
new file mode 100644
index 0000000..dbdb5a4
--- /dev/null
+++ b/extensions/ebt_nat.c
@@ -0,0 +1,222 @@
+#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_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 },
+ { "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 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 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_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) {
+ case NAT_S:
+ check_option(flags, OPT_SNAT);
+ to_source_supplied = 1;
+ 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 1;
+}
+
+#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) {
+ case NAT_D:
+ check_option(flags, OPT_DNAT);
+ to_dest_supplied = 1;
+ if (getmac(optarg, natinfo->mac))
+ 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 1;
+}
+
+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");
+ 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")) &&
+ (hook != NF_BR_BROUTING || strcmp(name, "broute")) )
+ print_error("Wrong chain for dnat");
+ if (to_dest_supplied == 0)
+ print_error("No dnat address supplied");
+}
+
+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(" --snat-target %s", standard_targets[natinfo->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(" --dnat-target %s", standard_targets[natinfo->target]);
+}
+
+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;
+
+
+ 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),
+ print_help_s,
+ init_s,
+ parse_s,
+ final_check_s,
+ print_s,
+ compare,
+ opts_s,
+};
+
+static struct ebt_u_target dnat_target =
+{
+ EBT_DNAT_TARGET,
+ sizeof(struct ebt_nat_info),
+ print_help_d,
+ init_d,
+ parse_d,
+ final_check_d,
+ print_d,
+ compare,
+ opts_d,
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_target(&snat_target);
+ register_target(&dnat_target);
+}
diff --git a/extensions/ebt_redirect.c b/extensions/ebt_redirect.c
new file mode 100644
index 0000000..3dff790
--- /dev/null
+++ b/extensions/ebt_redirect.c
@@ -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);
+}
diff --git a/extensions/ebt_standard.c b/extensions/ebt_standard.c
new file mode 100644
index 0000000..983d055
--- /dev/null
+++ b/extensions/ebt_standard.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#include <linux/netfilter_bridge/ebtables.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+
+static struct option opts[] =
+{
+ {0}
+};
+
+static void print_help()
+{
+ printf("Standard targets: DROP, ACCEPT and CONTINUE\n");
+}
+
+static void init(struct ebt_entry_target *t)
+{
+ ((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)
+{
+ 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 print(const struct ebt_u_entry *entry,
+ const struct ebt_entry_target *target)
+{
+ __u8 verdict = ((struct ebt_standard_target *)target)->verdict;
+
+ if (verdict == EBT_CONTINUE)
+ printf("Continue ");
+ else if (verdict == EBT_ACCEPT)
+ printf("Accept ");
+ else
+ printf("Drop ");
+}
+
+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;
+}
+
+static struct ebt_u_target standard =
+{
+ EBT_STANDARD_TARGET,
+ sizeof(struct ebt_standard_target) - sizeof(struct ebt_entry_target),
+ print_help,
+ init,
+ parse,
+ final_check,
+ print,
+ compare,
+ opts
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_target(&standard);
+}
diff --git a/extensions/ebt_vlan.c b/extensions/ebt_vlan.c
new file mode 100644
index 0000000..ad3e6f7
--- /dev/null
+++ b/extensions/ebt_vlan.c
@@ -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);
+}
diff --git a/extensions/ebtable_broute.c b/extensions/ebtable_broute.c
new file mode 100644
index 0000000..2abfcb6
--- /dev/null
+++ b/extensions/ebtable_broute.c
@@ -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/extensions/ebtable_filter.c b/extensions/ebtable_filter.c
new file mode 100644
index 0000000..cf26983
--- /dev/null
+++ b/extensions/ebtable_filter.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#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))
+
+static void print_help(char **hn)
+{
+ int i;
+
+ printf("Supported chains for the filter table:\n");
+ for (i = 0; i < NF_BR_NUMHOOKS; i++)
+ if (FILTER_VALID_HOOKS & (1 << i))
+ printf("%s ", hn[i]);
+ printf("\n");
+}
+
+static struct ebt_u_table table =
+{
+ "filter",
+ NULL,
+ print_help,
+ NULL
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_table(&table);
+}
diff --git a/extensions/ebtable_nat.c b/extensions/ebtable_nat.c
new file mode 100644
index 0000000..4b4ca48
--- /dev/null
+++ b/extensions/ebtable_nat.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#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))
+
+static void print_help(char **hn)
+{
+ int i;
+
+ printf("Supported chains for the nat table:\n");
+ for (i = 0; i < NF_BR_NUMHOOKS; i++)
+ if (NAT_VALID_HOOKS & (1 << i))
+ printf("%s ", hn[i]);
+ printf("\n");
+}
+
+static struct
+ebt_u_table table =
+{
+ "nat",
+ NULL,
+ print_help,
+ NULL
+};
+
+static void _init(void) __attribute__ ((constructor));
+static void _init(void)
+{
+ register_table(&table);
+}