xt_iface: allow matching against incoming/outgoing interface

This commit is contained in:
Jan Engelhardt
2010-10-31 01:38:12 +02:00
parent 6733265358
commit db76ea9a5c
5 changed files with 73 additions and 22 deletions

View File

@@ -1,6 +1,7 @@
HEAD HEAD
==== ====
- xt_iface: allow matching against incoming/outgoing interface
v1.30 (October 02 2010) v1.30 (October 02 2010)

View File

@@ -23,6 +23,8 @@ enum {
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'},
@@ -71,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"
@@ -112,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;
@@ -154,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");
} }
@@ -164,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");
@@ -183,7 +206,12 @@ 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;
printf(" --iface %s", info->ifname); 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);
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");

View File

@@ -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.

View File

@@ -40,12 +40,17 @@ 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 struct net_device *iface_get(const char *name) 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) #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
return dev_get_by_name(&init_net, name); return *put = dev_get_by_name(&init_net, info->ifname);
#else #else
return dev_get_by_name(name); return *put = dev_get_by_name(info->ifname);
#endif #endif
} }
@@ -66,13 +71,15 @@ 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 = iface_get(info->ifname); struct net_device *put = NULL;
const struct net_device *dev = iface_get(info, par, &put);
bool retval; bool retval;
if (dev == NULL) if (dev == NULL)
return false; return false;
retval = iface_flagtest(dev->flags, info->flags, info->invflags); retval = iface_flagtest(dev->flags, info->flags, info->invflags);
dev_put(dev); if (put != NULL)
dev_put(put);
return retval; return retval;
} }

View File

@@ -13,6 +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_DEV_IN = 1 << 11,
XT_IFACE_DEV_OUT = 1 << 12,
}; };
struct xt_iface_mtinfo { struct xt_iface_mtinfo {