mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
xtables: move icmp/icmpv6 logic to xt_tcpudp
icmp/icmp6 matches are baked into ip(6)_tables.ko. This means that even if iptables-nft is used, a rule like "-p icmp --icmp-type 1" will load the ip(6)tables modules. Move them to xt_tcpdudp.ko instead to avoid this. This will also allow to eventually add kconfig knobs to build kernels that support iptables-nft but not iptables-legacy (old set/getsockopt interface). Signed-off-by: Florian Westphal <fw@strlen.de>
This commit is contained in:
parent
bde7170a04
commit
36ce9982ef
@ -14,7 +14,6 @@
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/compat.h>
|
||||
#include <linux/uaccess.h>
|
||||
@ -31,7 +30,6 @@
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("IPv4 packet filter");
|
||||
MODULE_ALIAS("ipt_icmp");
|
||||
|
||||
void *ipt_alloc_initial_table(const struct xt_table *info)
|
||||
{
|
||||
@ -1799,52 +1797,6 @@ void ipt_unregister_table_exit(struct net *net, const char *name)
|
||||
__ipt_unregister_table(net, table);
|
||||
}
|
||||
|
||||
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
|
||||
static inline bool
|
||||
icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
|
||||
u_int8_t type, u_int8_t code,
|
||||
bool invert)
|
||||
{
|
||||
return ((test_type == 0xFF) ||
|
||||
(type == test_type && code >= min_code && code <= max_code))
|
||||
^ invert;
|
||||
}
|
||||
|
||||
static bool
|
||||
icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct icmphdr *ic;
|
||||
struct icmphdr _icmph;
|
||||
const struct ipt_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must not be a fragment. */
|
||||
if (par->fragoff != 0)
|
||||
return false;
|
||||
|
||||
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
|
||||
if (ic == NULL) {
|
||||
/* We've been asked to examine this packet, and we
|
||||
* can't. Hence, no choice but to drop.
|
||||
*/
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return icmp_type_code_match(icmpinfo->type,
|
||||
icmpinfo->code[0],
|
||||
icmpinfo->code[1],
|
||||
ic->type, ic->code,
|
||||
!!(icmpinfo->invflags&IPT_ICMP_INV));
|
||||
}
|
||||
|
||||
static int icmp_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ipt_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must specify no unknown invflags */
|
||||
return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static struct xt_target ipt_builtin_tg[] __read_mostly = {
|
||||
{
|
||||
.name = XT_STANDARD_TARGET,
|
||||
@ -1875,18 +1827,6 @@ static struct nf_sockopt_ops ipt_sockopts = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct xt_match ipt_builtin_mt[] __read_mostly = {
|
||||
{
|
||||
.name = "icmp",
|
||||
.match = icmp_match,
|
||||
.matchsize = sizeof(struct ipt_icmp),
|
||||
.checkentry = icmp_checkentry,
|
||||
.proto = IPPROTO_ICMP,
|
||||
.family = NFPROTO_IPV4,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init ip_tables_net_init(struct net *net)
|
||||
{
|
||||
return xt_proto_init(net, NFPROTO_IPV4);
|
||||
@ -1914,19 +1854,14 @@ static int __init ip_tables_init(void)
|
||||
ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
|
||||
if (ret < 0)
|
||||
goto err4;
|
||||
|
||||
/* Register setsockopt */
|
||||
ret = nf_register_sockopt(&ipt_sockopts);
|
||||
if (ret < 0)
|
||||
goto err5;
|
||||
goto err4;
|
||||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
|
||||
err4:
|
||||
xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
|
||||
err2:
|
||||
@ -1939,7 +1874,6 @@ static void __exit ip_tables_fini(void)
|
||||
{
|
||||
nf_unregister_sockopt(&ipt_sockopts);
|
||||
|
||||
xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
|
||||
xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
|
||||
unregister_pernet_subsys(&ip_tables_net_ops);
|
||||
}
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/poison.h>
|
||||
#include <linux/icmpv6.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/compat.h>
|
||||
#include <linux/uaccess.h>
|
||||
@ -35,7 +34,6 @@
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
MODULE_DESCRIPTION("IPv6 packet filter");
|
||||
MODULE_ALIAS("ip6t_icmp6");
|
||||
|
||||
void *ip6t_alloc_initial_table(const struct xt_table *info)
|
||||
{
|
||||
@ -1805,52 +1803,6 @@ void ip6t_unregister_table_exit(struct net *net, const char *name)
|
||||
__ip6t_unregister_table(net, table);
|
||||
}
|
||||
|
||||
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
|
||||
static inline bool
|
||||
icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
|
||||
u_int8_t type, u_int8_t code,
|
||||
bool invert)
|
||||
{
|
||||
return (type == test_type && code >= min_code && code <= max_code)
|
||||
^ invert;
|
||||
}
|
||||
|
||||
static bool
|
||||
icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct icmp6hdr *ic;
|
||||
struct icmp6hdr _icmph;
|
||||
const struct ip6t_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must not be a fragment. */
|
||||
if (par->fragoff != 0)
|
||||
return false;
|
||||
|
||||
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
|
||||
if (ic == NULL) {
|
||||
/* We've been asked to examine this packet, and we
|
||||
* can't. Hence, no choice but to drop.
|
||||
*/
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return icmp6_type_code_match(icmpinfo->type,
|
||||
icmpinfo->code[0],
|
||||
icmpinfo->code[1],
|
||||
ic->icmp6_type, ic->icmp6_code,
|
||||
!!(icmpinfo->invflags&IP6T_ICMP_INV));
|
||||
}
|
||||
|
||||
/* Called when user tries to insert an entry of this type. */
|
||||
static int icmp6_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ip6t_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must specify no unknown invflags */
|
||||
return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
/* The built-in targets: standard (NULL) and error. */
|
||||
static struct xt_target ip6t_builtin_tg[] __read_mostly = {
|
||||
{
|
||||
@ -1882,18 +1834,6 @@ static struct nf_sockopt_ops ip6t_sockopts = {
|
||||
.owner = THIS_MODULE,
|
||||
};
|
||||
|
||||
static struct xt_match ip6t_builtin_mt[] __read_mostly = {
|
||||
{
|
||||
.name = "icmp6",
|
||||
.match = icmp6_match,
|
||||
.matchsize = sizeof(struct ip6t_icmp),
|
||||
.checkentry = icmp6_checkentry,
|
||||
.proto = IPPROTO_ICMPV6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init ip6_tables_net_init(struct net *net)
|
||||
{
|
||||
return xt_proto_init(net, NFPROTO_IPV6);
|
||||
@ -1921,19 +1861,14 @@ static int __init ip6_tables_init(void)
|
||||
ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
|
||||
if (ret < 0)
|
||||
goto err2;
|
||||
ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
|
||||
if (ret < 0)
|
||||
goto err4;
|
||||
|
||||
/* Register setsockopt */
|
||||
ret = nf_register_sockopt(&ip6t_sockopts);
|
||||
if (ret < 0)
|
||||
goto err5;
|
||||
goto err4;
|
||||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
|
||||
err4:
|
||||
xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
|
||||
err2:
|
||||
@ -1946,7 +1881,6 @@ static void __exit ip6_tables_fini(void)
|
||||
{
|
||||
nf_unregister_sockopt(&ip6t_sockopts);
|
||||
|
||||
xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
|
||||
xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
|
||||
unregister_pernet_subsys(&ip6_tables_net_ops);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <net/ip.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <net/ipv6.h>
|
||||
#include <net/tcp.h>
|
||||
#include <net/udp.h>
|
||||
@ -20,6 +21,8 @@ MODULE_ALIAS("ipt_udp");
|
||||
MODULE_ALIAS("ipt_tcp");
|
||||
MODULE_ALIAS("ip6t_udp");
|
||||
MODULE_ALIAS("ip6t_tcp");
|
||||
MODULE_ALIAS("ipt_icmp");
|
||||
MODULE_ALIAS("ip6t_icmp6");
|
||||
|
||||
/* Returns 1 if the port is matched by the range, 0 otherwise */
|
||||
static inline bool
|
||||
@ -161,6 +164,95 @@ static int udp_mt_check(const struct xt_mtchk_param *par)
|
||||
return (udpinfo->invflags & ~XT_UDP_INV_MASK) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
|
||||
static bool type_code_in_range(u8 test_type, u8 min_code, u8 max_code,
|
||||
u8 type, u8 code)
|
||||
{
|
||||
return type == test_type && code >= min_code && code <= max_code;
|
||||
}
|
||||
|
||||
static bool icmp_type_code_match(u8 test_type, u8 min_code, u8 max_code,
|
||||
u8 type, u8 code, bool invert)
|
||||
{
|
||||
return (test_type == 0xFF ||
|
||||
type_code_in_range(test_type, min_code, max_code, type, code))
|
||||
^ invert;
|
||||
}
|
||||
|
||||
static bool icmp6_type_code_match(u8 test_type, u8 min_code, u8 max_code,
|
||||
u8 type, u8 code, bool invert)
|
||||
{
|
||||
return type_code_in_range(test_type, min_code, max_code, type, code) ^ invert;
|
||||
}
|
||||
|
||||
static bool
|
||||
icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct icmphdr *ic;
|
||||
struct icmphdr _icmph;
|
||||
const struct ipt_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must not be a fragment. */
|
||||
if (par->fragoff != 0)
|
||||
return false;
|
||||
|
||||
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
|
||||
if (!ic) {
|
||||
/* We've been asked to examine this packet, and we
|
||||
* can't. Hence, no choice but to drop.
|
||||
*/
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return icmp_type_code_match(icmpinfo->type,
|
||||
icmpinfo->code[0],
|
||||
icmpinfo->code[1],
|
||||
ic->type, ic->code,
|
||||
!!(icmpinfo->invflags & IPT_ICMP_INV));
|
||||
}
|
||||
|
||||
static bool
|
||||
icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
|
||||
{
|
||||
const struct icmp6hdr *ic;
|
||||
struct icmp6hdr _icmph;
|
||||
const struct ip6t_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
/* Must not be a fragment. */
|
||||
if (par->fragoff != 0)
|
||||
return false;
|
||||
|
||||
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
|
||||
if (!ic) {
|
||||
/* We've been asked to examine this packet, and we
|
||||
* can't. Hence, no choice but to drop.
|
||||
*/
|
||||
par->hotdrop = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
return icmp6_type_code_match(icmpinfo->type,
|
||||
icmpinfo->code[0],
|
||||
icmpinfo->code[1],
|
||||
ic->icmp6_type, ic->icmp6_code,
|
||||
!!(icmpinfo->invflags & IP6T_ICMP_INV));
|
||||
}
|
||||
|
||||
static int icmp_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ipt_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static int icmp6_checkentry(const struct xt_mtchk_param *par)
|
||||
{
|
||||
const struct ip6t_icmp *icmpinfo = par->matchinfo;
|
||||
|
||||
return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
static struct xt_match tcpudp_mt_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "tcp",
|
||||
@ -216,6 +308,24 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
|
||||
.proto = IPPROTO_UDPLITE,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "icmp",
|
||||
.match = icmp_match,
|
||||
.matchsize = sizeof(struct ipt_icmp),
|
||||
.checkentry = icmp_checkentry,
|
||||
.proto = IPPROTO_ICMP,
|
||||
.family = NFPROTO_IPV4,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "icmp6",
|
||||
.match = icmp6_match,
|
||||
.matchsize = sizeof(struct ip6t_icmp),
|
||||
.checkentry = icmp6_checkentry,
|
||||
.proto = IPPROTO_ICMPV6,
|
||||
.family = NFPROTO_IPV6,
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init tcpudp_mt_init(void)
|
||||
|
Loading…
Reference in New Issue
Block a user