summaryrefslogtreecommitdiff
path: root/polux/application/ebtables/extensions/ebt_plc.c
diff options
context:
space:
mode:
Diffstat (limited to 'polux/application/ebtables/extensions/ebt_plc.c')
-rw-r--r--polux/application/ebtables/extensions/ebt_plc.c233
1 files changed, 233 insertions, 0 deletions
diff --git a/polux/application/ebtables/extensions/ebt_plc.c b/polux/application/ebtables/extensions/ebt_plc.c
new file mode 100644
index 0000000000..313824a2a8
--- /dev/null
+++ b/polux/application/ebtables/extensions/ebt_plc.c
@@ -0,0 +1,233 @@
+/*
+ * Summary: ebt_plc - PLC extension module for userspace
+ *
+ * License: GNU GPL
+ *
+ * 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
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <getopt.h>
+#include "../include/ebtables_u.h"
+#include <linux/netfilter_bridge/ebt_plc.h>
+
+/*
+ * Helper functions for MAC address str<->bin conversions:
+ */
+ static int hex2num(char c)
+{
+ if (c >= '0' && c <= '9')
+ return c - '0';
+ if (c >= 'a' && c <= 'f')
+ return c - 'a' + 10;
+ if (c >= 'A' && c <= 'F')
+ return c - 'A' + 10;
+ return -1;
+}
+/*
+ * hwaddr_aton() - Convert ASCII string to MAC address
+ * @txt: MAC address as a string (e.g., "00:11:22:33:44:55")
+ * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes)
+ * Returns: 0 on success, -1 on failure (e.g., string not a MAC address)
+ */
+int hwaddr_aton(const char *txt, uint8_t *addr)
+{
+ int i;
+
+ for (i = 0; i < 6; i++) {
+ int a, b;
+
+ a = hex2num(*txt++);
+ if (a < 0)
+ return -1;
+ b = hex2num(*txt++);
+ if (b < 0)
+ return -1;
+ *addr++ = (a << 4) | b;
+ if (i < 5 && *txt++ != ':')
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * addr2str() - Converts MAC address to ASCII string.
+ */
+void addr2str(char *str, uint8_t *addr)
+{
+ int i;
+
+ for (i = 0; i < ETH_ALEN; i++)
+ sprintf(str + 3*i, "%.2x%s", addr[i], i < ETH_ALEN - 1 ? ":" : "");
+}
+
+
+#define PLC_SRC 0
+#define PLC_DST 1
+
+static struct option opts[] = {
+ {"plc-src", required_argument, 0, PLC_SRC},
+ {"plc-dst", required_argument, 0, PLC_DST},
+ {0}
+};
+
+/*
+ * Print out local help by "ebtables -h <match name>"
+ */
+static void print_help()
+{
+ printf("PLC extension options:\n");
+ printf("--plc-src address : source MAC address / unknown\n");
+ printf("--plc-dst address : destination MAC address / unknown\n");
+}
+
+/*
+ * Initialization function
+ */
+static void init(struct ebt_entry_match *match)
+{
+ struct ebt_plc_info *plcinfo =
+ (struct ebt_plc_info *) match->data;
+
+ /*
+ * Set initial values
+ */
+ memset(plcinfo->src_addr, 0, ETH_ALEN);
+ memset(plcinfo->dst_addr, 0, ETH_ALEN);
+ plcinfo->bitmask = 0;
+}
+
+
+/*
+ * 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)
+{
+ struct ebt_plc_info *plcinfo = (struct ebt_plc_info *) (*match)->data;
+
+ switch (c) {
+ case PLC_SRC:
+ check_option(flags, EBT_PLC_SRC);
+ if (optind > argc)
+ print_error ("Missing %s value", opts[c].name);
+ if (!strcmp(optarg, "unknown"))
+ SET_PLC_SRC_UNKNOWN(plcinfo->bitmask);
+ else if (hwaddr_aton(optarg, plcinfo->src_addr) < 0)
+ print_error("%s: Invalid %s argument", optarg, opts[c].name);
+ SET_PLC_SRC(plcinfo->bitmask);
+ break;
+ case PLC_DST:
+ check_option(flags, EBT_PLC_DST);
+ if (optind > argc)
+ print_error ("Missing %s value", opts[c].name);
+ if (!strcmp(optarg, "unknown"))
+ SET_PLC_DST_UNKNOWN(plcinfo->bitmask);
+ else if (hwaddr_aton(optarg, plcinfo->dst_addr) < 0)
+ print_error("%s: Invalid %s argument", optarg, opts[c].name);
+ SET_PLC_DST(plcinfo->bitmask);
+ break;
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+/*
+ * Final check - logical conditions (none for now)
+ */
+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)
+{
+}
+
+/*
+ * 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_plc_info *plcinfo =
+ (struct ebt_plc_info *) match->data;
+ char str_addr[ETH_ALEN * 3];
+
+ if (GET_PLC_SRC(plcinfo->bitmask)) {
+ if (GET_PLC_SRC_UNKNOWN(plcinfo->bitmask))
+ strcpy(str_addr, "unknown");
+ else
+ addr2str(str_addr, plcinfo->src_addr);
+ printf("--%s %s ", opts[PLC_SRC].name, str_addr);
+ }
+ if (GET_PLC_DST(plcinfo->bitmask)) {
+ if (GET_PLC_DST_UNKNOWN(plcinfo->bitmask))
+ strcpy(str_addr, "unknown");
+ else
+ addr2str(str_addr, plcinfo->dst_addr);
+ printf("--%s %s ", opts[PLC_DST].name, str_addr);
+ }
+}
+
+
+static int
+compare(const struct ebt_entry_match *match1, const struct ebt_entry_match *match2)
+{
+ struct ebt_plc_info *plcinfo1 =
+ (struct ebt_plc_info *) match1->data;
+ struct ebt_plc_info *plcinfo2 =
+ (struct ebt_plc_info *) match2->data;
+
+ /* Compare bitmaps.*/
+ if (plcinfo1->bitmask != plcinfo2->bitmask)
+ return 0;
+
+ /* Compare source address, if it is relevant and known. */
+ if (GET_PLC_SRC(plcinfo1->bitmask) && !GET_PLC_SRC_UNKNOWN(plcinfo1->bitmask) && memcmp(plcinfo1->src_addr, plcinfo2->src_addr, ETH_ALEN))
+ return 0;
+
+ /* Compare destination address, if it is relevant and known. */
+ if (GET_PLC_DST(plcinfo1->bitmask) && !GET_PLC_DST_UNKNOWN(plcinfo1->bitmask) && memcmp(plcinfo1->dst_addr, plcinfo2->dst_addr, ETH_ALEN))
+ return 0;
+
+ return 1;
+}
+
+static struct ebt_u_match plc_match = {
+ .name = EBT_PLC_MATCH,
+ .size = sizeof(struct ebt_plc_info),
+ .help = print_help,
+ .init = init,
+ .parse = parse,
+ .final_check = final_check,
+ .print = print,
+ .compare = compare,
+ .extra_ops = opts,
+};
+
+void ebt_plc_init(void)
+{
+ register_match(&plc_match);
+}