summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--extensions/libipt_physdev.c120
-rw-r--r--include/linux/netfilter_ipv4/ipt_physdev.h9
-rw-r--r--iptables.820
3 files changed, 108 insertions, 41 deletions
diff --git a/extensions/libipt_physdev.c b/extensions/libipt_physdev.c
index 30fcce92..9149d903 100644
--- a/extensions/libipt_physdev.c
+++ b/extensions/libipt_physdev.c
@@ -17,14 +17,20 @@ help(void)
{
printf(
"physdev v%s options:\n"
-" --physdev-in [!] input name[+] bridge port name ([+] for wildcard)\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}
};
@@ -83,26 +89,56 @@ parse(int c, char **argv, int invert, unsigned int *flags,
switch (c) {
case '1':
- if (*flags & IPT_PHYSDEV_OP_MATCH_IN)
- exit_error(PARAMETER_PROBLEM,
- "multiple --physdev-in not allowed");
+ if (*flags & IPT_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 |= IPT_PHYSDEV_OP_MATCH_IN;
- *flags |= IPT_PHYSDEV_OP_MATCH_IN;
+ info->invert |= IPT_PHYSDEV_OP_IN;
+ info->bitmask |= IPT_PHYSDEV_OP_IN;
+ *flags |= IPT_PHYSDEV_OP_IN;
break;
case '2':
- if (*flags & IPT_PHYSDEV_OP_MATCH_OUT)
- exit_error(PARAMETER_PROBLEM,
- "multiple --physdev-out not allowed");
+ if (*flags & IPT_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 |= IPT_PHYSDEV_OP_MATCH_OUT;
- *flags |= IPT_PHYSDEV_OP_MATCH_OUT;
+ info->invert |= IPT_PHYSDEV_OP_OUT;
+ info->bitmask |= IPT_PHYSDEV_OP_OUT;
+ *flags |= IPT_PHYSDEV_OP_OUT;
+ break;
+
+ case '3':
+ if (*flags & IPT_PHYSDEV_OP_ISIN)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ info->bitmask |= IPT_PHYSDEV_OP_ISIN;
+ if (invert)
+ info->invert |= IPT_PHYSDEV_OP_ISIN;
+ *flags |= IPT_PHYSDEV_OP_ISIN;
+ break;
+
+ case '4':
+ if (*flags & IPT_PHYSDEV_OP_ISOUT)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ info->bitmask |= IPT_PHYSDEV_OP_ISOUT;
+ if (invert)
+ info->invert |= IPT_PHYSDEV_OP_ISOUT;
+ *flags |= IPT_PHYSDEV_OP_ISOUT;
+ break;
+
+ case '5':
+ if (*flags & IPT_PHYSDEV_OP_BRIDGED)
+ goto multiple_use;
+ check_inverse(optarg, &invert, &optind, 0);
+ if (invert)
+ info->invert |= IPT_PHYSDEV_OP_BRIDGED;
+ *flags |= IPT_PHYSDEV_OP_BRIDGED;
+ info->bitmask |= IPT_PHYSDEV_OP_BRIDGED;
break;
default:
@@ -110,26 +146,16 @@ parse(int c, char **argv, int invert, unsigned int *flags,
}
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)
-{
}
-static void print_iface(u_int8_t invert, char *dev, char *prefix)
+static void final_check(unsigned int flags)
{
- 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);
- }
+ if (flags == 0)
+ exit_error(PARAMETER_PROBLEM, "PHYSDEV: no physdev option specified");
}
static void
@@ -141,10 +167,22 @@ print(const struct ipt_ip *ip,
(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=");
+ if (info->bitmask & IPT_PHYSDEV_OP_ISIN)
+ printf("%s --physdev-is-in",
+ info->invert & IPT_PHYSDEV_OP_ISIN ? " !":"");
+ if (info->bitmask & IPT_PHYSDEV_OP_IN)
+ printf("%s --physdev-in %s",
+ (info->invert & IPT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
+
+ if (info->bitmask & IPT_PHYSDEV_OP_ISOUT)
+ printf("%s --physdev-is-out",
+ info->invert & IPT_PHYSDEV_OP_ISOUT ? " !":"");
+ if (info->bitmask & IPT_PHYSDEV_OP_OUT)
+ printf("%s --physdev-out %s",
+ (info->invert & IPT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
+ if (info->bitmask & IPT_PHYSDEV_OP_BRIDGED)
+ printf("%s --physdev-is-bridged",
+ info->invert & IPT_PHYSDEV_OP_BRIDGED ? " !":"");
printf(" ");
}
@@ -153,10 +191,22 @@ 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 ");
+ if (info->bitmask & IPT_PHYSDEV_OP_ISIN)
+ printf("%s --physdev-is-in",
+ info->invert & IPT_PHYSDEV_OP_ISIN ? " !":"");
+ if (info->bitmask & IPT_PHYSDEV_OP_IN)
+ printf("%s --physdev-in %s",
+ (info->invert & IPT_PHYSDEV_OP_IN) ? " !":"", info->physindev);
+
+ if (info->bitmask & IPT_PHYSDEV_OP_ISOUT)
+ printf("%s --physdev-is-out",
+ info->invert & IPT_PHYSDEV_OP_ISOUT ? " !":"");
+ if (info->bitmask & IPT_PHYSDEV_OP_OUT)
+ printf("%s --physdev-out %s",
+ (info->invert & IPT_PHYSDEV_OP_OUT) ? " !":"", info->physoutdev);
+ if (info->bitmask & IPT_PHYSDEV_OP_BRIDGED)
+ printf("%s --physdev-is-bridged",
+ info->invert & IPT_PHYSDEV_OP_BRIDGED ? " !":"");
printf(" ");
}
diff --git a/include/linux/netfilter_ipv4/ipt_physdev.h b/include/linux/netfilter_ipv4/ipt_physdev.h
index 668e1a9f..01684a12 100644
--- a/include/linux/netfilter_ipv4/ipt_physdev.h
+++ b/include/linux/netfilter_ipv4/ipt_physdev.h
@@ -5,11 +5,16 @@
#include <linux/if.h>
#endif
-#define IPT_PHYSDEV_OP_MATCH_IN 0x01
-#define IPT_PHYSDEV_OP_MATCH_OUT 0x02
+#define IPT_PHYSDEV_OP_IN 0x01
+#define IPT_PHYSDEV_OP_OUT 0x02
+#define IPT_PHYSDEV_OP_BRIDGED 0x04
+#define IPT_PHYSDEV_OP_ISIN 0x08
+#define IPT_PHYSDEV_OP_ISOUT 0x10
+#define IPT_PHYSDEV_OP_MASK (0x20 - 1)
struct ipt_physdev_info {
u_int8_t invert;
+ u_int8_t bitmask;
char physindev[IFNAMSIZ];
char in_mask[IFNAMSIZ];
char physoutdev[IFNAMSIZ];
diff --git a/iptables.8 b/iptables.8
index c1039fb0..df5951aa 100644
--- a/iptables.8
+++ b/iptables.8
@@ -557,8 +557,7 @@ Matches if the packet was created by a process with the given command name.
supporting this feature)
.SS physdev
This module matches on the bridge port input and output devices enslaved
-to a bridge device. This is only useful if the input device or output device
-is a bridge device. This module is a part of the infrastructure that enables
+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
@@ -570,7 +569,8 @@ packets entering the
and
.B PREROUTING
chains). If the interface name ends in a "+", then any
-interface which begins with this name will match.
+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
@@ -585,7 +585,19 @@ interface which begins with this name will match. Note that in the
.B OUTPUT
chains one cannot match on the bridge output port, however one can in the
.B "filter OUTPUT"
-chain.
+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.
.SS pkttype
This module matches the link-layer packet type.
.TP