* [PATCH] port physdev to ip6tables
@ 2004-09-11 10:59 Bart De Schuymer
2004-09-12 23:17 ` Patrick McHardy
0 siblings, 1 reply; 2+ messages in thread
From: Bart De Schuymer @ 2004-09-11 10:59 UTC (permalink / raw)
To: netfilter-devel
[-- Attachment #1: Type: text/plain, Size: 252 bytes --]
Hi,
Attached are 2 patches, one against kernel 2.6.8.1 and the other against the
iptables userspace CVS. They add the physdev module to ip6tables. The physdev
module is quite essential for people wanting to filter bridged IPv6 frames.
cheers,
Bart
[-- Attachment #2: physdevipv6kernel.diff --]
[-- Type: text/x-diff, Size: 6501 bytes --]
--- linux-2.6.8.1/net/ipv6/netfilter/Makefile.old 2004-09-11 12:31:12.000000000 +0200
+++ linux-2.6.8.1/net/ipv6/netfilter/Makefile 2004-09-11 12:34:30.000000000 +0200
@@ -16,6 +16,7 @@ obj-$(CONFIG_IP6_NF_MATCH_AHESP) += ip6t
obj-$(CONFIG_IP6_NF_MATCH_EUI64) += ip6t_eui64.o
obj-$(CONFIG_IP6_NF_MATCH_MULTIPORT) += ip6t_multiport.o
obj-$(CONFIG_IP6_NF_MATCH_OWNER) += ip6t_owner.o
+obj-$(CONFIG_IP6_NF_MATCH_PHYSDEV) += ip6t_physdev.o
obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
obj-$(CONFIG_IP6_NF_TARGET_MARK) += ip6t_MARK.o
--- linux-2.6.8.1/net/ipv6/netfilter/Kconfig.old 2004-09-11 12:24:02.000000000 +0200
+++ linux-2.6.8.1/net/ipv6/netfilter/Kconfig 2004-09-11 12:36:30.000000000 +0200
@@ -158,6 +158,15 @@ config IP6_NF_MATCH_EUI64
To compile it as a module, choose M here. If unsure, say N.
+config IP6_NF_MATCH_PHYSDEV
+ tristate "Physdev match support"
+ depends on IP6_NF_IPTABLES && BRIDGE_NETFILTER
+ help
+ Physdev packet matching matches against the physical bridge ports
+ the IP packet arrived on or will leave by.
+
+ To compile it as a module, choose M here. If unsure, say N.
+
# dep_tristate ' Multiple port match support' CONFIG_IP6_NF_MATCH_MULTIPORT $CONFIG_IP6_NF_IPTABLES
# dep_tristate ' TOS match support' CONFIG_IP6_NF_MATCH_TOS $CONFIG_IP6_NF_IPTABLES
# if [ "$CONFIG_IP6_NF_CONNTRACK" != "n" ]; then
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8.1/net/ipv6/netfilter/ip6t_physdev.c 2004-09-11 12:40:41.000000000 +0200
@@ -0,0 +1,136 @@
+/* Kernel module to match the bridge port in and
+ * out device for IP packets coming into contact with a bridge. */
+
+/* (C) 2001-2003 Bart De Schuymer <bdschuym@pandora.be>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/netfilter_ipv6/ip6t_physdev.h>
+#include <linux/netfilter_ipv6/ip6_tables.h>
+#include <linux/netfilter_bridge.h>
+#define MATCH 1
+#define NOMATCH 0
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
+MODULE_DESCRIPTION("iptables bridge physical device match module");
+
+static int
+match(const struct sk_buff *skb,
+ const struct net_device *in,
+ const struct net_device *out,
+ const void *matchinfo,
+ int offset,
+ const void *hdr,
+ u_int16_t datalen,
+ int *hotdrop)
+{
+ int i;
+ static const char nulldevname[IFNAMSIZ];
+ const struct ip6t_physdev_info *info = matchinfo;
+ unsigned int ret;
+ const char *indev, *outdev;
+ struct nf_bridge_info *nf_bridge;
+
+ /* Not a bridged IP packet or no info available yet:
+ * LOCAL_OUT/mangle and LOCAL_OUT/nat don't know if
+ * the destination device will be a bridge. */
+ if (!(nf_bridge = skb->nf_bridge)) {
+ /* Return MATCH if the invert flags of the used options are on */
+ if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+ !(info->invert & IP6T_PHYSDEV_OP_BRIDGED))
+ return NOMATCH;
+ if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN) &&
+ !(info->invert & IP6T_PHYSDEV_OP_ISIN))
+ return NOMATCH;
+ if ((info->bitmask & IP6T_PHYSDEV_OP_ISOUT) &&
+ !(info->invert & IP6T_PHYSDEV_OP_ISOUT))
+ return NOMATCH;
+ if ((info->bitmask & IP6T_PHYSDEV_OP_IN) &&
+ !(info->invert & IP6T_PHYSDEV_OP_IN))
+ return NOMATCH;
+ if ((info->bitmask & IP6T_PHYSDEV_OP_OUT) &&
+ !(info->invert & IP6T_PHYSDEV_OP_OUT))
+ return NOMATCH;
+ return MATCH;
+ }
+
+ /* This only makes sense in the FORWARD and POSTROUTING chains */
+ if ((info->bitmask & IP6T_PHYSDEV_OP_BRIDGED) &&
+ (!!(nf_bridge->mask & BRNF_BRIDGED) ^
+ !(info->invert & IP6T_PHYSDEV_OP_BRIDGED)))
+ return NOMATCH;
+
+ if ((info->bitmask & IP6T_PHYSDEV_OP_ISIN &&
+ (!nf_bridge->physindev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISIN))) ||
+ (info->bitmask & IP6T_PHYSDEV_OP_ISOUT &&
+ (!nf_bridge->physoutdev ^ !!(info->invert & IP6T_PHYSDEV_OP_ISOUT))))
+ return NOMATCH;
+
+ if (!(info->bitmask & IP6T_PHYSDEV_OP_IN))
+ goto match_outdev;
+ indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
+ for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+ ret |= (((const unsigned int *)indev)[i]
+ ^ ((const unsigned int *)info->physindev)[i])
+ & ((const unsigned int *)info->in_mask)[i];
+ }
+
+ if ((ret == 0) ^ !(info->invert & IP6T_PHYSDEV_OP_IN))
+ return NOMATCH;
+
+match_outdev:
+ if (!(info->bitmask & IP6T_PHYSDEV_OP_OUT))
+ return MATCH;
+ outdev = nf_bridge->physoutdev ?
+ nf_bridge->physoutdev->name : nulldevname;
+ for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned int); i++) {
+ ret |= (((const unsigned int *)outdev)[i]
+ ^ ((const unsigned int *)info->physoutdev)[i])
+ & ((const unsigned int *)info->out_mask)[i];
+ }
+
+ return (ret != 0) ^ !(info->invert & IP6T_PHYSDEV_OP_OUT);
+}
+
+static int
+checkentry(const char *tablename,
+ const struct ip6t_ip6 *ip,
+ void *matchinfo,
+ unsigned int matchsize,
+ unsigned int hook_mask)
+{
+ const struct ip6t_physdev_info *info = matchinfo;
+
+ if (matchsize != IP6T_ALIGN(sizeof(struct ip6t_physdev_info)))
+ return 0;
+ if (!(info->bitmask & IP6T_PHYSDEV_OP_MASK) ||
+ info->bitmask & ~IP6T_PHYSDEV_OP_MASK)
+ return 0;
+ return 1;
+}
+
+static struct ip6t_match physdev_match = {
+ .name = "physdev",
+ .match = &match,
+ .checkentry = &checkentry,
+ .me = THIS_MODULE,
+};
+
+static int __init init(void)
+{
+ return ip6t_register_match(&physdev_match);
+}
+
+static void __exit fini(void)
+{
+ ip6t_unregister_match(&physdev_match);
+}
+
+module_init(init);
+module_exit(fini);
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ linux-2.6.8.1/include/linux/netfilter_ipv6/ip6t_physdev.h 2004-09-11 12:31:01.000000000 +0200
@@ -0,0 +1,24 @@
+#ifndef _IP6T_PHYSDEV_H
+#define _IP6T_PHYSDEV_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+
+#define IP6T_PHYSDEV_OP_IN 0x01
+#define IP6T_PHYSDEV_OP_OUT 0x02
+#define IP6T_PHYSDEV_OP_BRIDGED 0x04
+#define IP6T_PHYSDEV_OP_ISIN 0x08
+#define IP6T_PHYSDEV_OP_ISOUT 0x10
+#define IP6T_PHYSDEV_OP_MASK (0x20 - 1)
+
+struct ip6t_physdev_info {
+ char physindev[IFNAMSIZ];
+ char in_mask[IFNAMSIZ];
+ char physoutdev[IFNAMSIZ];
+ char out_mask[IFNAMSIZ];
+ u_int8_t invert;
+ u_int8_t bitmask;
+};
+
+#endif /*_IP6T_PHYSDEV_H*/
[-- Attachment #3: physdevipv6user.diff --]
[-- Type: text/x-diff, Size: 9760 bytes --]
--- iptables/extensions/Makefile.old 2004-09-09 23:52:37.000000000 +0200
+++ iptables/extensions/Makefile 2004-09-09 23:52:50.000000000 +0200
@@ -6,7 +6,7 @@
# package (HW)
#
PF_EXT_SLIB:=ah addrtype connlimit connmark conntrack dscp ecn esp helper icmp iprange length limit mac mark multiport owner physdev pkttype realm rpc sctp standard state tcp tcpmss tos ttl udp unclean CLASSIFY CONNMARK DNAT DSCP ECN LOG MARK MASQUERADE MIRROR NETMAP NOTRACK REDIRECT REJECT SAME SNAT TARPIT TCPMSS TOS TRACE TTL ULOG
-PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner standard tcp udp HL LOG MARK TRACE
+PF6_EXT_SLIB:=eui64 hl icmpv6 length limit mac mark multiport owner physdev standard tcp udp HL LOG MARK TRACE
# Optionals
PF_EXT_SLIB_OPTS:=$(foreach T,$(wildcard extensions/.*-test),$(shell KERNEL_DIR=$(KERNEL_DIR) $(T)))
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ iptables/extensions/libip6t_physdev.c 2004-09-11 12:30:22.000000000 +0200
@@ -0,0 +1,232 @@
+/* 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 <ip6tables.h>
+#include <linux/netfilter_ipv6/ip6t_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"
+" [!] --physdev-is-in arrived on a bridge device\n"
+" [!] --physdev-is-out will leave on a bridge device\n"
+" [!] --physdev-is-bridged it's a bridged packet\n"
+"\n", IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ { "physdev-in", 1, 0, '1' },
+ { "physdev-out", 1, 0, '2' },
+ { "physdev-is-in", 0, 0, '3' },
+ { "physdev-is-out", 0, 0, '4' },
+ { "physdev-is-bridged", 0, 0, '5' },
+ {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 ip6t_entry_match *m, unsigned int *nfcache)
+{
+}
+
+static int
+parse(int c, char **argv, int invert, unsigned int *flags,
+ const struct ip6t_entry *entry,
+ unsigned int *nfcache,
+ struct ip6t_entry_match **match)
+{
+ struct ip6t_physdev_info *info =
+ (struct ip6t_physdev_info*)(*match)->data;
+
+ switch (c) {
+ case '1':
+ if (*flags & IP6T_PHYSDEV_OP_IN)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_interface(argv[optind-1], info->physindev, info->in_mask);
+ if (invert)
+ info->invert |= IP6T_PHYSDEV_OP_IN;
+ info->bitmask |= IP6T_PHYSDEV_OP_IN;
+ *flags |= IP6T_PHYSDEV_OP_IN;
+ break;
+
+ case '2':
+ if (*flags & IP6T_PHYSDEV_OP_OUT)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ parse_interface(argv[optind-1], info->physoutdev,
+ info->out_mask);
+ if (invert)
+ info->invert |= IP6T_PHYSDEV_OP_OUT;
+ info->bitmask |= IP6T_PHYSDEV_OP_OUT;
+ *flags |= IP6T_PHYSDEV_OP_OUT;
+ break;
+
+ case '3':
+ if (*flags & IP6T_PHYSDEV_OP_ISIN)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ info->bitmask |= IP6T_PHYSDEV_OP_ISIN;
+ if (invert)
+ info->invert |= IP6T_PHYSDEV_OP_ISIN;
+ *flags |= IP6T_PHYSDEV_OP_ISIN;
+ break;
+
+ case '4':
+ if (*flags & IP6T_PHYSDEV_OP_ISOUT)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ info->bitmask |= IP6T_PHYSDEV_OP_ISOUT;
+ if (invert)
+ info->invert |= IP6T_PHYSDEV_OP_ISOUT;
+ *flags |= IP6T_PHYSDEV_OP_ISOUT;
+ break;
+
+ case '5':
+ if (*flags & IP6T_PHYSDEV_OP_BRIDGED)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ if (invert)
+ info->invert |= IP6T_PHYSDEV_OP_BRIDGED;
+ *flags |= IP6T_PHYSDEV_OP_BRIDGED;
+ info->bitmask |= IP6T_PHYSDEV_OP_BRIDGED;
+ break;
+
+ default:
+ return 0;
+ }
+
+ return 1;
+multiple_use:
+ exit_error(PARAMETER_PROBLEM,
+ "multiple use of the same physdev option is not allowed");
+
+}
+
+static void final_check(unsigned int flags)
+{
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
+}
+
+static void
+print(const struct ip6t_ip6 *ip,
+ const struct ip6t_entry_match *match,
+ int numeric)
+{
+ struct ip6t_physdev_info *info =
+ (struct ip6t_physdev_info*)match->data;
+
+ printf("PHYSDEV match");
+ if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
+ printf("%s --physdev-is-in",
+ info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
+ if (info->bitmask & IP6T_PHYSDEV_OP_IN)
+ printf("%s --physdev-in %s",
+ (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
+
+ if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
+ printf("%s --physdev-is-out",
+ info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
+ if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
+ printf("%s --physdev-out %s",
+ (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
+ if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
+ printf("%s --physdev-is-bridged",
+ info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
+ printf(" ");
+}
+
+static void save(const struct ip6t_ip6 *ip, const struct ip6t_entry_match *match)
+{
+ struct ip6t_physdev_info *info =
+ (struct ip6t_physdev_info*)match->data;
+
+ if (info->bitmask & IP6T_PHYSDEV_OP_ISIN)
+ printf("%s --physdev-is-in",
+ info->invert & IP6T_PHYSDEV_OP_ISIN ? " !":"");
+ if (info->bitmask & IP6T_PHYSDEV_OP_IN)
+ printf("%s --physdev-in %s",
+ (info->invert & IP6T_PHYSDEV_OP_IN) ? " !":"", info->physindev);
+
+ if (info->bitmask & IP6T_PHYSDEV_OP_ISOUT)
+ printf("%s --physdev-is-out",
+ info->invert & IP6T_PHYSDEV_OP_ISOUT ? " !":"");
+ if (info->bitmask & IP6T_PHYSDEV_OP_OUT)
+ printf("%s --physdev-out %s",
+ (info->invert & IP6T_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
+ if (info->bitmask & IP6T_PHYSDEV_OP_BRIDGED)
+ printf("%s --physdev-is-bridged",
+ info->invert & IP6T_PHYSDEV_OP_BRIDGED ? " !":"");
+ printf(" ");
+}
+
+static
+struct ip6tables_match physdev
+= { NULL,
+ "physdev",
+ IPTABLES_VERSION,
+ IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
+ IP6T_ALIGN(sizeof(struct ip6t_physdev_info)),
+ &help,
+ &init,
+ &parse,
+ &final_check,
+ &print,
+ &save,
+ opts
+};
+
+void _init(void)
+{
+ register_match6(&physdev);
+}
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ iptables/include/linux/netfilter_ipv6/ip6t_physdev.h 2004-09-11 12:44:11.000000000 +0200
@@ -0,0 +1,24 @@
+#ifndef _IP6T_PHYSDEV_H
+#define _IP6T_PHYSDEV_H
+
+#ifdef __KERNEL__
+#include <linux/if.h>
+#endif
+
+#define IP6T_PHYSDEV_OP_IN 0x01
+#define IP6T_PHYSDEV_OP_OUT 0x02
+#define IP6T_PHYSDEV_OP_BRIDGED 0x04
+#define IP6T_PHYSDEV_OP_ISIN 0x08
+#define IP6T_PHYSDEV_OP_ISOUT 0x10
+#define IP6T_PHYSDEV_OP_MASK (0x20 - 1)
+
+struct ip6t_physdev_info {
+ char physindev[IFNAMSIZ];
+ char in_mask[IFNAMSIZ];
+ char physoutdev[IFNAMSIZ];
+ char out_mask[IFNAMSIZ];
+ u_int8_t invert;
+ u_int8_t bitmask;
+};
+
+#endif /*_IP6T_PHYSDEV_H*/
--- /dev/null 1970-01-01 01:00:00.000000000 +0100
+++ iptables/extensions/libip6t_physdev.man 2004-09-09 23:27:20.000000000 +0200
@@ -0,0 +1,42 @@
+This module matches on the bridge port input and output devices enslaved
+to a bridge device. This module is a part of the infrastructure that enables
+a transparent bridging IP firewall and is only useful for kernel versions
+above version 2.5.44.
+.TP
+.B --physdev-in name
+Name of a bridge port via which a packet is received (only for
+packets entering the
+.BR INPUT ,
+.B FORWARD
+and
+.B PREROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. If the packet didn't arrive
+through a bridge device, this packet won't match this option, unless '!' is used.
+.TP
+.B --physdev-out name
+Name of a bridge port via which a packet is going to be sent (for packets
+entering the
+.BR FORWARD ,
+.B OUTPUT
+and
+.B POSTROUTING
+chains). If the interface name ends in a "+", then any
+interface which begins with this name will match. Note that in the
+.BR nat " and " mangle
+.B OUTPUT
+chains one cannot match on the bridge output port, however one can in the
+.B "filter OUTPUT"
+chain. If the packet won't leave by a bridge device or it is yet unknown what
+the output device will be, then the packet won't match this option, unless
+'!' is used.
+.TP
+.B --physdev-is-in
+Matches if the packet has entered through a bridge interface.
+.TP
+.B --physdev-is-out
+Matches if the packet will leave through a bridge interface.
+.TP
+.B --physdev-is-bridged
+Matches if the packet is being bridged and therefore is not being routed.
+This is only useful in the FORWARD and POSTROUTING chains.
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] port physdev to ip6tables
2004-09-11 10:59 [PATCH] port physdev to ip6tables Bart De Schuymer
@ 2004-09-12 23:17 ` Patrick McHardy
0 siblings, 0 replies; 2+ messages in thread
From: Patrick McHardy @ 2004-09-12 23:17 UTC (permalink / raw)
To: Bart De Schuymer; +Cc: netfilter-devel
Bart De Schuymer wrote:
>Hi,
>
>Attached are 2 patches, one against kernel 2.6.8.1 and the other against the
>iptables userspace CVS. They add the physdev module to ip6tables. The physdev
>module is quite essential for people wanting to filter bridged IPv6 frames.
>
Thanks, I've applied the userspace patch and will send the kernel patch
to Dave soon.
Regards
Patrick
>
>cheers,
>Bart
>
>
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2004-09-12 23:17 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-09-11 10:59 [PATCH] port physdev to ip6tables Bart De Schuymer
2004-09-12 23:17 ` Patrick McHardy
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.