summaryrefslogtreecommitdiffstats
path: root/extensions
diff options
context:
space:
mode:
authorBart De Schuymer <bdschuym@pandora.be>2003-02-11 20:19:04 +0000
committerHarald Welte <laforge@gnumonks.org>2003-02-11 20:19:04 +0000
commit1254871c88483cc1a0adc448a83cab6a9d4510a1 (patch)
treef1d643f260f98ba609bf344e6f70118ec46d4d0a /extensions
parent31ad6a249f3ead10e5d4111498f8022eb1169e19 (diff)
add libipt_physdev.c (Bart de Schumyer)
Diffstat (limited to 'extensions')
-rw-r--r--extensions/Makefile2
-rw-r--r--extensions/libipt_physdev.c182
2 files changed, 183 insertions, 1 deletions
diff --git a/extensions/Makefile b/extensions/Makefile
index 5d0d844e..2513b8b6 100644
--- a/extensions/Makefile
+++ b/extensions/Makefile
@@ -5,7 +5,7 @@
# header files are present in the include/linux directory of this iptables
# package (HW)
#
-PF_EXT_SLIB:=ah conntrack dscp ecn esp helper icmp iplimit length limit mac mark multiport owner pkttype rpc standard state tcp tcpmss tos ttl udp unclean DNAT DSCP ECN LOG MARK MASQUERADE MIRROR REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TTL ULOG
+PF_EXT_SLIB:=ah conntrack dscp ecn esp helper icmp iplimit length limit mac mark multiport owner physdev pkttype rpc standard state tcp tcpmss tos ttl udp unclean DNAT DSCP ECN LOG MARK MASQUERADE MIRROR REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TTL ULOG
PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner standard tcp udp HL LOG MARK
# Optionals
diff --git a/extensions/libipt_physdev.c b/extensions/libipt_physdev.c
new file mode 100644
index 00000000..30fcce92
--- /dev/null
+++ b/extensions/libipt_physdev.c
@@ -0,0 +1,182 @@
+/* Shared library add-on to iptables to add bridge port matching support. */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <ctype.h>
+#include <iptables.h>
+#include <linux/netfilter_ipv4/ipt_physdev.h>
+#if defined(__GLIBC__) && __GLIBC__ == 2
+#include <net/ethernet.h>
+#else
+#include <linux/if_ether.h>
+#endif
+
+static void
+help(void)
+{
+ printf(
+"physdev v%s options:\n"
+" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\n"
+" --physdev-out [!] output name[+] bridge port name ([+] for wildcard)\n"
+"\n", IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ { "physdev-in", 1, 0, '1' },
+ { "physdev-out", 1, 0, '2' },
+ {0}
+};
+
+/* copied from iptables.c */
+static void
+parse_interface(const char *arg, char *vianame, unsigned char *mask)
+{
+ int vialen = strlen(arg);
+ unsigned int i;
+
+ memset(mask, 0, IFNAMSIZ);
+ memset(vianame, 0, IFNAMSIZ);
+
+ if (vialen + 1 > IFNAMSIZ)
+ exit_error(PARAMETER_PROBLEM,
+ "interface name `%s' must be shorter than IFNAMSIZ"
+ " (%i)", arg, IFNAMSIZ-1);
+
+ strcpy(vianame, arg);
+ if (vialen == 0)
+ memset(mask, 0, IFNAMSIZ);
+ else if (vianame[vialen - 1] == '+') {
+ memset(mask, 0xFF, vialen - 1);
+ memset(mask + vialen - 1, 0, IFNAMSIZ - vialen + 1);
+ /* Don't remove `+' here! -HW */
+ } else {
+ /* Include nul-terminator in match */
+ memset(mask, 0xFF, vialen + 1);
+ memset(mask + vialen + 1, 0, IFNAMSIZ - vialen - 1);
+ for (i = 0; vianame[i]; i++) {
+ if (!isalnum(vianame[i])
+ && vianame[i] != '_'
+ && vianame[i] != '.') {
+ printf("Warning: wierd character in interface"
+ " `%s' (No aliases, :, ! or *).\n",
+ vianame);
+ break;
+ }
+ }
+ }
+}
+
+static void
+init(struct ipt_entry_match *m, unsigned int *nfcache)
+{
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ipt_entry *entry,
+ unsigned int *nfcache,
+ struct ipt_entry_match **match)
+{
+ struct ipt_physdev_info *info =
+ (struct ipt_physdev_info*)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & IPT_PHYSDEV_OP_MATCH_IN)
+ exit_error(PARAMETER_PROBLEM,
+ "multiple --physdev-in not allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_interface(argv[optind-1], info->physindev, info->in_mask);
+ if (invert)
+ info->invert |= IPT_PHYSDEV_OP_MATCH_IN;
+ *flags |= IPT_PHYSDEV_OP_MATCH_IN;
+ break;
+
+ case '2':
+ if (*flags & IPT_PHYSDEV_OP_MATCH_OUT)
+ exit_error(PARAMETER_PROBLEM,
+ "multiple --physdev-out not allowed");
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_interface(argv[optind-1], info->physoutdev,
+ info->out_mask);
+ if (invert)
+ info->invert |= IPT_PHYSDEV_OP_MATCH_OUT;
+ *flags |= IPT_PHYSDEV_OP_MATCH_OUT;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+}
+
+static void final_check(unsigned int flags)
+{
+}
+
+static void print_iface(u_int8_t invert, char *dev, char *prefix)
+{
+ char iface[IFNAMSIZ+2];
+
+ if (invert) {
+ iface[0] = '!';
+ iface[1] = '\0';
+ } else
+ iface[0] = '\0';
+
+ if (dev[0] != '\0') {
+ strcat(iface, dev);
+ printf("%s%s", prefix, iface);
+ }
+}
+
+static void
+print(const struct ipt_ip *ip,
+ const struct ipt_entry_match *match,
+ int numeric)
+{
+ struct ipt_physdev_info *info =
+ (struct ipt_physdev_info*)match->data;
+
+ printf("PHYSDEV match");
+ print_iface(info->invert & IPT_PHYSDEV_OP_MATCH_IN, info->physindev,
+ " physindev=");
+ print_iface(info->invert & IPT_PHYSDEV_OP_MATCH_OUT, info->physoutdev,
+ " physoutdev=");
+ printf(" ");
+}
+
+static void save(const struct ipt_ip *ip, const struct ipt_entry_match *match)
+{
+ struct ipt_physdev_info *info =
+ (struct ipt_physdev_info*)match->data;
+
+ print_iface(info->invert & IPT_PHYSDEV_OP_MATCH_IN, info->physindev,
+ "--physdev-in ");
+ print_iface(info->invert & IPT_PHYSDEV_OP_MATCH_OUT, info->physoutdev,
+ "--physdev-out ");
+ printf(" ");
+}
+
+static
+struct iptables_match physdev
+= { NULL,
+ "physdev",
+ IPTABLES_VERSION,
+ IPT_ALIGN(sizeof(struct ipt_physdev_info)),
+ IPT_ALIGN(sizeof(struct ipt_physdev_info)),
+ &help,
+ &init,
+ &parse,
+ &final_check,
+ &print,
+ &save,
+ opts
+};
+
+void _init(void)
+{
+ register_match(&physdev);
+}