mirror of
git://git.code.sf.net/p/xtables-addons/xtables-addons
synced 2025-09-07 13:15:12 +02:00
Merge remote branch 'origin/iface'
This commit is contained in:
@@ -7,6 +7,7 @@ HEAD
|
|||||||
--with-xtlibdir is no longer needed for ./configure in most cases
|
--with-xtlibdir is no longer needed for ./configure in most cases
|
||||||
(If I still see a distro using it, I will scold you for not
|
(If I still see a distro using it, I will scold you for not
|
||||||
reading this changelog.)
|
reading this changelog.)
|
||||||
|
- xt_iface: allow matching against incoming/outgoing interface
|
||||||
|
|
||||||
|
|
||||||
v1.30 (October 02 2010)
|
v1.30 (October 02 2010)
|
||||||
|
@@ -17,8 +17,14 @@
|
|||||||
#include "xt_iface.h"
|
#include "xt_iface.h"
|
||||||
#include "compat_user.h"
|
#include "compat_user.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
XT_IFACE_IFACE = 1 << 16,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct option iface_mt_opts[] = {
|
static const struct option iface_mt_opts[] = {
|
||||||
{.name = "iface", .has_arg = true, .val = 'i'},
|
{.name = "iface", .has_arg = true, .val = 'i'},
|
||||||
|
{.name = "dev-in", .has_arg = false, .val = 'I'},
|
||||||
|
{.name = "dev-out", .has_arg = false, .val = 'O'},
|
||||||
{.name = "up", .has_arg = false, .val = 'u'},
|
{.name = "up", .has_arg = false, .val = 'u'},
|
||||||
{.name = "down", .has_arg = false, .val = 'U'}, /* not up */
|
{.name = "down", .has_arg = false, .val = 'U'}, /* not up */
|
||||||
{.name = "broadcast", .has_arg = false, .val = 'b'},
|
{.name = "broadcast", .has_arg = false, .val = 'b'},
|
||||||
@@ -40,9 +46,7 @@ static void iface_print_opt(const struct xt_iface_mtinfo *info,
|
|||||||
const unsigned int option, const char *command)
|
const unsigned int option, const char *command)
|
||||||
{
|
{
|
||||||
if (info->flags & option)
|
if (info->flags & option)
|
||||||
printf(" %s", command);
|
printf(" %s%s", (info->invflags & option) ? "! " : "", command);
|
||||||
if (info->invflags & option)
|
|
||||||
printf(" ! %s", command);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void iface_setflag(struct xt_iface_mtinfo *info,
|
static void iface_setflag(struct xt_iface_mtinfo *info,
|
||||||
@@ -51,10 +55,9 @@ static void iface_setflag(struct xt_iface_mtinfo *info,
|
|||||||
if (*flags & flag)
|
if (*flags & flag)
|
||||||
xtables_error(PARAMETER_PROBLEM,
|
xtables_error(PARAMETER_PROBLEM,
|
||||||
"iface: \"--%s\" flag already specified", command);
|
"iface: \"--%s\" flag already specified", command);
|
||||||
|
info->flags |= flag;
|
||||||
if (invert)
|
if (invert)
|
||||||
info->invflags |= flag;
|
info->invflags |= flag;
|
||||||
else
|
|
||||||
info->flags |= flag;
|
|
||||||
*flags |= flag;
|
*flags |= flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +73,7 @@ static void iface_mt_help(void)
|
|||||||
printf(
|
printf(
|
||||||
"iface match options:\n"
|
"iface match options:\n"
|
||||||
" --iface interface Name of interface\n"
|
" --iface interface Name of interface\n"
|
||||||
|
" --dev-in / --dev-out Use incoming/outgoing interface instead\n"
|
||||||
"[!] --up / --down match if UP flag (not) set\n"
|
"[!] --up / --down match if UP flag (not) set\n"
|
||||||
"[!] --broadcast match if BROADCAST flag (not) set\n"
|
"[!] --broadcast match if BROADCAST flag (not) set\n"
|
||||||
"[!] --loopback match if LOOPBACK flag (not) set\n"
|
"[!] --loopback match if LOOPBACK flag (not) set\n"
|
||||||
@@ -111,6 +115,18 @@ static int iface_mt_parse(int c, char **argv, int invert, unsigned int *flags,
|
|||||||
strcpy(info->ifname, optarg);
|
strcpy(info->ifname, optarg);
|
||||||
*flags |= XT_IFACE_IFACE;
|
*flags |= XT_IFACE_IFACE;
|
||||||
return true;
|
return true;
|
||||||
|
case 'I': /* --dev-in */
|
||||||
|
xtables_param_act(XTF_ONLY_ONCE, "iface", "--dev-in",
|
||||||
|
*flags & XT_IFACE_IFACE);
|
||||||
|
*flags |= XT_IFACE_IFACE;
|
||||||
|
iface_setflag(info, flags, invert, XT_IFACE_DEV_IN, "dev-in");
|
||||||
|
return true;
|
||||||
|
case 'O': /* --dev-out */
|
||||||
|
xtables_param_act(XTF_ONLY_ONCE, "iface", "--dev-out",
|
||||||
|
*flags & XT_IFACE_IFACE);
|
||||||
|
*flags |= XT_IFACE_IFACE;
|
||||||
|
iface_setflag(info, flags, invert, XT_IFACE_DEV_OUT, "dev-out");
|
||||||
|
return true;
|
||||||
case 'u': /* UP */
|
case 'u': /* UP */
|
||||||
iface_setflag(info, flags, invert, XT_IFACE_UP, "up");
|
iface_setflag(info, flags, invert, XT_IFACE_UP, "up");
|
||||||
return true;
|
return true;
|
||||||
@@ -153,7 +169,8 @@ static void iface_mt_check(unsigned int flags)
|
|||||||
if (!(flags & XT_IFACE_IFACE))
|
if (!(flags & XT_IFACE_IFACE))
|
||||||
xtables_error(PARAMETER_PROBLEM,
|
xtables_error(PARAMETER_PROBLEM,
|
||||||
"iface: You must specify an interface");
|
"iface: You must specify an interface");
|
||||||
if (flags == 0 || flags == XT_IFACE_IFACE)
|
if ((flags & ~(XT_IFACE_IFACE | XT_IFACE_DEV_IN |
|
||||||
|
XT_IFACE_DEV_OUT)) == 0)
|
||||||
xtables_error(PARAMETER_PROBLEM,
|
xtables_error(PARAMETER_PROBLEM,
|
||||||
"iface: You must specify at least one option");
|
"iface: You must specify at least one option");
|
||||||
}
|
}
|
||||||
@@ -163,7 +180,14 @@ static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
|
|||||||
{
|
{
|
||||||
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
||||||
|
|
||||||
printf("iface: \"%s\" [state:", info->ifname);
|
printf("iface: ");
|
||||||
|
if (info->flags & XT_IFACE_DEV_IN)
|
||||||
|
printf("(in)");
|
||||||
|
else if (info->flags & XT_IFACE_DEV_OUT)
|
||||||
|
printf("(out)");
|
||||||
|
else
|
||||||
|
printf("%s", info->ifname);
|
||||||
|
printf(" [state:");
|
||||||
iface_print_opt(info, XT_IFACE_UP, "up");
|
iface_print_opt(info, XT_IFACE_UP, "up");
|
||||||
iface_print_opt(info, XT_IFACE_BROADCAST, "broadcast");
|
iface_print_opt(info, XT_IFACE_BROADCAST, "broadcast");
|
||||||
iface_print_opt(info, XT_IFACE_LOOPBACK, "loopback");
|
iface_print_opt(info, XT_IFACE_LOOPBACK, "loopback");
|
||||||
@@ -182,6 +206,11 @@ static void iface_mt_save(const void *ip, const struct xt_entry_match *match)
|
|||||||
{
|
{
|
||||||
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
const struct xt_iface_mtinfo *info = (const void *)match->data;
|
||||||
|
|
||||||
|
if (info->flags & XT_IFACE_DEV_IN)
|
||||||
|
printf("--dev-in");
|
||||||
|
else if (info->flags & XT_IFACE_DEV_OUT)
|
||||||
|
printf("--dev-out");
|
||||||
|
else
|
||||||
printf("--iface %s", info->ifname);
|
printf("--iface %s", info->ifname);
|
||||||
iface_print_opt(info, XT_IFACE_UP, "--up");
|
iface_print_opt(info, XT_IFACE_UP, "--up");
|
||||||
iface_print_opt(info, XT_IFACE_BROADCAST, "--broadcast");
|
iface_print_opt(info, XT_IFACE_BROADCAST, "--broadcast");
|
||||||
|
@@ -1,7 +1,20 @@
|
|||||||
Allows you to check interface states.
|
Allows you to check interface states. First, an interface needs to be selected
|
||||||
|
for comparison. Exactly one option of the following three must be specified:
|
||||||
.TP
|
.TP
|
||||||
\fB\-\-iface\fP \fIname\fP
|
\fB\-\-iface\fP \fIname\fP
|
||||||
Check the states on the given interface. This option is required.
|
Check the states on the given interface.
|
||||||
|
.TP
|
||||||
|
\fB\-\-dev\-in\fP
|
||||||
|
Check the states on the interface on which the packet came in. If the input
|
||||||
|
device is not set, because for example you are using \-m iface in the OUTPUT
|
||||||
|
chain, this submatch returns false.
|
||||||
|
.TP
|
||||||
|
\fB\-\-dev\-out\fP
|
||||||
|
Check the states on the interface on which the packet will go out. If the
|
||||||
|
output device is not set, because for example you are using \-m iface in the
|
||||||
|
INPUT chain, this submatch returns false.
|
||||||
|
.PP
|
||||||
|
Following that, one can select the interface properties to check for:
|
||||||
.TP
|
.TP
|
||||||
[\fB!\fP] \fB\-\-up\fP, [\fB!\fP] \fB\-\-down\fP
|
[\fB!\fP] \fB\-\-up\fP, [\fB!\fP] \fB\-\-down\fP
|
||||||
Check the UP flag.
|
Check the UP flag.
|
||||||
|
@@ -40,29 +40,46 @@ static const struct xt_iface_flag_pairs xt_iface_lookup[] =
|
|||||||
{.iface_flag = XT_IFACE_DORMANT, .iff_flag = IFF_DORMANT},
|
{.iface_flag = XT_IFACE_DORMANT, .iff_flag = IFF_DORMANT},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct net_device *iface_get(const struct xt_iface_mtinfo *info,
|
||||||
|
const struct xt_action_param *par, struct net_device **put)
|
||||||
|
{
|
||||||
|
if (info->flags & XT_IFACE_DEV_IN)
|
||||||
|
return par->in;
|
||||||
|
else if (info->flags & XT_IFACE_DEV_OUT)
|
||||||
|
return par->out;
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
||||||
|
return *put = dev_get_by_name(&init_net, info->ifname);
|
||||||
|
#else
|
||||||
|
return *put = dev_get_by_name(info->ifname);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool iface_flagtest(unsigned int devflags, unsigned int flags,
|
||||||
|
unsigned int invflags)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(xt_iface_lookup); ++i)
|
||||||
|
if ((flags & xt_iface_lookup[i].iface_flag) &&
|
||||||
|
!!(devflags & xt_iface_lookup[i].iff_flag) ^
|
||||||
|
!(invflags & xt_iface_lookup[i].iface_flag))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool xt_iface_mt(const struct sk_buff *skb,
|
static bool xt_iface_mt(const struct sk_buff *skb,
|
||||||
struct xt_action_param *par)
|
struct xt_action_param *par)
|
||||||
{
|
{
|
||||||
const struct xt_iface_mtinfo *info = par->matchinfo;
|
const struct xt_iface_mtinfo *info = par->matchinfo;
|
||||||
struct net_device *dev;
|
struct net_device *put = NULL;
|
||||||
|
const struct net_device *dev = iface_get(info, par, &put);
|
||||||
bool retval;
|
bool retval;
|
||||||
int i;
|
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
|
if (dev == NULL)
|
||||||
dev = dev_get_by_name(&init_net, info->ifname);
|
return false;
|
||||||
#else
|
retval = iface_flagtest(dev->flags, info->flags, info->invflags);
|
||||||
dev = dev_get_by_name(info->ifname);
|
if (put != NULL)
|
||||||
#endif
|
dev_put(put);
|
||||||
retval = dev != NULL;
|
|
||||||
if (retval) {
|
|
||||||
for (i = 0; i < ARRAY_SIZE(xt_iface_lookup) && retval; ++i) {
|
|
||||||
if (info->flags & xt_iface_lookup[i].iface_flag)
|
|
||||||
retval &= dev->flags & xt_iface_lookup[i].iff_flag;
|
|
||||||
if (info->invflags & xt_iface_lookup[i].iface_flag)
|
|
||||||
retval &= !(dev->flags & xt_iface_lookup[i].iff_flag);
|
|
||||||
}
|
|
||||||
dev_put(dev);
|
|
||||||
}
|
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -13,7 +13,8 @@ enum {
|
|||||||
XT_IFACE_DYNAMIC = 1 << 8,
|
XT_IFACE_DYNAMIC = 1 << 8,
|
||||||
XT_IFACE_LOWER_UP = 1 << 9,
|
XT_IFACE_LOWER_UP = 1 << 9,
|
||||||
XT_IFACE_DORMANT = 1 << 10,
|
XT_IFACE_DORMANT = 1 << 10,
|
||||||
XT_IFACE_IFACE = 1 << 15,
|
XT_IFACE_DEV_IN = 1 << 11,
|
||||||
|
XT_IFACE_DEV_OUT = 1 << 12,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct xt_iface_mtinfo {
|
struct xt_iface_mtinfo {
|
||||||
|
Reference in New Issue
Block a user