Skip to content

Commit 36ce998

Browse files
author
Florian Westphal
committed
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>
1 parent bde7170 commit 36ce998

File tree

3 files changed

+112
-134
lines changed

3 files changed

+112
-134
lines changed

net/ipv4/netfilter/ip_tables.c

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
#include <linux/vmalloc.h>
1515
#include <linux/netdevice.h>
1616
#include <linux/module.h>
17-
#include <linux/icmp.h>
1817
#include <net/ip.h>
1918
#include <net/compat.h>
2019
#include <linux/uaccess.h>
@@ -31,7 +30,6 @@
3130
MODULE_LICENSE("GPL");
3231
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
3332
MODULE_DESCRIPTION("IPv4 packet filter");
34-
MODULE_ALIAS("ipt_icmp");
3533

3634
void *ipt_alloc_initial_table(const struct xt_table *info)
3735
{
@@ -1799,52 +1797,6 @@ void ipt_unregister_table_exit(struct net *net, const char *name)
17991797
__ipt_unregister_table(net, table);
18001798
}
18011799

1802-
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
1803-
static inline bool
1804-
icmp_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1805-
u_int8_t type, u_int8_t code,
1806-
bool invert)
1807-
{
1808-
return ((test_type == 0xFF) ||
1809-
(type == test_type && code >= min_code && code <= max_code))
1810-
^ invert;
1811-
}
1812-
1813-
static bool
1814-
icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
1815-
{
1816-
const struct icmphdr *ic;
1817-
struct icmphdr _icmph;
1818-
const struct ipt_icmp *icmpinfo = par->matchinfo;
1819-
1820-
/* Must not be a fragment. */
1821-
if (par->fragoff != 0)
1822-
return false;
1823-
1824-
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
1825-
if (ic == NULL) {
1826-
/* We've been asked to examine this packet, and we
1827-
* can't. Hence, no choice but to drop.
1828-
*/
1829-
par->hotdrop = true;
1830-
return false;
1831-
}
1832-
1833-
return icmp_type_code_match(icmpinfo->type,
1834-
icmpinfo->code[0],
1835-
icmpinfo->code[1],
1836-
ic->type, ic->code,
1837-
!!(icmpinfo->invflags&IPT_ICMP_INV));
1838-
}
1839-
1840-
static int icmp_checkentry(const struct xt_mtchk_param *par)
1841-
{
1842-
const struct ipt_icmp *icmpinfo = par->matchinfo;
1843-
1844-
/* Must specify no unknown invflags */
1845-
return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
1846-
}
1847-
18481800
static struct xt_target ipt_builtin_tg[] __read_mostly = {
18491801
{
18501802
.name = XT_STANDARD_TARGET,
@@ -1875,18 +1827,6 @@ static struct nf_sockopt_ops ipt_sockopts = {
18751827
.owner = THIS_MODULE,
18761828
};
18771829

1878-
static struct xt_match ipt_builtin_mt[] __read_mostly = {
1879-
{
1880-
.name = "icmp",
1881-
.match = icmp_match,
1882-
.matchsize = sizeof(struct ipt_icmp),
1883-
.checkentry = icmp_checkentry,
1884-
.proto = IPPROTO_ICMP,
1885-
.family = NFPROTO_IPV4,
1886-
.me = THIS_MODULE,
1887-
},
1888-
};
1889-
18901830
static int __net_init ip_tables_net_init(struct net *net)
18911831
{
18921832
return xt_proto_init(net, NFPROTO_IPV4);
@@ -1914,19 +1854,14 @@ static int __init ip_tables_init(void)
19141854
ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
19151855
if (ret < 0)
19161856
goto err2;
1917-
ret = xt_register_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
1918-
if (ret < 0)
1919-
goto err4;
19201857

19211858
/* Register setsockopt */
19221859
ret = nf_register_sockopt(&ipt_sockopts);
19231860
if (ret < 0)
1924-
goto err5;
1861+
goto err4;
19251862

19261863
return 0;
19271864

1928-
err5:
1929-
xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
19301865
err4:
19311866
xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
19321867
err2:
@@ -1939,7 +1874,6 @@ static void __exit ip_tables_fini(void)
19391874
{
19401875
nf_unregister_sockopt(&ipt_sockopts);
19411876

1942-
xt_unregister_matches(ipt_builtin_mt, ARRAY_SIZE(ipt_builtin_mt));
19431877
xt_unregister_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg));
19441878
unregister_pernet_subsys(&ip_tables_net_ops);
19451879
}

net/ipv6/netfilter/ip6_tables.c

Lines changed: 1 addition & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include <linux/netdevice.h>
1919
#include <linux/module.h>
2020
#include <linux/poison.h>
21-
#include <linux/icmpv6.h>
2221
#include <net/ipv6.h>
2322
#include <net/compat.h>
2423
#include <linux/uaccess.h>
@@ -35,7 +34,6 @@
3534
MODULE_LICENSE("GPL");
3635
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
3736
MODULE_DESCRIPTION("IPv6 packet filter");
38-
MODULE_ALIAS("ip6t_icmp6");
3937

4038
void *ip6t_alloc_initial_table(const struct xt_table *info)
4139
{
@@ -1805,52 +1803,6 @@ void ip6t_unregister_table_exit(struct net *net, const char *name)
18051803
__ip6t_unregister_table(net, table);
18061804
}
18071805

1808-
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
1809-
static inline bool
1810-
icmp6_type_code_match(u_int8_t test_type, u_int8_t min_code, u_int8_t max_code,
1811-
u_int8_t type, u_int8_t code,
1812-
bool invert)
1813-
{
1814-
return (type == test_type && code >= min_code && code <= max_code)
1815-
^ invert;
1816-
}
1817-
1818-
static bool
1819-
icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
1820-
{
1821-
const struct icmp6hdr *ic;
1822-
struct icmp6hdr _icmph;
1823-
const struct ip6t_icmp *icmpinfo = par->matchinfo;
1824-
1825-
/* Must not be a fragment. */
1826-
if (par->fragoff != 0)
1827-
return false;
1828-
1829-
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
1830-
if (ic == NULL) {
1831-
/* We've been asked to examine this packet, and we
1832-
* can't. Hence, no choice but to drop.
1833-
*/
1834-
par->hotdrop = true;
1835-
return false;
1836-
}
1837-
1838-
return icmp6_type_code_match(icmpinfo->type,
1839-
icmpinfo->code[0],
1840-
icmpinfo->code[1],
1841-
ic->icmp6_type, ic->icmp6_code,
1842-
!!(icmpinfo->invflags&IP6T_ICMP_INV));
1843-
}
1844-
1845-
/* Called when user tries to insert an entry of this type. */
1846-
static int icmp6_checkentry(const struct xt_mtchk_param *par)
1847-
{
1848-
const struct ip6t_icmp *icmpinfo = par->matchinfo;
1849-
1850-
/* Must specify no unknown invflags */
1851-
return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
1852-
}
1853-
18541806
/* The built-in targets: standard (NULL) and error. */
18551807
static struct xt_target ip6t_builtin_tg[] __read_mostly = {
18561808
{
@@ -1882,18 +1834,6 @@ static struct nf_sockopt_ops ip6t_sockopts = {
18821834
.owner = THIS_MODULE,
18831835
};
18841836

1885-
static struct xt_match ip6t_builtin_mt[] __read_mostly = {
1886-
{
1887-
.name = "icmp6",
1888-
.match = icmp6_match,
1889-
.matchsize = sizeof(struct ip6t_icmp),
1890-
.checkentry = icmp6_checkentry,
1891-
.proto = IPPROTO_ICMPV6,
1892-
.family = NFPROTO_IPV6,
1893-
.me = THIS_MODULE,
1894-
},
1895-
};
1896-
18971837
static int __net_init ip6_tables_net_init(struct net *net)
18981838
{
18991839
return xt_proto_init(net, NFPROTO_IPV6);
@@ -1921,19 +1861,14 @@ static int __init ip6_tables_init(void)
19211861
ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
19221862
if (ret < 0)
19231863
goto err2;
1924-
ret = xt_register_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
1925-
if (ret < 0)
1926-
goto err4;
19271864

19281865
/* Register setsockopt */
19291866
ret = nf_register_sockopt(&ip6t_sockopts);
19301867
if (ret < 0)
1931-
goto err5;
1868+
goto err4;
19321869

19331870
return 0;
19341871

1935-
err5:
1936-
xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
19371872
err4:
19381873
xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
19391874
err2:
@@ -1946,7 +1881,6 @@ static void __exit ip6_tables_fini(void)
19461881
{
19471882
nf_unregister_sockopt(&ip6t_sockopts);
19481883

1949-
xt_unregister_matches(ip6t_builtin_mt, ARRAY_SIZE(ip6t_builtin_mt));
19501884
xt_unregister_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg));
19511885
unregister_pernet_subsys(&ip6_tables_net_ops);
19521886
}

net/netfilter/xt_tcpudp.c

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <linux/module.h>
55
#include <net/ip.h>
66
#include <linux/ipv6.h>
7+
#include <linux/icmp.h>
78
#include <net/ipv6.h>
89
#include <net/tcp.h>
910
#include <net/udp.h>
@@ -20,6 +21,8 @@ MODULE_ALIAS("ipt_udp");
2021
MODULE_ALIAS("ipt_tcp");
2122
MODULE_ALIAS("ip6t_udp");
2223
MODULE_ALIAS("ip6t_tcp");
24+
MODULE_ALIAS("ipt_icmp");
25+
MODULE_ALIAS("ip6t_icmp6");
2326

2427
/* Returns 1 if the port is matched by the range, 0 otherwise */
2528
static inline bool
@@ -161,6 +164,95 @@ static int udp_mt_check(const struct xt_mtchk_param *par)
161164
return (udpinfo->invflags & ~XT_UDP_INV_MASK) ? -EINVAL : 0;
162165
}
163166

167+
/* Returns 1 if the type and code is matched by the range, 0 otherwise */
168+
static bool type_code_in_range(u8 test_type, u8 min_code, u8 max_code,
169+
u8 type, u8 code)
170+
{
171+
return type == test_type && code >= min_code && code <= max_code;
172+
}
173+
174+
static bool icmp_type_code_match(u8 test_type, u8 min_code, u8 max_code,
175+
u8 type, u8 code, bool invert)
176+
{
177+
return (test_type == 0xFF ||
178+
type_code_in_range(test_type, min_code, max_code, type, code))
179+
^ invert;
180+
}
181+
182+
static bool icmp6_type_code_match(u8 test_type, u8 min_code, u8 max_code,
183+
u8 type, u8 code, bool invert)
184+
{
185+
return type_code_in_range(test_type, min_code, max_code, type, code) ^ invert;
186+
}
187+
188+
static bool
189+
icmp_match(const struct sk_buff *skb, struct xt_action_param *par)
190+
{
191+
const struct icmphdr *ic;
192+
struct icmphdr _icmph;
193+
const struct ipt_icmp *icmpinfo = par->matchinfo;
194+
195+
/* Must not be a fragment. */
196+
if (par->fragoff != 0)
197+
return false;
198+
199+
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
200+
if (!ic) {
201+
/* We've been asked to examine this packet, and we
202+
* can't. Hence, no choice but to drop.
203+
*/
204+
par->hotdrop = true;
205+
return false;
206+
}
207+
208+
return icmp_type_code_match(icmpinfo->type,
209+
icmpinfo->code[0],
210+
icmpinfo->code[1],
211+
ic->type, ic->code,
212+
!!(icmpinfo->invflags & IPT_ICMP_INV));
213+
}
214+
215+
static bool
216+
icmp6_match(const struct sk_buff *skb, struct xt_action_param *par)
217+
{
218+
const struct icmp6hdr *ic;
219+
struct icmp6hdr _icmph;
220+
const struct ip6t_icmp *icmpinfo = par->matchinfo;
221+
222+
/* Must not be a fragment. */
223+
if (par->fragoff != 0)
224+
return false;
225+
226+
ic = skb_header_pointer(skb, par->thoff, sizeof(_icmph), &_icmph);
227+
if (!ic) {
228+
/* We've been asked to examine this packet, and we
229+
* can't. Hence, no choice but to drop.
230+
*/
231+
par->hotdrop = true;
232+
return false;
233+
}
234+
235+
return icmp6_type_code_match(icmpinfo->type,
236+
icmpinfo->code[0],
237+
icmpinfo->code[1],
238+
ic->icmp6_type, ic->icmp6_code,
239+
!!(icmpinfo->invflags & IP6T_ICMP_INV));
240+
}
241+
242+
static int icmp_checkentry(const struct xt_mtchk_param *par)
243+
{
244+
const struct ipt_icmp *icmpinfo = par->matchinfo;
245+
246+
return (icmpinfo->invflags & ~IPT_ICMP_INV) ? -EINVAL : 0;
247+
}
248+
249+
static int icmp6_checkentry(const struct xt_mtchk_param *par)
250+
{
251+
const struct ip6t_icmp *icmpinfo = par->matchinfo;
252+
253+
return (icmpinfo->invflags & ~IP6T_ICMP_INV) ? -EINVAL : 0;
254+
}
255+
164256
static struct xt_match tcpudp_mt_reg[] __read_mostly = {
165257
{
166258
.name = "tcp",
@@ -216,6 +308,24 @@ static struct xt_match tcpudp_mt_reg[] __read_mostly = {
216308
.proto = IPPROTO_UDPLITE,
217309
.me = THIS_MODULE,
218310
},
311+
{
312+
.name = "icmp",
313+
.match = icmp_match,
314+
.matchsize = sizeof(struct ipt_icmp),
315+
.checkentry = icmp_checkentry,
316+
.proto = IPPROTO_ICMP,
317+
.family = NFPROTO_IPV4,
318+
.me = THIS_MODULE,
319+
},
320+
{
321+
.name = "icmp6",
322+
.match = icmp6_match,
323+
.matchsize = sizeof(struct ip6t_icmp),
324+
.checkentry = icmp6_checkentry,
325+
.proto = IPPROTO_ICMPV6,
326+
.family = NFPROTO_IPV6,
327+
.me = THIS_MODULE,
328+
},
219329
};
220330

221331
static int __init tcpudp_mt_init(void)

0 commit comments

Comments
 (0)