From 21cdf786f787c61717bc235ff4f252bf412ae052 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 24 Oct 2010 16:31:26 +0200 Subject: [PATCH 1/4] xt_iface: move XT_IFACE_IFACE out of the public header This flag is only used by the userspace component, so remove it from the kernel header. Also change the value to 1<<16 for the same reason. --- extensions/libxt_iface.c | 4 ++++ extensions/xt_iface.h | 1 - 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/extensions/libxt_iface.c b/extensions/libxt_iface.c index 6d1c79a..b1ae6ff 100644 --- a/extensions/libxt_iface.c +++ b/extensions/libxt_iface.c @@ -17,6 +17,10 @@ #include "xt_iface.h" #include "compat_user.h" +enum { + XT_IFACE_IFACE = 1 << 16, +}; + static const struct option iface_mt_opts[] = { {.name = "iface", .has_arg = true, .val = 'i'}, {.name = "up", .has_arg = false, .val = 'u'}, diff --git a/extensions/xt_iface.h b/extensions/xt_iface.h index f1dbba7..655fe23 100644 --- a/extensions/xt_iface.h +++ b/extensions/xt_iface.h @@ -13,7 +13,6 @@ enum { XT_IFACE_DYNAMIC = 1 << 8, XT_IFACE_LOWER_UP = 1 << 9, XT_IFACE_DORMANT = 1 << 10, - XT_IFACE_IFACE = 1 << 15, }; struct xt_iface_mtinfo { From f757049112655d7fee5037307b418aaa6b0550dd Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 24 Oct 2010 16:35:12 +0200 Subject: [PATCH 2/4] xt_iface: reduce indent by early return --- extensions/xt_iface.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/extensions/xt_iface.c b/extensions/xt_iface.c index 4bf5486..ce04915 100644 --- a/extensions/xt_iface.c +++ b/extensions/xt_iface.c @@ -53,16 +53,17 @@ static bool xt_iface_mt(const struct sk_buff *skb, #else dev = dev_get_by_name(info->ifname); #endif - 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); + if (dev == NULL) + return false; + + retval = true; + 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; } From 6733265358404e6ed7a98cb10acad26d1f1aa519 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 24 Oct 2010 18:13:28 +0200 Subject: [PATCH 3/4] xt_iface: reorder code for upcoming address checking From now on, info->flags lists the flags to test, not just the flags to test positively for. --- extensions/libxt_iface.c | 7 ++----- extensions/xt_iface.c | 39 ++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/extensions/libxt_iface.c b/extensions/libxt_iface.c index b1ae6ff..cefde6e 100644 --- a/extensions/libxt_iface.c +++ b/extensions/libxt_iface.c @@ -44,9 +44,7 @@ static void iface_print_opt(const struct xt_iface_mtinfo *info, const unsigned int option, const char *command) { if (info->flags & option) - printf(" %s", command); - if (info->invflags & option) - printf(" ! %s", command); + printf(" %s%s", (info->invflags & option) ? "! " : "", command); } static void iface_setflag(struct xt_iface_mtinfo *info, @@ -55,10 +53,9 @@ static void iface_setflag(struct xt_iface_mtinfo *info, if (*flags & flag) xtables_error(PARAMETER_PROBLEM, "iface: \"--%s\" flag already specified", command); + info->flags |= flag; if (invert) info->invflags |= flag; - else - info->flags |= flag; *flags |= flag; } diff --git a/extensions/xt_iface.c b/extensions/xt_iface.c index ce04915..cd16363 100644 --- a/extensions/xt_iface.c +++ b/extensions/xt_iface.c @@ -40,29 +40,38 @@ static const struct xt_iface_flag_pairs xt_iface_lookup[] = {.iface_flag = XT_IFACE_DORMANT, .iff_flag = IFF_DORMANT}, }; +static struct net_device *iface_get(const char *name) +{ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) + return dev_get_by_name(&init_net, name); +#else + return dev_get_by_name(name); +#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, struct xt_action_param *par) { const struct xt_iface_mtinfo *info = par->matchinfo; - struct net_device *dev; + struct net_device *dev = iface_get(info->ifname); bool retval; - int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) - dev = dev_get_by_name(&init_net, info->ifname); -#else - dev = dev_get_by_name(info->ifname); -#endif if (dev == NULL) return false; - - retval = true; - 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); - } + retval = iface_flagtest(dev->flags, info->flags, info->invflags); dev_put(dev); return retval; } From db76ea9a5cde42d9ae09589645a457358dbc7976 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Sun, 31 Oct 2010 01:38:12 +0200 Subject: [PATCH 4/4] xt_iface: allow matching against incoming/outgoing interface --- doc/changelog.txt | 1 + extensions/libxt_iface.c | 58 ++++++++++++++++++++++++++++---------- extensions/libxt_iface.man | 17 +++++++++-- extensions/xt_iface.c | 17 +++++++---- extensions/xt_iface.h | 2 ++ 5 files changed, 73 insertions(+), 22 deletions(-) diff --git a/doc/changelog.txt b/doc/changelog.txt index d00e3dd..0d6b2a9 100644 --- a/doc/changelog.txt +++ b/doc/changelog.txt @@ -1,6 +1,7 @@ HEAD ==== +- xt_iface: allow matching against incoming/outgoing interface v1.30 (October 02 2010) diff --git a/extensions/libxt_iface.c b/extensions/libxt_iface.c index cefde6e..7b430b6 100644 --- a/extensions/libxt_iface.c +++ b/extensions/libxt_iface.c @@ -23,6 +23,8 @@ enum { static const struct option iface_mt_opts[] = { {.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 = "down", .has_arg = false, .val = 'U'}, /* not up */ {.name = "broadcast", .has_arg = false, .val = 'b'}, @@ -70,19 +72,20 @@ static void iface_mt_help(void) { printf( "iface match options:\n" - " --iface interface Name of interface\n" - "[!] --up / --down match if UP flag (not) set\n" - "[!] --broadcast match if BROADCAST flag (not) set\n" - "[!] --loopback match if LOOPBACK flag (not) set\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" + "[!] --broadcast match if BROADCAST flag (not) set\n" + "[!] --loopback match if LOOPBACK flag (not) set\n" "[!] --pointopoint\n" - "[!] --pointtopoint match if POINTOPOINT flag (not) set\n" - "[!] --running match if RUNNING flag (not) set\n" - "[!] --noarp / --arp match if NOARP flag (not) set\n" - "[!] --promisc match if PROMISC flag (not) set\n" - "[!] --multicast match if MULTICAST flag (not) set\n" - "[!] --dynamic match if DYNAMIC flag (not) set\n" - "[!] --lower-up match if LOWER_UP flag (not) set\n" - "[!] --dormant match if DORMANT flag (not) set\n"); + "[!] --pointtopoint match if POINTOPOINT flag (not) set\n" + "[!] --running match if RUNNING flag (not) set\n" + "[!] --noarp / --arp match if NOARP flag (not) set\n" + "[!] --promisc match if PROMISC flag (not) set\n" + "[!] --multicast match if MULTICAST flag (not) set\n" + "[!] --dynamic match if DYNAMIC flag (not) set\n" + "[!] --lower-up match if LOWER_UP flag (not) set\n" + "[!] --dormant match if DORMANT flag (not) set\n"); } static int iface_mt_parse(int c, char **argv, int invert, unsigned int *flags, @@ -112,6 +115,18 @@ static int iface_mt_parse(int c, char **argv, int invert, unsigned int *flags, strcpy(info->ifname, optarg); *flags |= XT_IFACE_IFACE; 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 */ iface_setflag(info, flags, invert, XT_IFACE_UP, "up"); return true; @@ -154,7 +169,8 @@ static void iface_mt_check(unsigned int flags) if (!(flags & XT_IFACE_IFACE)) xtables_error(PARAMETER_PROBLEM, "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, "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; - 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_BROADCAST, "broadcast"); 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; - 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_BROADCAST, "--broadcast"); iface_print_opt(info, XT_IFACE_LOOPBACK, "--loopback"); diff --git a/extensions/libxt_iface.man b/extensions/libxt_iface.man index fb9c04e..810db6b 100644 --- a/extensions/libxt_iface.man +++ b/extensions/libxt_iface.man @@ -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 \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 [\fB!\fP] \fB\-\-up\fP, [\fB!\fP] \fB\-\-down\fP Check the UP flag. diff --git a/extensions/xt_iface.c b/extensions/xt_iface.c index cd16363..b97fd07 100644 --- a/extensions/xt_iface.c +++ b/extensions/xt_iface.c @@ -40,12 +40,17 @@ static const struct xt_iface_flag_pairs xt_iface_lookup[] = {.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) - return dev_get_by_name(&init_net, name); + return *put = dev_get_by_name(&init_net, info->ifname); #else - return dev_get_by_name(name); + return *put = dev_get_by_name(info->ifname); #endif } @@ -66,13 +71,15 @@ static bool xt_iface_mt(const struct sk_buff *skb, struct xt_action_param *par) { 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; if (dev == NULL) return false; retval = iface_flagtest(dev->flags, info->flags, info->invflags); - dev_put(dev); + if (put != NULL) + dev_put(put); return retval; } diff --git a/extensions/xt_iface.h b/extensions/xt_iface.h index 655fe23..b292bcf 100644 --- a/extensions/xt_iface.h +++ b/extensions/xt_iface.h @@ -13,6 +13,8 @@ enum { XT_IFACE_DYNAMIC = 1 << 8, XT_IFACE_LOWER_UP = 1 << 9, XT_IFACE_DORMANT = 1 << 10, + XT_IFACE_DEV_IN = 1 << 11, + XT_IFACE_DEV_OUT = 1 << 12, }; struct xt_iface_mtinfo {