On Tue, Nov 20, 2007 at 02:14:28PM +0100, Laszlo Attila Toth wrote:
> Interface group values can be checked on both input and output interfaces
> with optional mask.

> Index: extensions/libxt_ifgroup.c
> ===================================================================
> --- extensions/libxt_ifgroup.c        (revision 0)
> +++ extensions/libxt_ifgroup.c        (revision 0)

> +             info->in_group = strtoul(optarg, &end, 0);

This is somewhat inconsistent with the iproute patch which targets
specific groups (with names).
Should iptables be allowed to read "/etc/iproute2/rt_ifgroup"?
There is no standard API like getservbyname()...

I do have a draft patch for physdev which is however against
iptables-1.3.8 and linux-2.6.19 so it will need some more work
but I will attach it for discussion.

(This will leave ebtables to be touched...)

Best regards,
        Lutz
-- 
Dr.-Ing. Lutz Jänicke
CTO
Innominate Security Technologies AG  /protecting industrial networks/
tel: +49.30.6392-3308
fax: +49.30.6392-3307
Albert-Einstein-Str. 14
D-12489 Berlin, Germany
www.innominate.com

Register Court: AG Charlottenburg, HR B 81603
Management Board: Joachim Fietz, Dirk Seewald
Chairman of the Supervisory Board: Edward M. Stadum

----------------------------------------------------------------------------

Visit us at the SPS/IPC/Drives in Nuremberg / Germany

27 - 29 November 2007, Hall 9, Stand 9-141

----------------------------------------------------------------------------
diff -ruN iptables-1.3.8-vanilla/extensions/libipt_physdev.c 
iptables-1.3.8/extensions/libipt_physdev.c
--- iptables-1.3.8-vanilla/extensions/libipt_physdev.c  2007-01-23 
13:50:00.000000000 +0100
+++ iptables-1.3.8/extensions/libipt_physdev.c  2007-11-01 16:57:58.000000000 
+0100
@@ -19,6 +19,8 @@
 "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"
+" --physgroup-in [!] input group               bridge port group value\n"
+" --physgroup-out [!] output group     bridge port group value\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"
@@ -31,6 +33,8 @@
        { "physdev-is-in", 0, 0, '3' },
        { "physdev-is-out", 0, 0, '4' },
        { "physdev-is-bridged", 0, 0, '5' },
+       { "physgroup-in", 1, 0, '6' },
+       { "physgroup-out", 1, 0, '7' },
        {0}
 };
 
@@ -47,6 +51,7 @@
 {
        struct ipt_physdev_info *info =
                (struct ipt_physdev_info*)(*match)->data;
+       char *end;
 
        switch (c) {
        case '1':
@@ -103,6 +108,44 @@
                info->bitmask |= IPT_PHYSDEV_OP_BRIDGED;
                break;
 
+       case '6':
+               if (*flags & IPT_PHYSDEV_OP_GROUPIN)
+                       goto multiple_use;
+               check_inverse(argv[optind-1], &invert, &optind, 0);
+               end = optarg = argv[optind-1];
+               info->ingroup = strtoul(optarg, &end, 0);
+               info->ingroupmask = 0xffffffffUL;
+               if (*end == '/')
+                       info->ingroupmask = strtoul(end+1, &end, 0);
+               if (*end != '\0' || end == optarg)
+                       exit_error(PARAMETER_PROBLEM,
+                               "physdev match: Bad ifgroup value `%s'",
+                               optarg);
+               if (invert)
+                       info->invert |= IPT_PHYSDEV_OP_GROUPIN;
+               *flags |= IPT_PHYSDEV_OP_GROUPIN;
+               info->bitmask |= IPT_PHYSDEV_OP_GROUPIN;
+               break;
+
+       case '7':
+               if (*flags & IPT_PHYSDEV_OP_GROUPOUT)
+                       goto multiple_use;
+               check_inverse(argv[optind-1], &invert, &optind, 0);
+               end = optarg = argv[optind-1];
+               info->outgroup = strtoul(optarg, &end, 0);
+               info->outgroupmask = 0xffffffffUL;
+               if (*end == '/')
+                       info->outgroupmask = strtoul(end+1, &end, 0);
+               if (*end != '\0' || end == optarg)
+                       exit_error(PARAMETER_PROBLEM,
+                               "physdev match: Bad ifgroup value `%s'",
+                               optarg);
+               if (invert)
+                       info->invert |= IPT_PHYSDEV_OP_GROUPOUT;
+               *flags |= IPT_PHYSDEV_OP_GROUPOUT;
+               info->bitmask |= IPT_PHYSDEV_OP_GROUPOUT;
+               break;
+
        default:
                return 0;
        }
@@ -145,6 +186,13 @@
        if (info->bitmask & IPT_PHYSDEV_OP_BRIDGED)
                printf("%s --physdev-is-bridged",
                       info->invert & IPT_PHYSDEV_OP_BRIDGED ? " !":"");
+
+       if (info->bitmask & IPT_PHYSDEV_OP_GROUPIN)
+               printf("%s --physgroup-in 0x%x/0x%x",
+               (info->invert & IPT_PHYSDEV_OP_GROUPIN) ? " !":"", 
info->ingroup, info->ingroupmask);
+       if (info->bitmask & IPT_PHYSDEV_OP_GROUPOUT)
+               printf("%s --physgroup-out 0x%x/0x%x",
+               (info->invert & IPT_PHYSDEV_OP_GROUPOUT) ? " !":"", 
info->outgroup, info->outgroupmask);
        printf(" ");
 }
 
diff -ruN iptables-1.3.8-vanilla/include/linux/netfilter_ipv4/ipt_physdev.h 
iptables-1.3.8/include/linux/netfilter_ipv4/ipt_physdev.h
--- iptables-1.3.8-vanilla/include/linux/netfilter_ipv4/ipt_physdev.h   
2007-01-23 13:49:51.000000000 +0100
+++ iptables-1.3.8/include/linux/netfilter_ipv4/ipt_physdev.h   2007-11-01 
16:15:38.000000000 +0100
@@ -10,13 +10,19 @@
 #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)
+#define IPT_PHYSDEV_OP_GROUPIN         0x20
+#define IPT_PHYSDEV_OP_GROUPOUT                0x40
+#define IPT_PHYSDEV_OP_MASK            (0x80 - 1)
 
 struct ipt_physdev_info {
        char physindev[IFNAMSIZ];
        char in_mask[IFNAMSIZ];
        char physoutdev[IFNAMSIZ];
        char out_mask[IFNAMSIZ];
+       u_int32_t ingroup;
+       u_int32_t ingroupmask;
+       u_int32_t outgroup;
+       u_int32_t outgroupmask;
        u_int8_t invert;
        u_int8_t bitmask;
 };
diff -ruN iptables-1.3.8-vanilla/include/linux/netfilter_ipv6/ip6t_physdev.h 
iptables-1.3.8/include/linux/netfilter_ipv6/ip6t_physdev.h
--- iptables-1.3.8-vanilla/include/linux/netfilter_ipv6/ip6t_physdev.h  
2007-01-23 13:49:51.000000000 +0100
+++ iptables-1.3.8/include/linux/netfilter_ipv6/ip6t_physdev.h  2007-11-01 
16:15:21.000000000 +0100
@@ -10,13 +10,19 @@
 #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)
+#define IP6T_PHYSDEV_OP_GROUPIN                0x20
+#define IP6T_PHYSDEV_OP_GROUPOUT       0x40
+#define IP6T_PHYSDEV_OP_MASK           (0x80 - 1)
 
 struct ip6t_physdev_info {
        char physindev[IFNAMSIZ];
        char in_mask[IFNAMSIZ];
        char physoutdev[IFNAMSIZ];
        char out_mask[IFNAMSIZ];
+       u_int32_t ingroup;
+       u_int32_t ingroupmask;
+       u_int32_t outgroup;
+       u_int32_t outgroupmask;
        u_int8_t invert;
        u_int8_t bitmask;
 };
diff --git a/net/netfilter/xt_physdev.c b/net/netfilter/xt_physdev.c
index fbcc7ce..75cdc51 100644
--- a/net/netfilter/xt_physdev.c
+++ b/net/netfilter/xt_physdev.c
@@ -23,6 +23,23 @@ MODULE_DESCRIPTION("iptables bridge physical device match 
module");
 MODULE_ALIAS("ipt_physdev");
 MODULE_ALIAS("ip6t_physdev");
 
+static inline bool
+ifgroup_match_in(u_int32_t ingroup, 
+                const struct xt_physdev_info *info)
+{
+
+       return ((ingroup & info->ingroupmask) == info->ingroup) ^ 
+               ((info->invert & XT_PHYSDEV_OP_GROUPIN) == 
XT_PHYSDEV_OP_GROUPIN);
+}
+
+static inline bool
+ifgroup_match_out(u_int32_t outgroup,
+                const struct xt_physdev_info *info)
+{
+       return ((outgroup & info->outgroupmask) == info->outgroup) ^ 
+               ((info->invert & XT_PHYSDEV_OP_GROUPOUT) == 
XT_PHYSDEV_OP_GROUPOUT);
+}
+
 static int
 match(const struct sk_buff *skb,
       const struct net_device *in,
@@ -38,6 +55,7 @@ match(const struct sk_buff *skb,
        const struct xt_physdev_info *info = matchinfo;
        unsigned int ret;
        const char *indev, *outdev;
+       u_int32_t ingroup, outgroup;
        struct nf_bridge_info *nf_bridge;
 
        /* Not a bridged IP packet or no info available yet:
@@ -60,6 +78,12 @@ match(const struct sk_buff *skb,
                if ((info->bitmask & XT_PHYSDEV_OP_OUT) &&
                    !(info->invert & XT_PHYSDEV_OP_OUT))
                        return NOMATCH;
+               if ((info->bitmask & XT_PHYSDEV_OP_GROUPIN) &&
+                   !(info->invert & XT_PHYSDEV_OP_GROUPIN))
+                       return NOMATCH;
+               if ((info->bitmask & XT_PHYSDEV_OP_GROUPOUT) &&
+                   !(info->invert & XT_PHYSDEV_OP_GROUPOUT))
+                       return NOMATCH;
                return MATCH;
        }
 
@@ -75,6 +99,18 @@ match(const struct sk_buff *skb,
            (!nf_bridge->physoutdev ^ !!(info->invert & XT_PHYSDEV_OP_ISOUT))))
                return NOMATCH;
 
+       if (info->bitmask & XT_PHYSDEV_OP_GROUPIN) {
+               ingroup = nf_bridge->physindev ? nf_bridge->physindev->ifgroup 
: -1;
+               if (!ifgroup_match_in(ingroup, info))
+                       return NOMATCH;
+       }
+
+       if (info->bitmask & XT_PHYSDEV_OP_GROUPOUT) {
+               outgroup = nf_bridge->physoutdev ? 
nf_bridge->physoutdev->ifgroup : -1;
+               if (!ifgroup_match_out(outgroup, info))
+                       return NOMATCH;
+       }
+
        if (!(info->bitmask & XT_PHYSDEV_OP_IN))
                goto match_outdev;
        indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
@@ -114,6 +150,7 @@ checkentry(const char *tablename,
            info->bitmask & ~XT_PHYSDEV_OP_MASK)
                return 0;
        if (brnf_deferred_hooks == 0 &&
+           info->bitmask & XT_PHYSDEV_OP_GROUPOUT &&
            info->bitmask & XT_PHYSDEV_OP_OUT &&
            (!(info->bitmask & XT_PHYSDEV_OP_BRIDGED) ||
             info->invert & XT_PHYSDEV_OP_BRIDGED) &&

Reply via email to