ipt_physdev update (--physdev-is-{in,out,bridged}) by Bart de Schuymer
diff --git a/extensions/libipt_physdev.c b/extensions/libipt_physdev.c
index 30fcce9..9149d90 100644
--- a/extensions/libipt_physdev.c
+++ b/extensions/libipt_physdev.c
@@ -17,14 +17,20 @@
{
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 @@
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 @@
}
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)
-{
- 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 @@
(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 @@
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 668e1a9..01684a1 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 c1039fb..df5951a 100644
--- a/iptables.8
+++ b/iptables.8
@@ -557,8 +557,7 @@
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 @@
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 @@
.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