Merge branch 'iface'

This commit is contained in:
Jan Engelhardt
2009-04-27 20:50:05 +02:00
8 changed files with 396 additions and 0 deletions

View File

@@ -6,6 +6,7 @@
- fuzzy: fix bogus comparison logic leftover from move to new 1.4.3 API
- ipp2p: fix bogus varargs call
- ipp2p: fix typo in error message
- add "iface" match
- added rawpost table (for use with RAWNAT)
- added RAWSNAT/RAWDNAT targets

View File

@@ -19,6 +19,7 @@ obj-${build_TEE} += xt_TEE.o
obj-${build_condition} += xt_condition.o
obj-${build_fuzzy} += xt_fuzzy.o
obj-${build_geoip} += xt_geoip.o
obj-${build_iface} += xt_iface.o
obj-${build_ipp2p} += xt_ipp2p.o
obj-${build_ipset} += ipset/
obj-${build_ipv4options} += xt_ipv4options.o

View File

@@ -12,6 +12,7 @@ obj-${build_TEE} += libxt_TEE.so
obj-${build_condition} += libxt_condition.so
obj-${build_fuzzy} += libxt_fuzzy.so
obj-${build_geoip} += libxt_geoip.so
obj-${build_iface} += libxt_iface.so
obj-${build_ipp2p} += libxt_ipp2p.so
obj-${build_ipset} += ipset/
obj-${build_ipv4options} += libxt_ipv4options.so

233
extensions/libxt_iface.c Normal file
View File

@@ -0,0 +1,233 @@
/*
* Shared library add-on to iptables to add interface state matching
* support.
*
* (C) 2008 Gáspár Lajos <gaspar.lajos@glsys.eu>
*
* This program is released under the terms of GNU GPL version 2.
*/
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <xtables.h>
#include "xt_iface.h"
static const struct option iface_mt_opts[] = {
{.name = "iface", .has_arg = true, .val = 'i'},
{.name = "up", .has_arg = false, .val = 'u'},
{.name = "down", .has_arg = false, .val = 'U'}, /* not up */
{.name = "broadcast", .has_arg = false, .val = 'b'},
{.name = "loopback", .has_arg = false, .val = 'l'},
{.name = "pointopoint", .has_arg = false, .val = 'p'},
{.name = "pointtopoint", .has_arg = false, .val = 'p'}, /* eq pointopoint */
{.name = "running", .has_arg = false, .val = 'r'},
{.name = "noarp", .has_arg = false, .val = 'n'},
{.name = "arp", .has_arg = false, .val = 'N'}, /* not noarp */
{.name = "promisc", .has_arg = false, .val = 'o'},
{.name = "multicast", .has_arg = false, .val = 'm'},
{.name = "dynamic", .has_arg = false, .val = 'd'},
{.name = "lower-up", .has_arg = false, .val = 'w'},
{.name = "dormant", .has_arg = false, .val = 'a'},
{NULL},
};
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);
}
static void iface_setflag(struct xt_iface_mtinfo *info,
unsigned int *flags, int invert, u_int16_t flag, const char *command)
{
if (*flags & flag)
xtables_error(PARAMETER_PROBLEM,
"iface: \"--%s\" flag already specified", command);
if (invert)
info->invflags |= flag;
else
info->flags |= flag;
*flags |= flag;
}
static bool iface_valid_name(const char *name)
{
static const char invalid_chars[] = ".+!*";
return strlen(name) < IFNAMSIZ && strpbrk(name, invalid_chars) == NULL;
}
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"
"[!] --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");
}
static int iface_mt_parse(int c, char **argv, int invert, unsigned int *flags,
const void *entry, struct xt_entry_match **match)
{
struct xt_iface_mtinfo *info = (void *)(*match)->data;
switch (c) {
case 'U':
c = 'u';
invert = !invert;
break;
case 'N':
c = 'n';
invert = !invert;
break;
}
switch (c) {
case 'i': /* interface name */
if (*flags & XT_IFACE_IFACE)
xtables_error(PARAMETER_PROBLEM,
"iface: Interface name already specified");
if (!iface_valid_name(optarg))
xtables_error(PARAMETER_PROBLEM,
"iface: Invalid interface name!");
strcpy(info->ifname, optarg);
*flags |= XT_IFACE_IFACE;
return true;
case 'u': /* UP */
iface_setflag(info, flags, invert, XT_IFACE_UP, "up");
return true;
case 'b': /* BROADCAST */
iface_setflag(info, flags, invert, XT_IFACE_BROADCAST, "broadcast");
return true;
case 'l': /* LOOPBACK */
iface_setflag(info, flags, invert, XT_IFACE_LOOPBACK, "loopback");
return true;
case 'p': /* POINTOPOINT */
iface_setflag(info, flags, invert, XT_IFACE_POINTOPOINT, "pointopoint");
return true;
case 'r': /* RUNNING */
iface_setflag(info, flags, invert, XT_IFACE_RUNNING, "running");
return true;
case 'n': /* NOARP */
iface_setflag(info, flags, invert, XT_IFACE_NOARP, "noarp");
return true;
case 'o': /* PROMISC */
iface_setflag(info, flags, invert, XT_IFACE_PROMISC, "promisc");
return true;
case 'm': /* MULTICAST */
iface_setflag(info, flags, invert, XT_IFACE_MULTICAST, "multicast");
return true;
case 'd': /* DYNAMIC */
iface_setflag(info, flags, invert, XT_IFACE_DYNAMIC, "dynamic");
return true;
case 'w': /* LOWER_UP */
iface_setflag(info, flags, invert, XT_IFACE_LOWER_UP, "lower_up");
return true;
case 'a': /* DORMANT */
iface_setflag(info, flags, invert, XT_IFACE_DORMANT, "dormant");
return true;
}
return false;
}
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)
xtables_error(PARAMETER_PROBLEM,
"iface: You must specify at least one option");
}
static void iface_mt_print(const void *ip, const struct xt_entry_match *match,
int numeric)
{
const struct xt_iface_mtinfo *info = (const void *)match->data;
printf("iface: \"%s\" [state:", 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");
iface_print_opt(info, XT_IFACE_POINTOPOINT, "pointopoint");
iface_print_opt(info, XT_IFACE_RUNNING, "running");
iface_print_opt(info, XT_IFACE_NOARP, "noarp");
iface_print_opt(info, XT_IFACE_PROMISC, "promisc");
iface_print_opt(info, XT_IFACE_MULTICAST, "multicast");
iface_print_opt(info, XT_IFACE_DYNAMIC, "dynamic");
iface_print_opt(info, XT_IFACE_LOWER_UP, "lower_up");
iface_print_opt(info, XT_IFACE_DORMANT, "dormant");
printf("] ");
}
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);
iface_print_opt(info, XT_IFACE_UP, "--up");
iface_print_opt(info, XT_IFACE_BROADCAST, "--broadcast");
iface_print_opt(info, XT_IFACE_LOOPBACK, "--loopback");
iface_print_opt(info, XT_IFACE_POINTOPOINT, "--pointopoint");
iface_print_opt(info, XT_IFACE_RUNNING, "--running");
iface_print_opt(info, XT_IFACE_NOARP, "--noarp");
iface_print_opt(info, XT_IFACE_PROMISC, "--promisc");
iface_print_opt(info, XT_IFACE_MULTICAST, "--multicast");
iface_print_opt(info, XT_IFACE_DYNAMIC, "--dynamic");
iface_print_opt(info, XT_IFACE_LOWER_UP, "--lower_up");
iface_print_opt(info, XT_IFACE_DORMANT, "--dormant");
printf(" ");
}
static struct xtables_match iface_mt_reg = {
.version = XTABLES_VERSION,
.name = "iface",
.revision = 0,
.family = AF_INET,
.size = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.help = iface_mt_help,
.parse = iface_mt_parse,
.final_check = iface_mt_check,
.print = iface_mt_print,
.save = iface_mt_save,
.extra_opts = iface_mt_opts,
};
static struct xtables_match iface_mt6_reg = {
.version = XTABLES_VERSION,
.name = "iface",
.revision = 0,
.family = AF_INET6,
.size = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.userspacesize = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.help = iface_mt_help,
.parse = iface_mt_parse,
.final_check = iface_mt_check,
.print = iface_mt_print,
.save = iface_mt_save,
.extra_opts = iface_mt_opts,
};
static void _init(void)
{
xtables_register_match(&iface_mt_reg);
xtables_register_match(&iface_mt6_reg);
}

View File

@@ -0,0 +1,37 @@
Allows you to check interface states.
.TP
\fB\-\-iface\fP \fIname\fP
Check the states on the given interface. This option is required.
.TP
[\fB!\fP] \fB\-\-up\fP, [\fB!\fP] \fB\-\-down\fP
Check the UP flag.
.TP
[\fB!\fP] \fB\-\-broadcast\fP
Check the BROADCAST flag.
.TP
[\fB!\fP] \fB\-\-loopback\fP
Check the LOOPBACK flag.
.TP
[\fB!\fP] \fB\-\-pointtopoint\fP
Check the POINTTOPOINT flag.
.TP
[\fB!\fP] \fB\-\-running\fP
Check the RUNNING flag. Do NOT rely on it!
.TP
[\fB!\fP] \fB\-\-noarp\fP, [\fB!\fP] \fB\-\-arp\fP
Check the NOARP flag.
.TP
[\fB!\fP] \fB\-\-promisc\fP
Check the PROMISC flag.
.TP
[\fB!\fP] \fB\-\-multicast\fP
Check the MULTICAST flag.
.TP
[\fB!\fP] \fB\-\-dynamic\fP
Check the DYNAMIC flag.
.TP
[\fB!\fP] \fB\-\-lower-up\fP
Check the LOWER_UP flag.
.TP
[\fB!\fP] \fB\-\-dormant\fP
Check the DORMANT flag.

97
extensions/xt_iface.c Normal file
View File

@@ -0,0 +1,97 @@
/*
* xt_iface - kernel module to match interface state flags
*
* Original author: Gáspár Lajos <gaspar.lajos@glsys.eu>
*/
#include <linux/if.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#include <linux/netfilter/x_tables.h>
#include "xt_iface.h"
struct xt_iface_flag_pairs {
uint16_t iface_flag;
uint32_t iff_flag;
};
MODULE_AUTHOR("Gáspár Lajos <gaspar.lajos@glsys.eu>");
MODULE_DESCRIPTION("Xtables: iface match module");
MODULE_LICENSE("GPL");
MODULE_ALIAS("ipt_iface");
MODULE_ALIAS("ip6t_iface");
//MODULE_ALIAS("arpt_iface");
static const struct xt_iface_flag_pairs xt_iface_lookup[] =
{
{.iface_flag = XT_IFACE_UP, .iff_flag = IFF_UP},
{.iface_flag = XT_IFACE_BROADCAST, .iff_flag = IFF_BROADCAST},
{.iface_flag = XT_IFACE_LOOPBACK, .iff_flag = IFF_LOOPBACK},
{.iface_flag = XT_IFACE_POINTOPOINT, .iff_flag = IFF_POINTOPOINT},
{.iface_flag = XT_IFACE_RUNNING, .iff_flag = IFF_RUNNING},
{.iface_flag = XT_IFACE_NOARP, .iff_flag = IFF_NOARP},
{.iface_flag = XT_IFACE_PROMISC, .iff_flag = IFF_PROMISC},
{.iface_flag = XT_IFACE_MULTICAST, .iff_flag = IFF_MULTICAST},
{.iface_flag = XT_IFACE_DYNAMIC, .iff_flag = IFF_DYNAMIC},
{.iface_flag = XT_IFACE_LOWER_UP, .iff_flag = IFF_LOWER_UP},
{.iface_flag = XT_IFACE_DORMANT, .iff_flag = IFF_DORMANT},
};
static bool xt_iface_mt(const struct sk_buff *skb,
const struct xt_match_param *par)
{
const struct xt_iface_mtinfo *info = par->matchinfo;
struct net_device *dev;
bool retval;
int i;
dev = dev_get_by_name(&init_net, info->ifname);
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;
}
static struct xt_match xt_iface_mt_reg[] __read_mostly = {
{
.name = "iface",
.revision = 0,
.family = NFPROTO_IPV4,
.matchsize = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.match = xt_iface_mt,
.data = 0,
.me = THIS_MODULE,
},
{
.name = "iface",
.revision = 0,
.family = NFPROTO_IPV6,
.matchsize = XT_ALIGN(sizeof(struct xt_iface_mtinfo)),
.match = xt_iface_mt,
.data = 0,
.me = THIS_MODULE,
},
};
static int __init xt_iface_match_init(void)
{
return xt_register_matches(xt_iface_mt_reg,
ARRAY_SIZE(xt_iface_mt_reg));
}
static void __exit xt_iface_match_exit(void)
{
xt_unregister_matches(xt_iface_mt_reg, ARRAY_SIZE(xt_iface_mt_reg));
}
module_init(xt_iface_match_init);
module_exit(xt_iface_match_exit);

25
extensions/xt_iface.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef _LINUX_NETFILTER_XT_IFACE_H
#define _LINUX_NETFILTER_XT_IFACE_H 1
enum {
XT_IFACE_UP = 1 << 0,
XT_IFACE_BROADCAST = 1 << 1,
XT_IFACE_LOOPBACK = 1 << 2,
XT_IFACE_POINTOPOINT = 1 << 3,
XT_IFACE_RUNNING = 1 << 4,
XT_IFACE_NOARP = 1 << 5,
XT_IFACE_PROMISC = 1 << 6,
XT_IFACE_MULTICAST = 1 << 7,
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 {
char ifname[IFNAMSIZ];
__u16 flags;
__u16 invflags;
};
#endif

View File

@@ -14,6 +14,7 @@ build_TEE=m
build_condition=m
build_fuzzy=m
build_geoip=m
build_iface=m
build_ipp2p=m
build_ipset=m
build_ipv4options=m