aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiri Olsa <jolsa@redhat.com>2011-01-18 12:12:24 -0500
committerPatrick McHardy <kaber@trash.net>2011-01-18 12:12:24 -0500
commit93557f53e1fbd9e2b6574ab0a9b5852628fde9e3 (patch)
treeb6bc24a10d4a48c354935d8e4fe4d110cf6dc060
parent94d117a1c78df38abdea0c09ef00c205b923b567 (diff)
netfilter: nf_conntrack: nf_conntrack snmp helper
Adding support for SNMP broadcast connection tracking. The SNMP broadcast requests are now paired with the SNMP responses. Thus allowing using SNMP broadcasts with firewall enabled. Please refer to the following conversation: http://marc.info/?l=netfilter-devel&m=125992205006600&w=2 Patrick McHardy wrote: > > The best solution would be to add generic broadcast tracking, the > > use of expectations for this is a bit of abuse. > > The second best choice I guess would be to move the help() function > > to a shared module and generalize it so it can be used for both. This patch implements the "second best choice". Since the netbios-ns conntrack module uses the same helper functionality as the snmp, only one helper function is added for both snmp and netbios-ns modules into the new object - nf_conntrack_broadcast. Signed-off-by: Jiri Olsa <jolsa@redhat.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r--include/linux/netfilter/nf_conntrack_snmp.h9
-rw-r--r--include/net/netfilter/nf_conntrack_helper.h6
-rw-r--r--net/ipv4/netfilter/Kconfig3
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c9
-rw-r--r--net/netfilter/Kconfig19
-rw-r--r--net/netfilter/Makefile2
-rw-r--r--net/netfilter/nf_conntrack_broadcast.c82
-rw-r--r--net/netfilter/nf_conntrack_netbios_ns.c74
-rw-r--r--net/netfilter/nf_conntrack_snmp.c77
9 files changed, 211 insertions, 70 deletions
diff --git a/include/linux/netfilter/nf_conntrack_snmp.h b/include/linux/netfilter/nf_conntrack_snmp.h
new file mode 100644
index 000000000000..064bc63a5346
--- /dev/null
+++ b/include/linux/netfilter/nf_conntrack_snmp.h
@@ -0,0 +1,9 @@
1#ifndef _NF_CONNTRACK_SNMP_H
2#define _NF_CONNTRACK_SNMP_H
3
4extern int (*nf_nat_snmp_hook)(struct sk_buff *skb,
5 unsigned int protoff,
6 struct nf_conn *ct,
7 enum ip_conntrack_info ctinfo);
8
9#endif /* _NF_CONNTRACK_SNMP_H */
diff --git a/include/net/netfilter/nf_conntrack_helper.h b/include/net/netfilter/nf_conntrack_helper.h
index 32c305dbdab6..f1c1311adc2c 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -63,4 +63,10 @@ static inline struct nf_conn_help *nfct_help(const struct nf_conn *ct)
63extern int nf_conntrack_helper_init(void); 63extern int nf_conntrack_helper_init(void);
64extern void nf_conntrack_helper_fini(void); 64extern void nf_conntrack_helper_fini(void);
65 65
66extern int nf_conntrack_broadcast_help(struct sk_buff *skb,
67 unsigned int protoff,
68 struct nf_conn *ct,
69 enum ip_conntrack_info ctinfo,
70 unsigned int timeout);
71
66#endif /*_NF_CONNTRACK_HELPER_H*/ 72#endif /*_NF_CONNTRACK_HELPER_H*/
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index babd1a2bae5f..f926a310075d 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -206,8 +206,9 @@ config IP_NF_TARGET_REDIRECT
206 206
207config NF_NAT_SNMP_BASIC 207config NF_NAT_SNMP_BASIC
208 tristate "Basic SNMP-ALG support" 208 tristate "Basic SNMP-ALG support"
209 depends on NF_NAT 209 depends on NF_CONNTRACK_SNMP && NF_NAT
210 depends on NETFILTER_ADVANCED 210 depends on NETFILTER_ADVANCED
211 default NF_NAT && NF_CONNTRACK_SNMP
211 ---help--- 212 ---help---
212 213
213 This module implements an Application Layer Gateway (ALG) for 214 This module implements an Application Layer Gateway (ALG) for
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index ee5f419d0a56..8812a02078ab 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -54,6 +54,7 @@
54#include <net/netfilter/nf_conntrack_expect.h> 54#include <net/netfilter/nf_conntrack_expect.h>
55#include <net/netfilter/nf_conntrack_helper.h> 55#include <net/netfilter/nf_conntrack_helper.h>
56#include <net/netfilter/nf_nat_helper.h> 56#include <net/netfilter/nf_nat_helper.h>
57#include <linux/netfilter/nf_conntrack_snmp.h>
57 58
58MODULE_LICENSE("GPL"); 59MODULE_LICENSE("GPL");
59MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>"); 60MODULE_AUTHOR("James Morris <jmorris@intercode.com.au>");
@@ -1310,9 +1311,9 @@ static int __init nf_nat_snmp_basic_init(void)
1310{ 1311{
1311 int ret = 0; 1312 int ret = 0;
1312 1313
1313 ret = nf_conntrack_helper_register(&snmp_helper); 1314 BUG_ON(nf_nat_snmp_hook != NULL);
1314 if (ret < 0) 1315 rcu_assign_pointer(nf_nat_snmp_hook, help);
1315 return ret; 1316
1316 ret = nf_conntrack_helper_register(&snmp_trap_helper); 1317 ret = nf_conntrack_helper_register(&snmp_trap_helper);
1317 if (ret < 0) { 1318 if (ret < 0) {
1318 nf_conntrack_helper_unregister(&snmp_helper); 1319 nf_conntrack_helper_unregister(&snmp_helper);
@@ -1323,7 +1324,7 @@ static int __init nf_nat_snmp_basic_init(void)
1323 1324
1324static void __exit nf_nat_snmp_basic_fini(void) 1325static void __exit nf_nat_snmp_basic_fini(void)
1325{ 1326{
1326 nf_conntrack_helper_unregister(&snmp_helper); 1327 rcu_assign_pointer(nf_nat_snmp_hook, NULL);
1327 nf_conntrack_helper_unregister(&snmp_trap_helper); 1328 nf_conntrack_helper_unregister(&snmp_trap_helper);
1328} 1329}
1329 1330
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index e2480bddbfd5..939b504604c2 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -185,9 +185,13 @@ config NF_CONNTRACK_IRC
185 185
186 To compile it as a module, choose M here. If unsure, say N. 186 To compile it as a module, choose M here. If unsure, say N.
187 187
188config NF_CONNTRACK_BROADCAST
189 tristate
190
188config NF_CONNTRACK_NETBIOS_NS 191config NF_CONNTRACK_NETBIOS_NS
189 tristate "NetBIOS name service protocol support" 192 tristate "NetBIOS name service protocol support"
190 depends on NETFILTER_ADVANCED 193 depends on NETFILTER_ADVANCED
194 select NF_CONNTRACK_BROADCAST
191 help 195 help
192 NetBIOS name service requests are sent as broadcast messages from an 196 NetBIOS name service requests are sent as broadcast messages from an
193 unprivileged port and responded to with unicast messages to the 197 unprivileged port and responded to with unicast messages to the
@@ -204,6 +208,21 @@ config NF_CONNTRACK_NETBIOS_NS
204 208
205 To compile it as a module, choose M here. If unsure, say N. 209 To compile it as a module, choose M here. If unsure, say N.
206 210
211config NF_CONNTRACK_SNMP
212 tristate "SNMP service protocol support"
213 depends on NETFILTER_ADVANCED
214 select NF_CONNTRACK_BROADCAST
215 help
216 SNMP service requests are sent as broadcast messages from an
217 unprivileged port and responded to with unicast messages to the
218 same port. This make them hard to firewall properly because connection
219 tracking doesn't deal with broadcasts. This helper tracks locally
220 originating SNMP service requests and the corresponding
221 responses. It relies on correct IP address configuration, specifically
222 netmask and broadcast address.
223
224 To compile it as a module, choose M here. If unsure, say N.
225
207config NF_CONNTRACK_PPTP 226config NF_CONNTRACK_PPTP
208 tristate "PPtP protocol support" 227 tristate "PPtP protocol support"
209 depends on NETFILTER_ADVANCED 228 depends on NETFILTER_ADVANCED
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 401d574bdfd2..2c2628de9d3f 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -28,7 +28,9 @@ obj-$(CONFIG_NF_CONNTRACK_AMANDA) += nf_conntrack_amanda.o
28obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o 28obj-$(CONFIG_NF_CONNTRACK_FTP) += nf_conntrack_ftp.o
29obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o 29obj-$(CONFIG_NF_CONNTRACK_H323) += nf_conntrack_h323.o
30obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o 30obj-$(CONFIG_NF_CONNTRACK_IRC) += nf_conntrack_irc.o
31obj-$(CONFIG_NF_CONNTRACK_BROADCAST) += nf_conntrack_broadcast.o
31obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o 32obj-$(CONFIG_NF_CONNTRACK_NETBIOS_NS) += nf_conntrack_netbios_ns.o
33obj-$(CONFIG_NF_CONNTRACK_SNMP) += nf_conntrack_snmp.o
32obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o 34obj-$(CONFIG_NF_CONNTRACK_PPTP) += nf_conntrack_pptp.o
33obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o 35obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
34obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o 36obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
diff --git a/net/netfilter/nf_conntrack_broadcast.c b/net/netfilter/nf_conntrack_broadcast.c
new file mode 100644
index 000000000000..4e99cca61612
--- /dev/null
+++ b/net/netfilter/nf_conntrack_broadcast.c
@@ -0,0 +1,82 @@
1/*
2 * broadcast connection tracking helper
3 *
4 * (c) 2005 Patrick McHardy <kaber@trash.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11
12#include <linux/module.h>
13#include <linux/ip.h>
14#include <net/route.h>
15#include <linux/inetdevice.h>
16#include <linux/skbuff.h>
17
18#include <net/netfilter/nf_conntrack.h>
19#include <net/netfilter/nf_conntrack_helper.h>
20#include <net/netfilter/nf_conntrack_expect.h>
21
22int nf_conntrack_broadcast_help(struct sk_buff *skb,
23 unsigned int protoff,
24 struct nf_conn *ct,
25 enum ip_conntrack_info ctinfo,
26 unsigned int timeout)
27{
28 struct nf_conntrack_expect *exp;
29 struct iphdr *iph = ip_hdr(skb);
30 struct rtable *rt = skb_rtable(skb);
31 struct in_device *in_dev;
32 struct nf_conn_help *help = nfct_help(ct);
33 __be32 mask = 0;
34
35 /* we're only interested in locally generated packets */
36 if (skb->sk == NULL)
37 goto out;
38 if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
39 goto out;
40 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
41 goto out;
42
43 rcu_read_lock();
44 in_dev = __in_dev_get_rcu(rt->dst.dev);
45 if (in_dev != NULL) {
46 for_primary_ifa(in_dev) {
47 if (ifa->ifa_broadcast == iph->daddr) {
48 mask = ifa->ifa_mask;
49 break;
50 }
51 } endfor_ifa(in_dev);
52 }
53 rcu_read_unlock();
54
55 if (mask == 0)
56 goto out;
57
58 exp = nf_ct_expect_alloc(ct);
59 if (exp == NULL)
60 goto out;
61
62 exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
63 exp->tuple.src.u.udp.port = help->helper->tuple.src.u.udp.port;
64
65 exp->mask.src.u3.ip = mask;
66 exp->mask.src.u.udp.port = htons(0xFFFF);
67
68 exp->expectfn = NULL;
69 exp->flags = NF_CT_EXPECT_PERMANENT;
70 exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
71 exp->helper = NULL;
72
73 nf_ct_expect_related(exp);
74 nf_ct_expect_put(exp);
75
76 nf_ct_refresh(ct, skb, timeout * HZ);
77out:
78 return NF_ACCEPT;
79}
80EXPORT_SYMBOL_GPL(nf_conntrack_broadcast_help);
81
82MODULE_LICENSE("GPL");
diff --git a/net/netfilter/nf_conntrack_netbios_ns.c b/net/netfilter/nf_conntrack_netbios_ns.c
index aadde018a072..4c8f30a3d6d2 100644
--- a/net/netfilter/nf_conntrack_netbios_ns.c
+++ b/net/netfilter/nf_conntrack_netbios_ns.c
@@ -18,14 +18,7 @@
18#include <linux/kernel.h> 18#include <linux/kernel.h>
19#include <linux/module.h> 19#include <linux/module.h>
20#include <linux/init.h> 20#include <linux/init.h>
21#include <linux/skbuff.h>
22#include <linux/netdevice.h>
23#include <linux/inetdevice.h>
24#include <linux/if_addr.h>
25#include <linux/in.h> 21#include <linux/in.h>
26#include <linux/ip.h>
27#include <linux/netfilter.h>
28#include <net/route.h>
29 22
30#include <net/netfilter/nf_conntrack.h> 23#include <net/netfilter/nf_conntrack.h>
31#include <net/netfilter/nf_conntrack_helper.h> 24#include <net/netfilter/nf_conntrack_helper.h>
@@ -40,75 +33,26 @@ MODULE_ALIAS("ip_conntrack_netbios_ns");
40MODULE_ALIAS_NFCT_HELPER("netbios_ns"); 33MODULE_ALIAS_NFCT_HELPER("netbios_ns");
41 34
42static unsigned int timeout __read_mostly = 3; 35static unsigned int timeout __read_mostly = 3;
43module_param(timeout, uint, 0400); 36module_param(timeout, uint, S_IRUSR);
44MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds"); 37MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
45 38
46static int help(struct sk_buff *skb, unsigned int protoff,
47 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
48{
49 struct nf_conntrack_expect *exp;
50 struct iphdr *iph = ip_hdr(skb);
51 struct rtable *rt = skb_rtable(skb);
52 struct in_device *in_dev;
53 __be32 mask = 0;
54
55 /* we're only interested in locally generated packets */
56 if (skb->sk == NULL)
57 goto out;
58 if (rt == NULL || !(rt->rt_flags & RTCF_BROADCAST))
59 goto out;
60 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
61 goto out;
62
63 rcu_read_lock();
64 in_dev = __in_dev_get_rcu(rt->dst.dev);
65 if (in_dev != NULL) {
66 for_primary_ifa(in_dev) {
67 if (ifa->ifa_broadcast == iph->daddr) {
68 mask = ifa->ifa_mask;
69 break;
70 }
71 } endfor_ifa(in_dev);
72 }
73 rcu_read_unlock();
74
75 if (mask == 0)
76 goto out;
77
78 exp = nf_ct_expect_alloc(ct);
79 if (exp == NULL)
80 goto out;
81
82 exp->tuple = ct->tuplehash[IP_CT_DIR_REPLY].tuple;
83 exp->tuple.src.u.udp.port = htons(NMBD_PORT);
84
85 exp->mask.src.u3.ip = mask;
86 exp->mask.src.u.udp.port = htons(0xFFFF);
87
88 exp->expectfn = NULL;
89 exp->flags = NF_CT_EXPECT_PERMANENT;
90 exp->class = NF_CT_EXPECT_CLASS_DEFAULT;
91 exp->helper = NULL;
92
93 nf_ct_expect_related(exp);
94 nf_ct_expect_put(exp);
95
96 nf_ct_refresh(ct, skb, timeout * HZ);
97out:
98 return NF_ACCEPT;
99}
100
101static struct nf_conntrack_expect_policy exp_policy = { 39static struct nf_conntrack_expect_policy exp_policy = {
102 .max_expected = 1, 40 .max_expected = 1,
103}; 41};
104 42
43static int netbios_ns_help(struct sk_buff *skb, unsigned int protoff,
44 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
45{
46 return nf_conntrack_broadcast_help(skb, protoff, ct, ctinfo, timeout);
47}
48
105static struct nf_conntrack_helper helper __read_mostly = { 49static struct nf_conntrack_helper helper __read_mostly = {
106 .name = "netbios-ns", 50 .name = "netbios-ns",
107 .tuple.src.l3num = AF_INET, 51 .tuple.src.l3num = NFPROTO_IPV4,
108 .tuple.src.u.udp.port = cpu_to_be16(NMBD_PORT), 52 .tuple.src.u.udp.port = cpu_to_be16(NMBD_PORT),
109 .tuple.dst.protonum = IPPROTO_UDP, 53 .tuple.dst.protonum = IPPROTO_UDP,
110 .me = THIS_MODULE, 54 .me = THIS_MODULE,
111 .help = help, 55 .help = netbios_ns_help,
112 .expect_policy = &exp_policy, 56 .expect_policy = &exp_policy,
113}; 57};
114 58
diff --git a/net/netfilter/nf_conntrack_snmp.c b/net/netfilter/nf_conntrack_snmp.c
new file mode 100644
index 000000000000..6e545e26289e
--- /dev/null
+++ b/net/netfilter/nf_conntrack_snmp.c
@@ -0,0 +1,77 @@
1/*
2 * SNMP service broadcast connection tracking helper
3 *
4 * (c) 2011 Jiri Olsa <jolsa@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/init.h>
14#include <linux/in.h>
15
16#include <net/netfilter/nf_conntrack.h>
17#include <net/netfilter/nf_conntrack_helper.h>
18#include <net/netfilter/nf_conntrack_expect.h>
19
20#define SNMP_PORT 161
21
22MODULE_AUTHOR("Jiri Olsa <jolsa@redhat.com>");
23MODULE_DESCRIPTION("SNMP service broadcast connection tracking helper");
24MODULE_LICENSE("GPL");
25MODULE_ALIAS_NFCT_HELPER("snmp");
26
27static unsigned int timeout __read_mostly = 30;
28module_param(timeout, uint, S_IRUSR);
29MODULE_PARM_DESC(timeout, "timeout for master connection/replies in seconds");
30
31int (*nf_nat_snmp_hook)(struct sk_buff *skb,
32 unsigned int protoff,
33 struct nf_conn *ct,
34 enum ip_conntrack_info ctinfo);
35EXPORT_SYMBOL_GPL(nf_nat_snmp_hook);
36
37static int snmp_conntrack_help(struct sk_buff *skb, unsigned int protoff,
38 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
39{
40 typeof(nf_nat_snmp_hook) nf_nat_snmp;
41
42 nf_conntrack_broadcast_help(skb, protoff, ct, ctinfo, timeout);
43
44 nf_nat_snmp = rcu_dereference(nf_nat_snmp_hook);
45 if (nf_nat_snmp && ct->status & IPS_NAT_MASK)
46 return nf_nat_snmp(skb, protoff, ct, ctinfo);
47
48 return NF_ACCEPT;
49}
50
51static struct nf_conntrack_expect_policy exp_policy = {
52 .max_expected = 1,
53};
54
55static struct nf_conntrack_helper helper __read_mostly = {
56 .name = "snmp",
57 .tuple.src.l3num = NFPROTO_IPV4,
58 .tuple.src.u.udp.port = cpu_to_be16(SNMP_PORT),
59 .tuple.dst.protonum = IPPROTO_UDP,
60 .me = THIS_MODULE,
61 .help = snmp_conntrack_help,
62 .expect_policy = &exp_policy,
63};
64
65static int __init nf_conntrack_snmp_init(void)
66{
67 exp_policy.timeout = timeout;
68 return nf_conntrack_helper_register(&helper);
69}
70
71static void __exit nf_conntrack_snmp_fini(void)
72{
73 nf_conntrack_helper_unregister(&helper);
74}
75
76module_init(nf_conntrack_snmp_init);
77module_exit(nf_conntrack_snmp_fini);