Commit dacfd283 authored by Bart De Schuymer's avatar Bart De Schuymer Committed by David S. Miller

[NETFILTER]: Add ipt_physdev extension.

parent 103ad90e
......@@ -30,6 +30,7 @@
#define BRNF_PKT_TYPE 0x01
#define BRNF_BRIDGED_DNAT 0x02
#define BRNF_DONT_TAKE_PARENT 0x04
#define BRNF_BRIDGED 0x08
enum nf_br_hook_priorities {
NF_BR_PRI_FIRST = INT_MIN,
......
......@@ -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];
......
......@@ -348,6 +348,8 @@ static unsigned int br_nf_forward(unsigned int hook, struct sk_buff **pskb,
if (skb->pkt_type == PACKET_OTHERHOST) {
skb->pkt_type = PACKET_HOST;
nf_bridge->mask |= BRNF_PKT_TYPE;
/* The physdev module checks on this */
nf_bridge->mask |= BRNF_BRIDGED;
}
nf_bridge->physoutdev = skb->dev;
......
......@@ -4,6 +4,9 @@
#include <linux/skbuff.h>
#include <linux/netfilter_ipv4/ipt_physdev.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <linux/netfilter_bridge.h>
#define MATCH 1
#define NOMATCH 0
static int
match(const struct sk_buff *skb,
......@@ -25,29 +28,62 @@ match(const struct sk_buff *skb,
/* 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 1;
if (!(nf_bridge = skb->nf_bridge)) {
/* Return MATCH if the invert flags of the used options are on */
if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
!(info->invert & IPT_PHYSDEV_OP_BRIDGED))
return NOMATCH;
if ((info->bitmask & IPT_PHYSDEV_OP_ISIN) &&
!(info->invert & IPT_PHYSDEV_OP_ISIN))
return NOMATCH;
if ((info->bitmask & IPT_PHYSDEV_OP_ISOUT) &&
!(info->invert & IPT_PHYSDEV_OP_ISOUT))
return NOMATCH;
if ((info->bitmask & IPT_PHYSDEV_OP_IN) &&
!(info->invert & IPT_PHYSDEV_OP_IN))
return NOMATCH;
if ((info->bitmask & IPT_PHYSDEV_OP_OUT) &&
!(info->invert & IPT_PHYSDEV_OP_OUT))
return NOMATCH;
return MATCH;
}
indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
outdev = nf_bridge->physoutdev ?
nf_bridge->physoutdev->name : nulldevname;
/* This only makes sense in the FORWARD and POSTROUTING chains */
if ((info->bitmask & IPT_PHYSDEV_OP_BRIDGED) &&
(!!(nf_bridge->mask & BRNF_BRIDGED) ^
!(info->invert & IPT_PHYSDEV_OP_BRIDGED)))
return NOMATCH;
if ((info->bitmask & IPT_PHYSDEV_OP_ISIN &&
(!nf_bridge->physindev ^ !!(info->invert & IPT_PHYSDEV_OP_ISIN))) ||
(info->bitmask & IPT_PHYSDEV_OP_ISOUT &&
(!nf_bridge->physoutdev ^ !!(info->invert & IPT_PHYSDEV_OP_ISOUT))))
return NOMATCH;
if (!(info->bitmask & IPT_PHYSDEV_OP_IN))
goto match_outdev;
indev = nf_bridge->physindev ? nf_bridge->physindev->name : nulldevname;
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
ret |= (((const unsigned long *)indev)[i]
^ ((const unsigned long *)info->physindev)[i])
& ((const unsigned long *)info->in_mask)[i];
}
if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_MATCH_IN))
return 0;
if ((ret == 0) ^ !(info->invert & IPT_PHYSDEV_OP_IN))
return NOMATCH;
match_outdev:
if (!(info->bitmask & IPT_PHYSDEV_OP_OUT))
return MATCH;
outdev = nf_bridge->physoutdev ?
nf_bridge->physoutdev->name : nulldevname;
for (i = 0, ret = 0; i < IFNAMSIZ/sizeof(unsigned long); i++) {
ret |= (((const unsigned long *)outdev)[i]
^ ((const unsigned long *)info->physoutdev)[i])
& ((const unsigned long *)info->out_mask)[i];
}
return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_MATCH_OUT);
return (ret != 0) ^ !(info->invert & IPT_PHYSDEV_OP_OUT);
}
static int
......@@ -57,9 +93,13 @@ checkentry(const char *tablename,
unsigned int matchsize,
unsigned int hook_mask)
{
const struct ipt_physdev_info *info = matchinfo;
if (matchsize != IPT_ALIGN(sizeof(struct ipt_physdev_info)))
return 0;
if (!(info->bitmask & IPT_PHYSDEV_OP_MASK) ||
info->bitmask & ~IPT_PHYSDEV_OP_MASK)
return 0;
return 1;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment