aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-02-16 14:15:13 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-16 14:15:13 -0500
commit749f621e20ab0db35a15ff730088922603c809ba (patch)
tree2684d12199b58f2b9e0c5b7e6cc0ea3f002e611a /net
parent339c6e99853d2ef1f02ad8a313e079050a300427 (diff)
parent3e5e524ffb5fcf2447eb5dd9f8e54ad22dd9baa7 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/kaber/nf-next-2.6
Diffstat (limited to 'net')
-rw-r--r--net/bridge/netfilter/ebt_802_3.c2
-rw-r--r--net/bridge/netfilter/ebt_arp.c2
-rw-r--r--net/bridge/netfilter/ebt_arpreply.c2
-rw-r--r--net/bridge/netfilter/ebt_dnat.c2
-rw-r--r--net/bridge/netfilter/ebt_ip.c2
-rw-r--r--net/bridge/netfilter/ebt_ip6.c2
-rw-r--r--net/bridge/netfilter/ebt_limit.c2
-rw-r--r--net/bridge/netfilter/ebt_log.c2
-rw-r--r--net/bridge/netfilter/ebt_mark.c2
-rw-r--r--net/bridge/netfilter/ebt_mark_m.c2
-rw-r--r--net/bridge/netfilter/ebt_nflog.c2
-rw-r--r--net/bridge/netfilter/ebt_pkttype.c2
-rw-r--r--net/bridge/netfilter/ebt_redirect.c2
-rw-r--r--net/bridge/netfilter/ebt_snat.c2
-rw-r--r--net/bridge/netfilter/ebt_stp.c2
-rw-r--r--net/bridge/netfilter/ebt_ulog.c2
-rw-r--r--net/bridge/netfilter/ebt_vlan.c2
-rw-r--r--net/bridge/netfilter/ebtable_broute.c2
-rw-r--r--net/bridge/netfilter/ebtable_filter.c2
-rw-r--r--net/bridge/netfilter/ebtable_nat.c2
-rw-r--r--net/bridge/netfilter/ebtables.c94
-rw-r--r--net/ipv4/netfilter/arp_tables.c80
-rw-r--r--net/ipv4/netfilter/arptable_filter.c95
-rw-r--r--net/ipv4/netfilter/ip_tables.c156
-rw-r--r--net/ipv4/netfilter/ipt_CLUSTERIP.c14
-rw-r--r--net/ipv4/netfilter/ipt_ULOG.c4
-rw-r--r--net/ipv4/netfilter/iptable_filter.c124
-rw-r--r--net/ipv4/netfilter/iptable_mangle.c166
-rw-r--r--net/ipv4/netfilter/iptable_raw.c96
-rw-r--r--net/ipv4/netfilter/iptable_security.c117
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c3
-rw-r--r--net/ipv4/netfilter/nf_conntrack_proto_icmp.c11
-rw-r--r--net/ipv4/netfilter/nf_defrag_ipv4.c15
-rw-r--r--net/ipv4/netfilter/nf_nat_core.c24
-rw-r--r--net/ipv4/netfilter/nf_nat_ftp.c105
-rw-r--r--net/ipv4/netfilter/nf_nat_helper.c39
-rw-r--r--net/ipv4/netfilter/nf_nat_pptp.c3
-rw-r--r--net/ipv4/netfilter/nf_nat_rule.c41
-rw-r--r--net/ipv4/netfilter/nf_nat_sip.c154
-rw-r--r--net/ipv4/netfilter/nf_nat_snmp_basic.c31
-rw-r--r--net/ipv6/netfilter/ip6_tables.c158
-rw-r--r--net/ipv6/netfilter/ip6table_filter.c113
-rw-r--r--net/ipv6/netfilter/ip6table_mangle.c141
-rw-r--r--net/ipv6/netfilter/ip6table_raw.c86
-rw-r--r--net/ipv6/netfilter/ip6table_security.c109
-rw-r--r--net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c14
-rw-r--r--net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c11
-rw-r--r--net/ipv6/netfilter/nf_conntrack_reasm.c7
-rw-r--r--net/ipv6/reassembly.c4
-rw-r--r--net/netfilter/Kconfig25
-rw-r--r--net/netfilter/Makefile1
-rw-r--r--net/netfilter/ipvs/Kconfig4
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c42
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c8
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c2
-rw-r--r--net/netfilter/nf_conntrack_core.c164
-rw-r--r--net/netfilter/nf_conntrack_expect.c31
-rw-r--r--net/netfilter/nf_conntrack_extend.c1
-rw-r--r--net/netfilter/nf_conntrack_h323_main.c3
-rw-r--r--net/netfilter/nf_conntrack_helper.c44
-rw-r--r--net/netfilter/nf_conntrack_netlink.c210
-rw-r--r--net/netfilter/nf_conntrack_pptp.c14
-rw-r--r--net/netfilter/nf_conntrack_proto_dccp.c5
-rw-r--r--net/netfilter/nf_conntrack_proto_gre.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_sctp.c2
-rw-r--r--net/netfilter/nf_conntrack_proto_tcp.c4
-rw-r--r--net/netfilter/nf_conntrack_proto_udp.c6
-rw-r--r--net/netfilter/nf_conntrack_proto_udplite.c4
-rw-r--r--net/netfilter/nf_conntrack_sip.c330
-rw-r--r--net/netfilter/nf_conntrack_standalone.c6
-rw-r--r--net/netfilter/nfnetlink.c65
-rw-r--r--net/netfilter/nfnetlink_log.c3
-rw-r--r--net/netfilter/nfnetlink_queue.c7
-rw-r--r--net/netfilter/x_tables.c80
-rw-r--r--net/netfilter/xt_CT.c164
-rw-r--r--net/netfilter/xt_NFQUEUE.c6
-rw-r--r--net/netfilter/xt_RATEEST.c7
-rw-r--r--net/netfilter/xt_TCPMSS.c18
-rw-r--r--net/netfilter/xt_connlimit.c27
-rw-r--r--net/netfilter/xt_hashlimit.c219
-rw-r--r--net/netfilter/xt_limit.c4
-rw-r--r--net/netfilter/xt_osf.c4
-rw-r--r--net/netfilter/xt_recent.c164
-rw-r--r--net/netfilter/xt_repldata.h35
84 files changed, 2053 insertions, 1713 deletions
diff --git a/net/bridge/netfilter/ebt_802_3.c b/net/bridge/netfilter/ebt_802_3.c
index bd91dc58d49b..5d1176758ca5 100644
--- a/net/bridge/netfilter/ebt_802_3.c
+++ b/net/bridge/netfilter/ebt_802_3.c
@@ -52,7 +52,7 @@ static struct xt_match ebt_802_3_mt_reg __read_mostly = {
52 .family = NFPROTO_BRIDGE, 52 .family = NFPROTO_BRIDGE,
53 .match = ebt_802_3_mt, 53 .match = ebt_802_3_mt,
54 .checkentry = ebt_802_3_mt_check, 54 .checkentry = ebt_802_3_mt_check,
55 .matchsize = XT_ALIGN(sizeof(struct ebt_802_3_info)), 55 .matchsize = sizeof(struct ebt_802_3_info),
56 .me = THIS_MODULE, 56 .me = THIS_MODULE,
57}; 57};
58 58
diff --git a/net/bridge/netfilter/ebt_arp.c b/net/bridge/netfilter/ebt_arp.c
index b7ad60419f9a..e727697c5847 100644
--- a/net/bridge/netfilter/ebt_arp.c
+++ b/net/bridge/netfilter/ebt_arp.c
@@ -120,7 +120,7 @@ static struct xt_match ebt_arp_mt_reg __read_mostly = {
120 .family = NFPROTO_BRIDGE, 120 .family = NFPROTO_BRIDGE,
121 .match = ebt_arp_mt, 121 .match = ebt_arp_mt,
122 .checkentry = ebt_arp_mt_check, 122 .checkentry = ebt_arp_mt_check,
123 .matchsize = XT_ALIGN(sizeof(struct ebt_arp_info)), 123 .matchsize = sizeof(struct ebt_arp_info),
124 .me = THIS_MODULE, 124 .me = THIS_MODULE,
125}; 125};
126 126
diff --git a/net/bridge/netfilter/ebt_arpreply.c b/net/bridge/netfilter/ebt_arpreply.c
index 76584cd72e57..f392e9d93f53 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -78,7 +78,7 @@ static struct xt_target ebt_arpreply_tg_reg __read_mostly = {
78 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING), 78 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_PRE_ROUTING),
79 .target = ebt_arpreply_tg, 79 .target = ebt_arpreply_tg,
80 .checkentry = ebt_arpreply_tg_check, 80 .checkentry = ebt_arpreply_tg_check,
81 .targetsize = XT_ALIGN(sizeof(struct ebt_arpreply_info)), 81 .targetsize = sizeof(struct ebt_arpreply_info),
82 .me = THIS_MODULE, 82 .me = THIS_MODULE,
83}; 83};
84 84
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index 6b49ea9e31fb..2bb40d728a35 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -54,7 +54,7 @@ static struct xt_target ebt_dnat_tg_reg __read_mostly = {
54 (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING), 54 (1 << NF_BR_LOCAL_OUT) | (1 << NF_BR_BROUTING),
55 .target = ebt_dnat_tg, 55 .target = ebt_dnat_tg,
56 .checkentry = ebt_dnat_tg_check, 56 .checkentry = ebt_dnat_tg_check,
57 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), 57 .targetsize = sizeof(struct ebt_nat_info),
58 .me = THIS_MODULE, 58 .me = THIS_MODULE,
59}; 59};
60 60
diff --git a/net/bridge/netfilter/ebt_ip.c b/net/bridge/netfilter/ebt_ip.c
index d771bbfbcbe6..5de6df6f86b8 100644
--- a/net/bridge/netfilter/ebt_ip.c
+++ b/net/bridge/netfilter/ebt_ip.c
@@ -110,7 +110,7 @@ static struct xt_match ebt_ip_mt_reg __read_mostly = {
110 .family = NFPROTO_BRIDGE, 110 .family = NFPROTO_BRIDGE,
111 .match = ebt_ip_mt, 111 .match = ebt_ip_mt,
112 .checkentry = ebt_ip_mt_check, 112 .checkentry = ebt_ip_mt_check,
113 .matchsize = XT_ALIGN(sizeof(struct ebt_ip_info)), 113 .matchsize = sizeof(struct ebt_ip_info),
114 .me = THIS_MODULE, 114 .me = THIS_MODULE,
115}; 115};
116 116
diff --git a/net/bridge/netfilter/ebt_ip6.c b/net/bridge/netfilter/ebt_ip6.c
index 784a6573876c..bbf2534ef026 100644
--- a/net/bridge/netfilter/ebt_ip6.c
+++ b/net/bridge/netfilter/ebt_ip6.c
@@ -122,7 +122,7 @@ static struct xt_match ebt_ip6_mt_reg __read_mostly = {
122 .family = NFPROTO_BRIDGE, 122 .family = NFPROTO_BRIDGE,
123 .match = ebt_ip6_mt, 123 .match = ebt_ip6_mt,
124 .checkentry = ebt_ip6_mt_check, 124 .checkentry = ebt_ip6_mt_check,
125 .matchsize = XT_ALIGN(sizeof(struct ebt_ip6_info)), 125 .matchsize = sizeof(struct ebt_ip6_info),
126 .me = THIS_MODULE, 126 .me = THIS_MODULE,
127}; 127};
128 128
diff --git a/net/bridge/netfilter/ebt_limit.c b/net/bridge/netfilter/ebt_limit.c
index f7bd9192ff0c..9dd16e6b10e7 100644
--- a/net/bridge/netfilter/ebt_limit.c
+++ b/net/bridge/netfilter/ebt_limit.c
@@ -90,7 +90,7 @@ static struct xt_match ebt_limit_mt_reg __read_mostly = {
90 .family = NFPROTO_BRIDGE, 90 .family = NFPROTO_BRIDGE,
91 .match = ebt_limit_mt, 91 .match = ebt_limit_mt,
92 .checkentry = ebt_limit_mt_check, 92 .checkentry = ebt_limit_mt_check,
93 .matchsize = XT_ALIGN(sizeof(struct ebt_limit_info)), 93 .matchsize = sizeof(struct ebt_limit_info),
94 .me = THIS_MODULE, 94 .me = THIS_MODULE,
95}; 95};
96 96
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c
index e4ea3fdd1d41..e873924ddb5d 100644
--- a/net/bridge/netfilter/ebt_log.c
+++ b/net/bridge/netfilter/ebt_log.c
@@ -195,7 +195,7 @@ static struct xt_target ebt_log_tg_reg __read_mostly = {
195 .family = NFPROTO_BRIDGE, 195 .family = NFPROTO_BRIDGE,
196 .target = ebt_log_tg, 196 .target = ebt_log_tg,
197 .checkentry = ebt_log_tg_check, 197 .checkentry = ebt_log_tg_check,
198 .targetsize = XT_ALIGN(sizeof(struct ebt_log_info)), 198 .targetsize = sizeof(struct ebt_log_info),
199 .me = THIS_MODULE, 199 .me = THIS_MODULE,
200}; 200};
201 201
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 2fee7e8e2e93..153e167374a2 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -59,7 +59,7 @@ static struct xt_target ebt_mark_tg_reg __read_mostly = {
59 .family = NFPROTO_BRIDGE, 59 .family = NFPROTO_BRIDGE,
60 .target = ebt_mark_tg, 60 .target = ebt_mark_tg,
61 .checkentry = ebt_mark_tg_check, 61 .checkentry = ebt_mark_tg_check,
62 .targetsize = XT_ALIGN(sizeof(struct ebt_mark_t_info)), 62 .targetsize = sizeof(struct ebt_mark_t_info),
63 .me = THIS_MODULE, 63 .me = THIS_MODULE,
64}; 64};
65 65
diff --git a/net/bridge/netfilter/ebt_mark_m.c b/net/bridge/netfilter/ebt_mark_m.c
index ea570f214b1d..89abf4030399 100644
--- a/net/bridge/netfilter/ebt_mark_m.c
+++ b/net/bridge/netfilter/ebt_mark_m.c
@@ -41,7 +41,7 @@ static struct xt_match ebt_mark_mt_reg __read_mostly = {
41 .family = NFPROTO_BRIDGE, 41 .family = NFPROTO_BRIDGE,
42 .match = ebt_mark_mt, 42 .match = ebt_mark_mt,
43 .checkentry = ebt_mark_mt_check, 43 .checkentry = ebt_mark_mt_check,
44 .matchsize = XT_ALIGN(sizeof(struct ebt_mark_m_info)), 44 .matchsize = sizeof(struct ebt_mark_m_info),
45 .me = THIS_MODULE, 45 .me = THIS_MODULE,
46}; 46};
47 47
diff --git a/net/bridge/netfilter/ebt_nflog.c b/net/bridge/netfilter/ebt_nflog.c
index 2a63d996dd4e..40dbd248b9ae 100644
--- a/net/bridge/netfilter/ebt_nflog.c
+++ b/net/bridge/netfilter/ebt_nflog.c
@@ -51,7 +51,7 @@ static struct xt_target ebt_nflog_tg_reg __read_mostly = {
51 .family = NFPROTO_BRIDGE, 51 .family = NFPROTO_BRIDGE,
52 .target = ebt_nflog_tg, 52 .target = ebt_nflog_tg,
53 .checkentry = ebt_nflog_tg_check, 53 .checkentry = ebt_nflog_tg_check,
54 .targetsize = XT_ALIGN(sizeof(struct ebt_nflog_info)), 54 .targetsize = sizeof(struct ebt_nflog_info),
55 .me = THIS_MODULE, 55 .me = THIS_MODULE,
56}; 56};
57 57
diff --git a/net/bridge/netfilter/ebt_pkttype.c b/net/bridge/netfilter/ebt_pkttype.c
index 883e96e2a542..e2a07e6cbef3 100644
--- a/net/bridge/netfilter/ebt_pkttype.c
+++ b/net/bridge/netfilter/ebt_pkttype.c
@@ -36,7 +36,7 @@ static struct xt_match ebt_pkttype_mt_reg __read_mostly = {
36 .family = NFPROTO_BRIDGE, 36 .family = NFPROTO_BRIDGE,
37 .match = ebt_pkttype_mt, 37 .match = ebt_pkttype_mt,
38 .checkentry = ebt_pkttype_mt_check, 38 .checkentry = ebt_pkttype_mt_check,
39 .matchsize = XT_ALIGN(sizeof(struct ebt_pkttype_info)), 39 .matchsize = sizeof(struct ebt_pkttype_info),
40 .me = THIS_MODULE, 40 .me = THIS_MODULE,
41}; 41};
42 42
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c
index c8a49f7a57ba..9be8fbcd370b 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -59,7 +59,7 @@ static struct xt_target ebt_redirect_tg_reg __read_mostly = {
59 (1 << NF_BR_BROUTING), 59 (1 << NF_BR_BROUTING),
60 .target = ebt_redirect_tg, 60 .target = ebt_redirect_tg,
61 .checkentry = ebt_redirect_tg_check, 61 .checkentry = ebt_redirect_tg_check,
62 .targetsize = XT_ALIGN(sizeof(struct ebt_redirect_info)), 62 .targetsize = sizeof(struct ebt_redirect_info),
63 .me = THIS_MODULE, 63 .me = THIS_MODULE,
64}; 64};
65 65
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index 8d04d4c302bd..9c7b520765a2 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -67,7 +67,7 @@ static struct xt_target ebt_snat_tg_reg __read_mostly = {
67 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING), 67 .hooks = (1 << NF_BR_NUMHOOKS) | (1 << NF_BR_POST_ROUTING),
68 .target = ebt_snat_tg, 68 .target = ebt_snat_tg,
69 .checkentry = ebt_snat_tg_check, 69 .checkentry = ebt_snat_tg_check,
70 .targetsize = XT_ALIGN(sizeof(struct ebt_nat_info)), 70 .targetsize = sizeof(struct ebt_nat_info),
71 .me = THIS_MODULE, 71 .me = THIS_MODULE,
72}; 72};
73 73
diff --git a/net/bridge/netfilter/ebt_stp.c b/net/bridge/netfilter/ebt_stp.c
index 75e29a9cebda..92a93d363765 100644
--- a/net/bridge/netfilter/ebt_stp.c
+++ b/net/bridge/netfilter/ebt_stp.c
@@ -177,7 +177,7 @@ static struct xt_match ebt_stp_mt_reg __read_mostly = {
177 .family = NFPROTO_BRIDGE, 177 .family = NFPROTO_BRIDGE,
178 .match = ebt_stp_mt, 178 .match = ebt_stp_mt,
179 .checkentry = ebt_stp_mt_check, 179 .checkentry = ebt_stp_mt_check,
180 .matchsize = XT_ALIGN(sizeof(struct ebt_stp_info)), 180 .matchsize = sizeof(struct ebt_stp_info),
181 .me = THIS_MODULE, 181 .me = THIS_MODULE,
182}; 182};
183 183
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c
index ce50688a6431..c6ac657074a6 100644
--- a/net/bridge/netfilter/ebt_ulog.c
+++ b/net/bridge/netfilter/ebt_ulog.c
@@ -275,7 +275,7 @@ static struct xt_target ebt_ulog_tg_reg __read_mostly = {
275 .family = NFPROTO_BRIDGE, 275 .family = NFPROTO_BRIDGE,
276 .target = ebt_ulog_tg, 276 .target = ebt_ulog_tg,
277 .checkentry = ebt_ulog_tg_check, 277 .checkentry = ebt_ulog_tg_check,
278 .targetsize = XT_ALIGN(sizeof(struct ebt_ulog_info)), 278 .targetsize = sizeof(struct ebt_ulog_info),
279 .me = THIS_MODULE, 279 .me = THIS_MODULE,
280}; 280};
281 281
diff --git a/net/bridge/netfilter/ebt_vlan.c b/net/bridge/netfilter/ebt_vlan.c
index 3dddd489328e..be1dd2e1f615 100644
--- a/net/bridge/netfilter/ebt_vlan.c
+++ b/net/bridge/netfilter/ebt_vlan.c
@@ -163,7 +163,7 @@ static struct xt_match ebt_vlan_mt_reg __read_mostly = {
163 .family = NFPROTO_BRIDGE, 163 .family = NFPROTO_BRIDGE,
164 .match = ebt_vlan_mt, 164 .match = ebt_vlan_mt,
165 .checkentry = ebt_vlan_mt_check, 165 .checkentry = ebt_vlan_mt_check,
166 .matchsize = XT_ALIGN(sizeof(struct ebt_vlan_info)), 166 .matchsize = sizeof(struct ebt_vlan_info),
167 .me = THIS_MODULE, 167 .me = THIS_MODULE,
168}; 168};
169 169
diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
index d32ab13e728c..ae3f106c3908 100644
--- a/net/bridge/netfilter/ebtable_broute.c
+++ b/net/bridge/netfilter/ebtable_broute.c
@@ -71,7 +71,7 @@ static int __net_init broute_net_init(struct net *net)
71 71
72static void __net_exit broute_net_exit(struct net *net) 72static void __net_exit broute_net_exit(struct net *net)
73{ 73{
74 ebt_unregister_table(net->xt.broute_table); 74 ebt_unregister_table(net, net->xt.broute_table);
75} 75}
76 76
77static struct pernet_operations broute_net_ops = { 77static struct pernet_operations broute_net_ops = {
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
index 60b1a6ca7185..42e6bd094574 100644
--- a/net/bridge/netfilter/ebtable_filter.c
+++ b/net/bridge/netfilter/ebtable_filter.c
@@ -107,7 +107,7 @@ static int __net_init frame_filter_net_init(struct net *net)
107 107
108static void __net_exit frame_filter_net_exit(struct net *net) 108static void __net_exit frame_filter_net_exit(struct net *net)
109{ 109{
110 ebt_unregister_table(net->xt.frame_filter); 110 ebt_unregister_table(net, net->xt.frame_filter);
111} 111}
112 112
113static struct pernet_operations frame_filter_net_ops = { 113static struct pernet_operations frame_filter_net_ops = {
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
index 4a98804203b0..6dc2f878ae05 100644
--- a/net/bridge/netfilter/ebtable_nat.c
+++ b/net/bridge/netfilter/ebtable_nat.c
@@ -107,7 +107,7 @@ static int __net_init frame_nat_net_init(struct net *net)
107 107
108static void __net_exit frame_nat_net_exit(struct net *net) 108static void __net_exit frame_nat_net_exit(struct net *net)
109{ 109{
110 ebt_unregister_table(net->xt.frame_nat); 110 ebt_unregister_table(net, net->xt.frame_nat);
111} 111}
112 112
113static struct pernet_operations frame_nat_net_ops = { 113static struct pernet_operations frame_nat_net_ops = {
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c
index 0b7f262cd148..4370e9680487 100644
--- a/net/bridge/netfilter/ebtables.c
+++ b/net/bridge/netfilter/ebtables.c
@@ -82,7 +82,8 @@ static inline int ebt_do_match (struct ebt_entry_match *m,
82 return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH; 82 return m->u.match->match(skb, par) ? EBT_MATCH : EBT_NOMATCH;
83} 83}
84 84
85static inline int ebt_dev_check(char *entry, const struct net_device *device) 85static inline int
86ebt_dev_check(const char *entry, const struct net_device *device)
86{ 87{
87 int i = 0; 88 int i = 0;
88 const char *devname; 89 const char *devname;
@@ -100,8 +101,9 @@ static inline int ebt_dev_check(char *entry, const struct net_device *device)
100 101
101#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg)) 102#define FWINV2(bool,invflg) ((bool) ^ !!(e->invflags & invflg))
102/* process standard matches */ 103/* process standard matches */
103static inline int ebt_basic_match(struct ebt_entry *e, struct ethhdr *h, 104static inline int
104 const struct net_device *in, const struct net_device *out) 105ebt_basic_match(const struct ebt_entry *e, const struct ethhdr *h,
106 const struct net_device *in, const struct net_device *out)
105{ 107{
106 int verdict, i; 108 int verdict, i;
107 109
@@ -156,12 +158,12 @@ unsigned int ebt_do_table (unsigned int hook, struct sk_buff *skb,
156 int i, nentries; 158 int i, nentries;
157 struct ebt_entry *point; 159 struct ebt_entry *point;
158 struct ebt_counter *counter_base, *cb_base; 160 struct ebt_counter *counter_base, *cb_base;
159 struct ebt_entry_target *t; 161 const struct ebt_entry_target *t;
160 int verdict, sp = 0; 162 int verdict, sp = 0;
161 struct ebt_chainstack *cs; 163 struct ebt_chainstack *cs;
162 struct ebt_entries *chaininfo; 164 struct ebt_entries *chaininfo;
163 char *base; 165 const char *base;
164 struct ebt_table_info *private; 166 const struct ebt_table_info *private;
165 bool hotdrop = false; 167 bool hotdrop = false;
166 struct xt_match_param mtpar; 168 struct xt_match_param mtpar;
167 struct xt_target_param tgpar; 169 struct xt_target_param tgpar;
@@ -395,7 +397,7 @@ ebt_check_watcher(struct ebt_entry_watcher *w, struct xt_tgchk_param *par,
395 return 0; 397 return 0;
396} 398}
397 399
398static int ebt_verify_pointers(struct ebt_replace *repl, 400static int ebt_verify_pointers(const struct ebt_replace *repl,
399 struct ebt_table_info *newinfo) 401 struct ebt_table_info *newinfo)
400{ 402{
401 unsigned int limit = repl->entries_size; 403 unsigned int limit = repl->entries_size;
@@ -442,6 +444,8 @@ static int ebt_verify_pointers(struct ebt_replace *repl,
442 break; 444 break;
443 if (left < e->next_offset) 445 if (left < e->next_offset)
444 break; 446 break;
447 if (e->next_offset < sizeof(struct ebt_entry))
448 return -EINVAL;
445 offset += e->next_offset; 449 offset += e->next_offset;
446 } 450 }
447 } 451 }
@@ -466,8 +470,8 @@ static int ebt_verify_pointers(struct ebt_replace *repl,
466 * to parse the userspace data 470 * to parse the userspace data
467 */ 471 */
468static inline int 472static inline int
469ebt_check_entry_size_and_hooks(struct ebt_entry *e, 473ebt_check_entry_size_and_hooks(const struct ebt_entry *e,
470 struct ebt_table_info *newinfo, 474 const struct ebt_table_info *newinfo,
471 unsigned int *n, unsigned int *cnt, 475 unsigned int *n, unsigned int *cnt,
472 unsigned int *totalcnt, unsigned int *udc_cnt) 476 unsigned int *totalcnt, unsigned int *udc_cnt)
473{ 477{
@@ -561,13 +565,14 @@ ebt_get_udc_positions(struct ebt_entry *e, struct ebt_table_info *newinfo,
561} 565}
562 566
563static inline int 567static inline int
564ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i) 568ebt_cleanup_match(struct ebt_entry_match *m, struct net *net, unsigned int *i)
565{ 569{
566 struct xt_mtdtor_param par; 570 struct xt_mtdtor_param par;
567 571
568 if (i && (*i)-- == 0) 572 if (i && (*i)-- == 0)
569 return 1; 573 return 1;
570 574
575 par.net = net;
571 par.match = m->u.match; 576 par.match = m->u.match;
572 par.matchinfo = m->data; 577 par.matchinfo = m->data;
573 par.family = NFPROTO_BRIDGE; 578 par.family = NFPROTO_BRIDGE;
@@ -578,13 +583,14 @@ ebt_cleanup_match(struct ebt_entry_match *m, unsigned int *i)
578} 583}
579 584
580static inline int 585static inline int
581ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i) 586ebt_cleanup_watcher(struct ebt_entry_watcher *w, struct net *net, unsigned int *i)
582{ 587{
583 struct xt_tgdtor_param par; 588 struct xt_tgdtor_param par;
584 589
585 if (i && (*i)-- == 0) 590 if (i && (*i)-- == 0)
586 return 1; 591 return 1;
587 592
593 par.net = net;
588 par.target = w->u.watcher; 594 par.target = w->u.watcher;
589 par.targinfo = w->data; 595 par.targinfo = w->data;
590 par.family = NFPROTO_BRIDGE; 596 par.family = NFPROTO_BRIDGE;
@@ -595,7 +601,7 @@ ebt_cleanup_watcher(struct ebt_entry_watcher *w, unsigned int *i)
595} 601}
596 602
597static inline int 603static inline int
598ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt) 604ebt_cleanup_entry(struct ebt_entry *e, struct net *net, unsigned int *cnt)
599{ 605{
600 struct xt_tgdtor_param par; 606 struct xt_tgdtor_param par;
601 struct ebt_entry_target *t; 607 struct ebt_entry_target *t;
@@ -605,10 +611,11 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
605 /* we're done */ 611 /* we're done */
606 if (cnt && (*cnt)-- == 0) 612 if (cnt && (*cnt)-- == 0)
607 return 1; 613 return 1;
608 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, NULL); 614 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, NULL);
609 EBT_MATCH_ITERATE(e, ebt_cleanup_match, NULL); 615 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, NULL);
610 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset); 616 t = (struct ebt_entry_target *)(((char *)e) + e->target_offset);
611 617
618 par.net = net;
612 par.target = t->u.target; 619 par.target = t->u.target;
613 par.targinfo = t->data; 620 par.targinfo = t->data;
614 par.family = NFPROTO_BRIDGE; 621 par.family = NFPROTO_BRIDGE;
@@ -619,7 +626,8 @@ ebt_cleanup_entry(struct ebt_entry *e, unsigned int *cnt)
619} 626}
620 627
621static inline int 628static inline int
622ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo, 629ebt_check_entry(struct ebt_entry *e, struct net *net,
630 const struct ebt_table_info *newinfo,
623 const char *name, unsigned int *cnt, 631 const char *name, unsigned int *cnt,
624 struct ebt_cl_stack *cl_s, unsigned int udc_cnt) 632 struct ebt_cl_stack *cl_s, unsigned int udc_cnt)
625{ 633{
@@ -671,6 +679,7 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
671 } 679 }
672 i = 0; 680 i = 0;
673 681
682 mtpar.net = tgpar.net = net;
674 mtpar.table = tgpar.table = name; 683 mtpar.table = tgpar.table = name;
675 mtpar.entryinfo = tgpar.entryinfo = e; 684 mtpar.entryinfo = tgpar.entryinfo = e;
676 mtpar.hook_mask = tgpar.hook_mask = hookmask; 685 mtpar.hook_mask = tgpar.hook_mask = hookmask;
@@ -726,9 +735,9 @@ ebt_check_entry(struct ebt_entry *e, struct ebt_table_info *newinfo,
726 (*cnt)++; 735 (*cnt)++;
727 return 0; 736 return 0;
728cleanup_watchers: 737cleanup_watchers:
729 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, &j); 738 EBT_WATCHER_ITERATE(e, ebt_cleanup_watcher, net, &j);
730cleanup_matches: 739cleanup_matches:
731 EBT_MATCH_ITERATE(e, ebt_cleanup_match, &i); 740 EBT_MATCH_ITERATE(e, ebt_cleanup_match, net, &i);
732 return ret; 741 return ret;
733} 742}
734 743
@@ -737,12 +746,12 @@ cleanup_matches:
737 * the hook mask for udc tells us from which base chains the udc can be 746 * the hook mask for udc tells us from which base chains the udc can be
738 * accessed. This mask is a parameter to the check() functions of the extensions 747 * accessed. This mask is a parameter to the check() functions of the extensions
739 */ 748 */
740static int check_chainloops(struct ebt_entries *chain, struct ebt_cl_stack *cl_s, 749static int check_chainloops(const struct ebt_entries *chain, struct ebt_cl_stack *cl_s,
741 unsigned int udc_cnt, unsigned int hooknr, char *base) 750 unsigned int udc_cnt, unsigned int hooknr, char *base)
742{ 751{
743 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict; 752 int i, chain_nr = -1, pos = 0, nentries = chain->nentries, verdict;
744 struct ebt_entry *e = (struct ebt_entry *)chain->data; 753 const struct ebt_entry *e = (struct ebt_entry *)chain->data;
745 struct ebt_entry_target *t; 754 const struct ebt_entry_target *t;
746 755
747 while (pos < nentries || chain_nr != -1) { 756 while (pos < nentries || chain_nr != -1) {
748 /* end of udc, go back one 'recursion' step */ 757 /* end of udc, go back one 'recursion' step */
@@ -808,7 +817,8 @@ letscontinue:
808} 817}
809 818
810/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */ 819/* do the parsing of the table/chains/entries/matches/watchers/targets, heh */
811static int translate_table(char *name, struct ebt_table_info *newinfo) 820static int translate_table(struct net *net, const char *name,
821 struct ebt_table_info *newinfo)
812{ 822{
813 unsigned int i, j, k, udc_cnt; 823 unsigned int i, j, k, udc_cnt;
814 int ret; 824 int ret;
@@ -917,17 +927,17 @@ static int translate_table(char *name, struct ebt_table_info *newinfo)
917 /* used to know what we need to clean up if something goes wrong */ 927 /* used to know what we need to clean up if something goes wrong */
918 i = 0; 928 i = 0;
919 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 929 ret = EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
920 ebt_check_entry, newinfo, name, &i, cl_s, udc_cnt); 930 ebt_check_entry, net, newinfo, name, &i, cl_s, udc_cnt);
921 if (ret != 0) { 931 if (ret != 0) {
922 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 932 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
923 ebt_cleanup_entry, &i); 933 ebt_cleanup_entry, net, &i);
924 } 934 }
925 vfree(cl_s); 935 vfree(cl_s);
926 return ret; 936 return ret;
927} 937}
928 938
929/* called under write_lock */ 939/* called under write_lock */
930static void get_counters(struct ebt_counter *oldcounters, 940static void get_counters(const struct ebt_counter *oldcounters,
931 struct ebt_counter *counters, unsigned int nentries) 941 struct ebt_counter *counters, unsigned int nentries)
932{ 942{
933 int i, cpu; 943 int i, cpu;
@@ -950,7 +960,8 @@ static void get_counters(struct ebt_counter *oldcounters,
950} 960}
951 961
952/* replace the table */ 962/* replace the table */
953static int do_replace(struct net *net, void __user *user, unsigned int len) 963static int do_replace(struct net *net, const void __user *user,
964 unsigned int len)
954{ 965{
955 int ret, i, countersize; 966 int ret, i, countersize;
956 struct ebt_table_info *newinfo; 967 struct ebt_table_info *newinfo;
@@ -1017,7 +1028,7 @@ static int do_replace(struct net *net, void __user *user, unsigned int len)
1017 if (ret != 0) 1028 if (ret != 0)
1018 goto free_counterstmp; 1029 goto free_counterstmp;
1019 1030
1020 ret = translate_table(tmp.name, newinfo); 1031 ret = translate_table(net, tmp.name, newinfo);
1021 1032
1022 if (ret != 0) 1033 if (ret != 0)
1023 goto free_counterstmp; 1034 goto free_counterstmp;
@@ -1070,7 +1081,7 @@ static int do_replace(struct net *net, void __user *user, unsigned int len)
1070 1081
1071 /* decrease module count and free resources */ 1082 /* decrease module count and free resources */
1072 EBT_ENTRY_ITERATE(table->entries, table->entries_size, 1083 EBT_ENTRY_ITERATE(table->entries, table->entries_size,
1073 ebt_cleanup_entry, NULL); 1084 ebt_cleanup_entry, net, NULL);
1074 1085
1075 vfree(table->entries); 1086 vfree(table->entries);
1076 if (table->chainstack) { 1087 if (table->chainstack) {
@@ -1087,7 +1098,7 @@ free_unlock:
1087 mutex_unlock(&ebt_mutex); 1098 mutex_unlock(&ebt_mutex);
1088free_iterate: 1099free_iterate:
1089 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size, 1100 EBT_ENTRY_ITERATE(newinfo->entries, newinfo->entries_size,
1090 ebt_cleanup_entry, NULL); 1101 ebt_cleanup_entry, net, NULL);
1091free_counterstmp: 1102free_counterstmp:
1092 vfree(counterstmp); 1103 vfree(counterstmp);
1093 /* can be initialized in translate_table() */ 1104 /* can be initialized in translate_table() */
@@ -1154,7 +1165,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table)
1154 newinfo->hook_entry[i] = p + 1165 newinfo->hook_entry[i] = p +
1155 ((char *)repl->hook_entry[i] - repl->entries); 1166 ((char *)repl->hook_entry[i] - repl->entries);
1156 } 1167 }
1157 ret = translate_table(repl->name, newinfo); 1168 ret = translate_table(net, repl->name, newinfo);
1158 if (ret != 0) { 1169 if (ret != 0) {
1159 BUGPRINT("Translate_table failed\n"); 1170 BUGPRINT("Translate_table failed\n");
1160 goto free_chainstack; 1171 goto free_chainstack;
@@ -1204,7 +1215,7 @@ out:
1204 return ERR_PTR(ret); 1215 return ERR_PTR(ret);
1205} 1216}
1206 1217
1207void ebt_unregister_table(struct ebt_table *table) 1218void ebt_unregister_table(struct net *net, struct ebt_table *table)
1208{ 1219{
1209 int i; 1220 int i;
1210 1221
@@ -1216,7 +1227,7 @@ void ebt_unregister_table(struct ebt_table *table)
1216 list_del(&table->list); 1227 list_del(&table->list);
1217 mutex_unlock(&ebt_mutex); 1228 mutex_unlock(&ebt_mutex);
1218 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size, 1229 EBT_ENTRY_ITERATE(table->private->entries, table->private->entries_size,
1219 ebt_cleanup_entry, NULL); 1230 ebt_cleanup_entry, net, NULL);
1220 if (table->private->nentries) 1231 if (table->private->nentries)
1221 module_put(table->me); 1232 module_put(table->me);
1222 vfree(table->private->entries); 1233 vfree(table->private->entries);
@@ -1230,7 +1241,8 @@ void ebt_unregister_table(struct ebt_table *table)
1230} 1241}
1231 1242
1232/* userspace just supplied us with counters */ 1243/* userspace just supplied us with counters */
1233static int update_counters(struct net *net, void __user *user, unsigned int len) 1244static int update_counters(struct net *net, const void __user *user,
1245 unsigned int len)
1234{ 1246{
1235 int i, ret; 1247 int i, ret;
1236 struct ebt_counter *tmp; 1248 struct ebt_counter *tmp;
@@ -1285,8 +1297,8 @@ free_tmp:
1285 return ret; 1297 return ret;
1286} 1298}
1287 1299
1288static inline int ebt_make_matchname(struct ebt_entry_match *m, 1300static inline int ebt_make_matchname(const struct ebt_entry_match *m,
1289 char *base, char __user *ubase) 1301 const char *base, char __user *ubase)
1290{ 1302{
1291 char __user *hlp = ubase + ((char *)m - base); 1303 char __user *hlp = ubase + ((char *)m - base);
1292 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN)) 1304 if (copy_to_user(hlp, m->u.match->name, EBT_FUNCTION_MAXNAMELEN))
@@ -1294,8 +1306,8 @@ static inline int ebt_make_matchname(struct ebt_entry_match *m,
1294 return 0; 1306 return 0;
1295} 1307}
1296 1308
1297static inline int ebt_make_watchername(struct ebt_entry_watcher *w, 1309static inline int ebt_make_watchername(const struct ebt_entry_watcher *w,
1298 char *base, char __user *ubase) 1310 const char *base, char __user *ubase)
1299{ 1311{
1300 char __user *hlp = ubase + ((char *)w - base); 1312 char __user *hlp = ubase + ((char *)w - base);
1301 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN)) 1313 if (copy_to_user(hlp , w->u.watcher->name, EBT_FUNCTION_MAXNAMELEN))
@@ -1303,11 +1315,12 @@ static inline int ebt_make_watchername(struct ebt_entry_watcher *w,
1303 return 0; 1315 return 0;
1304} 1316}
1305 1317
1306static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *ubase) 1318static inline int
1319ebt_make_names(struct ebt_entry *e, const char *base, char __user *ubase)
1307{ 1320{
1308 int ret; 1321 int ret;
1309 char __user *hlp; 1322 char __user *hlp;
1310 struct ebt_entry_target *t; 1323 const struct ebt_entry_target *t;
1311 1324
1312 if (e->bitmask == 0) 1325 if (e->bitmask == 0)
1313 return 0; 1326 return 0;
@@ -1328,10 +1341,11 @@ static inline int ebt_make_names(struct ebt_entry *e, char *base, char __user *u
1328 1341
1329/* called with ebt_mutex locked */ 1342/* called with ebt_mutex locked */
1330static int copy_everything_to_user(struct ebt_table *t, void __user *user, 1343static int copy_everything_to_user(struct ebt_table *t, void __user *user,
1331 int *len, int cmd) 1344 const int *len, int cmd)
1332{ 1345{
1333 struct ebt_replace tmp; 1346 struct ebt_replace tmp;
1334 struct ebt_counter *counterstmp, *oldcounters; 1347 struct ebt_counter *counterstmp;
1348 const struct ebt_counter *oldcounters;
1335 unsigned int entries_size, nentries; 1349 unsigned int entries_size, nentries;
1336 char *entries; 1350 char *entries;
1337 1351
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
index 90203e1b9187..4db5c1ece0f9 100644
--- a/net/ipv4/netfilter/arp_tables.c
+++ b/net/ipv4/netfilter/arp_tables.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/netfilter/x_tables.h> 28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_arp/arp_tables.h> 29#include <linux/netfilter_arp/arp_tables.h>
30#include "../../netfilter/xt_repldata.h"
30 31
31MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
32MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); 33MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
@@ -58,6 +59,12 @@ do { \
58#define ARP_NF_ASSERT(x) 59#define ARP_NF_ASSERT(x)
59#endif 60#endif
60 61
62void *arpt_alloc_initial_table(const struct xt_table *info)
63{
64 return xt_alloc_initial_table(arpt, ARPT);
65}
66EXPORT_SYMBOL_GPL(arpt_alloc_initial_table);
67
61static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, 68static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap,
62 const char *hdr_addr, int len) 69 const char *hdr_addr, int len)
63{ 70{
@@ -226,7 +233,14 @@ arpt_error(struct sk_buff *skb, const struct xt_target_param *par)
226 return NF_DROP; 233 return NF_DROP;
227} 234}
228 235
229static inline struct arpt_entry *get_entry(void *base, unsigned int offset) 236static inline const struct arpt_entry_target *
237arpt_get_target_c(const struct arpt_entry *e)
238{
239 return arpt_get_target((struct arpt_entry *)e);
240}
241
242static inline struct arpt_entry *
243get_entry(const void *base, unsigned int offset)
230{ 244{
231 return (struct arpt_entry *)(base + offset); 245 return (struct arpt_entry *)(base + offset);
232} 246}
@@ -273,7 +287,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
273 287
274 arp = arp_hdr(skb); 288 arp = arp_hdr(skb);
275 do { 289 do {
276 struct arpt_entry_target *t; 290 const struct arpt_entry_target *t;
277 int hdr_len; 291 int hdr_len;
278 292
279 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) { 293 if (!arp_packet_match(arp, skb->dev, indev, outdev, &e->arp)) {
@@ -285,7 +299,7 @@ unsigned int arpt_do_table(struct sk_buff *skb,
285 (2 * skb->dev->addr_len); 299 (2 * skb->dev->addr_len);
286 ADD_COUNTER(e->counters, hdr_len, 1); 300 ADD_COUNTER(e->counters, hdr_len, 1);
287 301
288 t = arpt_get_target(e); 302 t = arpt_get_target_c(e);
289 303
290 /* Standard target? */ 304 /* Standard target? */
291 if (!t->u.kernel.target->target) { 305 if (!t->u.kernel.target->target) {
@@ -351,7 +365,7 @@ static inline bool unconditional(const struct arpt_arp *arp)
351/* Figures out from what hook each rule can be called: returns 0 if 365/* Figures out from what hook each rule can be called: returns 0 if
352 * there are loops. Puts hook bitmask in comefrom. 366 * there are loops. Puts hook bitmask in comefrom.
353 */ 367 */
354static int mark_source_chains(struct xt_table_info *newinfo, 368static int mark_source_chains(const struct xt_table_info *newinfo,
355 unsigned int valid_hooks, void *entry0) 369 unsigned int valid_hooks, void *entry0)
356{ 370{
357 unsigned int hook; 371 unsigned int hook;
@@ -372,7 +386,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
372 386
373 for (;;) { 387 for (;;) {
374 const struct arpt_standard_target *t 388 const struct arpt_standard_target *t
375 = (void *)arpt_get_target(e); 389 = (void *)arpt_get_target_c(e);
376 int visited = e->comefrom & (1 << hook); 390 int visited = e->comefrom & (1 << hook);
377 391
378 if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) { 392 if (e->comefrom & (1 << NF_ARP_NUMHOOKS)) {
@@ -456,7 +470,7 @@ static int mark_source_chains(struct xt_table_info *newinfo,
456 return 1; 470 return 1;
457} 471}
458 472
459static inline int check_entry(struct arpt_entry *e, const char *name) 473static inline int check_entry(const struct arpt_entry *e, const char *name)
460{ 474{
461 const struct arpt_entry_target *t; 475 const struct arpt_entry_target *t;
462 476
@@ -468,7 +482,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name)
468 if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset) 482 if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset)
469 return -EINVAL; 483 return -EINVAL;
470 484
471 t = arpt_get_target(e); 485 t = arpt_get_target_c(e);
472 if (e->target_offset + t->u.target_size > e->next_offset) 486 if (e->target_offset + t->u.target_size > e->next_offset)
473 return -EINVAL; 487 return -EINVAL;
474 488
@@ -533,14 +547,14 @@ out:
533 return ret; 547 return ret;
534} 548}
535 549
536static bool check_underflow(struct arpt_entry *e) 550static bool check_underflow(const struct arpt_entry *e)
537{ 551{
538 const struct arpt_entry_target *t; 552 const struct arpt_entry_target *t;
539 unsigned int verdict; 553 unsigned int verdict;
540 554
541 if (!unconditional(&e->arp)) 555 if (!unconditional(&e->arp))
542 return false; 556 return false;
543 t = arpt_get_target(e); 557 t = arpt_get_target_c(e);
544 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) 558 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
545 return false; 559 return false;
546 verdict = ((struct arpt_standard_target *)t)->verdict; 560 verdict = ((struct arpt_standard_target *)t)->verdict;
@@ -550,8 +564,8 @@ static bool check_underflow(struct arpt_entry *e)
550 564
551static inline int check_entry_size_and_hooks(struct arpt_entry *e, 565static inline int check_entry_size_and_hooks(struct arpt_entry *e,
552 struct xt_table_info *newinfo, 566 struct xt_table_info *newinfo,
553 unsigned char *base, 567 const unsigned char *base,
554 unsigned char *limit, 568 const unsigned char *limit,
555 const unsigned int *hook_entries, 569 const unsigned int *hook_entries,
556 const unsigned int *underflows, 570 const unsigned int *underflows,
557 unsigned int valid_hooks, 571 unsigned int valid_hooks,
@@ -761,11 +775,11 @@ static void get_counters(const struct xt_table_info *t,
761 local_bh_enable(); 775 local_bh_enable();
762} 776}
763 777
764static struct xt_counters *alloc_counters(struct xt_table *table) 778static struct xt_counters *alloc_counters(const struct xt_table *table)
765{ 779{
766 unsigned int countersize; 780 unsigned int countersize;
767 struct xt_counters *counters; 781 struct xt_counters *counters;
768 struct xt_table_info *private = table->private; 782 const struct xt_table_info *private = table->private;
769 783
770 /* We need atomic snapshot of counters: rest doesn't change 784 /* We need atomic snapshot of counters: rest doesn't change
771 * (other than comefrom, which userspace doesn't care 785 * (other than comefrom, which userspace doesn't care
@@ -783,11 +797,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
783} 797}
784 798
785static int copy_entries_to_user(unsigned int total_size, 799static int copy_entries_to_user(unsigned int total_size,
786 struct xt_table *table, 800 const struct xt_table *table,
787 void __user *userptr) 801 void __user *userptr)
788{ 802{
789 unsigned int off, num; 803 unsigned int off, num;
790 struct arpt_entry *e; 804 const struct arpt_entry *e;
791 struct xt_counters *counters; 805 struct xt_counters *counters;
792 struct xt_table_info *private = table->private; 806 struct xt_table_info *private = table->private;
793 int ret = 0; 807 int ret = 0;
@@ -807,7 +821,7 @@ static int copy_entries_to_user(unsigned int total_size,
807 /* FIXME: use iterator macros --RR */ 821 /* FIXME: use iterator macros --RR */
808 /* ... then go back and fix counters and names */ 822 /* ... then go back and fix counters and names */
809 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){ 823 for (off = 0, num = 0; off < total_size; off += e->next_offset, num++){
810 struct arpt_entry_target *t; 824 const struct arpt_entry_target *t;
811 825
812 e = (struct arpt_entry *)(loc_cpu_entry + off); 826 e = (struct arpt_entry *)(loc_cpu_entry + off);
813 if (copy_to_user(userptr + off 827 if (copy_to_user(userptr + off
@@ -818,7 +832,7 @@ static int copy_entries_to_user(unsigned int total_size,
818 goto free_counters; 832 goto free_counters;
819 } 833 }
820 834
821 t = arpt_get_target(e); 835 t = arpt_get_target_c(e);
822 if (copy_to_user(userptr + off + e->target_offset 836 if (copy_to_user(userptr + off + e->target_offset
823 + offsetof(struct arpt_entry_target, 837 + offsetof(struct arpt_entry_target,
824 u.user.name), 838 u.user.name),
@@ -835,7 +849,7 @@ static int copy_entries_to_user(unsigned int total_size,
835} 849}
836 850
837#ifdef CONFIG_COMPAT 851#ifdef CONFIG_COMPAT
838static void compat_standard_from_user(void *dst, void *src) 852static void compat_standard_from_user(void *dst, const void *src)
839{ 853{
840 int v = *(compat_int_t *)src; 854 int v = *(compat_int_t *)src;
841 855
@@ -844,7 +858,7 @@ static void compat_standard_from_user(void *dst, void *src)
844 memcpy(dst, &v, sizeof(v)); 858 memcpy(dst, &v, sizeof(v));
845} 859}
846 860
847static int compat_standard_to_user(void __user *dst, void *src) 861static int compat_standard_to_user(void __user *dst, const void *src)
848{ 862{
849 compat_int_t cv = *(int *)src; 863 compat_int_t cv = *(int *)src;
850 864
@@ -853,18 +867,18 @@ static int compat_standard_to_user(void __user *dst, void *src)
853 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0; 867 return copy_to_user(dst, &cv, sizeof(cv)) ? -EFAULT : 0;
854} 868}
855 869
856static int compat_calc_entry(struct arpt_entry *e, 870static int compat_calc_entry(const struct arpt_entry *e,
857 const struct xt_table_info *info, 871 const struct xt_table_info *info,
858 void *base, struct xt_table_info *newinfo) 872 const void *base, struct xt_table_info *newinfo)
859{ 873{
860 struct arpt_entry_target *t; 874 const struct arpt_entry_target *t;
861 unsigned int entry_offset; 875 unsigned int entry_offset;
862 int off, i, ret; 876 int off, i, ret;
863 877
864 off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry); 878 off = sizeof(struct arpt_entry) - sizeof(struct compat_arpt_entry);
865 entry_offset = (void *)e - base; 879 entry_offset = (void *)e - base;
866 880
867 t = arpt_get_target(e); 881 t = arpt_get_target_c(e);
868 off += xt_compat_target_offset(t->u.kernel.target); 882 off += xt_compat_target_offset(t->u.kernel.target);
869 newinfo->size -= off; 883 newinfo->size -= off;
870 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off); 884 ret = xt_compat_add_offset(NFPROTO_ARP, entry_offset, off);
@@ -900,7 +914,8 @@ static int compat_table_info(const struct xt_table_info *info,
900} 914}
901#endif 915#endif
902 916
903static int get_info(struct net *net, void __user *user, int *len, int compat) 917static int get_info(struct net *net, void __user *user,
918 const int *len, int compat)
904{ 919{
905 char name[ARPT_TABLE_MAXNAMELEN]; 920 char name[ARPT_TABLE_MAXNAMELEN];
906 struct xt_table *t; 921 struct xt_table *t;
@@ -959,7 +974,7 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
959} 974}
960 975
961static int get_entries(struct net *net, struct arpt_get_entries __user *uptr, 976static int get_entries(struct net *net, struct arpt_get_entries __user *uptr,
962 int *len) 977 const int *len)
963{ 978{
964 int ret; 979 int ret;
965 struct arpt_get_entries get; 980 struct arpt_get_entries get;
@@ -1073,7 +1088,8 @@ static int __do_replace(struct net *net, const char *name,
1073 return ret; 1088 return ret;
1074} 1089}
1075 1090
1076static int do_replace(struct net *net, void __user *user, unsigned int len) 1091static int do_replace(struct net *net, const void __user *user,
1092 unsigned int len)
1077{ 1093{
1078 int ret; 1094 int ret;
1079 struct arpt_replace tmp; 1095 struct arpt_replace tmp;
@@ -1133,8 +1149,8 @@ add_counter_to_entry(struct arpt_entry *e,
1133 return 0; 1149 return 0;
1134} 1150}
1135 1151
1136static int do_add_counters(struct net *net, void __user *user, unsigned int len, 1152static int do_add_counters(struct net *net, const void __user *user,
1137 int compat) 1153 unsigned int len, int compat)
1138{ 1154{
1139 unsigned int i, curcpu; 1155 unsigned int i, curcpu;
1140 struct xt_counters_info tmp; 1156 struct xt_counters_info tmp;
@@ -1238,10 +1254,10 @@ static inline int
1238check_compat_entry_size_and_hooks(struct compat_arpt_entry *e, 1254check_compat_entry_size_and_hooks(struct compat_arpt_entry *e,
1239 struct xt_table_info *newinfo, 1255 struct xt_table_info *newinfo,
1240 unsigned int *size, 1256 unsigned int *size,
1241 unsigned char *base, 1257 const unsigned char *base,
1242 unsigned char *limit, 1258 const unsigned char *limit,
1243 unsigned int *hook_entries, 1259 const unsigned int *hook_entries,
1244 unsigned int *underflows, 1260 const unsigned int *underflows,
1245 unsigned int *i, 1261 unsigned int *i,
1246 const char *name) 1262 const char *name)
1247{ 1263{
diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
index 97337601827a..bfe26f32b930 100644
--- a/net/ipv4/netfilter/arptable_filter.c
+++ b/net/ipv4/netfilter/arptable_filter.c
@@ -6,6 +6,7 @@
6 */ 6 */
7 7
8#include <linux/module.h> 8#include <linux/module.h>
9#include <linux/netfilter/x_tables.h>
9#include <linux/netfilter_arp/arp_tables.h> 10#include <linux/netfilter_arp/arp_tables.h>
10 11
11MODULE_LICENSE("GPL"); 12MODULE_LICENSE("GPL");
@@ -15,93 +16,37 @@ MODULE_DESCRIPTION("arptables filter table");
15#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \ 16#define FILTER_VALID_HOOKS ((1 << NF_ARP_IN) | (1 << NF_ARP_OUT) | \
16 (1 << NF_ARP_FORWARD)) 17 (1 << NF_ARP_FORWARD))
17 18
18static const struct
19{
20 struct arpt_replace repl;
21 struct arpt_standard entries[3];
22 struct arpt_error term;
23} initial_table __net_initdata = {
24 .repl = {
25 .name = "filter",
26 .valid_hooks = FILTER_VALID_HOOKS,
27 .num_entries = 4,
28 .size = sizeof(struct arpt_standard) * 3 + sizeof(struct arpt_error),
29 .hook_entry = {
30 [NF_ARP_IN] = 0,
31 [NF_ARP_OUT] = sizeof(struct arpt_standard),
32 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
33 },
34 .underflow = {
35 [NF_ARP_IN] = 0,
36 [NF_ARP_OUT] = sizeof(struct arpt_standard),
37 [NF_ARP_FORWARD] = 2 * sizeof(struct arpt_standard),
38 },
39 },
40 .entries = {
41 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_IN */
42 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_OUT */
43 ARPT_STANDARD_INIT(NF_ACCEPT), /* ARP_FORWARD */
44 },
45 .term = ARPT_ERROR_INIT,
46};
47
48static const struct xt_table packet_filter = { 19static const struct xt_table packet_filter = {
49 .name = "filter", 20 .name = "filter",
50 .valid_hooks = FILTER_VALID_HOOKS, 21 .valid_hooks = FILTER_VALID_HOOKS,
51 .me = THIS_MODULE, 22 .me = THIS_MODULE,
52 .af = NFPROTO_ARP, 23 .af = NFPROTO_ARP,
24 .priority = NF_IP_PRI_FILTER,
53}; 25};
54 26
55/* The work comes in here from netfilter.c */ 27/* The work comes in here from netfilter.c */
56static unsigned int arpt_in_hook(unsigned int hook, 28static unsigned int
57 struct sk_buff *skb, 29arptable_filter_hook(unsigned int hook, struct sk_buff *skb,
58 const struct net_device *in, 30 const struct net_device *in, const struct net_device *out,
59 const struct net_device *out, 31 int (*okfn)(struct sk_buff *))
60 int (*okfn)(struct sk_buff *))
61{ 32{
62 return arpt_do_table(skb, hook, in, out, 33 const struct net *net = dev_net((in != NULL) ? in : out);
63 dev_net(in)->ipv4.arptable_filter);
64}
65 34
66static unsigned int arpt_out_hook(unsigned int hook, 35 return arpt_do_table(skb, hook, in, out, net->ipv4.arptable_filter);
67 struct sk_buff *skb,
68 const struct net_device *in,
69 const struct net_device *out,
70 int (*okfn)(struct sk_buff *))
71{
72 return arpt_do_table(skb, hook, in, out,
73 dev_net(out)->ipv4.arptable_filter);
74} 36}
75 37
76static struct nf_hook_ops arpt_ops[] __read_mostly = { 38static struct nf_hook_ops *arpfilter_ops __read_mostly;
77 {
78 .hook = arpt_in_hook,
79 .owner = THIS_MODULE,
80 .pf = NFPROTO_ARP,
81 .hooknum = NF_ARP_IN,
82 .priority = NF_IP_PRI_FILTER,
83 },
84 {
85 .hook = arpt_out_hook,
86 .owner = THIS_MODULE,
87 .pf = NFPROTO_ARP,
88 .hooknum = NF_ARP_OUT,
89 .priority = NF_IP_PRI_FILTER,
90 },
91 {
92 .hook = arpt_in_hook,
93 .owner = THIS_MODULE,
94 .pf = NFPROTO_ARP,
95 .hooknum = NF_ARP_FORWARD,
96 .priority = NF_IP_PRI_FILTER,
97 },
98};
99 39
100static int __net_init arptable_filter_net_init(struct net *net) 40static int __net_init arptable_filter_net_init(struct net *net)
101{ 41{
102 /* Register table */ 42 struct arpt_replace *repl;
43
44 repl = arpt_alloc_initial_table(&packet_filter);
45 if (repl == NULL)
46 return -ENOMEM;
103 net->ipv4.arptable_filter = 47 net->ipv4.arptable_filter =
104 arpt_register_table(net, &packet_filter, &initial_table.repl); 48 arpt_register_table(net, &packet_filter, repl);
49 kfree(repl);
105 if (IS_ERR(net->ipv4.arptable_filter)) 50 if (IS_ERR(net->ipv4.arptable_filter))
106 return PTR_ERR(net->ipv4.arptable_filter); 51 return PTR_ERR(net->ipv4.arptable_filter);
107 return 0; 52 return 0;
@@ -125,9 +70,11 @@ static int __init arptable_filter_init(void)
125 if (ret < 0) 70 if (ret < 0)
126 return ret; 71 return ret;
127 72
128 ret = nf_register_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 73 arpfilter_ops = xt_hook_link(&packet_filter, arptable_filter_hook);
129 if (ret < 0) 74 if (IS_ERR(arpfilter_ops)) {
75 ret = PTR_ERR(arpfilter_ops);
130 goto cleanup_table; 76 goto cleanup_table;
77 }
131 return ret; 78 return ret;
132 79
133cleanup_table: 80cleanup_table:
@@ -137,7 +84,7 @@ cleanup_table:
137 84
138static void __exit arptable_filter_fini(void) 85static void __exit arptable_filter_fini(void)
139{ 86{
140 nf_unregister_hooks(arpt_ops, ARRAY_SIZE(arpt_ops)); 87 xt_hook_unlink(&packet_filter, arpfilter_ops);
141 unregister_pernet_subsys(&arptable_filter_net_ops); 88 unregister_pernet_subsys(&arptable_filter_net_ops);
142} 89}
143 90
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
index 3ce53cf13d5a..e94c18bdfc68 100644
--- a/net/ipv4/netfilter/ip_tables.c
+++ b/net/ipv4/netfilter/ip_tables.c
@@ -28,6 +28,7 @@
28#include <linux/netfilter/x_tables.h> 28#include <linux/netfilter/x_tables.h>
29#include <linux/netfilter_ipv4/ip_tables.h> 29#include <linux/netfilter_ipv4/ip_tables.h>
30#include <net/netfilter/nf_log.h> 30#include <net/netfilter/nf_log.h>
31#include "../../netfilter/xt_repldata.h"
31 32
32MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 34MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -66,6 +67,12 @@ do { \
66#define inline 67#define inline
67#endif 68#endif
68 69
70void *ipt_alloc_initial_table(const struct xt_table *info)
71{
72 return xt_alloc_initial_table(ipt, IPT);
73}
74EXPORT_SYMBOL_GPL(ipt_alloc_initial_table);
75
69/* 76/*
70 We keep a set of rules for each CPU, so we can avoid write-locking 77 We keep a set of rules for each CPU, so we can avoid write-locking
71 them in the softirq when updating the counters and therefore 78 them in the softirq when updating the counters and therefore
@@ -169,7 +176,7 @@ ipt_error(struct sk_buff *skb, const struct xt_target_param *par)
169 176
170/* Performance critical - called for every packet */ 177/* Performance critical - called for every packet */
171static inline bool 178static inline bool
172do_match(struct ipt_entry_match *m, const struct sk_buff *skb, 179do_match(const struct ipt_entry_match *m, const struct sk_buff *skb,
173 struct xt_match_param *par) 180 struct xt_match_param *par)
174{ 181{
175 par->match = m->u.kernel.match; 182 par->match = m->u.kernel.match;
@@ -184,7 +191,7 @@ do_match(struct ipt_entry_match *m, const struct sk_buff *skb,
184 191
185/* Performance critical */ 192/* Performance critical */
186static inline struct ipt_entry * 193static inline struct ipt_entry *
187get_entry(void *base, unsigned int offset) 194get_entry(const void *base, unsigned int offset)
188{ 195{
189 return (struct ipt_entry *)(base + offset); 196 return (struct ipt_entry *)(base + offset);
190} 197}
@@ -199,6 +206,13 @@ static inline bool unconditional(const struct ipt_ip *ip)
199#undef FWINV 206#undef FWINV
200} 207}
201 208
209/* for const-correctness */
210static inline const struct ipt_entry_target *
211ipt_get_target_c(const struct ipt_entry *e)
212{
213 return ipt_get_target((struct ipt_entry *)e);
214}
215
202#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 216#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
203 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) 217 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
204static const char *const hooknames[] = { 218static const char *const hooknames[] = {
@@ -233,11 +247,11 @@ static struct nf_loginfo trace_loginfo = {
233 247
234/* Mildly perf critical (only if packet tracing is on) */ 248/* Mildly perf critical (only if packet tracing is on) */
235static inline int 249static inline int
236get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e, 250get_chainname_rulenum(const struct ipt_entry *s, const struct ipt_entry *e,
237 const char *hookname, const char **chainname, 251 const char *hookname, const char **chainname,
238 const char **comment, unsigned int *rulenum) 252 const char **comment, unsigned int *rulenum)
239{ 253{
240 struct ipt_standard_target *t = (void *)ipt_get_target(s); 254 const struct ipt_standard_target *t = (void *)ipt_get_target_c(s);
241 255
242 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) { 256 if (strcmp(t->target.u.kernel.target->name, IPT_ERROR_TARGET) == 0) {
243 /* Head of user chain: ERROR target with chainname */ 257 /* Head of user chain: ERROR target with chainname */
@@ -263,15 +277,15 @@ get_chainname_rulenum(struct ipt_entry *s, struct ipt_entry *e,
263 return 0; 277 return 0;
264} 278}
265 279
266static void trace_packet(struct sk_buff *skb, 280static void trace_packet(const struct sk_buff *skb,
267 unsigned int hook, 281 unsigned int hook,
268 const struct net_device *in, 282 const struct net_device *in,
269 const struct net_device *out, 283 const struct net_device *out,
270 const char *tablename, 284 const char *tablename,
271 struct xt_table_info *private, 285 const struct xt_table_info *private,
272 struct ipt_entry *e) 286 const struct ipt_entry *e)
273{ 287{
274 void *table_base; 288 const void *table_base;
275 const struct ipt_entry *root; 289 const struct ipt_entry *root;
276 const char *hookname, *chainname, *comment; 290 const char *hookname, *chainname, *comment;
277 unsigned int rulenum = 0; 291 unsigned int rulenum = 0;
@@ -315,9 +329,9 @@ ipt_do_table(struct sk_buff *skb,
315 /* Initializing verdict to NF_DROP keeps gcc happy. */ 329 /* Initializing verdict to NF_DROP keeps gcc happy. */
316 unsigned int verdict = NF_DROP; 330 unsigned int verdict = NF_DROP;
317 const char *indev, *outdev; 331 const char *indev, *outdev;
318 void *table_base; 332 const void *table_base;
319 struct ipt_entry *e, *back; 333 struct ipt_entry *e, *back;
320 struct xt_table_info *private; 334 const struct xt_table_info *private;
321 struct xt_match_param mtpar; 335 struct xt_match_param mtpar;
322 struct xt_target_param tgpar; 336 struct xt_target_param tgpar;
323 337
@@ -350,7 +364,7 @@ ipt_do_table(struct sk_buff *skb,
350 back = get_entry(table_base, private->underflow[hook]); 364 back = get_entry(table_base, private->underflow[hook]);
351 365
352 do { 366 do {
353 struct ipt_entry_target *t; 367 const struct ipt_entry_target *t;
354 368
355 IP_NF_ASSERT(e); 369 IP_NF_ASSERT(e);
356 IP_NF_ASSERT(back); 370 IP_NF_ASSERT(back);
@@ -443,7 +457,7 @@ ipt_do_table(struct sk_buff *skb,
443/* Figures out from what hook each rule can be called: returns 0 if 457/* Figures out from what hook each rule can be called: returns 0 if
444 there are loops. Puts hook bitmask in comefrom. */ 458 there are loops. Puts hook bitmask in comefrom. */
445static int 459static int
446mark_source_chains(struct xt_table_info *newinfo, 460mark_source_chains(const struct xt_table_info *newinfo,
447 unsigned int valid_hooks, void *entry0) 461 unsigned int valid_hooks, void *entry0)
448{ 462{
449 unsigned int hook; 463 unsigned int hook;
@@ -461,8 +475,8 @@ mark_source_chains(struct xt_table_info *newinfo,
461 e->counters.pcnt = pos; 475 e->counters.pcnt = pos;
462 476
463 for (;;) { 477 for (;;) {
464 struct ipt_standard_target *t 478 const struct ipt_standard_target *t
465 = (void *)ipt_get_target(e); 479 = (void *)ipt_get_target_c(e);
466 int visited = e->comefrom & (1 << hook); 480 int visited = e->comefrom & (1 << hook);
467 481
468 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { 482 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
@@ -553,13 +567,14 @@ mark_source_chains(struct xt_table_info *newinfo,
553} 567}
554 568
555static int 569static int
556cleanup_match(struct ipt_entry_match *m, unsigned int *i) 570cleanup_match(struct ipt_entry_match *m, struct net *net, unsigned int *i)
557{ 571{
558 struct xt_mtdtor_param par; 572 struct xt_mtdtor_param par;
559 573
560 if (i && (*i)-- == 0) 574 if (i && (*i)-- == 0)
561 return 1; 575 return 1;
562 576
577 par.net = net;
563 par.match = m->u.kernel.match; 578 par.match = m->u.kernel.match;
564 par.matchinfo = m->data; 579 par.matchinfo = m->data;
565 par.family = NFPROTO_IPV4; 580 par.family = NFPROTO_IPV4;
@@ -570,9 +585,9 @@ cleanup_match(struct ipt_entry_match *m, unsigned int *i)
570} 585}
571 586
572static int 587static int
573check_entry(struct ipt_entry *e, const char *name) 588check_entry(const struct ipt_entry *e, const char *name)
574{ 589{
575 struct ipt_entry_target *t; 590 const struct ipt_entry_target *t;
576 591
577 if (!ip_checkentry(&e->ip)) { 592 if (!ip_checkentry(&e->ip)) {
578 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 593 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
@@ -583,7 +598,7 @@ check_entry(struct ipt_entry *e, const char *name)
583 e->next_offset) 598 e->next_offset)
584 return -EINVAL; 599 return -EINVAL;
585 600
586 t = ipt_get_target(e); 601 t = ipt_get_target_c(e);
587 if (e->target_offset + t->u.target_size > e->next_offset) 602 if (e->target_offset + t->u.target_size > e->next_offset)
588 return -EINVAL; 603 return -EINVAL;
589 604
@@ -637,10 +652,11 @@ err:
637 return ret; 652 return ret;
638} 653}
639 654
640static int check_target(struct ipt_entry *e, const char *name) 655static int check_target(struct ipt_entry *e, struct net *net, const char *name)
641{ 656{
642 struct ipt_entry_target *t = ipt_get_target(e); 657 struct ipt_entry_target *t = ipt_get_target(e);
643 struct xt_tgchk_param par = { 658 struct xt_tgchk_param par = {
659 .net = net,
644 .table = name, 660 .table = name,
645 .entryinfo = e, 661 .entryinfo = e,
646 .target = t->u.kernel.target, 662 .target = t->u.kernel.target,
@@ -661,8 +677,8 @@ static int check_target(struct ipt_entry *e, const char *name)
661} 677}
662 678
663static int 679static int
664find_check_entry(struct ipt_entry *e, const char *name, unsigned int size, 680find_check_entry(struct ipt_entry *e, struct net *net, const char *name,
665 unsigned int *i) 681 unsigned int size, unsigned int *i)
666{ 682{
667 struct ipt_entry_target *t; 683 struct ipt_entry_target *t;
668 struct xt_target *target; 684 struct xt_target *target;
@@ -675,6 +691,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
675 return ret; 691 return ret;
676 692
677 j = 0; 693 j = 0;
694 mtpar.net = net;
678 mtpar.table = name; 695 mtpar.table = name;
679 mtpar.entryinfo = &e->ip; 696 mtpar.entryinfo = &e->ip;
680 mtpar.hook_mask = e->comefrom; 697 mtpar.hook_mask = e->comefrom;
@@ -695,7 +712,7 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
695 } 712 }
696 t->u.kernel.target = target; 713 t->u.kernel.target = target;
697 714
698 ret = check_target(e, name); 715 ret = check_target(e, net, name);
699 if (ret) 716 if (ret)
700 goto err; 717 goto err;
701 718
@@ -704,18 +721,18 @@ find_check_entry(struct ipt_entry *e, const char *name, unsigned int size,
704 err: 721 err:
705 module_put(t->u.kernel.target->me); 722 module_put(t->u.kernel.target->me);
706 cleanup_matches: 723 cleanup_matches:
707 IPT_MATCH_ITERATE(e, cleanup_match, &j); 724 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
708 return ret; 725 return ret;
709} 726}
710 727
711static bool check_underflow(struct ipt_entry *e) 728static bool check_underflow(const struct ipt_entry *e)
712{ 729{
713 const struct ipt_entry_target *t; 730 const struct ipt_entry_target *t;
714 unsigned int verdict; 731 unsigned int verdict;
715 732
716 if (!unconditional(&e->ip)) 733 if (!unconditional(&e->ip))
717 return false; 734 return false;
718 t = ipt_get_target(e); 735 t = ipt_get_target_c(e);
719 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) 736 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
720 return false; 737 return false;
721 verdict = ((struct ipt_standard_target *)t)->verdict; 738 verdict = ((struct ipt_standard_target *)t)->verdict;
@@ -726,8 +743,8 @@ static bool check_underflow(struct ipt_entry *e)
726static int 743static int
727check_entry_size_and_hooks(struct ipt_entry *e, 744check_entry_size_and_hooks(struct ipt_entry *e,
728 struct xt_table_info *newinfo, 745 struct xt_table_info *newinfo,
729 unsigned char *base, 746 const unsigned char *base,
730 unsigned char *limit, 747 const unsigned char *limit,
731 const unsigned int *hook_entries, 748 const unsigned int *hook_entries,
732 const unsigned int *underflows, 749 const unsigned int *underflows,
733 unsigned int valid_hooks, 750 unsigned int valid_hooks,
@@ -774,7 +791,7 @@ check_entry_size_and_hooks(struct ipt_entry *e,
774} 791}
775 792
776static int 793static int
777cleanup_entry(struct ipt_entry *e, unsigned int *i) 794cleanup_entry(struct ipt_entry *e, struct net *net, unsigned int *i)
778{ 795{
779 struct xt_tgdtor_param par; 796 struct xt_tgdtor_param par;
780 struct ipt_entry_target *t; 797 struct ipt_entry_target *t;
@@ -783,9 +800,10 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
783 return 1; 800 return 1;
784 801
785 /* Cleanup all matches */ 802 /* Cleanup all matches */
786 IPT_MATCH_ITERATE(e, cleanup_match, NULL); 803 IPT_MATCH_ITERATE(e, cleanup_match, net, NULL);
787 t = ipt_get_target(e); 804 t = ipt_get_target(e);
788 805
806 par.net = net;
789 par.target = t->u.kernel.target; 807 par.target = t->u.kernel.target;
790 par.targinfo = t->data; 808 par.targinfo = t->data;
791 par.family = NFPROTO_IPV4; 809 par.family = NFPROTO_IPV4;
@@ -798,7 +816,8 @@ cleanup_entry(struct ipt_entry *e, unsigned int *i)
798/* Checks and translates the user-supplied table segment (held in 816/* Checks and translates the user-supplied table segment (held in
799 newinfo) */ 817 newinfo) */
800static int 818static int
801translate_table(const char *name, 819translate_table(struct net *net,
820 const char *name,
802 unsigned int valid_hooks, 821 unsigned int valid_hooks,
803 struct xt_table_info *newinfo, 822 struct xt_table_info *newinfo,
804 void *entry0, 823 void *entry0,
@@ -860,11 +879,11 @@ translate_table(const char *name,
860 /* Finally, each sanity check must pass */ 879 /* Finally, each sanity check must pass */
861 i = 0; 880 i = 0;
862 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, 881 ret = IPT_ENTRY_ITERATE(entry0, newinfo->size,
863 find_check_entry, name, size, &i); 882 find_check_entry, net, name, size, &i);
864 883
865 if (ret != 0) { 884 if (ret != 0) {
866 IPT_ENTRY_ITERATE(entry0, newinfo->size, 885 IPT_ENTRY_ITERATE(entry0, newinfo->size,
867 cleanup_entry, &i); 886 cleanup_entry, net, &i);
868 return ret; 887 return ret;
869 } 888 }
870 889
@@ -940,11 +959,11 @@ get_counters(const struct xt_table_info *t,
940 local_bh_enable(); 959 local_bh_enable();
941} 960}
942 961
943static struct xt_counters * alloc_counters(struct xt_table *table) 962static struct xt_counters *alloc_counters(const struct xt_table *table)
944{ 963{
945 unsigned int countersize; 964 unsigned int countersize;
946 struct xt_counters *counters; 965 struct xt_counters *counters;
947 struct xt_table_info *private = table->private; 966 const struct xt_table_info *private = table->private;
948 967
949 /* We need atomic snapshot of counters: rest doesn't change 968 /* We need atomic snapshot of counters: rest doesn't change
950 (other than comefrom, which userspace doesn't care 969 (other than comefrom, which userspace doesn't care
@@ -962,11 +981,11 @@ static struct xt_counters * alloc_counters(struct xt_table *table)
962 981
963static int 982static int
964copy_entries_to_user(unsigned int total_size, 983copy_entries_to_user(unsigned int total_size,
965 struct xt_table *table, 984 const struct xt_table *table,
966 void __user *userptr) 985 void __user *userptr)
967{ 986{
968 unsigned int off, num; 987 unsigned int off, num;
969 struct ipt_entry *e; 988 const struct ipt_entry *e;
970 struct xt_counters *counters; 989 struct xt_counters *counters;
971 const struct xt_table_info *private = table->private; 990 const struct xt_table_info *private = table->private;
972 int ret = 0; 991 int ret = 0;
@@ -1018,7 +1037,7 @@ copy_entries_to_user(unsigned int total_size,
1018 } 1037 }
1019 } 1038 }
1020 1039
1021 t = ipt_get_target(e); 1040 t = ipt_get_target_c(e);
1022 if (copy_to_user(userptr + off + e->target_offset 1041 if (copy_to_user(userptr + off + e->target_offset
1023 + offsetof(struct ipt_entry_target, 1042 + offsetof(struct ipt_entry_target,
1024 u.user.name), 1043 u.user.name),
@@ -1035,7 +1054,7 @@ copy_entries_to_user(unsigned int total_size,
1035} 1054}
1036 1055
1037#ifdef CONFIG_COMPAT 1056#ifdef CONFIG_COMPAT
1038static void compat_standard_from_user(void *dst, void *src) 1057static void compat_standard_from_user(void *dst, const void *src)
1039{ 1058{
1040 int v = *(compat_int_t *)src; 1059 int v = *(compat_int_t *)src;
1041 1060
@@ -1044,7 +1063,7 @@ static void compat_standard_from_user(void *dst, void *src)
1044 memcpy(dst, &v, sizeof(v)); 1063 memcpy(dst, &v, sizeof(v));
1045} 1064}
1046 1065
1047static int compat_standard_to_user(void __user *dst, void *src) 1066static int compat_standard_to_user(void __user *dst, const void *src)
1048{ 1067{
1049 compat_int_t cv = *(int *)src; 1068 compat_int_t cv = *(int *)src;
1050 1069
@@ -1054,24 +1073,24 @@ static int compat_standard_to_user(void __user *dst, void *src)
1054} 1073}
1055 1074
1056static inline int 1075static inline int
1057compat_calc_match(struct ipt_entry_match *m, int *size) 1076compat_calc_match(const struct ipt_entry_match *m, int *size)
1058{ 1077{
1059 *size += xt_compat_match_offset(m->u.kernel.match); 1078 *size += xt_compat_match_offset(m->u.kernel.match);
1060 return 0; 1079 return 0;
1061} 1080}
1062 1081
1063static int compat_calc_entry(struct ipt_entry *e, 1082static int compat_calc_entry(const struct ipt_entry *e,
1064 const struct xt_table_info *info, 1083 const struct xt_table_info *info,
1065 void *base, struct xt_table_info *newinfo) 1084 const void *base, struct xt_table_info *newinfo)
1066{ 1085{
1067 struct ipt_entry_target *t; 1086 const struct ipt_entry_target *t;
1068 unsigned int entry_offset; 1087 unsigned int entry_offset;
1069 int off, i, ret; 1088 int off, i, ret;
1070 1089
1071 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry); 1090 off = sizeof(struct ipt_entry) - sizeof(struct compat_ipt_entry);
1072 entry_offset = (void *)e - base; 1091 entry_offset = (void *)e - base;
1073 IPT_MATCH_ITERATE(e, compat_calc_match, &off); 1092 IPT_MATCH_ITERATE(e, compat_calc_match, &off);
1074 t = ipt_get_target(e); 1093 t = ipt_get_target_c(e);
1075 off += xt_compat_target_offset(t->u.kernel.target); 1094 off += xt_compat_target_offset(t->u.kernel.target);
1076 newinfo->size -= off; 1095 newinfo->size -= off;
1077 ret = xt_compat_add_offset(AF_INET, entry_offset, off); 1096 ret = xt_compat_add_offset(AF_INET, entry_offset, off);
@@ -1107,7 +1126,8 @@ static int compat_table_info(const struct xt_table_info *info,
1107} 1126}
1108#endif 1127#endif
1109 1128
1110static int get_info(struct net *net, void __user *user, int *len, int compat) 1129static int get_info(struct net *net, void __user *user,
1130 const int *len, int compat)
1111{ 1131{
1112 char name[IPT_TABLE_MAXNAMELEN]; 1132 char name[IPT_TABLE_MAXNAMELEN];
1113 struct xt_table *t; 1133 struct xt_table *t;
@@ -1167,7 +1187,8 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
1167} 1187}
1168 1188
1169static int 1189static int
1170get_entries(struct net *net, struct ipt_get_entries __user *uptr, int *len) 1190get_entries(struct net *net, struct ipt_get_entries __user *uptr,
1191 const int *len)
1171{ 1192{
1172 int ret; 1193 int ret;
1173 struct ipt_get_entries get; 1194 struct ipt_get_entries get;
@@ -1258,7 +1279,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1258 /* Decrease module usage counts and free resource */ 1279 /* Decrease module usage counts and free resource */
1259 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1280 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1260 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1281 IPT_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1261 NULL); 1282 net, NULL);
1262 xt_free_table_info(oldinfo); 1283 xt_free_table_info(oldinfo);
1263 if (copy_to_user(counters_ptr, counters, 1284 if (copy_to_user(counters_ptr, counters,
1264 sizeof(struct xt_counters) * num_counters) != 0) 1285 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1277,7 +1298,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1277} 1298}
1278 1299
1279static int 1300static int
1280do_replace(struct net *net, void __user *user, unsigned int len) 1301do_replace(struct net *net, const void __user *user, unsigned int len)
1281{ 1302{
1282 int ret; 1303 int ret;
1283 struct ipt_replace tmp; 1304 struct ipt_replace tmp;
@@ -1303,7 +1324,7 @@ do_replace(struct net *net, void __user *user, unsigned int len)
1303 goto free_newinfo; 1324 goto free_newinfo;
1304 } 1325 }
1305 1326
1306 ret = translate_table(tmp.name, tmp.valid_hooks, 1327 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1307 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, 1328 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1308 tmp.hook_entry, tmp.underflow); 1329 tmp.hook_entry, tmp.underflow);
1309 if (ret != 0) 1330 if (ret != 0)
@@ -1318,7 +1339,7 @@ do_replace(struct net *net, void __user *user, unsigned int len)
1318 return 0; 1339 return 0;
1319 1340
1320 free_newinfo_untrans: 1341 free_newinfo_untrans:
1321 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1342 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1322 free_newinfo: 1343 free_newinfo:
1323 xt_free_table_info(newinfo); 1344 xt_free_table_info(newinfo);
1324 return ret; 1345 return ret;
@@ -1338,7 +1359,8 @@ add_counter_to_entry(struct ipt_entry *e,
1338} 1359}
1339 1360
1340static int 1361static int
1341do_add_counters(struct net *net, void __user *user, unsigned int len, int compat) 1362do_add_counters(struct net *net, const void __user *user,
1363 unsigned int len, int compat)
1342{ 1364{
1343 unsigned int i, curcpu; 1365 unsigned int i, curcpu;
1344 struct xt_counters_info tmp; 1366 struct xt_counters_info tmp;
@@ -1534,10 +1556,10 @@ static int
1534check_compat_entry_size_and_hooks(struct compat_ipt_entry *e, 1556check_compat_entry_size_and_hooks(struct compat_ipt_entry *e,
1535 struct xt_table_info *newinfo, 1557 struct xt_table_info *newinfo,
1536 unsigned int *size, 1558 unsigned int *size,
1537 unsigned char *base, 1559 const unsigned char *base,
1538 unsigned char *limit, 1560 const unsigned char *limit,
1539 unsigned int *hook_entries, 1561 const unsigned int *hook_entries,
1540 unsigned int *underflows, 1562 const unsigned int *underflows,
1541 unsigned int *i, 1563 unsigned int *i,
1542 const char *name) 1564 const char *name)
1543{ 1565{
@@ -1655,7 +1677,7 @@ compat_copy_entry_from_user(struct compat_ipt_entry *e, void **dstptr,
1655} 1677}
1656 1678
1657static int 1679static int
1658compat_check_entry(struct ipt_entry *e, const char *name, 1680compat_check_entry(struct ipt_entry *e, struct net *net, const char *name,
1659 unsigned int *i) 1681 unsigned int *i)
1660{ 1682{
1661 struct xt_mtchk_param mtpar; 1683 struct xt_mtchk_param mtpar;
@@ -1663,6 +1685,7 @@ compat_check_entry(struct ipt_entry *e, const char *name,
1663 int ret; 1685 int ret;
1664 1686
1665 j = 0; 1687 j = 0;
1688 mtpar.net = net;
1666 mtpar.table = name; 1689 mtpar.table = name;
1667 mtpar.entryinfo = &e->ip; 1690 mtpar.entryinfo = &e->ip;
1668 mtpar.hook_mask = e->comefrom; 1691 mtpar.hook_mask = e->comefrom;
@@ -1671,7 +1694,7 @@ compat_check_entry(struct ipt_entry *e, const char *name,
1671 if (ret) 1694 if (ret)
1672 goto cleanup_matches; 1695 goto cleanup_matches;
1673 1696
1674 ret = check_target(e, name); 1697 ret = check_target(e, net, name);
1675 if (ret) 1698 if (ret)
1676 goto cleanup_matches; 1699 goto cleanup_matches;
1677 1700
@@ -1679,12 +1702,13 @@ compat_check_entry(struct ipt_entry *e, const char *name,
1679 return 0; 1702 return 0;
1680 1703
1681 cleanup_matches: 1704 cleanup_matches:
1682 IPT_MATCH_ITERATE(e, cleanup_match, &j); 1705 IPT_MATCH_ITERATE(e, cleanup_match, net, &j);
1683 return ret; 1706 return ret;
1684} 1707}
1685 1708
1686static int 1709static int
1687translate_compat_table(const char *name, 1710translate_compat_table(struct net *net,
1711 const char *name,
1688 unsigned int valid_hooks, 1712 unsigned int valid_hooks,
1689 struct xt_table_info **pinfo, 1713 struct xt_table_info **pinfo,
1690 void **pentry0, 1714 void **pentry0,
@@ -1773,12 +1797,12 @@ translate_compat_table(const char *name,
1773 1797
1774 i = 0; 1798 i = 0;
1775 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1799 ret = IPT_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1776 name, &i); 1800 net, name, &i);
1777 if (ret) { 1801 if (ret) {
1778 j -= i; 1802 j -= i;
1779 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1803 COMPAT_IPT_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1780 compat_release_entry, &j); 1804 compat_release_entry, &j);
1781 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); 1805 IPT_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);
1782 xt_free_table_info(newinfo); 1806 xt_free_table_info(newinfo);
1783 return ret; 1807 return ret;
1784 } 1808 }
@@ -1833,7 +1857,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1833 goto free_newinfo; 1857 goto free_newinfo;
1834 } 1858 }
1835 1859
1836 ret = translate_compat_table(tmp.name, tmp.valid_hooks, 1860 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1837 &newinfo, &loc_cpu_entry, tmp.size, 1861 &newinfo, &loc_cpu_entry, tmp.size,
1838 tmp.num_entries, tmp.hook_entry, 1862 tmp.num_entries, tmp.hook_entry,
1839 tmp.underflow); 1863 tmp.underflow);
@@ -1849,7 +1873,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1849 return 0; 1873 return 0;
1850 1874
1851 free_newinfo_untrans: 1875 free_newinfo_untrans:
1852 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1876 IPT_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1853 free_newinfo: 1877 free_newinfo:
1854 xt_free_table_info(newinfo); 1878 xt_free_table_info(newinfo);
1855 return ret; 1879 return ret;
@@ -2086,7 +2110,7 @@ struct xt_table *ipt_register_table(struct net *net,
2086 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2110 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2087 memcpy(loc_cpu_entry, repl->entries, repl->size); 2111 memcpy(loc_cpu_entry, repl->entries, repl->size);
2088 2112
2089 ret = translate_table(table->name, table->valid_hooks, 2113 ret = translate_table(net, table->name, table->valid_hooks,
2090 newinfo, loc_cpu_entry, repl->size, 2114 newinfo, loc_cpu_entry, repl->size,
2091 repl->num_entries, 2115 repl->num_entries,
2092 repl->hook_entry, 2116 repl->hook_entry,
@@ -2108,7 +2132,7 @@ out:
2108 return ERR_PTR(ret); 2132 return ERR_PTR(ret);
2109} 2133}
2110 2134
2111void ipt_unregister_table(struct xt_table *table) 2135void ipt_unregister_table(struct net *net, struct xt_table *table)
2112{ 2136{
2113 struct xt_table_info *private; 2137 struct xt_table_info *private;
2114 void *loc_cpu_entry; 2138 void *loc_cpu_entry;
@@ -2118,7 +2142,7 @@ void ipt_unregister_table(struct xt_table *table)
2118 2142
2119 /* Decrease module usage counts and free resources */ 2143 /* Decrease module usage counts and free resources */
2120 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2144 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2121 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); 2145 IPT_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);
2122 if (private->number > private->initial_entries) 2146 if (private->number > private->initial_entries)
2123 module_put(table_owner); 2147 module_put(table_owner);
2124 xt_free_table_info(private); 2148 xt_free_table_info(private);
diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 40ca2d240abb..0886f96c736b 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -560,8 +560,7 @@ struct clusterip_seq_position {
560 560
561static void *clusterip_seq_start(struct seq_file *s, loff_t *pos) 561static void *clusterip_seq_start(struct seq_file *s, loff_t *pos)
562{ 562{
563 const struct proc_dir_entry *pde = s->private; 563 struct clusterip_config *c = s->private;
564 struct clusterip_config *c = pde->data;
565 unsigned int weight; 564 unsigned int weight;
566 u_int32_t local_nodes; 565 u_int32_t local_nodes;
567 struct clusterip_seq_position *idx; 566 struct clusterip_seq_position *idx;
@@ -632,10 +631,9 @@ static int clusterip_proc_open(struct inode *inode, struct file *file)
632 631
633 if (!ret) { 632 if (!ret) {
634 struct seq_file *sf = file->private_data; 633 struct seq_file *sf = file->private_data;
635 struct proc_dir_entry *pde = PDE(inode); 634 struct clusterip_config *c = PDE(inode)->data;
636 struct clusterip_config *c = pde->data;
637 635
638 sf->private = pde; 636 sf->private = c;
639 637
640 clusterip_config_get(c); 638 clusterip_config_get(c);
641 } 639 }
@@ -645,8 +643,7 @@ static int clusterip_proc_open(struct inode *inode, struct file *file)
645 643
646static int clusterip_proc_release(struct inode *inode, struct file *file) 644static int clusterip_proc_release(struct inode *inode, struct file *file)
647{ 645{
648 struct proc_dir_entry *pde = PDE(inode); 646 struct clusterip_config *c = PDE(inode)->data;
649 struct clusterip_config *c = pde->data;
650 int ret; 647 int ret;
651 648
652 ret = seq_release(inode, file); 649 ret = seq_release(inode, file);
@@ -660,10 +657,9 @@ static int clusterip_proc_release(struct inode *inode, struct file *file)
660static ssize_t clusterip_proc_write(struct file *file, const char __user *input, 657static ssize_t clusterip_proc_write(struct file *file, const char __user *input,
661 size_t size, loff_t *ofs) 658 size_t size, loff_t *ofs)
662{ 659{
660 struct clusterip_config *c = PDE(file->f_path.dentry->d_inode)->data;
663#define PROC_WRITELEN 10 661#define PROC_WRITELEN 10
664 char buffer[PROC_WRITELEN+1]; 662 char buffer[PROC_WRITELEN+1];
665 const struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode);
666 struct clusterip_config *c = pde->data;
667 unsigned long nodenum; 663 unsigned long nodenum;
668 664
669 if (copy_from_user(buffer, input, PROC_WRITELEN)) 665 if (copy_from_user(buffer, input, PROC_WRITELEN))
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c
index 399061c3fd7d..09a5d3f7cc41 100644
--- a/net/ipv4/netfilter/ipt_ULOG.c
+++ b/net/ipv4/netfilter/ipt_ULOG.c
@@ -338,7 +338,7 @@ struct compat_ipt_ulog_info {
338 char prefix[ULOG_PREFIX_LEN]; 338 char prefix[ULOG_PREFIX_LEN];
339}; 339};
340 340
341static void ulog_tg_compat_from_user(void *dst, void *src) 341static void ulog_tg_compat_from_user(void *dst, const void *src)
342{ 342{
343 const struct compat_ipt_ulog_info *cl = src; 343 const struct compat_ipt_ulog_info *cl = src;
344 struct ipt_ulog_info l = { 344 struct ipt_ulog_info l = {
@@ -351,7 +351,7 @@ static void ulog_tg_compat_from_user(void *dst, void *src)
351 memcpy(dst, &l, sizeof(l)); 351 memcpy(dst, &l, sizeof(l));
352} 352}
353 353
354static int ulog_tg_compat_to_user(void __user *dst, void *src) 354static int ulog_tg_compat_to_user(void __user *dst, const void *src)
355{ 355{
356 const struct ipt_ulog_info *l = src; 356 const struct ipt_ulog_info *l = src;
357 struct compat_ipt_ulog_info cl = { 357 struct compat_ipt_ulog_info cl = {
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
index df566cbd68e5..c8dc9800d620 100644
--- a/net/ipv4/netfilter/iptable_filter.c
+++ b/net/ipv4/netfilter/iptable_filter.c
@@ -23,104 +23,32 @@ MODULE_DESCRIPTION("iptables filter table");
23 (1 << NF_INET_FORWARD) | \ 23 (1 << NF_INET_FORWARD) | \
24 (1 << NF_INET_LOCAL_OUT)) 24 (1 << NF_INET_LOCAL_OUT))
25 25
26static struct
27{
28 struct ipt_replace repl;
29 struct ipt_standard entries[3];
30 struct ipt_error term;
31} initial_table __net_initdata = {
32 .repl = {
33 .name = "filter",
34 .valid_hooks = FILTER_VALID_HOOKS,
35 .num_entries = 4,
36 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
37 .hook_entry = {
38 [NF_INET_LOCAL_IN] = 0,
39 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
40 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
41 },
42 .underflow = {
43 [NF_INET_LOCAL_IN] = 0,
44 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
45 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
46 },
47 },
48 .entries = {
49 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
50 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
51 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
52 },
53 .term = IPT_ERROR_INIT, /* ERROR */
54};
55
56static const struct xt_table packet_filter = { 26static const struct xt_table packet_filter = {
57 .name = "filter", 27 .name = "filter",
58 .valid_hooks = FILTER_VALID_HOOKS, 28 .valid_hooks = FILTER_VALID_HOOKS,
59 .me = THIS_MODULE, 29 .me = THIS_MODULE,
60 .af = NFPROTO_IPV4, 30 .af = NFPROTO_IPV4,
31 .priority = NF_IP_PRI_FILTER,
61}; 32};
62 33
63/* The work comes in here from netfilter.c. */
64static unsigned int
65ipt_local_in_hook(unsigned int hook,
66 struct sk_buff *skb,
67 const struct net_device *in,
68 const struct net_device *out,
69 int (*okfn)(struct sk_buff *))
70{
71 return ipt_do_table(skb, hook, in, out,
72 dev_net(in)->ipv4.iptable_filter);
73}
74
75static unsigned int 34static unsigned int
76ipt_hook(unsigned int hook, 35iptable_filter_hook(unsigned int hook, struct sk_buff *skb,
77 struct sk_buff *skb, 36 const struct net_device *in, const struct net_device *out,
78 const struct net_device *in, 37 int (*okfn)(struct sk_buff *))
79 const struct net_device *out,
80 int (*okfn)(struct sk_buff *))
81{ 38{
82 return ipt_do_table(skb, hook, in, out, 39 const struct net *net;
83 dev_net(in)->ipv4.iptable_filter);
84}
85 40
86static unsigned int 41 if (hook == NF_INET_LOCAL_OUT &&
87ipt_local_out_hook(unsigned int hook, 42 (skb->len < sizeof(struct iphdr) ||
88 struct sk_buff *skb, 43 ip_hdrlen(skb) < sizeof(struct iphdr)))
89 const struct net_device *in, 44 /* root is playing with raw sockets. */
90 const struct net_device *out,
91 int (*okfn)(struct sk_buff *))
92{
93 /* root is playing with raw sockets. */
94 if (skb->len < sizeof(struct iphdr) ||
95 ip_hdrlen(skb) < sizeof(struct iphdr))
96 return NF_ACCEPT; 45 return NF_ACCEPT;
97 return ipt_do_table(skb, hook, in, out, 46
98 dev_net(out)->ipv4.iptable_filter); 47 net = dev_net((in != NULL) ? in : out);
48 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_filter);
99} 49}
100 50
101static struct nf_hook_ops ipt_ops[] __read_mostly = { 51static struct nf_hook_ops *filter_ops __read_mostly;
102 {
103 .hook = ipt_local_in_hook,
104 .owner = THIS_MODULE,
105 .pf = NFPROTO_IPV4,
106 .hooknum = NF_INET_LOCAL_IN,
107 .priority = NF_IP_PRI_FILTER,
108 },
109 {
110 .hook = ipt_hook,
111 .owner = THIS_MODULE,
112 .pf = NFPROTO_IPV4,
113 .hooknum = NF_INET_FORWARD,
114 .priority = NF_IP_PRI_FILTER,
115 },
116 {
117 .hook = ipt_local_out_hook,
118 .owner = THIS_MODULE,
119 .pf = NFPROTO_IPV4,
120 .hooknum = NF_INET_LOCAL_OUT,
121 .priority = NF_IP_PRI_FILTER,
122 },
123};
124 52
125/* Default to forward because I got too much mail already. */ 53/* Default to forward because I got too much mail already. */
126static int forward = NF_ACCEPT; 54static int forward = NF_ACCEPT;
@@ -128,9 +56,18 @@ module_param(forward, bool, 0000);
128 56
129static int __net_init iptable_filter_net_init(struct net *net) 57static int __net_init iptable_filter_net_init(struct net *net)
130{ 58{
131 /* Register table */ 59 struct ipt_replace *repl;
60
61 repl = ipt_alloc_initial_table(&packet_filter);
62 if (repl == NULL)
63 return -ENOMEM;
64 /* Entry 1 is the FORWARD hook */
65 ((struct ipt_standard *)repl->entries)[1].target.verdict =
66 -forward - 1;
67
132 net->ipv4.iptable_filter = 68 net->ipv4.iptable_filter =
133 ipt_register_table(net, &packet_filter, &initial_table.repl); 69 ipt_register_table(net, &packet_filter, repl);
70 kfree(repl);
134 if (IS_ERR(net->ipv4.iptable_filter)) 71 if (IS_ERR(net->ipv4.iptable_filter))
135 return PTR_ERR(net->ipv4.iptable_filter); 72 return PTR_ERR(net->ipv4.iptable_filter);
136 return 0; 73 return 0;
@@ -138,7 +75,7 @@ static int __net_init iptable_filter_net_init(struct net *net)
138 75
139static void __net_exit iptable_filter_net_exit(struct net *net) 76static void __net_exit iptable_filter_net_exit(struct net *net)
140{ 77{
141 ipt_unregister_table(net->ipv4.iptable_filter); 78 ipt_unregister_table(net, net->ipv4.iptable_filter);
142} 79}
143 80
144static struct pernet_operations iptable_filter_net_ops = { 81static struct pernet_operations iptable_filter_net_ops = {
@@ -155,17 +92,16 @@ static int __init iptable_filter_init(void)
155 return -EINVAL; 92 return -EINVAL;
156 } 93 }
157 94
158 /* Entry 1 is the FORWARD hook */
159 initial_table.entries[1].target.verdict = -forward - 1;
160
161 ret = register_pernet_subsys(&iptable_filter_net_ops); 95 ret = register_pernet_subsys(&iptable_filter_net_ops);
162 if (ret < 0) 96 if (ret < 0)
163 return ret; 97 return ret;
164 98
165 /* Register hooks */ 99 /* Register hooks */
166 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 100 filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook);
167 if (ret < 0) 101 if (IS_ERR(filter_ops)) {
102 ret = PTR_ERR(filter_ops);
168 goto cleanup_table; 103 goto cleanup_table;
104 }
169 105
170 return ret; 106 return ret;
171 107
@@ -176,7 +112,7 @@ static int __init iptable_filter_init(void)
176 112
177static void __exit iptable_filter_fini(void) 113static void __exit iptable_filter_fini(void)
178{ 114{
179 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 115 xt_hook_unlink(&packet_filter, filter_ops);
180 unregister_pernet_subsys(&iptable_filter_net_ops); 116 unregister_pernet_subsys(&iptable_filter_net_ops);
181} 117}
182 118
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
index fae78c3076c4..b9b83464cbf4 100644
--- a/net/ipv4/netfilter/iptable_mangle.c
+++ b/net/ipv4/netfilter/iptable_mangle.c
@@ -27,101 +27,16 @@ MODULE_DESCRIPTION("iptables mangle table");
27 (1 << NF_INET_LOCAL_OUT) | \ 27 (1 << NF_INET_LOCAL_OUT) | \
28 (1 << NF_INET_POST_ROUTING)) 28 (1 << NF_INET_POST_ROUTING))
29 29
30/* Ouch - five different hooks? Maybe this should be a config option..... -- BC */
31static const struct
32{
33 struct ipt_replace repl;
34 struct ipt_standard entries[5];
35 struct ipt_error term;
36} initial_table __net_initdata = {
37 .repl = {
38 .name = "mangle",
39 .valid_hooks = MANGLE_VALID_HOOKS,
40 .num_entries = 6,
41 .size = sizeof(struct ipt_standard) * 5 + sizeof(struct ipt_error),
42 .hook_entry = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
45 [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
46 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
47 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
48 },
49 .underflow = {
50 [NF_INET_PRE_ROUTING] = 0,
51 [NF_INET_LOCAL_IN] = sizeof(struct ipt_standard),
52 [NF_INET_FORWARD] = sizeof(struct ipt_standard) * 2,
53 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 3,
54 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard) * 4,
55 },
56 },
57 .entries = {
58 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
59 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
60 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
61 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
62 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
63 },
64 .term = IPT_ERROR_INIT, /* ERROR */
65};
66
67static const struct xt_table packet_mangler = { 30static const struct xt_table packet_mangler = {
68 .name = "mangle", 31 .name = "mangle",
69 .valid_hooks = MANGLE_VALID_HOOKS, 32 .valid_hooks = MANGLE_VALID_HOOKS,
70 .me = THIS_MODULE, 33 .me = THIS_MODULE,
71 .af = NFPROTO_IPV4, 34 .af = NFPROTO_IPV4,
35 .priority = NF_IP_PRI_MANGLE,
72}; 36};
73 37
74/* The work comes in here from netfilter.c. */
75static unsigned int
76ipt_pre_routing_hook(unsigned int hook,
77 struct sk_buff *skb,
78 const struct net_device *in,
79 const struct net_device *out,
80 int (*okfn)(struct sk_buff *))
81{
82 return ipt_do_table(skb, hook, in, out,
83 dev_net(in)->ipv4.iptable_mangle);
84}
85
86static unsigned int
87ipt_post_routing_hook(unsigned int hook,
88 struct sk_buff *skb,
89 const struct net_device *in,
90 const struct net_device *out,
91 int (*okfn)(struct sk_buff *))
92{
93 return ipt_do_table(skb, hook, in, out,
94 dev_net(out)->ipv4.iptable_mangle);
95}
96
97static unsigned int
98ipt_local_in_hook(unsigned int hook,
99 struct sk_buff *skb,
100 const struct net_device *in,
101 const struct net_device *out,
102 int (*okfn)(struct sk_buff *))
103{
104 return ipt_do_table(skb, hook, in, out,
105 dev_net(in)->ipv4.iptable_mangle);
106}
107
108static unsigned int
109ipt_forward_hook(unsigned int hook,
110 struct sk_buff *skb,
111 const struct net_device *in,
112 const struct net_device *out,
113 int (*okfn)(struct sk_buff *))
114{
115 return ipt_do_table(skb, hook, in, out,
116 dev_net(in)->ipv4.iptable_mangle);
117}
118
119static unsigned int 38static unsigned int
120ipt_local_hook(unsigned int hook, 39ipt_mangle_out(struct sk_buff *skb, const struct net_device *out)
121 struct sk_buff *skb,
122 const struct net_device *in,
123 const struct net_device *out,
124 int (*okfn)(struct sk_buff *))
125{ 40{
126 unsigned int ret; 41 unsigned int ret;
127 const struct iphdr *iph; 42 const struct iphdr *iph;
@@ -141,7 +56,7 @@ ipt_local_hook(unsigned int hook,
141 daddr = iph->daddr; 56 daddr = iph->daddr;
142 tos = iph->tos; 57 tos = iph->tos;
143 58
144 ret = ipt_do_table(skb, hook, in, out, 59 ret = ipt_do_table(skb, NF_INET_LOCAL_OUT, NULL, out,
145 dev_net(out)->ipv4.iptable_mangle); 60 dev_net(out)->ipv4.iptable_mangle);
146 /* Reroute for ANY change. */ 61 /* Reroute for ANY change. */
147 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) { 62 if (ret != NF_DROP && ret != NF_STOLEN && ret != NF_QUEUE) {
@@ -158,49 +73,36 @@ ipt_local_hook(unsigned int hook,
158 return ret; 73 return ret;
159} 74}
160 75
161static struct nf_hook_ops ipt_ops[] __read_mostly = { 76/* The work comes in here from netfilter.c. */
162 { 77static unsigned int
163 .hook = ipt_pre_routing_hook, 78iptable_mangle_hook(unsigned int hook,
164 .owner = THIS_MODULE, 79 struct sk_buff *skb,
165 .pf = NFPROTO_IPV4, 80 const struct net_device *in,
166 .hooknum = NF_INET_PRE_ROUTING, 81 const struct net_device *out,
167 .priority = NF_IP_PRI_MANGLE, 82 int (*okfn)(struct sk_buff *))
168 }, 83{
169 { 84 if (hook == NF_INET_LOCAL_OUT)
170 .hook = ipt_local_in_hook, 85 return ipt_mangle_out(skb, out);
171 .owner = THIS_MODULE, 86 if (hook == NF_INET_POST_ROUTING)
172 .pf = NFPROTO_IPV4, 87 return ipt_do_table(skb, hook, in, out,
173 .hooknum = NF_INET_LOCAL_IN, 88 dev_net(out)->ipv4.iptable_mangle);
174 .priority = NF_IP_PRI_MANGLE, 89 /* PREROUTING/INPUT/FORWARD: */
175 }, 90 return ipt_do_table(skb, hook, in, out,
176 { 91 dev_net(in)->ipv4.iptable_mangle);
177 .hook = ipt_forward_hook, 92}
178 .owner = THIS_MODULE, 93
179 .pf = NFPROTO_IPV4, 94static struct nf_hook_ops *mangle_ops __read_mostly;
180 .hooknum = NF_INET_FORWARD,
181 .priority = NF_IP_PRI_MANGLE,
182 },
183 {
184 .hook = ipt_local_hook,
185 .owner = THIS_MODULE,
186 .pf = NFPROTO_IPV4,
187 .hooknum = NF_INET_LOCAL_OUT,
188 .priority = NF_IP_PRI_MANGLE,
189 },
190 {
191 .hook = ipt_post_routing_hook,
192 .owner = THIS_MODULE,
193 .pf = NFPROTO_IPV4,
194 .hooknum = NF_INET_POST_ROUTING,
195 .priority = NF_IP_PRI_MANGLE,
196 },
197};
198 95
199static int __net_init iptable_mangle_net_init(struct net *net) 96static int __net_init iptable_mangle_net_init(struct net *net)
200{ 97{
201 /* Register table */ 98 struct ipt_replace *repl;
99
100 repl = ipt_alloc_initial_table(&packet_mangler);
101 if (repl == NULL)
102 return -ENOMEM;
202 net->ipv4.iptable_mangle = 103 net->ipv4.iptable_mangle =
203 ipt_register_table(net, &packet_mangler, &initial_table.repl); 104 ipt_register_table(net, &packet_mangler, repl);
105 kfree(repl);
204 if (IS_ERR(net->ipv4.iptable_mangle)) 106 if (IS_ERR(net->ipv4.iptable_mangle))
205 return PTR_ERR(net->ipv4.iptable_mangle); 107 return PTR_ERR(net->ipv4.iptable_mangle);
206 return 0; 108 return 0;
@@ -208,7 +110,7 @@ static int __net_init iptable_mangle_net_init(struct net *net)
208 110
209static void __net_exit iptable_mangle_net_exit(struct net *net) 111static void __net_exit iptable_mangle_net_exit(struct net *net)
210{ 112{
211 ipt_unregister_table(net->ipv4.iptable_mangle); 113 ipt_unregister_table(net, net->ipv4.iptable_mangle);
212} 114}
213 115
214static struct pernet_operations iptable_mangle_net_ops = { 116static struct pernet_operations iptable_mangle_net_ops = {
@@ -225,9 +127,11 @@ static int __init iptable_mangle_init(void)
225 return ret; 127 return ret;
226 128
227 /* Register hooks */ 129 /* Register hooks */
228 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 130 mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook);
229 if (ret < 0) 131 if (IS_ERR(mangle_ops)) {
132 ret = PTR_ERR(mangle_ops);
230 goto cleanup_table; 133 goto cleanup_table;
134 }
231 135
232 return ret; 136 return ret;
233 137
@@ -238,7 +142,7 @@ static int __init iptable_mangle_init(void)
238 142
239static void __exit iptable_mangle_fini(void) 143static void __exit iptable_mangle_fini(void)
240{ 144{
241 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 145 xt_hook_unlink(&packet_mangler, mangle_ops);
242 unregister_pernet_subsys(&iptable_mangle_net_ops); 146 unregister_pernet_subsys(&iptable_mangle_net_ops);
243} 147}
244 148
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
index 993edc23be09..06fb9d11953c 100644
--- a/net/ipv4/netfilter/iptable_raw.c
+++ b/net/ipv4/netfilter/iptable_raw.c
@@ -9,90 +9,44 @@
9 9
10#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 10#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
11 11
12static const struct
13{
14 struct ipt_replace repl;
15 struct ipt_standard entries[2];
16 struct ipt_error term;
17} initial_table __net_initdata = {
18 .repl = {
19 .name = "raw",
20 .valid_hooks = RAW_VALID_HOOKS,
21 .num_entries = 3,
22 .size = sizeof(struct ipt_standard) * 2 + sizeof(struct ipt_error),
23 .hook_entry = {
24 [NF_INET_PRE_ROUTING] = 0,
25 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
26 },
27 .underflow = {
28 [NF_INET_PRE_ROUTING] = 0,
29 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard)
30 },
31 },
32 .entries = {
33 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
34 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
35 },
36 .term = IPT_ERROR_INIT, /* ERROR */
37};
38
39static const struct xt_table packet_raw = { 12static const struct xt_table packet_raw = {
40 .name = "raw", 13 .name = "raw",
41 .valid_hooks = RAW_VALID_HOOKS, 14 .valid_hooks = RAW_VALID_HOOKS,
42 .me = THIS_MODULE, 15 .me = THIS_MODULE,
43 .af = NFPROTO_IPV4, 16 .af = NFPROTO_IPV4,
17 .priority = NF_IP_PRI_RAW,
44}; 18};
45 19
46/* The work comes in here from netfilter.c. */ 20/* The work comes in here from netfilter.c. */
47static unsigned int 21static unsigned int
48ipt_hook(unsigned int hook, 22iptable_raw_hook(unsigned int hook, struct sk_buff *skb,
49 struct sk_buff *skb, 23 const struct net_device *in, const struct net_device *out,
50 const struct net_device *in, 24 int (*okfn)(struct sk_buff *))
51 const struct net_device *out,
52 int (*okfn)(struct sk_buff *))
53{ 25{
54 return ipt_do_table(skb, hook, in, out, 26 const struct net *net;
55 dev_net(in)->ipv4.iptable_raw);
56}
57 27
58static unsigned int 28 if (hook == NF_INET_LOCAL_OUT &&
59ipt_local_hook(unsigned int hook, 29 (skb->len < sizeof(struct iphdr) ||
60 struct sk_buff *skb, 30 ip_hdrlen(skb) < sizeof(struct iphdr)))
61 const struct net_device *in, 31 /* root is playing with raw sockets. */
62 const struct net_device *out,
63 int (*okfn)(struct sk_buff *))
64{
65 /* root is playing with raw sockets. */
66 if (skb->len < sizeof(struct iphdr) ||
67 ip_hdrlen(skb) < sizeof(struct iphdr))
68 return NF_ACCEPT; 32 return NF_ACCEPT;
69 return ipt_do_table(skb, hook, in, out, 33
70 dev_net(out)->ipv4.iptable_raw); 34 net = dev_net((in != NULL) ? in : out);
35 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_raw);
71} 36}
72 37
73/* 'raw' is the very first table. */ 38static struct nf_hook_ops *rawtable_ops __read_mostly;
74static struct nf_hook_ops ipt_ops[] __read_mostly = {
75 {
76 .hook = ipt_hook,
77 .pf = NFPROTO_IPV4,
78 .hooknum = NF_INET_PRE_ROUTING,
79 .priority = NF_IP_PRI_RAW,
80 .owner = THIS_MODULE,
81 },
82 {
83 .hook = ipt_local_hook,
84 .pf = NFPROTO_IPV4,
85 .hooknum = NF_INET_LOCAL_OUT,
86 .priority = NF_IP_PRI_RAW,
87 .owner = THIS_MODULE,
88 },
89};
90 39
91static int __net_init iptable_raw_net_init(struct net *net) 40static int __net_init iptable_raw_net_init(struct net *net)
92{ 41{
93 /* Register table */ 42 struct ipt_replace *repl;
43
44 repl = ipt_alloc_initial_table(&packet_raw);
45 if (repl == NULL)
46 return -ENOMEM;
94 net->ipv4.iptable_raw = 47 net->ipv4.iptable_raw =
95 ipt_register_table(net, &packet_raw, &initial_table.repl); 48 ipt_register_table(net, &packet_raw, repl);
49 kfree(repl);
96 if (IS_ERR(net->ipv4.iptable_raw)) 50 if (IS_ERR(net->ipv4.iptable_raw))
97 return PTR_ERR(net->ipv4.iptable_raw); 51 return PTR_ERR(net->ipv4.iptable_raw);
98 return 0; 52 return 0;
@@ -100,7 +54,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
100 54
101static void __net_exit iptable_raw_net_exit(struct net *net) 55static void __net_exit iptable_raw_net_exit(struct net *net)
102{ 56{
103 ipt_unregister_table(net->ipv4.iptable_raw); 57 ipt_unregister_table(net, net->ipv4.iptable_raw);
104} 58}
105 59
106static struct pernet_operations iptable_raw_net_ops = { 60static struct pernet_operations iptable_raw_net_ops = {
@@ -117,9 +71,11 @@ static int __init iptable_raw_init(void)
117 return ret; 71 return ret;
118 72
119 /* Register hooks */ 73 /* Register hooks */
120 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 74 rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook);
121 if (ret < 0) 75 if (IS_ERR(rawtable_ops)) {
76 ret = PTR_ERR(rawtable_ops);
122 goto cleanup_table; 77 goto cleanup_table;
78 }
123 79
124 return ret; 80 return ret;
125 81
@@ -130,7 +86,7 @@ static int __init iptable_raw_init(void)
130 86
131static void __exit iptable_raw_fini(void) 87static void __exit iptable_raw_fini(void)
132{ 88{
133 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 89 xt_hook_unlink(&packet_raw, rawtable_ops);
134 unregister_pernet_subsys(&iptable_raw_net_ops); 90 unregister_pernet_subsys(&iptable_raw_net_ops);
135} 91}
136 92
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
index 3bd3d6388da5..cce2f64e6f21 100644
--- a/net/ipv4/netfilter/iptable_security.c
+++ b/net/ipv4/netfilter/iptable_security.c
@@ -27,109 +27,44 @@ MODULE_DESCRIPTION("iptables security table, for MAC rules");
27 (1 << NF_INET_FORWARD) | \ 27 (1 << NF_INET_FORWARD) | \
28 (1 << NF_INET_LOCAL_OUT) 28 (1 << NF_INET_LOCAL_OUT)
29 29
30static const struct
31{
32 struct ipt_replace repl;
33 struct ipt_standard entries[3];
34 struct ipt_error term;
35} initial_table __net_initdata = {
36 .repl = {
37 .name = "security",
38 .valid_hooks = SECURITY_VALID_HOOKS,
39 .num_entries = 4,
40 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
41 .hook_entry = {
42 [NF_INET_LOCAL_IN] = 0,
43 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
44 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
45 },
46 .underflow = {
47 [NF_INET_LOCAL_IN] = 0,
48 [NF_INET_FORWARD] = sizeof(struct ipt_standard),
49 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2,
50 },
51 },
52 .entries = {
53 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
54 IPT_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
55 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
56 },
57 .term = IPT_ERROR_INIT, /* ERROR */
58};
59
60static const struct xt_table security_table = { 30static const struct xt_table security_table = {
61 .name = "security", 31 .name = "security",
62 .valid_hooks = SECURITY_VALID_HOOKS, 32 .valid_hooks = SECURITY_VALID_HOOKS,
63 .me = THIS_MODULE, 33 .me = THIS_MODULE,
64 .af = NFPROTO_IPV4, 34 .af = NFPROTO_IPV4,
35 .priority = NF_IP_PRI_SECURITY,
65}; 36};
66 37
67static unsigned int 38static unsigned int
68ipt_local_in_hook(unsigned int hook, 39iptable_security_hook(unsigned int hook, struct sk_buff *skb,
69 struct sk_buff *skb, 40 const struct net_device *in,
70 const struct net_device *in, 41 const struct net_device *out,
71 const struct net_device *out, 42 int (*okfn)(struct sk_buff *))
72 int (*okfn)(struct sk_buff *))
73{
74 return ipt_do_table(skb, hook, in, out,
75 dev_net(in)->ipv4.iptable_security);
76}
77
78static unsigned int
79ipt_forward_hook(unsigned int hook,
80 struct sk_buff *skb,
81 const struct net_device *in,
82 const struct net_device *out,
83 int (*okfn)(struct sk_buff *))
84{ 43{
85 return ipt_do_table(skb, hook, in, out, 44 const struct net *net;
86 dev_net(in)->ipv4.iptable_security);
87}
88 45
89static unsigned int 46 if (hook == NF_INET_LOCAL_OUT &&
90ipt_local_out_hook(unsigned int hook, 47 (skb->len < sizeof(struct iphdr) ||
91 struct sk_buff *skb, 48 ip_hdrlen(skb) < sizeof(struct iphdr)))
92 const struct net_device *in, 49 /* Somebody is playing with raw sockets. */
93 const struct net_device *out,
94 int (*okfn)(struct sk_buff *))
95{
96 /* Somebody is playing with raw sockets. */
97 if (skb->len < sizeof(struct iphdr) ||
98 ip_hdrlen(skb) < sizeof(struct iphdr))
99 return NF_ACCEPT; 50 return NF_ACCEPT;
100 return ipt_do_table(skb, hook, in, out, 51
101 dev_net(out)->ipv4.iptable_security); 52 net = dev_net((in != NULL) ? in : out);
53 return ipt_do_table(skb, hook, in, out, net->ipv4.iptable_security);
102} 54}
103 55
104static struct nf_hook_ops ipt_ops[] __read_mostly = { 56static struct nf_hook_ops *sectbl_ops __read_mostly;
105 {
106 .hook = ipt_local_in_hook,
107 .owner = THIS_MODULE,
108 .pf = NFPROTO_IPV4,
109 .hooknum = NF_INET_LOCAL_IN,
110 .priority = NF_IP_PRI_SECURITY,
111 },
112 {
113 .hook = ipt_forward_hook,
114 .owner = THIS_MODULE,
115 .pf = NFPROTO_IPV4,
116 .hooknum = NF_INET_FORWARD,
117 .priority = NF_IP_PRI_SECURITY,
118 },
119 {
120 .hook = ipt_local_out_hook,
121 .owner = THIS_MODULE,
122 .pf = NFPROTO_IPV4,
123 .hooknum = NF_INET_LOCAL_OUT,
124 .priority = NF_IP_PRI_SECURITY,
125 },
126};
127 57
128static int __net_init iptable_security_net_init(struct net *net) 58static int __net_init iptable_security_net_init(struct net *net)
129{ 59{
130 net->ipv4.iptable_security = 60 struct ipt_replace *repl;
131 ipt_register_table(net, &security_table, &initial_table.repl);
132 61
62 repl = ipt_alloc_initial_table(&security_table);
63 if (repl == NULL)
64 return -ENOMEM;
65 net->ipv4.iptable_security =
66 ipt_register_table(net, &security_table, repl);
67 kfree(repl);
133 if (IS_ERR(net->ipv4.iptable_security)) 68 if (IS_ERR(net->ipv4.iptable_security))
134 return PTR_ERR(net->ipv4.iptable_security); 69 return PTR_ERR(net->ipv4.iptable_security);
135 70
@@ -138,7 +73,7 @@ static int __net_init iptable_security_net_init(struct net *net)
138 73
139static void __net_exit iptable_security_net_exit(struct net *net) 74static void __net_exit iptable_security_net_exit(struct net *net)
140{ 75{
141 ipt_unregister_table(net->ipv4.iptable_security); 76 ipt_unregister_table(net, net->ipv4.iptable_security);
142} 77}
143 78
144static struct pernet_operations iptable_security_net_ops = { 79static struct pernet_operations iptable_security_net_ops = {
@@ -154,9 +89,11 @@ static int __init iptable_security_init(void)
154 if (ret < 0) 89 if (ret < 0)
155 return ret; 90 return ret;
156 91
157 ret = nf_register_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 92 sectbl_ops = xt_hook_link(&security_table, iptable_security_hook);
158 if (ret < 0) 93 if (IS_ERR(sectbl_ops)) {
94 ret = PTR_ERR(sectbl_ops);
159 goto cleanup_table; 95 goto cleanup_table;
96 }
160 97
161 return ret; 98 return ret;
162 99
@@ -167,7 +104,7 @@ cleanup_table:
167 104
168static void __exit iptable_security_fini(void) 105static void __exit iptable_security_fini(void)
169{ 106{
170 nf_unregister_hooks(ipt_ops, ARRAY_SIZE(ipt_ops)); 107 xt_hook_unlink(&security_table, sectbl_ops);
171 unregister_pernet_subsys(&iptable_security_net_ops); 108 unregister_pernet_subsys(&iptable_security_net_ops);
172} 109}
173 110
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
index d1ea38a7c490..2bb1f87051c4 100644
--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
@@ -22,6 +22,7 @@
22#include <net/netfilter/nf_conntrack_helper.h> 22#include <net/netfilter/nf_conntrack_helper.h>
23#include <net/netfilter/nf_conntrack_l4proto.h> 23#include <net/netfilter/nf_conntrack_l4proto.h>
24#include <net/netfilter/nf_conntrack_l3proto.h> 24#include <net/netfilter/nf_conntrack_l3proto.h>
25#include <net/netfilter/nf_conntrack_zones.h>
25#include <net/netfilter/nf_conntrack_core.h> 26#include <net/netfilter/nf_conntrack_core.h>
26#include <net/netfilter/ipv4/nf_conntrack_ipv4.h> 27#include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
27#include <net/netfilter/nf_nat_helper.h> 28#include <net/netfilter/nf_nat_helper.h>
@@ -266,7 +267,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len)
266 return -EINVAL; 267 return -EINVAL;
267 } 268 }
268 269
269 h = nf_conntrack_find_get(sock_net(sk), &tuple); 270 h = nf_conntrack_find_get(sock_net(sk), NF_CT_DEFAULT_ZONE, &tuple);
270 if (h) { 271 if (h) {
271 struct sockaddr_in sin; 272 struct sockaddr_in sin;
272 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); 273 struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 7afd39b5b781..7404bde95994 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -18,6 +18,7 @@
18#include <net/netfilter/nf_conntrack_tuple.h> 18#include <net/netfilter/nf_conntrack_tuple.h>
19#include <net/netfilter/nf_conntrack_l4proto.h> 19#include <net/netfilter/nf_conntrack_l4proto.h>
20#include <net/netfilter/nf_conntrack_core.h> 20#include <net/netfilter/nf_conntrack_core.h>
21#include <net/netfilter/nf_conntrack_zones.h>
21#include <net/netfilter/nf_log.h> 22#include <net/netfilter/nf_log.h>
22 23
23static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ; 24static unsigned int nf_ct_icmp_timeout __read_mostly = 30*HZ;
@@ -114,13 +115,14 @@ static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
114 115
115/* Returns conntrack if it dealt with ICMP, and filled in skb fields */ 116/* Returns conntrack if it dealt with ICMP, and filled in skb fields */
116static int 117static int
117icmp_error_message(struct net *net, struct sk_buff *skb, 118icmp_error_message(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
118 enum ip_conntrack_info *ctinfo, 119 enum ip_conntrack_info *ctinfo,
119 unsigned int hooknum) 120 unsigned int hooknum)
120{ 121{
121 struct nf_conntrack_tuple innertuple, origtuple; 122 struct nf_conntrack_tuple innertuple, origtuple;
122 const struct nf_conntrack_l4proto *innerproto; 123 const struct nf_conntrack_l4proto *innerproto;
123 const struct nf_conntrack_tuple_hash *h; 124 const struct nf_conntrack_tuple_hash *h;
125 u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
124 126
125 NF_CT_ASSERT(skb->nfct == NULL); 127 NF_CT_ASSERT(skb->nfct == NULL);
126 128
@@ -146,7 +148,7 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
146 148
147 *ctinfo = IP_CT_RELATED; 149 *ctinfo = IP_CT_RELATED;
148 150
149 h = nf_conntrack_find_get(net, &innertuple); 151 h = nf_conntrack_find_get(net, zone, &innertuple);
150 if (!h) { 152 if (!h) {
151 pr_debug("icmp_error_message: no match\n"); 153 pr_debug("icmp_error_message: no match\n");
152 return -NF_ACCEPT; 154 return -NF_ACCEPT;
@@ -163,7 +165,8 @@ icmp_error_message(struct net *net, struct sk_buff *skb,
163 165
164/* Small and modified version of icmp_rcv */ 166/* Small and modified version of icmp_rcv */
165static int 167static int
166icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, 168icmp_error(struct net *net, struct nf_conn *tmpl,
169 struct sk_buff *skb, unsigned int dataoff,
167 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) 170 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
168{ 171{
169 const struct icmphdr *icmph; 172 const struct icmphdr *icmph;
@@ -208,7 +211,7 @@ icmp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
208 icmph->type != ICMP_REDIRECT) 211 icmph->type != ICMP_REDIRECT)
209 return NF_ACCEPT; 212 return NF_ACCEPT;
210 213
211 return icmp_error_message(net, skb, ctinfo, hooknum); 214 return icmp_error_message(net, tmpl, skb, ctinfo, hooknum);
212} 215}
213 216
214#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 217#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
index 331ead3ebd1b..d498a704d456 100644
--- a/net/ipv4/netfilter/nf_defrag_ipv4.c
+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
@@ -16,7 +16,9 @@
16 16
17#include <linux/netfilter_bridge.h> 17#include <linux/netfilter_bridge.h>
18#include <linux/netfilter_ipv4.h> 18#include <linux/netfilter_ipv4.h>
19#include <net/netfilter/nf_conntrack_zones.h>
19#include <net/netfilter/ipv4/nf_defrag_ipv4.h> 20#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
21#include <net/netfilter/nf_conntrack.h>
20 22
21/* Returns new sk_buff, or NULL */ 23/* Returns new sk_buff, or NULL */
22static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user) 24static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
@@ -38,15 +40,20 @@ static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
38static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, 40static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum,
39 struct sk_buff *skb) 41 struct sk_buff *skb)
40{ 42{
43 u16 zone = NF_CT_DEFAULT_ZONE;
44
45 if (skb->nfct)
46 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
47
41#ifdef CONFIG_BRIDGE_NETFILTER 48#ifdef CONFIG_BRIDGE_NETFILTER
42 if (skb->nf_bridge && 49 if (skb->nf_bridge &&
43 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) 50 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
44 return IP_DEFRAG_CONNTRACK_BRIDGE_IN; 51 return IP_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
45#endif 52#endif
46 if (hooknum == NF_INET_PRE_ROUTING) 53 if (hooknum == NF_INET_PRE_ROUTING)
47 return IP_DEFRAG_CONNTRACK_IN; 54 return IP_DEFRAG_CONNTRACK_IN + zone;
48 else 55 else
49 return IP_DEFRAG_CONNTRACK_OUT; 56 return IP_DEFRAG_CONNTRACK_OUT + zone;
50} 57}
51 58
52static unsigned int ipv4_conntrack_defrag(unsigned int hooknum, 59static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
@@ -59,7 +66,7 @@ static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
59#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE) 66#if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE)
60 /* Previously seen (loopback)? Ignore. Do this before 67 /* Previously seen (loopback)? Ignore. Do this before
61 fragment check. */ 68 fragment check. */
62 if (skb->nfct) 69 if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
63 return NF_ACCEPT; 70 return NF_ACCEPT;
64#endif 71#endif
65#endif 72#endif
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c
index 26066a2327ad..4595281c2863 100644
--- a/net/ipv4/netfilter/nf_nat_core.c
+++ b/net/ipv4/netfilter/nf_nat_core.c
@@ -30,6 +30,7 @@
30#include <net/netfilter/nf_conntrack_helper.h> 30#include <net/netfilter/nf_conntrack_helper.h>
31#include <net/netfilter/nf_conntrack_l3proto.h> 31#include <net/netfilter/nf_conntrack_l3proto.h>
32#include <net/netfilter/nf_conntrack_l4proto.h> 32#include <net/netfilter/nf_conntrack_l4proto.h>
33#include <net/netfilter/nf_conntrack_zones.h>
33 34
34static DEFINE_SPINLOCK(nf_nat_lock); 35static DEFINE_SPINLOCK(nf_nat_lock);
35 36
@@ -69,13 +70,14 @@ EXPORT_SYMBOL_GPL(nf_nat_proto_put);
69 70
70/* We keep an extra hash for each conntrack, for fast searching. */ 71/* We keep an extra hash for each conntrack, for fast searching. */
71static inline unsigned int 72static inline unsigned int
72hash_by_src(const struct net *net, const struct nf_conntrack_tuple *tuple) 73hash_by_src(const struct net *net, u16 zone,
74 const struct nf_conntrack_tuple *tuple)
73{ 75{
74 unsigned int hash; 76 unsigned int hash;
75 77
76 /* Original src, to ensure we map it consistently if poss. */ 78 /* Original src, to ensure we map it consistently if poss. */
77 hash = jhash_3words((__force u32)tuple->src.u3.ip, 79 hash = jhash_3words((__force u32)tuple->src.u3.ip,
78 (__force u32)tuple->src.u.all, 80 (__force u32)tuple->src.u.all ^ zone,
79 tuple->dst.protonum, 0); 81 tuple->dst.protonum, 0);
80 return ((u64)hash * net->ipv4.nat_htable_size) >> 32; 82 return ((u64)hash * net->ipv4.nat_htable_size) >> 32;
81} 83}
@@ -139,12 +141,12 @@ same_src(const struct nf_conn *ct,
139 141
140/* Only called for SRC manip */ 142/* Only called for SRC manip */
141static int 143static int
142find_appropriate_src(struct net *net, 144find_appropriate_src(struct net *net, u16 zone,
143 const struct nf_conntrack_tuple *tuple, 145 const struct nf_conntrack_tuple *tuple,
144 struct nf_conntrack_tuple *result, 146 struct nf_conntrack_tuple *result,
145 const struct nf_nat_range *range) 147 const struct nf_nat_range *range)
146{ 148{
147 unsigned int h = hash_by_src(net, tuple); 149 unsigned int h = hash_by_src(net, zone, tuple);
148 const struct nf_conn_nat *nat; 150 const struct nf_conn_nat *nat;
149 const struct nf_conn *ct; 151 const struct nf_conn *ct;
150 const struct hlist_node *n; 152 const struct hlist_node *n;
@@ -152,7 +154,7 @@ find_appropriate_src(struct net *net,
152 rcu_read_lock(); 154 rcu_read_lock();
153 hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { 155 hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) {
154 ct = nat->ct; 156 ct = nat->ct;
155 if (same_src(ct, tuple)) { 157 if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) {
156 /* Copy source part from reply tuple. */ 158 /* Copy source part from reply tuple. */
157 nf_ct_invert_tuplepr(result, 159 nf_ct_invert_tuplepr(result,
158 &ct->tuplehash[IP_CT_DIR_REPLY].tuple); 160 &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
@@ -175,7 +177,7 @@ find_appropriate_src(struct net *net,
175 the ip with the lowest src-ip/dst-ip/proto usage. 177 the ip with the lowest src-ip/dst-ip/proto usage.
176*/ 178*/
177static void 179static void
178find_best_ips_proto(struct nf_conntrack_tuple *tuple, 180find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple,
179 const struct nf_nat_range *range, 181 const struct nf_nat_range *range,
180 const struct nf_conn *ct, 182 const struct nf_conn *ct,
181 enum nf_nat_manip_type maniptype) 183 enum nf_nat_manip_type maniptype)
@@ -209,7 +211,7 @@ find_best_ips_proto(struct nf_conntrack_tuple *tuple,
209 maxip = ntohl(range->max_ip); 211 maxip = ntohl(range->max_ip);
210 j = jhash_2words((__force u32)tuple->src.u3.ip, 212 j = jhash_2words((__force u32)tuple->src.u3.ip,
211 range->flags & IP_NAT_RANGE_PERSISTENT ? 213 range->flags & IP_NAT_RANGE_PERSISTENT ?
212 0 : (__force u32)tuple->dst.u3.ip, 0); 214 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0);
213 j = ((u64)j * (maxip - minip + 1)) >> 32; 215 j = ((u64)j * (maxip - minip + 1)) >> 32;
214 *var_ipp = htonl(minip + j); 216 *var_ipp = htonl(minip + j);
215} 217}
@@ -229,6 +231,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
229{ 231{
230 struct net *net = nf_ct_net(ct); 232 struct net *net = nf_ct_net(ct);
231 const struct nf_nat_protocol *proto; 233 const struct nf_nat_protocol *proto;
234 u16 zone = nf_ct_zone(ct);
232 235
233 /* 1) If this srcip/proto/src-proto-part is currently mapped, 236 /* 1) If this srcip/proto/src-proto-part is currently mapped,
234 and that same mapping gives a unique tuple within the given 237 and that same mapping gives a unique tuple within the given
@@ -239,7 +242,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
239 manips not an issue. */ 242 manips not an issue. */
240 if (maniptype == IP_NAT_MANIP_SRC && 243 if (maniptype == IP_NAT_MANIP_SRC &&
241 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { 244 !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) {
242 if (find_appropriate_src(net, orig_tuple, tuple, range)) { 245 if (find_appropriate_src(net, zone, orig_tuple, tuple, range)) {
243 pr_debug("get_unique_tuple: Found current src map\n"); 246 pr_debug("get_unique_tuple: Found current src map\n");
244 if (!nf_nat_used_tuple(tuple, ct)) 247 if (!nf_nat_used_tuple(tuple, ct))
245 return; 248 return;
@@ -249,7 +252,7 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple,
249 /* 2) Select the least-used IP/proto combination in the given 252 /* 2) Select the least-used IP/proto combination in the given
250 range. */ 253 range. */
251 *tuple = *orig_tuple; 254 *tuple = *orig_tuple;
252 find_best_ips_proto(tuple, range, ct, maniptype); 255 find_best_ips_proto(zone, tuple, range, ct, maniptype);
253 256
254 /* 3) The per-protocol part of the manip is made to map into 257 /* 3) The per-protocol part of the manip is made to map into
255 the range to make a unique tuple. */ 258 the range to make a unique tuple. */
@@ -327,7 +330,8 @@ nf_nat_setup_info(struct nf_conn *ct,
327 if (have_to_hash) { 330 if (have_to_hash) {
328 unsigned int srchash; 331 unsigned int srchash;
329 332
330 srchash = hash_by_src(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 333 srchash = hash_by_src(net, nf_ct_zone(ct),
334 &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
331 spin_lock_bh(&nf_nat_lock); 335 spin_lock_bh(&nf_nat_lock);
332 /* nf_conntrack_alter_reply might re-allocate exntension aera */ 336 /* nf_conntrack_alter_reply might re-allocate exntension aera */
333 nat = nfct_nat(ct); 337 nat = nfct_nat(ct);
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/ipv4/netfilter/nf_nat_ftp.c
index a1d5d58a58bf..86e0e84ff0a0 100644
--- a/net/ipv4/netfilter/nf_nat_ftp.c
+++ b/net/ipv4/netfilter/nf_nat_ftp.c
@@ -27,76 +27,29 @@ MODULE_ALIAS("ip_nat_ftp");
27 27
28/* FIXME: Time out? --RR */ 28/* FIXME: Time out? --RR */
29 29
30static int 30static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type,
31mangle_rfc959_packet(struct sk_buff *skb, 31 char *buffer, size_t buflen,
32 __be32 newip, 32 __be32 addr, u16 port)
33 u_int16_t port,
34 unsigned int matchoff,
35 unsigned int matchlen,
36 struct nf_conn *ct,
37 enum ip_conntrack_info ctinfo)
38{ 33{
39 char buffer[sizeof("nnn,nnn,nnn,nnn,nnn,nnn")]; 34 switch (type) {
40 35 case NF_CT_FTP_PORT:
41 sprintf(buffer, "%u,%u,%u,%u,%u,%u", 36 case NF_CT_FTP_PASV:
42 NIPQUAD(newip), port>>8, port&0xFF); 37 return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u",
43 38 ((unsigned char *)&addr)[0],
44 pr_debug("calling nf_nat_mangle_tcp_packet\n"); 39 ((unsigned char *)&addr)[1],
45 40 ((unsigned char *)&addr)[2],
46 return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, 41 ((unsigned char *)&addr)[3],
47 matchlen, buffer, strlen(buffer)); 42 port >> 8,
48} 43 port & 0xFF);
49 44 case NF_CT_FTP_EPRT:
50/* |1|132.235.1.2|6275| */ 45 return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port);
51static int 46 case NF_CT_FTP_EPSV:
52mangle_eprt_packet(struct sk_buff *skb, 47 return snprintf(buffer, buflen, "|||%u|", port);
53 __be32 newip, 48 }
54 u_int16_t port,
55 unsigned int matchoff,
56 unsigned int matchlen,
57 struct nf_conn *ct,
58 enum ip_conntrack_info ctinfo)
59{
60 char buffer[sizeof("|1|255.255.255.255|65535|")];
61
62 sprintf(buffer, "|1|%u.%u.%u.%u|%u|", NIPQUAD(newip), port);
63
64 pr_debug("calling nf_nat_mangle_tcp_packet\n");
65
66 return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
67 matchlen, buffer, strlen(buffer));
68}
69
70/* |1|132.235.1.2|6275| */
71static int
72mangle_epsv_packet(struct sk_buff *skb,
73 __be32 newip,
74 u_int16_t port,
75 unsigned int matchoff,
76 unsigned int matchlen,
77 struct nf_conn *ct,
78 enum ip_conntrack_info ctinfo)
79{
80 char buffer[sizeof("|||65535|")];
81
82 sprintf(buffer, "|||%u|", port);
83
84 pr_debug("calling nf_nat_mangle_tcp_packet\n");
85 49
86 return nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, 50 return 0;
87 matchlen, buffer, strlen(buffer));
88} 51}
89 52
90static int (*mangle[])(struct sk_buff *, __be32, u_int16_t,
91 unsigned int, unsigned int, struct nf_conn *,
92 enum ip_conntrack_info)
93= {
94 [NF_CT_FTP_PORT] = mangle_rfc959_packet,
95 [NF_CT_FTP_PASV] = mangle_rfc959_packet,
96 [NF_CT_FTP_EPRT] = mangle_eprt_packet,
97 [NF_CT_FTP_EPSV] = mangle_epsv_packet
98};
99
100/* So, this packet has hit the connection tracking matching code. 53/* So, this packet has hit the connection tracking matching code.
101 Mangle it, and change the expectation to match the new version. */ 54 Mangle it, and change the expectation to match the new version. */
102static unsigned int nf_nat_ftp(struct sk_buff *skb, 55static unsigned int nf_nat_ftp(struct sk_buff *skb,
@@ -110,6 +63,8 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
110 u_int16_t port; 63 u_int16_t port;
111 int dir = CTINFO2DIR(ctinfo); 64 int dir = CTINFO2DIR(ctinfo);
112 struct nf_conn *ct = exp->master; 65 struct nf_conn *ct = exp->master;
66 char buffer[sizeof("|1|255.255.255.255|65535|")];
67 unsigned int buflen;
113 68
114 pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); 69 pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen);
115 70
@@ -132,11 +87,21 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb,
132 if (port == 0) 87 if (port == 0)
133 return NF_DROP; 88 return NF_DROP;
134 89
135 if (!mangle[type](skb, newip, port, matchoff, matchlen, ct, ctinfo)) { 90 buflen = nf_nat_ftp_fmt_cmd(type, buffer, sizeof(buffer), newip, port);
136 nf_ct_unexpect_related(exp); 91 if (!buflen)
137 return NF_DROP; 92 goto out;
138 } 93
94 pr_debug("calling nf_nat_mangle_tcp_packet\n");
95
96 if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff,
97 matchlen, buffer, buflen))
98 goto out;
99
139 return NF_ACCEPT; 100 return NF_ACCEPT;
101
102out:
103 nf_ct_unexpect_related(exp);
104 return NF_DROP;
140} 105}
141 106
142static void __exit nf_nat_ftp_fini(void) 107static void __exit nf_nat_ftp_fini(void)
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
index 7f10a6be0191..4b6af4bb1f50 100644
--- a/net/ipv4/netfilter/nf_nat_helper.c
+++ b/net/ipv4/netfilter/nf_nat_helper.c
@@ -141,6 +141,17 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
141 return 1; 141 return 1;
142} 142}
143 143
144void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo,
145 __be32 seq, s16 off)
146{
147 if (!off)
148 return;
149 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status);
150 adjust_tcp_sequence(ntohl(seq), off, ct, ctinfo);
151 nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
152}
153EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust);
154
144/* Generic function for mangling variable-length address changes inside 155/* Generic function for mangling variable-length address changes inside
145 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX 156 * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX
146 * command in FTP). 157 * command in FTP).
@@ -149,14 +160,13 @@ static int enlarge_skb(struct sk_buff *skb, unsigned int extra)
149 * skb enlargement, ... 160 * skb enlargement, ...
150 * 161 *
151 * */ 162 * */
152int 163int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
153nf_nat_mangle_tcp_packet(struct sk_buff *skb, 164 struct nf_conn *ct,
154 struct nf_conn *ct, 165 enum ip_conntrack_info ctinfo,
155 enum ip_conntrack_info ctinfo, 166 unsigned int match_offset,
156 unsigned int match_offset, 167 unsigned int match_len,
157 unsigned int match_len, 168 const char *rep_buffer,
158 const char *rep_buffer, 169 unsigned int rep_len, bool adjust)
159 unsigned int rep_len)
160{ 170{
161 struct rtable *rt = skb_rtable(skb); 171 struct rtable *rt = skb_rtable(skb);
162 struct iphdr *iph; 172 struct iphdr *iph;
@@ -202,16 +212,13 @@ nf_nat_mangle_tcp_packet(struct sk_buff *skb,
202 inet_proto_csum_replace2(&tcph->check, skb, 212 inet_proto_csum_replace2(&tcph->check, skb,
203 htons(oldlen), htons(datalen), 1); 213 htons(oldlen), htons(datalen), 1);
204 214
205 if (rep_len != match_len) { 215 if (adjust && rep_len != match_len)
206 set_bit(IPS_SEQ_ADJUST_BIT, &ct->status); 216 nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq,
207 adjust_tcp_sequence(ntohl(tcph->seq), 217 (int)rep_len - (int)match_len);
208 (int)rep_len - (int)match_len, 218
209 ct, ctinfo);
210 nf_conntrack_event_cache(IPCT_NATSEQADJ, ct);
211 }
212 return 1; 219 return 1;
213} 220}
214EXPORT_SYMBOL(nf_nat_mangle_tcp_packet); 221EXPORT_SYMBOL(__nf_nat_mangle_tcp_packet);
215 222
216/* Generic function for mangling variable-length address changes inside 223/* Generic function for mangling variable-length address changes inside
217 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX 224 * NATed UDP connections (like the CONNECT DATA XXXXX MESG XXXXX INDEX XXXXX
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index 9eb171056c63..4c060038d29f 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -25,6 +25,7 @@
25#include <net/netfilter/nf_nat_rule.h> 25#include <net/netfilter/nf_nat_rule.h>
26#include <net/netfilter/nf_conntrack_helper.h> 26#include <net/netfilter/nf_conntrack_helper.h>
27#include <net/netfilter/nf_conntrack_expect.h> 27#include <net/netfilter/nf_conntrack_expect.h>
28#include <net/netfilter/nf_conntrack_zones.h>
28#include <linux/netfilter/nf_conntrack_proto_gre.h> 29#include <linux/netfilter/nf_conntrack_proto_gre.h>
29#include <linux/netfilter/nf_conntrack_pptp.h> 30#include <linux/netfilter/nf_conntrack_pptp.h>
30 31
@@ -74,7 +75,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
74 75
75 pr_debug("trying to unexpect other dir: "); 76 pr_debug("trying to unexpect other dir: ");
76 nf_ct_dump_tuple_ip(&t); 77 nf_ct_dump_tuple_ip(&t);
77 other_exp = nf_ct_expect_find_get(net, &t); 78 other_exp = nf_ct_expect_find_get(net, nf_ct_zone(ct), &t);
78 if (other_exp) { 79 if (other_exp) {
79 nf_ct_unexpect_related(other_exp); 80 nf_ct_unexpect_related(other_exp);
80 nf_ct_expect_put(other_exp); 81 nf_ct_expect_put(other_exp);
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c
index 9e81e0dfb4ec..ab74cc0535e2 100644
--- a/net/ipv4/netfilter/nf_nat_rule.c
+++ b/net/ipv4/netfilter/nf_nat_rule.c
@@ -28,36 +28,6 @@
28 (1 << NF_INET_POST_ROUTING) | \ 28 (1 << NF_INET_POST_ROUTING) | \
29 (1 << NF_INET_LOCAL_OUT)) 29 (1 << NF_INET_LOCAL_OUT))
30 30
31static const struct
32{
33 struct ipt_replace repl;
34 struct ipt_standard entries[3];
35 struct ipt_error term;
36} nat_initial_table __net_initdata = {
37 .repl = {
38 .name = "nat",
39 .valid_hooks = NAT_VALID_HOOKS,
40 .num_entries = 4,
41 .size = sizeof(struct ipt_standard) * 3 + sizeof(struct ipt_error),
42 .hook_entry = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
45 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
46 },
47 .underflow = {
48 [NF_INET_PRE_ROUTING] = 0,
49 [NF_INET_POST_ROUTING] = sizeof(struct ipt_standard),
50 [NF_INET_LOCAL_OUT] = sizeof(struct ipt_standard) * 2
51 },
52 },
53 .entries = {
54 IPT_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
55 IPT_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56 IPT_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
57 },
58 .term = IPT_ERROR_INIT, /* ERROR */
59};
60
61static const struct xt_table nat_table = { 31static const struct xt_table nat_table = {
62 .name = "nat", 32 .name = "nat",
63 .valid_hooks = NAT_VALID_HOOKS, 33 .valid_hooks = NAT_VALID_HOOKS,
@@ -186,8 +156,13 @@ static struct xt_target ipt_dnat_reg __read_mostly = {
186 156
187static int __net_init nf_nat_rule_net_init(struct net *net) 157static int __net_init nf_nat_rule_net_init(struct net *net)
188{ 158{
189 net->ipv4.nat_table = ipt_register_table(net, &nat_table, 159 struct ipt_replace *repl;
190 &nat_initial_table.repl); 160
161 repl = ipt_alloc_initial_table(&nat_table);
162 if (repl == NULL)
163 return -ENOMEM;
164 net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
165 kfree(repl);
191 if (IS_ERR(net->ipv4.nat_table)) 166 if (IS_ERR(net->ipv4.nat_table))
192 return PTR_ERR(net->ipv4.nat_table); 167 return PTR_ERR(net->ipv4.nat_table);
193 return 0; 168 return 0;
@@ -195,7 +170,7 @@ static int __net_init nf_nat_rule_net_init(struct net *net)
195 170
196static void __net_exit nf_nat_rule_net_exit(struct net *net) 171static void __net_exit nf_nat_rule_net_exit(struct net *net)
197{ 172{
198 ipt_unregister_table(net->ipv4.nat_table); 173 ipt_unregister_table(net, net->ipv4.nat_table);
199} 174}
200 175
201static struct pernet_operations nf_nat_rule_net_ops = { 176static struct pernet_operations nf_nat_rule_net_ops = {
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c
index 07d61a57613c..11b538deaaec 100644
--- a/net/ipv4/netfilter/nf_nat_sip.c
+++ b/net/ipv4/netfilter/nf_nat_sip.c
@@ -1,4 +1,4 @@
1/* SIP extension for UDP NAT alteration. 1/* SIP extension for NAT alteration.
2 * 2 *
3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> 3 * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar>
4 * based on RR's ip_nat_ftp.c and other modules. 4 * based on RR's ip_nat_ftp.c and other modules.
@@ -15,6 +15,7 @@
15#include <linux/ip.h> 15#include <linux/ip.h>
16#include <net/ip.h> 16#include <net/ip.h>
17#include <linux/udp.h> 17#include <linux/udp.h>
18#include <linux/tcp.h>
18 19
19#include <net/netfilter/nf_nat.h> 20#include <net/netfilter/nf_nat.h>
20#include <net/netfilter/nf_nat_helper.h> 21#include <net/netfilter/nf_nat_helper.h>
@@ -29,25 +30,42 @@ MODULE_DESCRIPTION("SIP NAT helper");
29MODULE_ALIAS("ip_nat_sip"); 30MODULE_ALIAS("ip_nat_sip");
30 31
31 32
32static unsigned int mangle_packet(struct sk_buff *skb, 33static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff,
33 const char **dptr, unsigned int *datalen, 34 const char **dptr, unsigned int *datalen,
34 unsigned int matchoff, unsigned int matchlen, 35 unsigned int matchoff, unsigned int matchlen,
35 const char *buffer, unsigned int buflen) 36 const char *buffer, unsigned int buflen)
36{ 37{
37 enum ip_conntrack_info ctinfo; 38 enum ip_conntrack_info ctinfo;
38 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 39 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
39 40 struct tcphdr *th;
40 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, matchoff, matchlen, 41 unsigned int baseoff;
41 buffer, buflen)) 42
42 return 0; 43 if (nf_ct_protonum(ct) == IPPROTO_TCP) {
44 th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
45 baseoff = ip_hdrlen(skb) + th->doff * 4;
46 matchoff += dataoff - baseoff;
47
48 if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
49 matchoff, matchlen,
50 buffer, buflen, false))
51 return 0;
52 } else {
53 baseoff = ip_hdrlen(skb) + sizeof(struct udphdr);
54 matchoff += dataoff - baseoff;
55
56 if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
57 matchoff, matchlen,
58 buffer, buflen))
59 return 0;
60 }
43 61
44 /* Reload data pointer and adjust datalen value */ 62 /* Reload data pointer and adjust datalen value */
45 *dptr = skb->data + ip_hdrlen(skb) + sizeof(struct udphdr); 63 *dptr = skb->data + dataoff;
46 *datalen += buflen - matchlen; 64 *datalen += buflen - matchlen;
47 return 1; 65 return 1;
48} 66}
49 67
50static int map_addr(struct sk_buff *skb, 68static int map_addr(struct sk_buff *skb, unsigned int dataoff,
51 const char **dptr, unsigned int *datalen, 69 const char **dptr, unsigned int *datalen,
52 unsigned int matchoff, unsigned int matchlen, 70 unsigned int matchoff, unsigned int matchlen,
53 union nf_inet_addr *addr, __be16 port) 71 union nf_inet_addr *addr, __be16 port)
@@ -76,11 +94,11 @@ static int map_addr(struct sk_buff *skb,
76 94
77 buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport)); 95 buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport));
78 96
79 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 97 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
80 buffer, buflen); 98 buffer, buflen);
81} 99}
82 100
83static int map_sip_addr(struct sk_buff *skb, 101static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff,
84 const char **dptr, unsigned int *datalen, 102 const char **dptr, unsigned int *datalen,
85 enum sip_header_types type) 103 enum sip_header_types type)
86{ 104{
@@ -93,16 +111,18 @@ static int map_sip_addr(struct sk_buff *skb,
93 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, 111 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL,
94 &matchoff, &matchlen, &addr, &port) <= 0) 112 &matchoff, &matchlen, &addr, &port) <= 0)
95 return 1; 113 return 1;
96 return map_addr(skb, dptr, datalen, matchoff, matchlen, &addr, port); 114 return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
115 &addr, port);
97} 116}
98 117
99static unsigned int ip_nat_sip(struct sk_buff *skb, 118static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff,
100 const char **dptr, unsigned int *datalen) 119 const char **dptr, unsigned int *datalen)
101{ 120{
102 enum ip_conntrack_info ctinfo; 121 enum ip_conntrack_info ctinfo;
103 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 122 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
104 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 123 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
105 unsigned int dataoff, matchoff, matchlen; 124 unsigned int coff, matchoff, matchlen;
125 enum sip_header_types hdr;
106 union nf_inet_addr addr; 126 union nf_inet_addr addr;
107 __be16 port; 127 __be16 port;
108 int request, in_header; 128 int request, in_header;
@@ -112,16 +132,21 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
112 if (ct_sip_parse_request(ct, *dptr, *datalen, 132 if (ct_sip_parse_request(ct, *dptr, *datalen,
113 &matchoff, &matchlen, 133 &matchoff, &matchlen,
114 &addr, &port) > 0 && 134 &addr, &port) > 0 &&
115 !map_addr(skb, dptr, datalen, matchoff, matchlen, 135 !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
116 &addr, port)) 136 &addr, port))
117 return NF_DROP; 137 return NF_DROP;
118 request = 1; 138 request = 1;
119 } else 139 } else
120 request = 0; 140 request = 0;
121 141
142 if (nf_ct_protonum(ct) == IPPROTO_TCP)
143 hdr = SIP_HDR_VIA_TCP;
144 else
145 hdr = SIP_HDR_VIA_UDP;
146
122 /* Translate topmost Via header and parameters */ 147 /* Translate topmost Via header and parameters */
123 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, 148 if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen,
124 SIP_HDR_VIA, NULL, &matchoff, &matchlen, 149 hdr, NULL, &matchoff, &matchlen,
125 &addr, &port) > 0) { 150 &addr, &port) > 0) {
126 unsigned int matchend, poff, plen, buflen, n; 151 unsigned int matchend, poff, plen, buflen, n;
127 char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; 152 char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")];
@@ -138,7 +163,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
138 goto next; 163 goto next;
139 } 164 }
140 165
141 if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 166 if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
142 &addr, port)) 167 &addr, port))
143 return NF_DROP; 168 return NF_DROP;
144 169
@@ -153,8 +178,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
153 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { 178 addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) {
154 buflen = sprintf(buffer, "%pI4", 179 buflen = sprintf(buffer, "%pI4",
155 &ct->tuplehash[!dir].tuple.dst.u3.ip); 180 &ct->tuplehash[!dir].tuple.dst.u3.ip);
156 if (!mangle_packet(skb, dptr, datalen, poff, plen, 181 if (!mangle_packet(skb, dataoff, dptr, datalen,
157 buffer, buflen)) 182 poff, plen, buffer, buflen))
158 return NF_DROP; 183 return NF_DROP;
159 } 184 }
160 185
@@ -167,8 +192,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
167 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { 192 addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) {
168 buflen = sprintf(buffer, "%pI4", 193 buflen = sprintf(buffer, "%pI4",
169 &ct->tuplehash[!dir].tuple.src.u3.ip); 194 &ct->tuplehash[!dir].tuple.src.u3.ip);
170 if (!mangle_packet(skb, dptr, datalen, poff, plen, 195 if (!mangle_packet(skb, dataoff, dptr, datalen,
171 buffer, buflen)) 196 poff, plen, buffer, buflen))
172 return NF_DROP; 197 return NF_DROP;
173 } 198 }
174 199
@@ -181,31 +206,45 @@ static unsigned int ip_nat_sip(struct sk_buff *skb,
181 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { 206 htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) {
182 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; 207 __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port;
183 buflen = sprintf(buffer, "%u", ntohs(p)); 208 buflen = sprintf(buffer, "%u", ntohs(p));
184 if (!mangle_packet(skb, dptr, datalen, poff, plen, 209 if (!mangle_packet(skb, dataoff, dptr, datalen,
185 buffer, buflen)) 210 poff, plen, buffer, buflen))
186 return NF_DROP; 211 return NF_DROP;
187 } 212 }
188 } 213 }
189 214
190next: 215next:
191 /* Translate Contact headers */ 216 /* Translate Contact headers */
192 dataoff = 0; 217 coff = 0;
193 in_header = 0; 218 in_header = 0;
194 while (ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 219 while (ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
195 SIP_HDR_CONTACT, &in_header, 220 SIP_HDR_CONTACT, &in_header,
196 &matchoff, &matchlen, 221 &matchoff, &matchlen,
197 &addr, &port) > 0) { 222 &addr, &port) > 0) {
198 if (!map_addr(skb, dptr, datalen, matchoff, matchlen, 223 if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen,
199 &addr, port)) 224 &addr, port))
200 return NF_DROP; 225 return NF_DROP;
201 } 226 }
202 227
203 if (!map_sip_addr(skb, dptr, datalen, SIP_HDR_FROM) || 228 if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) ||
204 !map_sip_addr(skb, dptr, datalen, SIP_HDR_TO)) 229 !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO))
205 return NF_DROP; 230 return NF_DROP;
231
206 return NF_ACCEPT; 232 return NF_ACCEPT;
207} 233}
208 234
235static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off)
236{
237 enum ip_conntrack_info ctinfo;
238 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
239 const struct tcphdr *th;
240
241 if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0)
242 return;
243
244 th = (struct tcphdr *)(skb->data + ip_hdrlen(skb));
245 nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off);
246}
247
209/* Handles expected signalling connections and media streams */ 248/* Handles expected signalling connections and media streams */
210static void ip_nat_sip_expected(struct nf_conn *ct, 249static void ip_nat_sip_expected(struct nf_conn *ct,
211 struct nf_conntrack_expect *exp) 250 struct nf_conntrack_expect *exp)
@@ -232,7 +271,7 @@ static void ip_nat_sip_expected(struct nf_conn *ct,
232 } 271 }
233} 272}
234 273
235static unsigned int ip_nat_sip_expect(struct sk_buff *skb, 274static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff,
236 const char **dptr, unsigned int *datalen, 275 const char **dptr, unsigned int *datalen,
237 struct nf_conntrack_expect *exp, 276 struct nf_conntrack_expect *exp,
238 unsigned int matchoff, 277 unsigned int matchoff,
@@ -279,8 +318,8 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb,
279 if (exp->tuple.dst.u3.ip != exp->saved_ip || 318 if (exp->tuple.dst.u3.ip != exp->saved_ip ||
280 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { 319 exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) {
281 buflen = sprintf(buffer, "%pI4:%u", &newip, port); 320 buflen = sprintf(buffer, "%pI4:%u", &newip, port);
282 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 321 if (!mangle_packet(skb, dataoff, dptr, datalen,
283 buffer, buflen)) 322 matchoff, matchlen, buffer, buflen))
284 goto err; 323 goto err;
285 } 324 }
286 return NF_ACCEPT; 325 return NF_ACCEPT;
@@ -290,7 +329,7 @@ err:
290 return NF_DROP; 329 return NF_DROP;
291} 330}
292 331
293static int mangle_content_len(struct sk_buff *skb, 332static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff,
294 const char **dptr, unsigned int *datalen) 333 const char **dptr, unsigned int *datalen)
295{ 334{
296 enum ip_conntrack_info ctinfo; 335 enum ip_conntrack_info ctinfo;
@@ -312,12 +351,13 @@ static int mangle_content_len(struct sk_buff *skb,
312 return 0; 351 return 0;
313 352
314 buflen = sprintf(buffer, "%u", c_len); 353 buflen = sprintf(buffer, "%u", c_len);
315 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 354 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
316 buffer, buflen); 355 buffer, buflen);
317} 356}
318 357
319static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr, 358static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff,
320 unsigned int dataoff, unsigned int *datalen, 359 const char **dptr, unsigned int *datalen,
360 unsigned int sdpoff,
321 enum sdp_header_types type, 361 enum sdp_header_types type,
322 enum sdp_header_types term, 362 enum sdp_header_types term,
323 char *buffer, int buflen) 363 char *buffer, int buflen)
@@ -326,16 +366,16 @@ static int mangle_sdp_packet(struct sk_buff *skb, const char **dptr,
326 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 366 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
327 unsigned int matchlen, matchoff; 367 unsigned int matchlen, matchoff;
328 368
329 if (ct_sip_get_sdp_header(ct, *dptr, dataoff, *datalen, type, term, 369 if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term,
330 &matchoff, &matchlen) <= 0) 370 &matchoff, &matchlen) <= 0)
331 return -ENOENT; 371 return -ENOENT;
332 return mangle_packet(skb, dptr, datalen, matchoff, matchlen, 372 return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
333 buffer, buflen) ? 0 : -EINVAL; 373 buffer, buflen) ? 0 : -EINVAL;
334} 374}
335 375
336static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr, 376static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff,
337 unsigned int dataoff, 377 const char **dptr, unsigned int *datalen,
338 unsigned int *datalen, 378 unsigned int sdpoff,
339 enum sdp_header_types type, 379 enum sdp_header_types type,
340 enum sdp_header_types term, 380 enum sdp_header_types term,
341 const union nf_inet_addr *addr) 381 const union nf_inet_addr *addr)
@@ -344,16 +384,15 @@ static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, const char **dptr,
344 unsigned int buflen; 384 unsigned int buflen;
345 385
346 buflen = sprintf(buffer, "%pI4", &addr->ip); 386 buflen = sprintf(buffer, "%pI4", &addr->ip);
347 if (mangle_sdp_packet(skb, dptr, dataoff, datalen, type, term, 387 if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term,
348 buffer, buflen)) 388 buffer, buflen))
349 return 0; 389 return 0;
350 390
351 return mangle_content_len(skb, dptr, datalen); 391 return mangle_content_len(skb, dataoff, dptr, datalen);
352} 392}
353 393
354static unsigned int ip_nat_sdp_port(struct sk_buff *skb, 394static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff,
355 const char **dptr, 395 const char **dptr, unsigned int *datalen,
356 unsigned int *datalen,
357 unsigned int matchoff, 396 unsigned int matchoff,
358 unsigned int matchlen, 397 unsigned int matchlen,
359 u_int16_t port) 398 u_int16_t port)
@@ -362,16 +401,16 @@ static unsigned int ip_nat_sdp_port(struct sk_buff *skb,
362 unsigned int buflen; 401 unsigned int buflen;
363 402
364 buflen = sprintf(buffer, "%u", port); 403 buflen = sprintf(buffer, "%u", port);
365 if (!mangle_packet(skb, dptr, datalen, matchoff, matchlen, 404 if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen,
366 buffer, buflen)) 405 buffer, buflen))
367 return 0; 406 return 0;
368 407
369 return mangle_content_len(skb, dptr, datalen); 408 return mangle_content_len(skb, dataoff, dptr, datalen);
370} 409}
371 410
372static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr, 411static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff,
373 unsigned int dataoff, 412 const char **dptr, unsigned int *datalen,
374 unsigned int *datalen, 413 unsigned int sdpoff,
375 const union nf_inet_addr *addr) 414 const union nf_inet_addr *addr)
376{ 415{
377 char buffer[sizeof("nnn.nnn.nnn.nnn")]; 416 char buffer[sizeof("nnn.nnn.nnn.nnn")];
@@ -379,12 +418,12 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
379 418
380 /* Mangle session description owner and contact addresses */ 419 /* Mangle session description owner and contact addresses */
381 buflen = sprintf(buffer, "%pI4", &addr->ip); 420 buflen = sprintf(buffer, "%pI4", &addr->ip);
382 if (mangle_sdp_packet(skb, dptr, dataoff, datalen, 421 if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
383 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, 422 SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA,
384 buffer, buflen)) 423 buffer, buflen))
385 return 0; 424 return 0;
386 425
387 switch (mangle_sdp_packet(skb, dptr, dataoff, datalen, 426 switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff,
388 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, 427 SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA,
389 buffer, buflen)) { 428 buffer, buflen)) {
390 case 0: 429 case 0:
@@ -401,14 +440,13 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, const char **dptr,
401 return 0; 440 return 0;
402 } 441 }
403 442
404 return mangle_content_len(skb, dptr, datalen); 443 return mangle_content_len(skb, dataoff, dptr, datalen);
405} 444}
406 445
407/* So, this packet has hit the connection tracking matching code. 446/* So, this packet has hit the connection tracking matching code.
408 Mangle it, and change the expectation to match the new version. */ 447 Mangle it, and change the expectation to match the new version. */
409static unsigned int ip_nat_sdp_media(struct sk_buff *skb, 448static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
410 const char **dptr, 449 const char **dptr, unsigned int *datalen,
411 unsigned int *datalen,
412 struct nf_conntrack_expect *rtp_exp, 450 struct nf_conntrack_expect *rtp_exp,
413 struct nf_conntrack_expect *rtcp_exp, 451 struct nf_conntrack_expect *rtcp_exp,
414 unsigned int mediaoff, 452 unsigned int mediaoff,
@@ -456,7 +494,8 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb,
456 494
457 /* Update media port. */ 495 /* Update media port. */
458 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && 496 if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port &&
459 !ip_nat_sdp_port(skb, dptr, datalen, mediaoff, medialen, port)) 497 !ip_nat_sdp_port(skb, dataoff, dptr, datalen,
498 mediaoff, medialen, port))
460 goto err2; 499 goto err2;
461 500
462 return NF_ACCEPT; 501 return NF_ACCEPT;
@@ -471,6 +510,7 @@ err1:
471static void __exit nf_nat_sip_fini(void) 510static void __exit nf_nat_sip_fini(void)
472{ 511{
473 rcu_assign_pointer(nf_nat_sip_hook, NULL); 512 rcu_assign_pointer(nf_nat_sip_hook, NULL);
513 rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, NULL);
474 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL); 514 rcu_assign_pointer(nf_nat_sip_expect_hook, NULL);
475 rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL); 515 rcu_assign_pointer(nf_nat_sdp_addr_hook, NULL);
476 rcu_assign_pointer(nf_nat_sdp_port_hook, NULL); 516 rcu_assign_pointer(nf_nat_sdp_port_hook, NULL);
@@ -482,12 +522,14 @@ static void __exit nf_nat_sip_fini(void)
482static int __init nf_nat_sip_init(void) 522static int __init nf_nat_sip_init(void)
483{ 523{
484 BUG_ON(nf_nat_sip_hook != NULL); 524 BUG_ON(nf_nat_sip_hook != NULL);
525 BUG_ON(nf_nat_sip_seq_adjust_hook != NULL);
485 BUG_ON(nf_nat_sip_expect_hook != NULL); 526 BUG_ON(nf_nat_sip_expect_hook != NULL);
486 BUG_ON(nf_nat_sdp_addr_hook != NULL); 527 BUG_ON(nf_nat_sdp_addr_hook != NULL);
487 BUG_ON(nf_nat_sdp_port_hook != NULL); 528 BUG_ON(nf_nat_sdp_port_hook != NULL);
488 BUG_ON(nf_nat_sdp_session_hook != NULL); 529 BUG_ON(nf_nat_sdp_session_hook != NULL);
489 BUG_ON(nf_nat_sdp_media_hook != NULL); 530 BUG_ON(nf_nat_sdp_media_hook != NULL);
490 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip); 531 rcu_assign_pointer(nf_nat_sip_hook, ip_nat_sip);
532 rcu_assign_pointer(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust);
491 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect); 533 rcu_assign_pointer(nf_nat_sip_expect_hook, ip_nat_sip_expect);
492 rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr); 534 rcu_assign_pointer(nf_nat_sdp_addr_hook, ip_nat_sdp_addr);
493 rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port); 535 rcu_assign_pointer(nf_nat_sdp_port_hook, ip_nat_sdp_port);
diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index d9521f6f9ed0..0b9c7ce3d6c5 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1038,7 +1038,7 @@ static int snmp_parse_mangle(unsigned char *msg,
1038 unsigned int cls, con, tag, vers, pdutype; 1038 unsigned int cls, con, tag, vers, pdutype;
1039 struct asn1_ctx ctx; 1039 struct asn1_ctx ctx;
1040 struct asn1_octstr comm; 1040 struct asn1_octstr comm;
1041 struct snmp_object **obj; 1041 struct snmp_object *obj;
1042 1042
1043 if (debug > 1) 1043 if (debug > 1)
1044 hex_dump(msg, len); 1044 hex_dump(msg, len);
@@ -1148,43 +1148,34 @@ static int snmp_parse_mangle(unsigned char *msg,
1148 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ) 1148 if (cls != ASN1_UNI || con != ASN1_CON || tag != ASN1_SEQ)
1149 return 0; 1149 return 0;
1150 1150
1151 obj = kmalloc(sizeof(struct snmp_object), GFP_ATOMIC);
1152 if (obj == NULL) {
1153 if (net_ratelimit())
1154 printk(KERN_WARNING "OOM in bsalg(%d)\n", __LINE__);
1155 return 0;
1156 }
1157
1158 while (!asn1_eoc_decode(&ctx, eoc)) { 1151 while (!asn1_eoc_decode(&ctx, eoc)) {
1159 unsigned int i; 1152 unsigned int i;
1160 1153
1161 if (!snmp_object_decode(&ctx, obj)) { 1154 if (!snmp_object_decode(&ctx, &obj)) {
1162 if (*obj) { 1155 if (obj) {
1163 kfree((*obj)->id); 1156 kfree(obj->id);
1164 kfree(*obj); 1157 kfree(obj);
1165 } 1158 }
1166 kfree(obj);
1167 return 0; 1159 return 0;
1168 } 1160 }
1169 1161
1170 if (debug > 1) { 1162 if (debug > 1) {
1171 printk(KERN_DEBUG "bsalg: object: "); 1163 printk(KERN_DEBUG "bsalg: object: ");
1172 for (i = 0; i < (*obj)->id_len; i++) { 1164 for (i = 0; i < obj->id_len; i++) {
1173 if (i > 0) 1165 if (i > 0)
1174 printk("."); 1166 printk(".");
1175 printk("%lu", (*obj)->id[i]); 1167 printk("%lu", obj->id[i]);
1176 } 1168 }
1177 printk(": type=%u\n", (*obj)->type); 1169 printk(": type=%u\n", obj->type);
1178 1170
1179 } 1171 }
1180 1172
1181 if ((*obj)->type == SNMP_IPADDR) 1173 if (obj->type == SNMP_IPADDR)
1182 mangle_address(ctx.begin, ctx.pointer - 4 , map, check); 1174 mangle_address(ctx.begin, ctx.pointer - 4 , map, check);
1183 1175
1184 kfree((*obj)->id); 1176 kfree(obj->id);
1185 kfree(*obj); 1177 kfree(obj);
1186 } 1178 }
1187 kfree(obj);
1188 1179
1189 if (!asn1_eoc_decode(&ctx, eoc)) 1180 if (!asn1_eoc_decode(&ctx, eoc))
1190 return 0; 1181 return 0;
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 8a7e0f52e177..4185099c2943 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -29,6 +29,7 @@
29#include <linux/netfilter_ipv6/ip6_tables.h> 29#include <linux/netfilter_ipv6/ip6_tables.h>
30#include <linux/netfilter/x_tables.h> 30#include <linux/netfilter/x_tables.h>
31#include <net/netfilter/nf_log.h> 31#include <net/netfilter/nf_log.h>
32#include "../../netfilter/xt_repldata.h"
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); 35MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
@@ -67,6 +68,12 @@ do { \
67#define inline 68#define inline
68#endif 69#endif
69 70
71void *ip6t_alloc_initial_table(const struct xt_table *info)
72{
73 return xt_alloc_initial_table(ip6t, IP6T);
74}
75EXPORT_SYMBOL_GPL(ip6t_alloc_initial_table);
76
70/* 77/*
71 We keep a set of rules for each CPU, so we can avoid write-locking 78 We keep a set of rules for each CPU, so we can avoid write-locking
72 them in the softirq when updating the counters and therefore 79 them in the softirq when updating the counters and therefore
@@ -201,7 +208,7 @@ ip6t_error(struct sk_buff *skb, const struct xt_target_param *par)
201 208
202/* Performance critical - called for every packet */ 209/* Performance critical - called for every packet */
203static inline bool 210static inline bool
204do_match(struct ip6t_entry_match *m, const struct sk_buff *skb, 211do_match(const struct ip6t_entry_match *m, const struct sk_buff *skb,
205 struct xt_match_param *par) 212 struct xt_match_param *par)
206{ 213{
207 par->match = m->u.kernel.match; 214 par->match = m->u.kernel.match;
@@ -215,7 +222,7 @@ do_match(struct ip6t_entry_match *m, const struct sk_buff *skb,
215} 222}
216 223
217static inline struct ip6t_entry * 224static inline struct ip6t_entry *
218get_entry(void *base, unsigned int offset) 225get_entry(const void *base, unsigned int offset)
219{ 226{
220 return (struct ip6t_entry *)(base + offset); 227 return (struct ip6t_entry *)(base + offset);
221} 228}
@@ -229,6 +236,12 @@ static inline bool unconditional(const struct ip6t_ip6 *ipv6)
229 return memcmp(ipv6, &uncond, sizeof(uncond)) == 0; 236 return memcmp(ipv6, &uncond, sizeof(uncond)) == 0;
230} 237}
231 238
239static inline const struct ip6t_entry_target *
240ip6t_get_target_c(const struct ip6t_entry *e)
241{
242 return ip6t_get_target((struct ip6t_entry *)e);
243}
244
232#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 245#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
233 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE) 246 defined(CONFIG_NETFILTER_XT_TARGET_TRACE_MODULE)
234/* This cries for unification! */ 247/* This cries for unification! */
@@ -264,11 +277,11 @@ static struct nf_loginfo trace_loginfo = {
264 277
265/* Mildly perf critical (only if packet tracing is on) */ 278/* Mildly perf critical (only if packet tracing is on) */
266static inline int 279static inline int
267get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e, 280get_chainname_rulenum(const struct ip6t_entry *s, const struct ip6t_entry *e,
268 const char *hookname, const char **chainname, 281 const char *hookname, const char **chainname,
269 const char **comment, unsigned int *rulenum) 282 const char **comment, unsigned int *rulenum)
270{ 283{
271 struct ip6t_standard_target *t = (void *)ip6t_get_target(s); 284 const struct ip6t_standard_target *t = (void *)ip6t_get_target_c(s);
272 285
273 if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) { 286 if (strcmp(t->target.u.kernel.target->name, IP6T_ERROR_TARGET) == 0) {
274 /* Head of user chain: ERROR target with chainname */ 287 /* Head of user chain: ERROR target with chainname */
@@ -294,15 +307,15 @@ get_chainname_rulenum(struct ip6t_entry *s, struct ip6t_entry *e,
294 return 0; 307 return 0;
295} 308}
296 309
297static void trace_packet(struct sk_buff *skb, 310static void trace_packet(const struct sk_buff *skb,
298 unsigned int hook, 311 unsigned int hook,
299 const struct net_device *in, 312 const struct net_device *in,
300 const struct net_device *out, 313 const struct net_device *out,
301 const char *tablename, 314 const char *tablename,
302 struct xt_table_info *private, 315 const struct xt_table_info *private,
303 struct ip6t_entry *e) 316 const struct ip6t_entry *e)
304{ 317{
305 void *table_base; 318 const void *table_base;
306 const struct ip6t_entry *root; 319 const struct ip6t_entry *root;
307 const char *hookname, *chainname, *comment; 320 const char *hookname, *chainname, *comment;
308 unsigned int rulenum = 0; 321 unsigned int rulenum = 0;
@@ -345,9 +358,9 @@ ip6t_do_table(struct sk_buff *skb,
345 /* Initializing verdict to NF_DROP keeps gcc happy. */ 358 /* Initializing verdict to NF_DROP keeps gcc happy. */
346 unsigned int verdict = NF_DROP; 359 unsigned int verdict = NF_DROP;
347 const char *indev, *outdev; 360 const char *indev, *outdev;
348 void *table_base; 361 const void *table_base;
349 struct ip6t_entry *e, *back; 362 struct ip6t_entry *e, *back;
350 struct xt_table_info *private; 363 const struct xt_table_info *private;
351 struct xt_match_param mtpar; 364 struct xt_match_param mtpar;
352 struct xt_target_param tgpar; 365 struct xt_target_param tgpar;
353 366
@@ -378,7 +391,7 @@ ip6t_do_table(struct sk_buff *skb,
378 back = get_entry(table_base, private->underflow[hook]); 391 back = get_entry(table_base, private->underflow[hook]);
379 392
380 do { 393 do {
381 struct ip6t_entry_target *t; 394 const struct ip6t_entry_target *t;
382 395
383 IP_NF_ASSERT(e); 396 IP_NF_ASSERT(e);
384 IP_NF_ASSERT(back); 397 IP_NF_ASSERT(back);
@@ -393,7 +406,7 @@ ip6t_do_table(struct sk_buff *skb,
393 ntohs(ipv6_hdr(skb)->payload_len) + 406 ntohs(ipv6_hdr(skb)->payload_len) +
394 sizeof(struct ipv6hdr), 1); 407 sizeof(struct ipv6hdr), 1);
395 408
396 t = ip6t_get_target(e); 409 t = ip6t_get_target_c(e);
397 IP_NF_ASSERT(t->u.kernel.target); 410 IP_NF_ASSERT(t->u.kernel.target);
398 411
399#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \ 412#if defined(CONFIG_NETFILTER_XT_TARGET_TRACE) || \
@@ -475,7 +488,7 @@ ip6t_do_table(struct sk_buff *skb,
475/* Figures out from what hook each rule can be called: returns 0 if 488/* Figures out from what hook each rule can be called: returns 0 if
476 there are loops. Puts hook bitmask in comefrom. */ 489 there are loops. Puts hook bitmask in comefrom. */
477static int 490static int
478mark_source_chains(struct xt_table_info *newinfo, 491mark_source_chains(const struct xt_table_info *newinfo,
479 unsigned int valid_hooks, void *entry0) 492 unsigned int valid_hooks, void *entry0)
480{ 493{
481 unsigned int hook; 494 unsigned int hook;
@@ -493,8 +506,8 @@ mark_source_chains(struct xt_table_info *newinfo,
493 e->counters.pcnt = pos; 506 e->counters.pcnt = pos;
494 507
495 for (;;) { 508 for (;;) {
496 struct ip6t_standard_target *t 509 const struct ip6t_standard_target *t
497 = (void *)ip6t_get_target(e); 510 = (void *)ip6t_get_target_c(e);
498 int visited = e->comefrom & (1 << hook); 511 int visited = e->comefrom & (1 << hook);
499 512
500 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) { 513 if (e->comefrom & (1 << NF_INET_NUMHOOKS)) {
@@ -585,13 +598,14 @@ mark_source_chains(struct xt_table_info *newinfo,
585} 598}
586 599
587static int 600static int
588cleanup_match(struct ip6t_entry_match *m, unsigned int *i) 601cleanup_match(struct ip6t_entry_match *m, struct net *net, unsigned int *i)
589{ 602{
590 struct xt_mtdtor_param par; 603 struct xt_mtdtor_param par;
591 604
592 if (i && (*i)-- == 0) 605 if (i && (*i)-- == 0)
593 return 1; 606 return 1;
594 607
608 par.net = net;
595 par.match = m->u.kernel.match; 609 par.match = m->u.kernel.match;
596 par.matchinfo = m->data; 610 par.matchinfo = m->data;
597 par.family = NFPROTO_IPV6; 611 par.family = NFPROTO_IPV6;
@@ -602,9 +616,9 @@ cleanup_match(struct ip6t_entry_match *m, unsigned int *i)
602} 616}
603 617
604static int 618static int
605check_entry(struct ip6t_entry *e, const char *name) 619check_entry(const struct ip6t_entry *e, const char *name)
606{ 620{
607 struct ip6t_entry_target *t; 621 const struct ip6t_entry_target *t;
608 622
609 if (!ip6_checkentry(&e->ipv6)) { 623 if (!ip6_checkentry(&e->ipv6)) {
610 duprintf("ip_tables: ip check failed %p %s.\n", e, name); 624 duprintf("ip_tables: ip check failed %p %s.\n", e, name);
@@ -615,7 +629,7 @@ check_entry(struct ip6t_entry *e, const char *name)
615 e->next_offset) 629 e->next_offset)
616 return -EINVAL; 630 return -EINVAL;
617 631
618 t = ip6t_get_target(e); 632 t = ip6t_get_target_c(e);
619 if (e->target_offset + t->u.target_size > e->next_offset) 633 if (e->target_offset + t->u.target_size > e->next_offset)
620 return -EINVAL; 634 return -EINVAL;
621 635
@@ -668,10 +682,11 @@ err:
668 return ret; 682 return ret;
669} 683}
670 684
671static int check_target(struct ip6t_entry *e, const char *name) 685static int check_target(struct ip6t_entry *e, struct net *net, const char *name)
672{ 686{
673 struct ip6t_entry_target *t = ip6t_get_target(e); 687 struct ip6t_entry_target *t = ip6t_get_target(e);
674 struct xt_tgchk_param par = { 688 struct xt_tgchk_param par = {
689 .net = net,
675 .table = name, 690 .table = name,
676 .entryinfo = e, 691 .entryinfo = e,
677 .target = t->u.kernel.target, 692 .target = t->u.kernel.target,
@@ -693,8 +708,8 @@ static int check_target(struct ip6t_entry *e, const char *name)
693} 708}
694 709
695static int 710static int
696find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size, 711find_check_entry(struct ip6t_entry *e, struct net *net, const char *name,
697 unsigned int *i) 712 unsigned int size, unsigned int *i)
698{ 713{
699 struct ip6t_entry_target *t; 714 struct ip6t_entry_target *t;
700 struct xt_target *target; 715 struct xt_target *target;
@@ -707,6 +722,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
707 return ret; 722 return ret;
708 723
709 j = 0; 724 j = 0;
725 mtpar.net = net;
710 mtpar.table = name; 726 mtpar.table = name;
711 mtpar.entryinfo = &e->ipv6; 727 mtpar.entryinfo = &e->ipv6;
712 mtpar.hook_mask = e->comefrom; 728 mtpar.hook_mask = e->comefrom;
@@ -727,7 +743,7 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
727 } 743 }
728 t->u.kernel.target = target; 744 t->u.kernel.target = target;
729 745
730 ret = check_target(e, name); 746 ret = check_target(e, net, name);
731 if (ret) 747 if (ret)
732 goto err; 748 goto err;
733 749
@@ -736,18 +752,18 @@ find_check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
736 err: 752 err:
737 module_put(t->u.kernel.target->me); 753 module_put(t->u.kernel.target->me);
738 cleanup_matches: 754 cleanup_matches:
739 IP6T_MATCH_ITERATE(e, cleanup_match, &j); 755 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);
740 return ret; 756 return ret;
741} 757}
742 758
743static bool check_underflow(struct ip6t_entry *e) 759static bool check_underflow(const struct ip6t_entry *e)
744{ 760{
745 const struct ip6t_entry_target *t; 761 const struct ip6t_entry_target *t;
746 unsigned int verdict; 762 unsigned int verdict;
747 763
748 if (!unconditional(&e->ipv6)) 764 if (!unconditional(&e->ipv6))
749 return false; 765 return false;
750 t = ip6t_get_target(e); 766 t = ip6t_get_target_c(e);
751 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0) 767 if (strcmp(t->u.user.name, XT_STANDARD_TARGET) != 0)
752 return false; 768 return false;
753 verdict = ((struct ip6t_standard_target *)t)->verdict; 769 verdict = ((struct ip6t_standard_target *)t)->verdict;
@@ -758,8 +774,8 @@ static bool check_underflow(struct ip6t_entry *e)
758static int 774static int
759check_entry_size_and_hooks(struct ip6t_entry *e, 775check_entry_size_and_hooks(struct ip6t_entry *e,
760 struct xt_table_info *newinfo, 776 struct xt_table_info *newinfo,
761 unsigned char *base, 777 const unsigned char *base,
762 unsigned char *limit, 778 const unsigned char *limit,
763 const unsigned int *hook_entries, 779 const unsigned int *hook_entries,
764 const unsigned int *underflows, 780 const unsigned int *underflows,
765 unsigned int valid_hooks, 781 unsigned int valid_hooks,
@@ -806,7 +822,7 @@ check_entry_size_and_hooks(struct ip6t_entry *e,
806} 822}
807 823
808static int 824static int
809cleanup_entry(struct ip6t_entry *e, unsigned int *i) 825cleanup_entry(struct ip6t_entry *e, struct net *net, unsigned int *i)
810{ 826{
811 struct xt_tgdtor_param par; 827 struct xt_tgdtor_param par;
812 struct ip6t_entry_target *t; 828 struct ip6t_entry_target *t;
@@ -815,9 +831,10 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
815 return 1; 831 return 1;
816 832
817 /* Cleanup all matches */ 833 /* Cleanup all matches */
818 IP6T_MATCH_ITERATE(e, cleanup_match, NULL); 834 IP6T_MATCH_ITERATE(e, cleanup_match, net, NULL);
819 t = ip6t_get_target(e); 835 t = ip6t_get_target(e);
820 836
837 par.net = net;
821 par.target = t->u.kernel.target; 838 par.target = t->u.kernel.target;
822 par.targinfo = t->data; 839 par.targinfo = t->data;
823 par.family = NFPROTO_IPV6; 840 par.family = NFPROTO_IPV6;
@@ -830,7 +847,8 @@ cleanup_entry(struct ip6t_entry *e, unsigned int *i)
830/* Checks and translates the user-supplied table segment (held in 847/* Checks and translates the user-supplied table segment (held in
831 newinfo) */ 848 newinfo) */
832static int 849static int
833translate_table(const char *name, 850translate_table(struct net *net,
851 const char *name,
834 unsigned int valid_hooks, 852 unsigned int valid_hooks,
835 struct xt_table_info *newinfo, 853 struct xt_table_info *newinfo,
836 void *entry0, 854 void *entry0,
@@ -892,11 +910,11 @@ translate_table(const char *name,
892 /* Finally, each sanity check must pass */ 910 /* Finally, each sanity check must pass */
893 i = 0; 911 i = 0;
894 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 912 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
895 find_check_entry, name, size, &i); 913 find_check_entry, net, name, size, &i);
896 914
897 if (ret != 0) { 915 if (ret != 0) {
898 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 916 IP6T_ENTRY_ITERATE(entry0, newinfo->size,
899 cleanup_entry, &i); 917 cleanup_entry, net, &i);
900 return ret; 918 return ret;
901 } 919 }
902 920
@@ -972,11 +990,11 @@ get_counters(const struct xt_table_info *t,
972 local_bh_enable(); 990 local_bh_enable();
973} 991}
974 992
975static struct xt_counters *alloc_counters(struct xt_table *table) 993static struct xt_counters *alloc_counters(const struct xt_table *table)
976{ 994{
977 unsigned int countersize; 995 unsigned int countersize;
978 struct xt_counters *counters; 996 struct xt_counters *counters;
979 struct xt_table_info *private = table->private; 997 const struct xt_table_info *private = table->private;
980 998
981 /* We need atomic snapshot of counters: rest doesn't change 999 /* We need atomic snapshot of counters: rest doesn't change
982 (other than comefrom, which userspace doesn't care 1000 (other than comefrom, which userspace doesn't care
@@ -994,11 +1012,11 @@ static struct xt_counters *alloc_counters(struct xt_table *table)
994 1012
995static int 1013static int
996copy_entries_to_user(unsigned int total_size, 1014copy_entries_to_user(unsigned int total_size,
997 struct xt_table *table, 1015 const struct xt_table *table,
998 void __user *userptr) 1016 void __user *userptr)
999{ 1017{
1000 unsigned int off, num; 1018 unsigned int off, num;
1001 struct ip6t_entry *e; 1019 const struct ip6t_entry *e;
1002 struct xt_counters *counters; 1020 struct xt_counters *counters;
1003 const struct xt_table_info *private = table->private; 1021 const struct xt_table_info *private = table->private;
1004 int ret = 0; 1022 int ret = 0;
@@ -1050,7 +1068,7 @@ copy_entries_to_user(unsigned int total_size,
1050 } 1068 }
1051 } 1069 }
1052 1070
1053 t = ip6t_get_target(e); 1071 t = ip6t_get_target_c(e);
1054 if (copy_to_user(userptr + off + e->target_offset 1072 if (copy_to_user(userptr + off + e->target_offset
1055 + offsetof(struct ip6t_entry_target, 1073 + offsetof(struct ip6t_entry_target,
1056 u.user.name), 1074 u.user.name),
@@ -1067,7 +1085,7 @@ copy_entries_to_user(unsigned int total_size,
1067} 1085}
1068 1086
1069#ifdef CONFIG_COMPAT 1087#ifdef CONFIG_COMPAT
1070static void compat_standard_from_user(void *dst, void *src) 1088static void compat_standard_from_user(void *dst, const void *src)
1071{ 1089{
1072 int v = *(compat_int_t *)src; 1090 int v = *(compat_int_t *)src;
1073 1091
@@ -1076,7 +1094,7 @@ static void compat_standard_from_user(void *dst, void *src)
1076 memcpy(dst, &v, sizeof(v)); 1094 memcpy(dst, &v, sizeof(v));
1077} 1095}
1078 1096
1079static int compat_standard_to_user(void __user *dst, void *src) 1097static int compat_standard_to_user(void __user *dst, const void *src)
1080{ 1098{
1081 compat_int_t cv = *(int *)src; 1099 compat_int_t cv = *(int *)src;
1082 1100
@@ -1086,24 +1104,24 @@ static int compat_standard_to_user(void __user *dst, void *src)
1086} 1104}
1087 1105
1088static inline int 1106static inline int
1089compat_calc_match(struct ip6t_entry_match *m, int *size) 1107compat_calc_match(const struct ip6t_entry_match *m, int *size)
1090{ 1108{
1091 *size += xt_compat_match_offset(m->u.kernel.match); 1109 *size += xt_compat_match_offset(m->u.kernel.match);
1092 return 0; 1110 return 0;
1093} 1111}
1094 1112
1095static int compat_calc_entry(struct ip6t_entry *e, 1113static int compat_calc_entry(const struct ip6t_entry *e,
1096 const struct xt_table_info *info, 1114 const struct xt_table_info *info,
1097 void *base, struct xt_table_info *newinfo) 1115 const void *base, struct xt_table_info *newinfo)
1098{ 1116{
1099 struct ip6t_entry_target *t; 1117 const struct ip6t_entry_target *t;
1100 unsigned int entry_offset; 1118 unsigned int entry_offset;
1101 int off, i, ret; 1119 int off, i, ret;
1102 1120
1103 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry); 1121 off = sizeof(struct ip6t_entry) - sizeof(struct compat_ip6t_entry);
1104 entry_offset = (void *)e - base; 1122 entry_offset = (void *)e - base;
1105 IP6T_MATCH_ITERATE(e, compat_calc_match, &off); 1123 IP6T_MATCH_ITERATE(e, compat_calc_match, &off);
1106 t = ip6t_get_target(e); 1124 t = ip6t_get_target_c(e);
1107 off += xt_compat_target_offset(t->u.kernel.target); 1125 off += xt_compat_target_offset(t->u.kernel.target);
1108 newinfo->size -= off; 1126 newinfo->size -= off;
1109 ret = xt_compat_add_offset(AF_INET6, entry_offset, off); 1127 ret = xt_compat_add_offset(AF_INET6, entry_offset, off);
@@ -1139,7 +1157,8 @@ static int compat_table_info(const struct xt_table_info *info,
1139} 1157}
1140#endif 1158#endif
1141 1159
1142static int get_info(struct net *net, void __user *user, int *len, int compat) 1160static int get_info(struct net *net, void __user *user,
1161 const int *len, int compat)
1143{ 1162{
1144 char name[IP6T_TABLE_MAXNAMELEN]; 1163 char name[IP6T_TABLE_MAXNAMELEN];
1145 struct xt_table *t; 1164 struct xt_table *t;
@@ -1199,7 +1218,8 @@ static int get_info(struct net *net, void __user *user, int *len, int compat)
1199} 1218}
1200 1219
1201static int 1220static int
1202get_entries(struct net *net, struct ip6t_get_entries __user *uptr, int *len) 1221get_entries(struct net *net, struct ip6t_get_entries __user *uptr,
1222 const int *len)
1203{ 1223{
1204 int ret; 1224 int ret;
1205 struct ip6t_get_entries get; 1225 struct ip6t_get_entries get;
@@ -1291,7 +1311,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1291 /* Decrease module usage counts and free resource */ 1311 /* Decrease module usage counts and free resource */
1292 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()]; 1312 loc_cpu_old_entry = oldinfo->entries[raw_smp_processor_id()];
1293 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry, 1313 IP6T_ENTRY_ITERATE(loc_cpu_old_entry, oldinfo->size, cleanup_entry,
1294 NULL); 1314 net, NULL);
1295 xt_free_table_info(oldinfo); 1315 xt_free_table_info(oldinfo);
1296 if (copy_to_user(counters_ptr, counters, 1316 if (copy_to_user(counters_ptr, counters,
1297 sizeof(struct xt_counters) * num_counters) != 0) 1317 sizeof(struct xt_counters) * num_counters) != 0)
@@ -1310,7 +1330,7 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks,
1310} 1330}
1311 1331
1312static int 1332static int
1313do_replace(struct net *net, void __user *user, unsigned int len) 1333do_replace(struct net *net, const void __user *user, unsigned int len)
1314{ 1334{
1315 int ret; 1335 int ret;
1316 struct ip6t_replace tmp; 1336 struct ip6t_replace tmp;
@@ -1336,7 +1356,7 @@ do_replace(struct net *net, void __user *user, unsigned int len)
1336 goto free_newinfo; 1356 goto free_newinfo;
1337 } 1357 }
1338 1358
1339 ret = translate_table(tmp.name, tmp.valid_hooks, 1359 ret = translate_table(net, tmp.name, tmp.valid_hooks,
1340 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries, 1360 newinfo, loc_cpu_entry, tmp.size, tmp.num_entries,
1341 tmp.hook_entry, tmp.underflow); 1361 tmp.hook_entry, tmp.underflow);
1342 if (ret != 0) 1362 if (ret != 0)
@@ -1351,7 +1371,7 @@ do_replace(struct net *net, void __user *user, unsigned int len)
1351 return 0; 1371 return 0;
1352 1372
1353 free_newinfo_untrans: 1373 free_newinfo_untrans:
1354 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1374 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1355 free_newinfo: 1375 free_newinfo:
1356 xt_free_table_info(newinfo); 1376 xt_free_table_info(newinfo);
1357 return ret; 1377 return ret;
@@ -1371,7 +1391,7 @@ add_counter_to_entry(struct ip6t_entry *e,
1371} 1391}
1372 1392
1373static int 1393static int
1374do_add_counters(struct net *net, void __user *user, unsigned int len, 1394do_add_counters(struct net *net, const void __user *user, unsigned int len,
1375 int compat) 1395 int compat)
1376{ 1396{
1377 unsigned int i, curcpu; 1397 unsigned int i, curcpu;
@@ -1570,10 +1590,10 @@ static int
1570check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e, 1590check_compat_entry_size_and_hooks(struct compat_ip6t_entry *e,
1571 struct xt_table_info *newinfo, 1591 struct xt_table_info *newinfo,
1572 unsigned int *size, 1592 unsigned int *size,
1573 unsigned char *base, 1593 const unsigned char *base,
1574 unsigned char *limit, 1594 const unsigned char *limit,
1575 unsigned int *hook_entries, 1595 const unsigned int *hook_entries,
1576 unsigned int *underflows, 1596 const unsigned int *underflows,
1577 unsigned int *i, 1597 unsigned int *i,
1578 const char *name) 1598 const char *name)
1579{ 1599{
@@ -1690,14 +1710,15 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr,
1690 return ret; 1710 return ret;
1691} 1711}
1692 1712
1693static int compat_check_entry(struct ip6t_entry *e, const char *name, 1713static int compat_check_entry(struct ip6t_entry *e, struct net *net,
1694 unsigned int *i) 1714 const char *name, unsigned int *i)
1695{ 1715{
1696 unsigned int j; 1716 unsigned int j;
1697 int ret; 1717 int ret;
1698 struct xt_mtchk_param mtpar; 1718 struct xt_mtchk_param mtpar;
1699 1719
1700 j = 0; 1720 j = 0;
1721 mtpar.net = net;
1701 mtpar.table = name; 1722 mtpar.table = name;
1702 mtpar.entryinfo = &e->ipv6; 1723 mtpar.entryinfo = &e->ipv6;
1703 mtpar.hook_mask = e->comefrom; 1724 mtpar.hook_mask = e->comefrom;
@@ -1706,7 +1727,7 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name,
1706 if (ret) 1727 if (ret)
1707 goto cleanup_matches; 1728 goto cleanup_matches;
1708 1729
1709 ret = check_target(e, name); 1730 ret = check_target(e, net, name);
1710 if (ret) 1731 if (ret)
1711 goto cleanup_matches; 1732 goto cleanup_matches;
1712 1733
@@ -1714,12 +1735,13 @@ static int compat_check_entry(struct ip6t_entry *e, const char *name,
1714 return 0; 1735 return 0;
1715 1736
1716 cleanup_matches: 1737 cleanup_matches:
1717 IP6T_MATCH_ITERATE(e, cleanup_match, &j); 1738 IP6T_MATCH_ITERATE(e, cleanup_match, net, &j);
1718 return ret; 1739 return ret;
1719} 1740}
1720 1741
1721static int 1742static int
1722translate_compat_table(const char *name, 1743translate_compat_table(struct net *net,
1744 const char *name,
1723 unsigned int valid_hooks, 1745 unsigned int valid_hooks,
1724 struct xt_table_info **pinfo, 1746 struct xt_table_info **pinfo,
1725 void **pentry0, 1747 void **pentry0,
@@ -1808,12 +1830,12 @@ translate_compat_table(const char *name,
1808 1830
1809 i = 0; 1831 i = 0;
1810 ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry, 1832 ret = IP6T_ENTRY_ITERATE(entry1, newinfo->size, compat_check_entry,
1811 name, &i); 1833 net, name, &i);
1812 if (ret) { 1834 if (ret) {
1813 j -= i; 1835 j -= i;
1814 COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i, 1836 COMPAT_IP6T_ENTRY_ITERATE_CONTINUE(entry0, newinfo->size, i,
1815 compat_release_entry, &j); 1837 compat_release_entry, &j);
1816 IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, &i); 1838 IP6T_ENTRY_ITERATE(entry1, newinfo->size, cleanup_entry, net, &i);
1817 xt_free_table_info(newinfo); 1839 xt_free_table_info(newinfo);
1818 return ret; 1840 return ret;
1819 } 1841 }
@@ -1868,7 +1890,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1868 goto free_newinfo; 1890 goto free_newinfo;
1869 } 1891 }
1870 1892
1871 ret = translate_compat_table(tmp.name, tmp.valid_hooks, 1893 ret = translate_compat_table(net, tmp.name, tmp.valid_hooks,
1872 &newinfo, &loc_cpu_entry, tmp.size, 1894 &newinfo, &loc_cpu_entry, tmp.size,
1873 tmp.num_entries, tmp.hook_entry, 1895 tmp.num_entries, tmp.hook_entry,
1874 tmp.underflow); 1896 tmp.underflow);
@@ -1884,7 +1906,7 @@ compat_do_replace(struct net *net, void __user *user, unsigned int len)
1884 return 0; 1906 return 0;
1885 1907
1886 free_newinfo_untrans: 1908 free_newinfo_untrans:
1887 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, NULL); 1909 IP6T_ENTRY_ITERATE(loc_cpu_entry, newinfo->size, cleanup_entry, net, NULL);
1888 free_newinfo: 1910 free_newinfo:
1889 xt_free_table_info(newinfo); 1911 xt_free_table_info(newinfo);
1890 return ret; 1912 return ret;
@@ -2121,7 +2143,7 @@ struct xt_table *ip6t_register_table(struct net *net,
2121 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()]; 2143 loc_cpu_entry = newinfo->entries[raw_smp_processor_id()];
2122 memcpy(loc_cpu_entry, repl->entries, repl->size); 2144 memcpy(loc_cpu_entry, repl->entries, repl->size);
2123 2145
2124 ret = translate_table(table->name, table->valid_hooks, 2146 ret = translate_table(net, table->name, table->valid_hooks,
2125 newinfo, loc_cpu_entry, repl->size, 2147 newinfo, loc_cpu_entry, repl->size,
2126 repl->num_entries, 2148 repl->num_entries,
2127 repl->hook_entry, 2149 repl->hook_entry,
@@ -2142,7 +2164,7 @@ out:
2142 return ERR_PTR(ret); 2164 return ERR_PTR(ret);
2143} 2165}
2144 2166
2145void ip6t_unregister_table(struct xt_table *table) 2167void ip6t_unregister_table(struct net *net, struct xt_table *table)
2146{ 2168{
2147 struct xt_table_info *private; 2169 struct xt_table_info *private;
2148 void *loc_cpu_entry; 2170 void *loc_cpu_entry;
@@ -2152,7 +2174,7 @@ void ip6t_unregister_table(struct xt_table *table)
2152 2174
2153 /* Decrease module usage counts and free resources */ 2175 /* Decrease module usage counts and free resources */
2154 loc_cpu_entry = private->entries[raw_smp_processor_id()]; 2176 loc_cpu_entry = private->entries[raw_smp_processor_id()];
2155 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, NULL); 2177 IP6T_ENTRY_ITERATE(loc_cpu_entry, private->size, cleanup_entry, net, NULL);
2156 if (private->number > private->initial_entries) 2178 if (private->number > private->initial_entries)
2157 module_put(table_owner); 2179 module_put(table_owner);
2158 xt_free_table_info(private); 2180 xt_free_table_info(private);
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
index ad378efd0eb8..36b72cafc227 100644
--- a/net/ipv6/netfilter/ip6table_filter.c
+++ b/net/ipv6/netfilter/ip6table_filter.c
@@ -21,99 +21,26 @@ MODULE_DESCRIPTION("ip6tables filter table");
21 (1 << NF_INET_FORWARD) | \ 21 (1 << NF_INET_FORWARD) | \
22 (1 << NF_INET_LOCAL_OUT)) 22 (1 << NF_INET_LOCAL_OUT))
23 23
24static struct
25{
26 struct ip6t_replace repl;
27 struct ip6t_standard entries[3];
28 struct ip6t_error term;
29} initial_table __net_initdata = {
30 .repl = {
31 .name = "filter",
32 .valid_hooks = FILTER_VALID_HOOKS,
33 .num_entries = 4,
34 .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
35 .hook_entry = {
36 [NF_INET_LOCAL_IN] = 0,
37 [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
38 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
39 },
40 .underflow = {
41 [NF_INET_LOCAL_IN] = 0,
42 [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
43 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2
44 },
45 },
46 .entries = {
47 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
48 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
49 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
50 },
51 .term = IP6T_ERROR_INIT, /* ERROR */
52};
53
54static const struct xt_table packet_filter = { 24static const struct xt_table packet_filter = {
55 .name = "filter", 25 .name = "filter",
56 .valid_hooks = FILTER_VALID_HOOKS, 26 .valid_hooks = FILTER_VALID_HOOKS,
57 .me = THIS_MODULE, 27 .me = THIS_MODULE,
58 .af = NFPROTO_IPV6, 28 .af = NFPROTO_IPV6,
29 .priority = NF_IP6_PRI_FILTER,
59}; 30};
60 31
61/* The work comes in here from netfilter.c. */ 32/* The work comes in here from netfilter.c. */
62static unsigned int 33static unsigned int
63ip6t_in_hook(unsigned int hook, 34ip6table_filter_hook(unsigned int hook, struct sk_buff *skb,
64 struct sk_buff *skb, 35 const struct net_device *in, const struct net_device *out,
65 const struct net_device *in, 36 int (*okfn)(struct sk_buff *))
66 const struct net_device *out,
67 int (*okfn)(struct sk_buff *))
68{
69 return ip6t_do_table(skb, hook, in, out,
70 dev_net(in)->ipv6.ip6table_filter);
71}
72
73static unsigned int
74ip6t_local_out_hook(unsigned int hook,
75 struct sk_buff *skb,
76 const struct net_device *in,
77 const struct net_device *out,
78 int (*okfn)(struct sk_buff *))
79{ 37{
80#if 0 38 const struct net *net = dev_net((in != NULL) ? in : out);
81 /* root is playing with raw sockets. */
82 if (skb->len < sizeof(struct iphdr) ||
83 ip_hdrlen(skb) < sizeof(struct iphdr)) {
84 if (net_ratelimit())
85 printk("ip6t_hook: happy cracking.\n");
86 return NF_ACCEPT;
87 }
88#endif
89 39
90 return ip6t_do_table(skb, hook, in, out, 40 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_filter);
91 dev_net(out)->ipv6.ip6table_filter);
92} 41}
93 42
94static struct nf_hook_ops ip6t_ops[] __read_mostly = { 43static struct nf_hook_ops *filter_ops __read_mostly;
95 {
96 .hook = ip6t_in_hook,
97 .owner = THIS_MODULE,
98 .pf = NFPROTO_IPV6,
99 .hooknum = NF_INET_LOCAL_IN,
100 .priority = NF_IP6_PRI_FILTER,
101 },
102 {
103 .hook = ip6t_in_hook,
104 .owner = THIS_MODULE,
105 .pf = NFPROTO_IPV6,
106 .hooknum = NF_INET_FORWARD,
107 .priority = NF_IP6_PRI_FILTER,
108 },
109 {
110 .hook = ip6t_local_out_hook,
111 .owner = THIS_MODULE,
112 .pf = NFPROTO_IPV6,
113 .hooknum = NF_INET_LOCAL_OUT,
114 .priority = NF_IP6_PRI_FILTER,
115 },
116};
117 44
118/* Default to forward because I got too much mail already. */ 45/* Default to forward because I got too much mail already. */
119static int forward = NF_ACCEPT; 46static int forward = NF_ACCEPT;
@@ -121,9 +48,18 @@ module_param(forward, bool, 0000);
121 48
122static int __net_init ip6table_filter_net_init(struct net *net) 49static int __net_init ip6table_filter_net_init(struct net *net)
123{ 50{
124 /* Register table */ 51 struct ip6t_replace *repl;
52
53 repl = ip6t_alloc_initial_table(&packet_filter);
54 if (repl == NULL)
55 return -ENOMEM;
56 /* Entry 1 is the FORWARD hook */
57 ((struct ip6t_standard *)repl->entries)[1].target.verdict =
58 -forward - 1;
59
125 net->ipv6.ip6table_filter = 60 net->ipv6.ip6table_filter =
126 ip6t_register_table(net, &packet_filter, &initial_table.repl); 61 ip6t_register_table(net, &packet_filter, repl);
62 kfree(repl);
127 if (IS_ERR(net->ipv6.ip6table_filter)) 63 if (IS_ERR(net->ipv6.ip6table_filter))
128 return PTR_ERR(net->ipv6.ip6table_filter); 64 return PTR_ERR(net->ipv6.ip6table_filter);
129 return 0; 65 return 0;
@@ -131,7 +67,7 @@ static int __net_init ip6table_filter_net_init(struct net *net)
131 67
132static void __net_exit ip6table_filter_net_exit(struct net *net) 68static void __net_exit ip6table_filter_net_exit(struct net *net)
133{ 69{
134 ip6t_unregister_table(net->ipv6.ip6table_filter); 70 ip6t_unregister_table(net, net->ipv6.ip6table_filter);
135} 71}
136 72
137static struct pernet_operations ip6table_filter_net_ops = { 73static struct pernet_operations ip6table_filter_net_ops = {
@@ -148,17 +84,16 @@ static int __init ip6table_filter_init(void)
148 return -EINVAL; 84 return -EINVAL;
149 } 85 }
150 86
151 /* Entry 1 is the FORWARD hook */
152 initial_table.entries[1].target.verdict = -forward - 1;
153
154 ret = register_pernet_subsys(&ip6table_filter_net_ops); 87 ret = register_pernet_subsys(&ip6table_filter_net_ops);
155 if (ret < 0) 88 if (ret < 0)
156 return ret; 89 return ret;
157 90
158 /* Register hooks */ 91 /* Register hooks */
159 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 92 filter_ops = xt_hook_link(&packet_filter, ip6table_filter_hook);
160 if (ret < 0) 93 if (IS_ERR(filter_ops)) {
94 ret = PTR_ERR(filter_ops);
161 goto cleanup_table; 95 goto cleanup_table;
96 }
162 97
163 return ret; 98 return ret;
164 99
@@ -169,7 +104,7 @@ static int __init ip6table_filter_init(void)
169 104
170static void __exit ip6table_filter_fini(void) 105static void __exit ip6table_filter_fini(void)
171{ 106{
172 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 107 xt_hook_unlink(&packet_filter, filter_ops);
173 unregister_pernet_subsys(&ip6table_filter_net_ops); 108 unregister_pernet_subsys(&ip6table_filter_net_ops);
174} 109}
175 110
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
index a929c19d30e3..7844e557c0ec 100644
--- a/net/ipv6/netfilter/ip6table_mangle.c
+++ b/net/ipv6/netfilter/ip6table_mangle.c
@@ -21,80 +21,17 @@ MODULE_DESCRIPTION("ip6tables mangle table");
21 (1 << NF_INET_LOCAL_OUT) | \ 21 (1 << NF_INET_LOCAL_OUT) | \
22 (1 << NF_INET_POST_ROUTING)) 22 (1 << NF_INET_POST_ROUTING))
23 23
24static const struct
25{
26 struct ip6t_replace repl;
27 struct ip6t_standard entries[5];
28 struct ip6t_error term;
29} initial_table __net_initdata = {
30 .repl = {
31 .name = "mangle",
32 .valid_hooks = MANGLE_VALID_HOOKS,
33 .num_entries = 6,
34 .size = sizeof(struct ip6t_standard) * 5 + sizeof(struct ip6t_error),
35 .hook_entry = {
36 [NF_INET_PRE_ROUTING] = 0,
37 [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
38 [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
39 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
40 [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
41 },
42 .underflow = {
43 [NF_INET_PRE_ROUTING] = 0,
44 [NF_INET_LOCAL_IN] = sizeof(struct ip6t_standard),
45 [NF_INET_FORWARD] = sizeof(struct ip6t_standard) * 2,
46 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 3,
47 [NF_INET_POST_ROUTING] = sizeof(struct ip6t_standard) * 4,
48 },
49 },
50 .entries = {
51 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
52 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
53 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
54 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
55 IP6T_STANDARD_INIT(NF_ACCEPT), /* POST_ROUTING */
56 },
57 .term = IP6T_ERROR_INIT, /* ERROR */
58};
59
60static const struct xt_table packet_mangler = { 24static const struct xt_table packet_mangler = {
61 .name = "mangle", 25 .name = "mangle",
62 .valid_hooks = MANGLE_VALID_HOOKS, 26 .valid_hooks = MANGLE_VALID_HOOKS,
63 .me = THIS_MODULE, 27 .me = THIS_MODULE,
64 .af = NFPROTO_IPV6, 28 .af = NFPROTO_IPV6,
29 .priority = NF_IP6_PRI_MANGLE,
65}; 30};
66 31
67/* The work comes in here from netfilter.c. */
68static unsigned int
69ip6t_in_hook(unsigned int hook,
70 struct sk_buff *skb,
71 const struct net_device *in,
72 const struct net_device *out,
73 int (*okfn)(struct sk_buff *))
74{
75 return ip6t_do_table(skb, hook, in, out,
76 dev_net(in)->ipv6.ip6table_mangle);
77}
78
79static unsigned int
80ip6t_post_routing_hook(unsigned int hook,
81 struct sk_buff *skb,
82 const struct net_device *in,
83 const struct net_device *out,
84 int (*okfn)(struct sk_buff *))
85{
86 return ip6t_do_table(skb, hook, in, out,
87 dev_net(out)->ipv6.ip6table_mangle);
88}
89
90static unsigned int 32static unsigned int
91ip6t_local_out_hook(unsigned int hook, 33ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out)
92 struct sk_buff *skb,
93 const struct net_device *in,
94 const struct net_device *out,
95 int (*okfn)(struct sk_buff *))
96{ 34{
97
98 unsigned int ret; 35 unsigned int ret;
99 struct in6_addr saddr, daddr; 36 struct in6_addr saddr, daddr;
100 u_int8_t hop_limit; 37 u_int8_t hop_limit;
@@ -119,7 +56,7 @@ ip6t_local_out_hook(unsigned int hook,
119 /* flowlabel and prio (includes version, which shouldn't change either */ 56 /* flowlabel and prio (includes version, which shouldn't change either */
120 flowlabel = *((u_int32_t *)ipv6_hdr(skb)); 57 flowlabel = *((u_int32_t *)ipv6_hdr(skb));
121 58
122 ret = ip6t_do_table(skb, hook, in, out, 59 ret = ip6t_do_table(skb, NF_INET_LOCAL_OUT, NULL, out,
123 dev_net(out)->ipv6.ip6table_mangle); 60 dev_net(out)->ipv6.ip6table_mangle);
124 61
125 if (ret != NF_DROP && ret != NF_STOLEN && 62 if (ret != NF_DROP && ret != NF_STOLEN &&
@@ -132,49 +69,33 @@ ip6t_local_out_hook(unsigned int hook,
132 return ret; 69 return ret;
133} 70}
134 71
135static struct nf_hook_ops ip6t_ops[] __read_mostly = { 72/* The work comes in here from netfilter.c. */
136 { 73static unsigned int
137 .hook = ip6t_in_hook, 74ip6table_mangle_hook(unsigned int hook, struct sk_buff *skb,
138 .owner = THIS_MODULE, 75 const struct net_device *in, const struct net_device *out,
139 .pf = NFPROTO_IPV6, 76 int (*okfn)(struct sk_buff *))
140 .hooknum = NF_INET_PRE_ROUTING, 77{
141 .priority = NF_IP6_PRI_MANGLE, 78 if (hook == NF_INET_LOCAL_OUT)
142 }, 79 return ip6t_mangle_out(skb, out);
143 { 80 if (hook == NF_INET_POST_ROUTING)
144 .hook = ip6t_in_hook, 81 return ip6t_do_table(skb, hook, in, out,
145 .owner = THIS_MODULE, 82 dev_net(out)->ipv6.ip6table_mangle);
146 .pf = NFPROTO_IPV6, 83 /* INPUT/FORWARD */
147 .hooknum = NF_INET_LOCAL_IN, 84 return ip6t_do_table(skb, hook, in, out,
148 .priority = NF_IP6_PRI_MANGLE, 85 dev_net(in)->ipv6.ip6table_mangle);
149 }, 86}
150 {
151 .hook = ip6t_in_hook,
152 .owner = THIS_MODULE,
153 .pf = NFPROTO_IPV6,
154 .hooknum = NF_INET_FORWARD,
155 .priority = NF_IP6_PRI_MANGLE,
156 },
157 {
158 .hook = ip6t_local_out_hook,
159 .owner = THIS_MODULE,
160 .pf = NFPROTO_IPV6,
161 .hooknum = NF_INET_LOCAL_OUT,
162 .priority = NF_IP6_PRI_MANGLE,
163 },
164 {
165 .hook = ip6t_post_routing_hook,
166 .owner = THIS_MODULE,
167 .pf = NFPROTO_IPV6,
168 .hooknum = NF_INET_POST_ROUTING,
169 .priority = NF_IP6_PRI_MANGLE,
170 },
171};
172 87
88static struct nf_hook_ops *mangle_ops __read_mostly;
173static int __net_init ip6table_mangle_net_init(struct net *net) 89static int __net_init ip6table_mangle_net_init(struct net *net)
174{ 90{
175 /* Register table */ 91 struct ip6t_replace *repl;
92
93 repl = ip6t_alloc_initial_table(&packet_mangler);
94 if (repl == NULL)
95 return -ENOMEM;
176 net->ipv6.ip6table_mangle = 96 net->ipv6.ip6table_mangle =
177 ip6t_register_table(net, &packet_mangler, &initial_table.repl); 97 ip6t_register_table(net, &packet_mangler, repl);
98 kfree(repl);
178 if (IS_ERR(net->ipv6.ip6table_mangle)) 99 if (IS_ERR(net->ipv6.ip6table_mangle))
179 return PTR_ERR(net->ipv6.ip6table_mangle); 100 return PTR_ERR(net->ipv6.ip6table_mangle);
180 return 0; 101 return 0;
@@ -182,7 +103,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
182 103
183static void __net_exit ip6table_mangle_net_exit(struct net *net) 104static void __net_exit ip6table_mangle_net_exit(struct net *net)
184{ 105{
185 ip6t_unregister_table(net->ipv6.ip6table_mangle); 106 ip6t_unregister_table(net, net->ipv6.ip6table_mangle);
186} 107}
187 108
188static struct pernet_operations ip6table_mangle_net_ops = { 109static struct pernet_operations ip6table_mangle_net_ops = {
@@ -199,9 +120,11 @@ static int __init ip6table_mangle_init(void)
199 return ret; 120 return ret;
200 121
201 /* Register hooks */ 122 /* Register hooks */
202 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 123 mangle_ops = xt_hook_link(&packet_mangler, ip6table_mangle_hook);
203 if (ret < 0) 124 if (IS_ERR(mangle_ops)) {
125 ret = PTR_ERR(mangle_ops);
204 goto cleanup_table; 126 goto cleanup_table;
127 }
205 128
206 return ret; 129 return ret;
207 130
@@ -212,7 +135,7 @@ static int __init ip6table_mangle_init(void)
212 135
213static void __exit ip6table_mangle_fini(void) 136static void __exit ip6table_mangle_fini(void)
214{ 137{
215 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 138 xt_hook_unlink(&packet_mangler, mangle_ops);
216 unregister_pernet_subsys(&ip6table_mangle_net_ops); 139 unregister_pernet_subsys(&ip6table_mangle_net_ops);
217} 140}
218 141
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
index ed1a1180f3b3..aef31a29de9e 100644
--- a/net/ipv6/netfilter/ip6table_raw.c
+++ b/net/ipv6/netfilter/ip6table_raw.c
@@ -8,85 +8,37 @@
8 8
9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT)) 9#define RAW_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT))
10 10
11static const struct
12{
13 struct ip6t_replace repl;
14 struct ip6t_standard entries[2];
15 struct ip6t_error term;
16} initial_table __net_initdata = {
17 .repl = {
18 .name = "raw",
19 .valid_hooks = RAW_VALID_HOOKS,
20 .num_entries = 3,
21 .size = sizeof(struct ip6t_standard) * 2 + sizeof(struct ip6t_error),
22 .hook_entry = {
23 [NF_INET_PRE_ROUTING] = 0,
24 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
25 },
26 .underflow = {
27 [NF_INET_PRE_ROUTING] = 0,
28 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard)
29 },
30 },
31 .entries = {
32 IP6T_STANDARD_INIT(NF_ACCEPT), /* PRE_ROUTING */
33 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
34 },
35 .term = IP6T_ERROR_INIT, /* ERROR */
36};
37
38static const struct xt_table packet_raw = { 11static const struct xt_table packet_raw = {
39 .name = "raw", 12 .name = "raw",
40 .valid_hooks = RAW_VALID_HOOKS, 13 .valid_hooks = RAW_VALID_HOOKS,
41 .me = THIS_MODULE, 14 .me = THIS_MODULE,
42 .af = NFPROTO_IPV6, 15 .af = NFPROTO_IPV6,
16 .priority = NF_IP6_PRI_FIRST,
43}; 17};
44 18
45/* The work comes in here from netfilter.c. */ 19/* The work comes in here from netfilter.c. */
46static unsigned int 20static unsigned int
47ip6t_pre_routing_hook(unsigned int hook, 21ip6table_raw_hook(unsigned int hook, struct sk_buff *skb,
48 struct sk_buff *skb, 22 const struct net_device *in, const struct net_device *out,
49 const struct net_device *in, 23 int (*okfn)(struct sk_buff *))
50 const struct net_device *out,
51 int (*okfn)(struct sk_buff *))
52{ 24{
53 return ip6t_do_table(skb, hook, in, out, 25 const struct net *net = dev_net((in != NULL) ? in : out);
54 dev_net(in)->ipv6.ip6table_raw);
55}
56 26
57static unsigned int 27 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_raw);
58ip6t_local_out_hook(unsigned int hook,
59 struct sk_buff *skb,
60 const struct net_device *in,
61 const struct net_device *out,
62 int (*okfn)(struct sk_buff *))
63{
64 return ip6t_do_table(skb, hook, in, out,
65 dev_net(out)->ipv6.ip6table_raw);
66} 28}
67 29
68static struct nf_hook_ops ip6t_ops[] __read_mostly = { 30static struct nf_hook_ops *rawtable_ops __read_mostly;
69 {
70 .hook = ip6t_pre_routing_hook,
71 .pf = NFPROTO_IPV6,
72 .hooknum = NF_INET_PRE_ROUTING,
73 .priority = NF_IP6_PRI_FIRST,
74 .owner = THIS_MODULE,
75 },
76 {
77 .hook = ip6t_local_out_hook,
78 .pf = NFPROTO_IPV6,
79 .hooknum = NF_INET_LOCAL_OUT,
80 .priority = NF_IP6_PRI_FIRST,
81 .owner = THIS_MODULE,
82 },
83};
84 31
85static int __net_init ip6table_raw_net_init(struct net *net) 32static int __net_init ip6table_raw_net_init(struct net *net)
86{ 33{
87 /* Register table */ 34 struct ip6t_replace *repl;
35
36 repl = ip6t_alloc_initial_table(&packet_raw);
37 if (repl == NULL)
38 return -ENOMEM;
88 net->ipv6.ip6table_raw = 39 net->ipv6.ip6table_raw =
89 ip6t_register_table(net, &packet_raw, &initial_table.repl); 40 ip6t_register_table(net, &packet_raw, repl);
41 kfree(repl);
90 if (IS_ERR(net->ipv6.ip6table_raw)) 42 if (IS_ERR(net->ipv6.ip6table_raw))
91 return PTR_ERR(net->ipv6.ip6table_raw); 43 return PTR_ERR(net->ipv6.ip6table_raw);
92 return 0; 44 return 0;
@@ -94,7 +46,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
94 46
95static void __net_exit ip6table_raw_net_exit(struct net *net) 47static void __net_exit ip6table_raw_net_exit(struct net *net)
96{ 48{
97 ip6t_unregister_table(net->ipv6.ip6table_raw); 49 ip6t_unregister_table(net, net->ipv6.ip6table_raw);
98} 50}
99 51
100static struct pernet_operations ip6table_raw_net_ops = { 52static struct pernet_operations ip6table_raw_net_ops = {
@@ -111,9 +63,11 @@ static int __init ip6table_raw_init(void)
111 return ret; 63 return ret;
112 64
113 /* Register hooks */ 65 /* Register hooks */
114 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 66 rawtable_ops = xt_hook_link(&packet_raw, ip6table_raw_hook);
115 if (ret < 0) 67 if (IS_ERR(rawtable_ops)) {
68 ret = PTR_ERR(rawtable_ops);
116 goto cleanup_table; 69 goto cleanup_table;
70 }
117 71
118 return ret; 72 return ret;
119 73
@@ -124,7 +78,7 @@ static int __init ip6table_raw_init(void)
124 78
125static void __exit ip6table_raw_fini(void) 79static void __exit ip6table_raw_fini(void)
126{ 80{
127 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 81 xt_hook_unlink(&packet_raw, rawtable_ops);
128 unregister_pernet_subsys(&ip6table_raw_net_ops); 82 unregister_pernet_subsys(&ip6table_raw_net_ops);
129} 83}
130 84
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
index 41b444c60934..0824d865aa9b 100644
--- a/net/ipv6/netfilter/ip6table_security.c
+++ b/net/ipv6/netfilter/ip6table_security.c
@@ -26,106 +26,37 @@ MODULE_DESCRIPTION("ip6tables security table, for MAC rules");
26 (1 << NF_INET_FORWARD) | \ 26 (1 << NF_INET_FORWARD) | \
27 (1 << NF_INET_LOCAL_OUT) 27 (1 << NF_INET_LOCAL_OUT)
28 28
29static const struct
30{
31 struct ip6t_replace repl;
32 struct ip6t_standard entries[3];
33 struct ip6t_error term;
34} initial_table __net_initdata = {
35 .repl = {
36 .name = "security",
37 .valid_hooks = SECURITY_VALID_HOOKS,
38 .num_entries = 4,
39 .size = sizeof(struct ip6t_standard) * 3 + sizeof(struct ip6t_error),
40 .hook_entry = {
41 [NF_INET_LOCAL_IN] = 0,
42 [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
43 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2,
44 },
45 .underflow = {
46 [NF_INET_LOCAL_IN] = 0,
47 [NF_INET_FORWARD] = sizeof(struct ip6t_standard),
48 [NF_INET_LOCAL_OUT] = sizeof(struct ip6t_standard) * 2,
49 },
50 },
51 .entries = {
52 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_IN */
53 IP6T_STANDARD_INIT(NF_ACCEPT), /* FORWARD */
54 IP6T_STANDARD_INIT(NF_ACCEPT), /* LOCAL_OUT */
55 },
56 .term = IP6T_ERROR_INIT, /* ERROR */
57};
58
59static const struct xt_table security_table = { 29static const struct xt_table security_table = {
60 .name = "security", 30 .name = "security",
61 .valid_hooks = SECURITY_VALID_HOOKS, 31 .valid_hooks = SECURITY_VALID_HOOKS,
62 .me = THIS_MODULE, 32 .me = THIS_MODULE,
63 .af = NFPROTO_IPV6, 33 .af = NFPROTO_IPV6,
34 .priority = NF_IP6_PRI_SECURITY,
64}; 35};
65 36
66static unsigned int 37static unsigned int
67ip6t_local_in_hook(unsigned int hook, 38ip6table_security_hook(unsigned int hook, struct sk_buff *skb,
68 struct sk_buff *skb, 39 const struct net_device *in,
69 const struct net_device *in, 40 const struct net_device *out,
70 const struct net_device *out, 41 int (*okfn)(struct sk_buff *))
71 int (*okfn)(struct sk_buff *))
72{
73 return ip6t_do_table(skb, hook, in, out,
74 dev_net(in)->ipv6.ip6table_security);
75}
76
77static unsigned int
78ip6t_forward_hook(unsigned int hook,
79 struct sk_buff *skb,
80 const struct net_device *in,
81 const struct net_device *out,
82 int (*okfn)(struct sk_buff *))
83{ 42{
84 return ip6t_do_table(skb, hook, in, out, 43 const struct net *net = dev_net((in != NULL) ? in : out);
85 dev_net(in)->ipv6.ip6table_security);
86}
87 44
88static unsigned int 45 return ip6t_do_table(skb, hook, in, out, net->ipv6.ip6table_security);
89ip6t_local_out_hook(unsigned int hook,
90 struct sk_buff *skb,
91 const struct net_device *in,
92 const struct net_device *out,
93 int (*okfn)(struct sk_buff *))
94{
95 /* TBD: handle short packets via raw socket */
96 return ip6t_do_table(skb, hook, in, out,
97 dev_net(out)->ipv6.ip6table_security);
98} 46}
99 47
100static struct nf_hook_ops ip6t_ops[] __read_mostly = { 48static struct nf_hook_ops *sectbl_ops __read_mostly;
101 {
102 .hook = ip6t_local_in_hook,
103 .owner = THIS_MODULE,
104 .pf = NFPROTO_IPV6,
105 .hooknum = NF_INET_LOCAL_IN,
106 .priority = NF_IP6_PRI_SECURITY,
107 },
108 {
109 .hook = ip6t_forward_hook,
110 .owner = THIS_MODULE,
111 .pf = NFPROTO_IPV6,
112 .hooknum = NF_INET_FORWARD,
113 .priority = NF_IP6_PRI_SECURITY,
114 },
115 {
116 .hook = ip6t_local_out_hook,
117 .owner = THIS_MODULE,
118 .pf = NFPROTO_IPV6,
119 .hooknum = NF_INET_LOCAL_OUT,
120 .priority = NF_IP6_PRI_SECURITY,
121 },
122};
123 49
124static int __net_init ip6table_security_net_init(struct net *net) 50static int __net_init ip6table_security_net_init(struct net *net)
125{ 51{
126 net->ipv6.ip6table_security = 52 struct ip6t_replace *repl;
127 ip6t_register_table(net, &security_table, &initial_table.repl);
128 53
54 repl = ip6t_alloc_initial_table(&security_table);
55 if (repl == NULL)
56 return -ENOMEM;
57 net->ipv6.ip6table_security =
58 ip6t_register_table(net, &security_table, repl);
59 kfree(repl);
129 if (IS_ERR(net->ipv6.ip6table_security)) 60 if (IS_ERR(net->ipv6.ip6table_security))
130 return PTR_ERR(net->ipv6.ip6table_security); 61 return PTR_ERR(net->ipv6.ip6table_security);
131 62
@@ -134,7 +65,7 @@ static int __net_init ip6table_security_net_init(struct net *net)
134 65
135static void __net_exit ip6table_security_net_exit(struct net *net) 66static void __net_exit ip6table_security_net_exit(struct net *net)
136{ 67{
137 ip6t_unregister_table(net->ipv6.ip6table_security); 68 ip6t_unregister_table(net, net->ipv6.ip6table_security);
138} 69}
139 70
140static struct pernet_operations ip6table_security_net_ops = { 71static struct pernet_operations ip6table_security_net_ops = {
@@ -150,9 +81,11 @@ static int __init ip6table_security_init(void)
150 if (ret < 0) 81 if (ret < 0)
151 return ret; 82 return ret;
152 83
153 ret = nf_register_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 84 sectbl_ops = xt_hook_link(&security_table, ip6table_security_hook);
154 if (ret < 0) 85 if (IS_ERR(sectbl_ops)) {
86 ret = PTR_ERR(sectbl_ops);
155 goto cleanup_table; 87 goto cleanup_table;
88 }
156 89
157 return ret; 90 return ret;
158 91
@@ -163,7 +96,7 @@ cleanup_table:
163 96
164static void __exit ip6table_security_fini(void) 97static void __exit ip6table_security_fini(void)
165{ 98{
166 nf_unregister_hooks(ip6t_ops, ARRAY_SIZE(ip6t_ops)); 99 xt_hook_unlink(&security_table, sectbl_ops);
167 unregister_pernet_subsys(&ip6table_security_net_ops); 100 unregister_pernet_subsys(&ip6table_security_net_ops);
168} 101}
169 102
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
index 0956ebabbff2..996c3f41fecd 100644
--- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c
@@ -27,6 +27,7 @@
27#include <net/netfilter/nf_conntrack_l4proto.h> 27#include <net/netfilter/nf_conntrack_l4proto.h>
28#include <net/netfilter/nf_conntrack_l3proto.h> 28#include <net/netfilter/nf_conntrack_l3proto.h>
29#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_core.h>
30#include <net/netfilter/nf_conntrack_zones.h>
30#include <net/netfilter/ipv6/nf_conntrack_ipv6.h> 31#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
31#include <net/netfilter/nf_log.h> 32#include <net/netfilter/nf_log.h>
32 33
@@ -191,15 +192,20 @@ out:
191static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum, 192static enum ip6_defrag_users nf_ct6_defrag_user(unsigned int hooknum,
192 struct sk_buff *skb) 193 struct sk_buff *skb)
193{ 194{
195 u16 zone = NF_CT_DEFAULT_ZONE;
196
197 if (skb->nfct)
198 zone = nf_ct_zone((struct nf_conn *)skb->nfct);
199
194#ifdef CONFIG_BRIDGE_NETFILTER 200#ifdef CONFIG_BRIDGE_NETFILTER
195 if (skb->nf_bridge && 201 if (skb->nf_bridge &&
196 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING) 202 skb->nf_bridge->mask & BRNF_NF_BRIDGE_PREROUTING)
197 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN; 203 return IP6_DEFRAG_CONNTRACK_BRIDGE_IN + zone;
198#endif 204#endif
199 if (hooknum == NF_INET_PRE_ROUTING) 205 if (hooknum == NF_INET_PRE_ROUTING)
200 return IP6_DEFRAG_CONNTRACK_IN; 206 return IP6_DEFRAG_CONNTRACK_IN + zone;
201 else 207 else
202 return IP6_DEFRAG_CONNTRACK_OUT; 208 return IP6_DEFRAG_CONNTRACK_OUT + zone;
203 209
204} 210}
205 211
@@ -212,7 +218,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum,
212 struct sk_buff *reasm; 218 struct sk_buff *reasm;
213 219
214 /* Previously seen (loopback)? */ 220 /* Previously seen (loopback)? */
215 if (skb->nfct) 221 if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct))
216 return NF_ACCEPT; 222 return NF_ACCEPT;
217 223
218 reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb)); 224 reasm = nf_ct_frag6_gather(skb, nf_ct6_defrag_user(hooknum, skb));
diff --git a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
index c7b8bd1d7984..9be81776415e 100644
--- a/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
+++ b/net/ipv6/netfilter/nf_conntrack_proto_icmpv6.c
@@ -23,6 +23,7 @@
23#include <net/netfilter/nf_conntrack_tuple.h> 23#include <net/netfilter/nf_conntrack_tuple.h>
24#include <net/netfilter/nf_conntrack_l4proto.h> 24#include <net/netfilter/nf_conntrack_l4proto.h>
25#include <net/netfilter/nf_conntrack_core.h> 25#include <net/netfilter/nf_conntrack_core.h>
26#include <net/netfilter/nf_conntrack_zones.h>
26#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h> 27#include <net/netfilter/ipv6/nf_conntrack_icmpv6.h>
27#include <net/netfilter/nf_log.h> 28#include <net/netfilter/nf_log.h>
28 29
@@ -128,7 +129,7 @@ static bool icmpv6_new(struct nf_conn *ct, const struct sk_buff *skb,
128} 129}
129 130
130static int 131static int
131icmpv6_error_message(struct net *net, 132icmpv6_error_message(struct net *net, struct nf_conn *tmpl,
132 struct sk_buff *skb, 133 struct sk_buff *skb,
133 unsigned int icmp6off, 134 unsigned int icmp6off,
134 enum ip_conntrack_info *ctinfo, 135 enum ip_conntrack_info *ctinfo,
@@ -137,6 +138,7 @@ icmpv6_error_message(struct net *net,
137 struct nf_conntrack_tuple intuple, origtuple; 138 struct nf_conntrack_tuple intuple, origtuple;
138 const struct nf_conntrack_tuple_hash *h; 139 const struct nf_conntrack_tuple_hash *h;
139 const struct nf_conntrack_l4proto *inproto; 140 const struct nf_conntrack_l4proto *inproto;
141 u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
140 142
141 NF_CT_ASSERT(skb->nfct == NULL); 143 NF_CT_ASSERT(skb->nfct == NULL);
142 144
@@ -163,7 +165,7 @@ icmpv6_error_message(struct net *net,
163 165
164 *ctinfo = IP_CT_RELATED; 166 *ctinfo = IP_CT_RELATED;
165 167
166 h = nf_conntrack_find_get(net, &intuple); 168 h = nf_conntrack_find_get(net, zone, &intuple);
167 if (!h) { 169 if (!h) {
168 pr_debug("icmpv6_error: no match\n"); 170 pr_debug("icmpv6_error: no match\n");
169 return -NF_ACCEPT; 171 return -NF_ACCEPT;
@@ -179,7 +181,8 @@ icmpv6_error_message(struct net *net,
179} 181}
180 182
181static int 183static int
182icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, 184icmpv6_error(struct net *net, struct nf_conn *tmpl,
185 struct sk_buff *skb, unsigned int dataoff,
183 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum) 186 enum ip_conntrack_info *ctinfo, u_int8_t pf, unsigned int hooknum)
184{ 187{
185 const struct icmp6hdr *icmp6h; 188 const struct icmp6hdr *icmp6h;
@@ -215,7 +218,7 @@ icmpv6_error(struct net *net, struct sk_buff *skb, unsigned int dataoff,
215 if (icmp6h->icmp6_type >= 128) 218 if (icmp6h->icmp6_type >= 128)
216 return NF_ACCEPT; 219 return NF_ACCEPT;
217 220
218 return icmpv6_error_message(net, skb, dataoff, ctinfo, hooknum); 221 return icmpv6_error_message(net, tmpl, skb, dataoff, ctinfo, hooknum);
219} 222}
220 223
221#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 224#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c
index 624a54832a7c..ad1fcda6898b 100644
--- a/net/ipv6/netfilter/nf_conntrack_reasm.c
+++ b/net/ipv6/netfilter/nf_conntrack_reasm.c
@@ -45,9 +45,6 @@
45#include <linux/kernel.h> 45#include <linux/kernel.h>
46#include <linux/module.h> 46#include <linux/module.h>
47 47
48#define NF_CT_FRAG6_HIGH_THRESH 262144 /* == 256*1024 */
49#define NF_CT_FRAG6_LOW_THRESH 196608 /* == 192*1024 */
50#define NF_CT_FRAG6_TIMEOUT IPV6_FRAG_TIMEOUT
51 48
52struct nf_ct_frag6_skb_cb 49struct nf_ct_frag6_skb_cb
53{ 50{
@@ -670,8 +667,8 @@ int nf_ct_frag6_init(void)
670 nf_frags.frag_expire = nf_ct_frag6_expire; 667 nf_frags.frag_expire = nf_ct_frag6_expire;
671 nf_frags.secret_interval = 10 * 60 * HZ; 668 nf_frags.secret_interval = 10 * 60 * HZ;
672 nf_init_frags.timeout = IPV6_FRAG_TIMEOUT; 669 nf_init_frags.timeout = IPV6_FRAG_TIMEOUT;
673 nf_init_frags.high_thresh = 256 * 1024; 670 nf_init_frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
674 nf_init_frags.low_thresh = 192 * 1024; 671 nf_init_frags.low_thresh = IPV6_FRAG_LOW_THRESH;
675 inet_frags_init_net(&nf_init_frags); 672 inet_frags_init_net(&nf_init_frags);
676 inet_frags_init(&nf_frags); 673 inet_frags_init(&nf_frags);
677 674
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c
index fe27eb4264d6..b2847ed6a7d9 100644
--- a/net/ipv6/reassembly.c
+++ b/net/ipv6/reassembly.c
@@ -742,8 +742,8 @@ static inline void ip6_frags_sysctl_unregister(void)
742 742
743static int __net_init ipv6_frags_init_net(struct net *net) 743static int __net_init ipv6_frags_init_net(struct net *net)
744{ 744{
745 net->ipv6.frags.high_thresh = 256 * 1024; 745 net->ipv6.frags.high_thresh = IPV6_FRAG_HIGH_THRESH;
746 net->ipv6.frags.low_thresh = 192 * 1024; 746 net->ipv6.frags.low_thresh = IPV6_FRAG_LOW_THRESH;
747 net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT; 747 net->ipv6.frags.timeout = IPV6_FRAG_TIMEOUT;
748 748
749 inet_frags_init_net(&net->ipv6.frags); 749 inet_frags_init_net(&net->ipv6.frags);
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index 634d14affc8d..18d77b5c351a 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -83,6 +83,19 @@ config NF_CONNTRACK_SECMARK
83 83
84 If unsure, say 'N'. 84 If unsure, say 'N'.
85 85
86config NF_CONNTRACK_ZONES
87 bool 'Connection tracking zones'
88 depends on NETFILTER_ADVANCED
89 depends on NETFILTER_XT_TARGET_CT
90 help
91 This option enables support for connection tracking zones.
92 Normally, each connection needs to have a unique system wide
93 identity. Connection tracking zones allow to have multiple
94 connections using the same identity, as long as they are
95 contained in different zones.
96
97 If unsure, say `N'.
98
86config NF_CONNTRACK_EVENTS 99config NF_CONNTRACK_EVENTS
87 bool "Connection tracking events" 100 bool "Connection tracking events"
88 depends on NETFILTER_ADVANCED 101 depends on NETFILTER_ADVANCED
@@ -341,6 +354,18 @@ config NETFILTER_XT_TARGET_CONNSECMARK
341 354
342 To compile it as a module, choose M here. If unsure, say N. 355 To compile it as a module, choose M here. If unsure, say N.
343 356
357config NETFILTER_XT_TARGET_CT
358 tristate '"CT" target support'
359 depends on NF_CONNTRACK
360 depends on IP_NF_RAW || IP6_NF_RAW
361 depends on NETFILTER_ADVANCED
362 help
363 This options adds a `CT' target, which allows to specify initial
364 connection tracking parameters like events to be delivered and
365 the helper to be used.
366
367 To compile it as a module, choose M here. If unsure, say N.
368
344config NETFILTER_XT_TARGET_DSCP 369config NETFILTER_XT_TARGET_DSCP
345 tristate '"DSCP" and "TOS" target support' 370 tristate '"DSCP" and "TOS" target support'
346 depends on IP_NF_MANGLE || IP6_NF_MANGLE 371 depends on IP_NF_MANGLE || IP6_NF_MANGLE
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
index 49f62ee4e9ff..f873644f02f6 100644
--- a/net/netfilter/Makefile
+++ b/net/netfilter/Makefile
@@ -44,6 +44,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
44obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o 44obj-$(CONFIG_NETFILTER_XT_TARGET_CLASSIFY) += xt_CLASSIFY.o
45obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o 45obj-$(CONFIG_NETFILTER_XT_TARGET_CONNMARK) += xt_CONNMARK.o
46obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o 46obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o
47obj-$(CONFIG_NETFILTER_XT_TARGET_CT) += xt_CT.o
47obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o 48obj-$(CONFIG_NETFILTER_XT_TARGET_DSCP) += xt_DSCP.o
48obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o 49obj-$(CONFIG_NETFILTER_XT_TARGET_HL) += xt_HL.o
49obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o 50obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index f2d76238b9b5..817a8898203b 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -68,6 +68,10 @@ config IP_VS_TAB_BITS
68 each hash entry uses 8 bytes, so you can estimate how much memory is 68 each hash entry uses 8 bytes, so you can estimate how much memory is
69 needed for your box. 69 needed for your box.
70 70
71 You can overwrite this number setting conn_tab_bits module parameter
72 or by appending ip_vs.conn_tab_bits=? to the kernel command line
73 if IP VS was compiled built-in.
74
71comment "IPVS transport protocol load balancing support" 75comment "IPVS transport protocol load balancing support"
72 76
73config IP_VS_PROTO_TCP 77config IP_VS_PROTO_TCP
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 27c30cf933da..60bb41a8d8d4 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -40,6 +40,21 @@
40#include <net/ip_vs.h> 40#include <net/ip_vs.h>
41 41
42 42
43#ifndef CONFIG_IP_VS_TAB_BITS
44#define CONFIG_IP_VS_TAB_BITS 12
45#endif
46
47/*
48 * Connection hash size. Default is what was selected at compile time.
49*/
50int ip_vs_conn_tab_bits = CONFIG_IP_VS_TAB_BITS;
51module_param_named(conn_tab_bits, ip_vs_conn_tab_bits, int, 0444);
52MODULE_PARM_DESC(conn_tab_bits, "Set connections' hash size");
53
54/* size and mask values */
55int ip_vs_conn_tab_size;
56int ip_vs_conn_tab_mask;
57
43/* 58/*
44 * Connection hash table: for input and output packets lookups of IPVS 59 * Connection hash table: for input and output packets lookups of IPVS
45 */ 60 */
@@ -125,11 +140,11 @@ static unsigned int ip_vs_conn_hashkey(int af, unsigned proto,
125 if (af == AF_INET6) 140 if (af == AF_INET6)
126 return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd), 141 return jhash_3words(jhash(addr, 16, ip_vs_conn_rnd),
127 (__force u32)port, proto, ip_vs_conn_rnd) 142 (__force u32)port, proto, ip_vs_conn_rnd)
128 & IP_VS_CONN_TAB_MASK; 143 & ip_vs_conn_tab_mask;
129#endif 144#endif
130 return jhash_3words((__force u32)addr->ip, (__force u32)port, proto, 145 return jhash_3words((__force u32)addr->ip, (__force u32)port, proto,
131 ip_vs_conn_rnd) 146 ip_vs_conn_rnd)
132 & IP_VS_CONN_TAB_MASK; 147 & ip_vs_conn_tab_mask;
133} 148}
134 149
135 150
@@ -760,7 +775,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
760 int idx; 775 int idx;
761 struct ip_vs_conn *cp; 776 struct ip_vs_conn *cp;
762 777
763 for(idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) { 778 for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
764 ct_read_lock_bh(idx); 779 ct_read_lock_bh(idx);
765 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) { 780 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
766 if (pos-- == 0) { 781 if (pos-- == 0) {
@@ -797,7 +812,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
797 idx = l - ip_vs_conn_tab; 812 idx = l - ip_vs_conn_tab;
798 ct_read_unlock_bh(idx); 813 ct_read_unlock_bh(idx);
799 814
800 while (++idx < IP_VS_CONN_TAB_SIZE) { 815 while (++idx < ip_vs_conn_tab_size) {
801 ct_read_lock_bh(idx); 816 ct_read_lock_bh(idx);
802 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) { 817 list_for_each_entry(cp, &ip_vs_conn_tab[idx], c_list) {
803 seq->private = &ip_vs_conn_tab[idx]; 818 seq->private = &ip_vs_conn_tab[idx];
@@ -976,8 +991,8 @@ void ip_vs_random_dropentry(void)
976 /* 991 /*
977 * Randomly scan 1/32 of the whole table every second 992 * Randomly scan 1/32 of the whole table every second
978 */ 993 */
979 for (idx = 0; idx < (IP_VS_CONN_TAB_SIZE>>5); idx++) { 994 for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
980 unsigned hash = net_random() & IP_VS_CONN_TAB_MASK; 995 unsigned hash = net_random() & ip_vs_conn_tab_mask;
981 996
982 /* 997 /*
983 * Lock is actually needed in this loop. 998 * Lock is actually needed in this loop.
@@ -1029,7 +1044,7 @@ static void ip_vs_conn_flush(void)
1029 struct ip_vs_conn *cp; 1044 struct ip_vs_conn *cp;
1030 1045
1031 flush_again: 1046 flush_again:
1032 for (idx=0; idx<IP_VS_CONN_TAB_SIZE; idx++) { 1047 for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
1033 /* 1048 /*
1034 * Lock is actually needed in this loop. 1049 * Lock is actually needed in this loop.
1035 */ 1050 */
@@ -1060,10 +1075,15 @@ int __init ip_vs_conn_init(void)
1060{ 1075{
1061 int idx; 1076 int idx;
1062 1077
1078 /* Compute size and mask */
1079 ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
1080 ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1;
1081
1063 /* 1082 /*
1064 * Allocate the connection hash table and initialize its list heads 1083 * Allocate the connection hash table and initialize its list heads
1065 */ 1084 */
1066 ip_vs_conn_tab = vmalloc(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head)); 1085 ip_vs_conn_tab = vmalloc(ip_vs_conn_tab_size *
1086 sizeof(struct list_head));
1067 if (!ip_vs_conn_tab) 1087 if (!ip_vs_conn_tab)
1068 return -ENOMEM; 1088 return -ENOMEM;
1069 1089
@@ -1078,12 +1098,12 @@ int __init ip_vs_conn_init(void)
1078 1098
1079 pr_info("Connection hash table configured " 1099 pr_info("Connection hash table configured "
1080 "(size=%d, memory=%ldKbytes)\n", 1100 "(size=%d, memory=%ldKbytes)\n",
1081 IP_VS_CONN_TAB_SIZE, 1101 ip_vs_conn_tab_size,
1082 (long)(IP_VS_CONN_TAB_SIZE*sizeof(struct list_head))/1024); 1102 (long)(ip_vs_conn_tab_size*sizeof(struct list_head))/1024);
1083 IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least\n", 1103 IP_VS_DBG(0, "Each connection entry needs %Zd bytes at least\n",
1084 sizeof(struct ip_vs_conn)); 1104 sizeof(struct ip_vs_conn));
1085 1105
1086 for (idx = 0; idx < IP_VS_CONN_TAB_SIZE; idx++) { 1106 for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
1087 INIT_LIST_HEAD(&ip_vs_conn_tab[idx]); 1107 INIT_LIST_HEAD(&ip_vs_conn_tab[idx]);
1088 } 1108 }
1089 1109
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index c37ac2d7bec4..00d0b152db39 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1843,7 +1843,7 @@ static int ip_vs_info_seq_show(struct seq_file *seq, void *v)
1843 if (v == SEQ_START_TOKEN) { 1843 if (v == SEQ_START_TOKEN) {
1844 seq_printf(seq, 1844 seq_printf(seq,
1845 "IP Virtual Server version %d.%d.%d (size=%d)\n", 1845 "IP Virtual Server version %d.%d.%d (size=%d)\n",
1846 NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE); 1846 NVERSION(IP_VS_VERSION_CODE), ip_vs_conn_tab_size);
1847 seq_puts(seq, 1847 seq_puts(seq,
1848 "Prot LocalAddress:Port Scheduler Flags\n"); 1848 "Prot LocalAddress:Port Scheduler Flags\n");
1849 seq_puts(seq, 1849 seq_puts(seq,
@@ -2386,7 +2386,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2386 char buf[64]; 2386 char buf[64];
2387 2387
2388 sprintf(buf, "IP Virtual Server version %d.%d.%d (size=%d)", 2388 sprintf(buf, "IP Virtual Server version %d.%d.%d (size=%d)",
2389 NVERSION(IP_VS_VERSION_CODE), IP_VS_CONN_TAB_SIZE); 2389 NVERSION(IP_VS_VERSION_CODE), ip_vs_conn_tab_size);
2390 if (copy_to_user(user, buf, strlen(buf)+1) != 0) { 2390 if (copy_to_user(user, buf, strlen(buf)+1) != 0) {
2391 ret = -EFAULT; 2391 ret = -EFAULT;
2392 goto out; 2392 goto out;
@@ -2399,7 +2399,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len)
2399 { 2399 {
2400 struct ip_vs_getinfo info; 2400 struct ip_vs_getinfo info;
2401 info.version = IP_VS_VERSION_CODE; 2401 info.version = IP_VS_VERSION_CODE;
2402 info.size = IP_VS_CONN_TAB_SIZE; 2402 info.size = ip_vs_conn_tab_size;
2403 info.num_services = ip_vs_num_services; 2403 info.num_services = ip_vs_num_services;
2404 if (copy_to_user(user, &info, sizeof(info)) != 0) 2404 if (copy_to_user(user, &info, sizeof(info)) != 0)
2405 ret = -EFAULT; 2405 ret = -EFAULT;
@@ -3243,7 +3243,7 @@ static int ip_vs_genl_get_cmd(struct sk_buff *skb, struct genl_info *info)
3243 case IPVS_CMD_GET_INFO: 3243 case IPVS_CMD_GET_INFO:
3244 NLA_PUT_U32(msg, IPVS_INFO_ATTR_VERSION, IP_VS_VERSION_CODE); 3244 NLA_PUT_U32(msg, IPVS_INFO_ATTR_VERSION, IP_VS_VERSION_CODE);
3245 NLA_PUT_U32(msg, IPVS_INFO_ATTR_CONN_TAB_SIZE, 3245 NLA_PUT_U32(msg, IPVS_INFO_ATTR_CONN_TAB_SIZE,
3246 IP_VS_CONN_TAB_SIZE); 3246 ip_vs_conn_tab_size);
3247 break; 3247 break;
3248 } 3248 }
3249 3249
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 33e2c799cba7..73f38ea98f25 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -208,7 +208,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
208 */ 208 */
209 from.ip = n_cp->vaddr.ip; 209 from.ip = n_cp->vaddr.ip;
210 port = n_cp->vport; 210 port = n_cp->vport;
211 sprintf(buf, "%d,%d,%d,%d,%d,%d", NIPQUAD(from.ip), 211 sprintf(buf, "%u,%u,%u,%u,%u,%u", NIPQUAD(from.ip),
212 (ntohs(port)>>8)&255, ntohs(port)&255); 212 (ntohs(port)>>8)&255, ntohs(port)&255);
213 buf_len = strlen(buf); 213 buf_len = strlen(buf);
214 214
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 4d79e3c1616c..0c9bbe93cc16 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -42,6 +42,7 @@
42#include <net/netfilter/nf_conntrack_extend.h> 42#include <net/netfilter/nf_conntrack_extend.h>
43#include <net/netfilter/nf_conntrack_acct.h> 43#include <net/netfilter/nf_conntrack_acct.h>
44#include <net/netfilter/nf_conntrack_ecache.h> 44#include <net/netfilter/nf_conntrack_ecache.h>
45#include <net/netfilter/nf_conntrack_zones.h>
45#include <net/netfilter/nf_nat.h> 46#include <net/netfilter/nf_nat.h>
46#include <net/netfilter/nf_nat_core.h> 47#include <net/netfilter/nf_nat_core.h>
47 48
@@ -68,7 +69,7 @@ static int nf_conntrack_hash_rnd_initted;
68static unsigned int nf_conntrack_hash_rnd; 69static unsigned int nf_conntrack_hash_rnd;
69 70
70static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple, 71static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
71 unsigned int size, unsigned int rnd) 72 u16 zone, unsigned int size, unsigned int rnd)
72{ 73{
73 unsigned int n; 74 unsigned int n;
74 u_int32_t h; 75 u_int32_t h;
@@ -79,16 +80,16 @@ static u_int32_t __hash_conntrack(const struct nf_conntrack_tuple *tuple,
79 */ 80 */
80 n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32); 81 n = (sizeof(tuple->src) + sizeof(tuple->dst.u3)) / sizeof(u32);
81 h = jhash2((u32 *)tuple, n, 82 h = jhash2((u32 *)tuple, n,
82 rnd ^ (((__force __u16)tuple->dst.u.all << 16) | 83 zone ^ rnd ^ (((__force __u16)tuple->dst.u.all << 16) |
83 tuple->dst.protonum)); 84 tuple->dst.protonum));
84 85
85 return ((u64)h * size) >> 32; 86 return ((u64)h * size) >> 32;
86} 87}
87 88
88static inline u_int32_t hash_conntrack(const struct net *net, 89static inline u_int32_t hash_conntrack(const struct net *net, u16 zone,
89 const struct nf_conntrack_tuple *tuple) 90 const struct nf_conntrack_tuple *tuple)
90{ 91{
91 return __hash_conntrack(tuple, net->ct.htable_size, 92 return __hash_conntrack(tuple, zone, net->ct.htable_size,
92 nf_conntrack_hash_rnd); 93 nf_conntrack_hash_rnd);
93} 94}
94 95
@@ -292,11 +293,12 @@ static void death_by_timeout(unsigned long ul_conntrack)
292 * - Caller must lock nf_conntrack_lock before calling this function 293 * - Caller must lock nf_conntrack_lock before calling this function
293 */ 294 */
294struct nf_conntrack_tuple_hash * 295struct nf_conntrack_tuple_hash *
295__nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple) 296__nf_conntrack_find(struct net *net, u16 zone,
297 const struct nf_conntrack_tuple *tuple)
296{ 298{
297 struct nf_conntrack_tuple_hash *h; 299 struct nf_conntrack_tuple_hash *h;
298 struct hlist_nulls_node *n; 300 struct hlist_nulls_node *n;
299 unsigned int hash = hash_conntrack(net, tuple); 301 unsigned int hash = hash_conntrack(net, zone, tuple);
300 302
301 /* Disable BHs the entire time since we normally need to disable them 303 /* Disable BHs the entire time since we normally need to disable them
302 * at least once for the stats anyway. 304 * at least once for the stats anyway.
@@ -304,7 +306,8 @@ __nf_conntrack_find(struct net *net, const struct nf_conntrack_tuple *tuple)
304 local_bh_disable(); 306 local_bh_disable();
305begin: 307begin:
306 hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { 308 hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) {
307 if (nf_ct_tuple_equal(tuple, &h->tuple)) { 309 if (nf_ct_tuple_equal(tuple, &h->tuple) &&
310 nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)) == zone) {
308 NF_CT_STAT_INC(net, found); 311 NF_CT_STAT_INC(net, found);
309 local_bh_enable(); 312 local_bh_enable();
310 return h; 313 return h;
@@ -326,21 +329,23 @@ EXPORT_SYMBOL_GPL(__nf_conntrack_find);
326 329
327/* Find a connection corresponding to a tuple. */ 330/* Find a connection corresponding to a tuple. */
328struct nf_conntrack_tuple_hash * 331struct nf_conntrack_tuple_hash *
329nf_conntrack_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) 332nf_conntrack_find_get(struct net *net, u16 zone,
333 const struct nf_conntrack_tuple *tuple)
330{ 334{
331 struct nf_conntrack_tuple_hash *h; 335 struct nf_conntrack_tuple_hash *h;
332 struct nf_conn *ct; 336 struct nf_conn *ct;
333 337
334 rcu_read_lock(); 338 rcu_read_lock();
335begin: 339begin:
336 h = __nf_conntrack_find(net, tuple); 340 h = __nf_conntrack_find(net, zone, tuple);
337 if (h) { 341 if (h) {
338 ct = nf_ct_tuplehash_to_ctrack(h); 342 ct = nf_ct_tuplehash_to_ctrack(h);
339 if (unlikely(nf_ct_is_dying(ct) || 343 if (unlikely(nf_ct_is_dying(ct) ||
340 !atomic_inc_not_zero(&ct->ct_general.use))) 344 !atomic_inc_not_zero(&ct->ct_general.use)))
341 h = NULL; 345 h = NULL;
342 else { 346 else {
343 if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple))) { 347 if (unlikely(!nf_ct_tuple_equal(tuple, &h->tuple) ||
348 nf_ct_zone(ct) != zone)) {
344 nf_ct_put(ct); 349 nf_ct_put(ct);
345 goto begin; 350 goto begin;
346 } 351 }
@@ -368,9 +373,11 @@ void nf_conntrack_hash_insert(struct nf_conn *ct)
368{ 373{
369 struct net *net = nf_ct_net(ct); 374 struct net *net = nf_ct_net(ct);
370 unsigned int hash, repl_hash; 375 unsigned int hash, repl_hash;
376 u16 zone;
371 377
372 hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 378 zone = nf_ct_zone(ct);
373 repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); 379 hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
380 repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
374 381
375 __nf_conntrack_hash_insert(ct, hash, repl_hash); 382 __nf_conntrack_hash_insert(ct, hash, repl_hash);
376} 383}
@@ -387,6 +394,7 @@ __nf_conntrack_confirm(struct sk_buff *skb)
387 struct hlist_nulls_node *n; 394 struct hlist_nulls_node *n;
388 enum ip_conntrack_info ctinfo; 395 enum ip_conntrack_info ctinfo;
389 struct net *net; 396 struct net *net;
397 u16 zone;
390 398
391 ct = nf_ct_get(skb, &ctinfo); 399 ct = nf_ct_get(skb, &ctinfo);
392 net = nf_ct_net(ct); 400 net = nf_ct_net(ct);
@@ -398,8 +406,9 @@ __nf_conntrack_confirm(struct sk_buff *skb)
398 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL) 406 if (CTINFO2DIR(ctinfo) != IP_CT_DIR_ORIGINAL)
399 return NF_ACCEPT; 407 return NF_ACCEPT;
400 408
401 hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); 409 zone = nf_ct_zone(ct);
402 repl_hash = hash_conntrack(net, &ct->tuplehash[IP_CT_DIR_REPLY].tuple); 410 hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple);
411 repl_hash = hash_conntrack(net, zone, &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
403 412
404 /* We're not in hash table, and we refuse to set up related 413 /* We're not in hash table, and we refuse to set up related
405 connections for unconfirmed conns. But packet copies and 414 connections for unconfirmed conns. But packet copies and
@@ -418,11 +427,13 @@ __nf_conntrack_confirm(struct sk_buff *skb)
418 not in the hash. If there is, we lost race. */ 427 not in the hash. If there is, we lost race. */
419 hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) 428 hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode)
420 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, 429 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
421 &h->tuple)) 430 &h->tuple) &&
431 zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))
422 goto out; 432 goto out;
423 hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) 433 hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode)
424 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, 434 if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple,
425 &h->tuple)) 435 &h->tuple) &&
436 zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h)))
426 goto out; 437 goto out;
427 438
428 /* Remove from unconfirmed list */ 439 /* Remove from unconfirmed list */
@@ -469,15 +480,19 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
469 struct net *net = nf_ct_net(ignored_conntrack); 480 struct net *net = nf_ct_net(ignored_conntrack);
470 struct nf_conntrack_tuple_hash *h; 481 struct nf_conntrack_tuple_hash *h;
471 struct hlist_nulls_node *n; 482 struct hlist_nulls_node *n;
472 unsigned int hash = hash_conntrack(net, tuple); 483 struct nf_conn *ct;
484 u16 zone = nf_ct_zone(ignored_conntrack);
485 unsigned int hash = hash_conntrack(net, zone, tuple);
473 486
474 /* Disable BHs the entire time since we need to disable them at 487 /* Disable BHs the entire time since we need to disable them at
475 * least once for the stats anyway. 488 * least once for the stats anyway.
476 */ 489 */
477 rcu_read_lock_bh(); 490 rcu_read_lock_bh();
478 hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) { 491 hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], hnnode) {
479 if (nf_ct_tuplehash_to_ctrack(h) != ignored_conntrack && 492 ct = nf_ct_tuplehash_to_ctrack(h);
480 nf_ct_tuple_equal(tuple, &h->tuple)) { 493 if (ct != ignored_conntrack &&
494 nf_ct_tuple_equal(tuple, &h->tuple) &&
495 nf_ct_zone(ct) == zone) {
481 NF_CT_STAT_INC(net, found); 496 NF_CT_STAT_INC(net, found);
482 rcu_read_unlock_bh(); 497 rcu_read_unlock_bh();
483 return 1; 498 return 1;
@@ -540,7 +555,7 @@ static noinline int early_drop(struct net *net, unsigned int hash)
540 return dropped; 555 return dropped;
541} 556}
542 557
543struct nf_conn *nf_conntrack_alloc(struct net *net, 558struct nf_conn *nf_conntrack_alloc(struct net *net, u16 zone,
544 const struct nf_conntrack_tuple *orig, 559 const struct nf_conntrack_tuple *orig,
545 const struct nf_conntrack_tuple *repl, 560 const struct nf_conntrack_tuple *repl,
546 gfp_t gfp) 561 gfp_t gfp)
@@ -558,7 +573,7 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
558 573
559 if (nf_conntrack_max && 574 if (nf_conntrack_max &&
560 unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { 575 unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) {
561 unsigned int hash = hash_conntrack(net, orig); 576 unsigned int hash = hash_conntrack(net, zone, orig);
562 if (!early_drop(net, hash)) { 577 if (!early_drop(net, hash)) {
563 atomic_dec(&net->ct.count); 578 atomic_dec(&net->ct.count);
564 if (net_ratelimit()) 579 if (net_ratelimit())
@@ -595,13 +610,28 @@ struct nf_conn *nf_conntrack_alloc(struct net *net,
595#ifdef CONFIG_NET_NS 610#ifdef CONFIG_NET_NS
596 ct->ct_net = net; 611 ct->ct_net = net;
597#endif 612#endif
598 613#ifdef CONFIG_NF_CONNTRACK_ZONES
614 if (zone) {
615 struct nf_conntrack_zone *nf_ct_zone;
616
617 nf_ct_zone = nf_ct_ext_add(ct, NF_CT_EXT_ZONE, GFP_ATOMIC);
618 if (!nf_ct_zone)
619 goto out_free;
620 nf_ct_zone->id = zone;
621 }
622#endif
599 /* 623 /*
600 * changes to lookup keys must be done before setting refcnt to 1 624 * changes to lookup keys must be done before setting refcnt to 1
601 */ 625 */
602 smp_wmb(); 626 smp_wmb();
603 atomic_set(&ct->ct_general.use, 1); 627 atomic_set(&ct->ct_general.use, 1);
604 return ct; 628 return ct;
629
630#ifdef CONFIG_NF_CONNTRACK_ZONES
631out_free:
632 kmem_cache_free(net->ct.nf_conntrack_cachep, ct);
633 return ERR_PTR(-ENOMEM);
634#endif
605} 635}
606EXPORT_SYMBOL_GPL(nf_conntrack_alloc); 636EXPORT_SYMBOL_GPL(nf_conntrack_alloc);
607 637
@@ -619,7 +649,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_free);
619/* Allocate a new conntrack: we return -ENOMEM if classification 649/* Allocate a new conntrack: we return -ENOMEM if classification
620 failed due to stress. Otherwise it really is unclassifiable. */ 650 failed due to stress. Otherwise it really is unclassifiable. */
621static struct nf_conntrack_tuple_hash * 651static struct nf_conntrack_tuple_hash *
622init_conntrack(struct net *net, 652init_conntrack(struct net *net, struct nf_conn *tmpl,
623 const struct nf_conntrack_tuple *tuple, 653 const struct nf_conntrack_tuple *tuple,
624 struct nf_conntrack_l3proto *l3proto, 654 struct nf_conntrack_l3proto *l3proto,
625 struct nf_conntrack_l4proto *l4proto, 655 struct nf_conntrack_l4proto *l4proto,
@@ -629,14 +659,16 @@ init_conntrack(struct net *net,
629 struct nf_conn *ct; 659 struct nf_conn *ct;
630 struct nf_conn_help *help; 660 struct nf_conn_help *help;
631 struct nf_conntrack_tuple repl_tuple; 661 struct nf_conntrack_tuple repl_tuple;
662 struct nf_conntrack_ecache *ecache;
632 struct nf_conntrack_expect *exp; 663 struct nf_conntrack_expect *exp;
664 u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
633 665
634 if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) { 666 if (!nf_ct_invert_tuple(&repl_tuple, tuple, l3proto, l4proto)) {
635 pr_debug("Can't invert tuple.\n"); 667 pr_debug("Can't invert tuple.\n");
636 return NULL; 668 return NULL;
637 } 669 }
638 670
639 ct = nf_conntrack_alloc(net, tuple, &repl_tuple, GFP_ATOMIC); 671 ct = nf_conntrack_alloc(net, zone, tuple, &repl_tuple, GFP_ATOMIC);
640 if (IS_ERR(ct)) { 672 if (IS_ERR(ct)) {
641 pr_debug("Can't allocate conntrack.\n"); 673 pr_debug("Can't allocate conntrack.\n");
642 return (struct nf_conntrack_tuple_hash *)ct; 674 return (struct nf_conntrack_tuple_hash *)ct;
@@ -649,10 +681,14 @@ init_conntrack(struct net *net,
649 } 681 }
650 682
651 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 683 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
652 nf_ct_ecache_ext_add(ct, GFP_ATOMIC); 684
685 ecache = tmpl ? nf_ct_ecache_find(tmpl) : NULL;
686 nf_ct_ecache_ext_add(ct, ecache ? ecache->ctmask : 0,
687 ecache ? ecache->expmask : 0,
688 GFP_ATOMIC);
653 689
654 spin_lock_bh(&nf_conntrack_lock); 690 spin_lock_bh(&nf_conntrack_lock);
655 exp = nf_ct_find_expectation(net, tuple); 691 exp = nf_ct_find_expectation(net, zone, tuple);
656 if (exp) { 692 if (exp) {
657 pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", 693 pr_debug("conntrack: expectation arrives ct=%p exp=%p\n",
658 ct, exp); 694 ct, exp);
@@ -674,7 +710,7 @@ init_conntrack(struct net *net,
674 nf_conntrack_get(&ct->master->ct_general); 710 nf_conntrack_get(&ct->master->ct_general);
675 NF_CT_STAT_INC(net, expect_new); 711 NF_CT_STAT_INC(net, expect_new);
676 } else { 712 } else {
677 __nf_ct_try_assign_helper(ct, GFP_ATOMIC); 713 __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC);
678 NF_CT_STAT_INC(net, new); 714 NF_CT_STAT_INC(net, new);
679 } 715 }
680 716
@@ -695,7 +731,7 @@ init_conntrack(struct net *net,
695 731
696/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */ 732/* On success, returns conntrack ptr, sets skb->nfct and ctinfo */
697static inline struct nf_conn * 733static inline struct nf_conn *
698resolve_normal_ct(struct net *net, 734resolve_normal_ct(struct net *net, struct nf_conn *tmpl,
699 struct sk_buff *skb, 735 struct sk_buff *skb,
700 unsigned int dataoff, 736 unsigned int dataoff,
701 u_int16_t l3num, 737 u_int16_t l3num,
@@ -708,6 +744,7 @@ resolve_normal_ct(struct net *net,
708 struct nf_conntrack_tuple tuple; 744 struct nf_conntrack_tuple tuple;
709 struct nf_conntrack_tuple_hash *h; 745 struct nf_conntrack_tuple_hash *h;
710 struct nf_conn *ct; 746 struct nf_conn *ct;
747 u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE;
711 748
712 if (!nf_ct_get_tuple(skb, skb_network_offset(skb), 749 if (!nf_ct_get_tuple(skb, skb_network_offset(skb),
713 dataoff, l3num, protonum, &tuple, l3proto, 750 dataoff, l3num, protonum, &tuple, l3proto,
@@ -717,9 +754,10 @@ resolve_normal_ct(struct net *net,
717 } 754 }
718 755
719 /* look for tuple match */ 756 /* look for tuple match */
720 h = nf_conntrack_find_get(net, &tuple); 757 h = nf_conntrack_find_get(net, zone, &tuple);
721 if (!h) { 758 if (!h) {
722 h = init_conntrack(net, &tuple, l3proto, l4proto, skb, dataoff); 759 h = init_conntrack(net, tmpl, &tuple, l3proto, l4proto,
760 skb, dataoff);
723 if (!h) 761 if (!h)
724 return NULL; 762 return NULL;
725 if (IS_ERR(h)) 763 if (IS_ERR(h))
@@ -756,7 +794,7 @@ unsigned int
756nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, 794nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
757 struct sk_buff *skb) 795 struct sk_buff *skb)
758{ 796{
759 struct nf_conn *ct; 797 struct nf_conn *ct, *tmpl = NULL;
760 enum ip_conntrack_info ctinfo; 798 enum ip_conntrack_info ctinfo;
761 struct nf_conntrack_l3proto *l3proto; 799 struct nf_conntrack_l3proto *l3proto;
762 struct nf_conntrack_l4proto *l4proto; 800 struct nf_conntrack_l4proto *l4proto;
@@ -765,10 +803,14 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
765 int set_reply = 0; 803 int set_reply = 0;
766 int ret; 804 int ret;
767 805
768 /* Previously seen (loopback or untracked)? Ignore. */
769 if (skb->nfct) { 806 if (skb->nfct) {
770 NF_CT_STAT_INC_ATOMIC(net, ignore); 807 /* Previously seen (loopback or untracked)? Ignore. */
771 return NF_ACCEPT; 808 tmpl = (struct nf_conn *)skb->nfct;
809 if (!nf_ct_is_template(tmpl)) {
810 NF_CT_STAT_INC_ATOMIC(net, ignore);
811 return NF_ACCEPT;
812 }
813 skb->nfct = NULL;
772 } 814 }
773 815
774 /* rcu_read_lock()ed by nf_hook_slow */ 816 /* rcu_read_lock()ed by nf_hook_slow */
@@ -779,7 +821,8 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
779 pr_debug("not prepared to track yet or error occured\n"); 821 pr_debug("not prepared to track yet or error occured\n");
780 NF_CT_STAT_INC_ATOMIC(net, error); 822 NF_CT_STAT_INC_ATOMIC(net, error);
781 NF_CT_STAT_INC_ATOMIC(net, invalid); 823 NF_CT_STAT_INC_ATOMIC(net, invalid);
782 return -ret; 824 ret = -ret;
825 goto out;
783 } 826 }
784 827
785 l4proto = __nf_ct_l4proto_find(pf, protonum); 828 l4proto = __nf_ct_l4proto_find(pf, protonum);
@@ -788,26 +831,30 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
788 * inverse of the return code tells to the netfilter 831 * inverse of the return code tells to the netfilter
789 * core what to do with the packet. */ 832 * core what to do with the packet. */
790 if (l4proto->error != NULL) { 833 if (l4proto->error != NULL) {
791 ret = l4proto->error(net, skb, dataoff, &ctinfo, pf, hooknum); 834 ret = l4proto->error(net, tmpl, skb, dataoff, &ctinfo,
835 pf, hooknum);
792 if (ret <= 0) { 836 if (ret <= 0) {
793 NF_CT_STAT_INC_ATOMIC(net, error); 837 NF_CT_STAT_INC_ATOMIC(net, error);
794 NF_CT_STAT_INC_ATOMIC(net, invalid); 838 NF_CT_STAT_INC_ATOMIC(net, invalid);
795 return -ret; 839 ret = -ret;
840 goto out;
796 } 841 }
797 } 842 }
798 843
799 ct = resolve_normal_ct(net, skb, dataoff, pf, protonum, 844 ct = resolve_normal_ct(net, tmpl, skb, dataoff, pf, protonum,
800 l3proto, l4proto, &set_reply, &ctinfo); 845 l3proto, l4proto, &set_reply, &ctinfo);
801 if (!ct) { 846 if (!ct) {
802 /* Not valid part of a connection */ 847 /* Not valid part of a connection */
803 NF_CT_STAT_INC_ATOMIC(net, invalid); 848 NF_CT_STAT_INC_ATOMIC(net, invalid);
804 return NF_ACCEPT; 849 ret = NF_ACCEPT;
850 goto out;
805 } 851 }
806 852
807 if (IS_ERR(ct)) { 853 if (IS_ERR(ct)) {
808 /* Too stressed to deal. */ 854 /* Too stressed to deal. */
809 NF_CT_STAT_INC_ATOMIC(net, drop); 855 NF_CT_STAT_INC_ATOMIC(net, drop);
810 return NF_DROP; 856 ret = NF_DROP;
857 goto out;
811 } 858 }
812 859
813 NF_CT_ASSERT(skb->nfct); 860 NF_CT_ASSERT(skb->nfct);
@@ -822,11 +869,15 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
822 NF_CT_STAT_INC_ATOMIC(net, invalid); 869 NF_CT_STAT_INC_ATOMIC(net, invalid);
823 if (ret == -NF_DROP) 870 if (ret == -NF_DROP)
824 NF_CT_STAT_INC_ATOMIC(net, drop); 871 NF_CT_STAT_INC_ATOMIC(net, drop);
825 return -ret; 872 ret = -ret;
873 goto out;
826 } 874 }
827 875
828 if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status)) 876 if (set_reply && !test_and_set_bit(IPS_SEEN_REPLY_BIT, &ct->status))
829 nf_conntrack_event_cache(IPCT_STATUS, ct); 877 nf_conntrack_event_cache(IPCT_REPLY, ct);
878out:
879 if (tmpl)
880 nf_ct_put(tmpl);
830 881
831 return ret; 882 return ret;
832} 883}
@@ -865,7 +916,7 @@ void nf_conntrack_alter_reply(struct nf_conn *ct,
865 return; 916 return;
866 917
867 rcu_read_lock(); 918 rcu_read_lock();
868 __nf_ct_try_assign_helper(ct, GFP_ATOMIC); 919 __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
869 rcu_read_unlock(); 920 rcu_read_unlock();
870} 921}
871EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply); 922EXPORT_SYMBOL_GPL(nf_conntrack_alter_reply);
@@ -939,6 +990,14 @@ bool __nf_ct_kill_acct(struct nf_conn *ct,
939} 990}
940EXPORT_SYMBOL_GPL(__nf_ct_kill_acct); 991EXPORT_SYMBOL_GPL(__nf_ct_kill_acct);
941 992
993#ifdef CONFIG_NF_CONNTRACK_ZONES
994static struct nf_ct_ext_type nf_ct_zone_extend __read_mostly = {
995 .len = sizeof(struct nf_conntrack_zone),
996 .align = __alignof__(struct nf_conntrack_zone),
997 .id = NF_CT_EXT_ZONE,
998};
999#endif
1000
942#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) 1001#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
943 1002
944#include <linux/netfilter/nfnetlink.h> 1003#include <linux/netfilter/nfnetlink.h>
@@ -1120,6 +1179,9 @@ static void nf_conntrack_cleanup_init_net(void)
1120 1179
1121 nf_conntrack_helper_fini(); 1180 nf_conntrack_helper_fini();
1122 nf_conntrack_proto_fini(); 1181 nf_conntrack_proto_fini();
1182#ifdef CONFIG_NF_CONNTRACK_ZONES
1183 nf_ct_extend_unregister(&nf_ct_zone_extend);
1184#endif
1123} 1185}
1124 1186
1125static void nf_conntrack_cleanup_net(struct net *net) 1187static void nf_conntrack_cleanup_net(struct net *net)
@@ -1195,6 +1257,7 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
1195 unsigned int hashsize, old_size; 1257 unsigned int hashsize, old_size;
1196 struct hlist_nulls_head *hash, *old_hash; 1258 struct hlist_nulls_head *hash, *old_hash;
1197 struct nf_conntrack_tuple_hash *h; 1259 struct nf_conntrack_tuple_hash *h;
1260 struct nf_conn *ct;
1198 1261
1199 if (current->nsproxy->net_ns != &init_net) 1262 if (current->nsproxy->net_ns != &init_net)
1200 return -EOPNOTSUPP; 1263 return -EOPNOTSUPP;
@@ -1221,8 +1284,10 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp)
1221 while (!hlist_nulls_empty(&init_net.ct.hash[i])) { 1284 while (!hlist_nulls_empty(&init_net.ct.hash[i])) {
1222 h = hlist_nulls_entry(init_net.ct.hash[i].first, 1285 h = hlist_nulls_entry(init_net.ct.hash[i].first,
1223 struct nf_conntrack_tuple_hash, hnnode); 1286 struct nf_conntrack_tuple_hash, hnnode);
1287 ct = nf_ct_tuplehash_to_ctrack(h);
1224 hlist_nulls_del_rcu(&h->hnnode); 1288 hlist_nulls_del_rcu(&h->hnnode);
1225 bucket = __hash_conntrack(&h->tuple, hashsize, 1289 bucket = __hash_conntrack(&h->tuple, nf_ct_zone(ct),
1290 hashsize,
1226 nf_conntrack_hash_rnd); 1291 nf_conntrack_hash_rnd);
1227 hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]); 1292 hlist_nulls_add_head_rcu(&h->hnnode, &hash[bucket]);
1228 } 1293 }
@@ -1280,6 +1345,11 @@ static int nf_conntrack_init_init_net(void)
1280 if (ret < 0) 1345 if (ret < 0)
1281 goto err_helper; 1346 goto err_helper;
1282 1347
1348#ifdef CONFIG_NF_CONNTRACK_ZONES
1349 ret = nf_ct_extend_register(&nf_ct_zone_extend);
1350 if (ret < 0)
1351 goto err_extend;
1352#endif
1283 /* Set up fake conntrack: to never be deleted, not in any hashes */ 1353 /* Set up fake conntrack: to never be deleted, not in any hashes */
1284#ifdef CONFIG_NET_NS 1354#ifdef CONFIG_NET_NS
1285 nf_conntrack_untracked.ct_net = &init_net; 1355 nf_conntrack_untracked.ct_net = &init_net;
@@ -1290,6 +1360,10 @@ static int nf_conntrack_init_init_net(void)
1290 1360
1291 return 0; 1361 return 0;
1292 1362
1363#ifdef CONFIG_NF_CONNTRACK_ZONES
1364err_extend:
1365 nf_conntrack_helper_fini();
1366#endif
1293err_helper: 1367err_helper:
1294 nf_conntrack_proto_fini(); 1368 nf_conntrack_proto_fini();
1295err_proto: 1369err_proto:
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 2f25ff610982..acb29ccaa41f 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -27,6 +27,7 @@
27#include <net/netfilter/nf_conntrack_expect.h> 27#include <net/netfilter/nf_conntrack_expect.h>
28#include <net/netfilter/nf_conntrack_helper.h> 28#include <net/netfilter/nf_conntrack_helper.h>
29#include <net/netfilter/nf_conntrack_tuple.h> 29#include <net/netfilter/nf_conntrack_tuple.h>
30#include <net/netfilter/nf_conntrack_zones.h>
30 31
31unsigned int nf_ct_expect_hsize __read_mostly; 32unsigned int nf_ct_expect_hsize __read_mostly;
32EXPORT_SYMBOL_GPL(nf_ct_expect_hsize); 33EXPORT_SYMBOL_GPL(nf_ct_expect_hsize);
@@ -84,7 +85,8 @@ static unsigned int nf_ct_expect_dst_hash(const struct nf_conntrack_tuple *tuple
84} 85}
85 86
86struct nf_conntrack_expect * 87struct nf_conntrack_expect *
87__nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple) 88__nf_ct_expect_find(struct net *net, u16 zone,
89 const struct nf_conntrack_tuple *tuple)
88{ 90{
89 struct nf_conntrack_expect *i; 91 struct nf_conntrack_expect *i;
90 struct hlist_node *n; 92 struct hlist_node *n;
@@ -95,7 +97,8 @@ __nf_ct_expect_find(struct net *net, const struct nf_conntrack_tuple *tuple)
95 97
96 h = nf_ct_expect_dst_hash(tuple); 98 h = nf_ct_expect_dst_hash(tuple);
97 hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) { 99 hlist_for_each_entry_rcu(i, n, &net->ct.expect_hash[h], hnode) {
98 if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) 100 if (nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
101 nf_ct_zone(i->master) == zone)
99 return i; 102 return i;
100 } 103 }
101 return NULL; 104 return NULL;
@@ -104,12 +107,13 @@ EXPORT_SYMBOL_GPL(__nf_ct_expect_find);
104 107
105/* Just find a expectation corresponding to a tuple. */ 108/* Just find a expectation corresponding to a tuple. */
106struct nf_conntrack_expect * 109struct nf_conntrack_expect *
107nf_ct_expect_find_get(struct net *net, const struct nf_conntrack_tuple *tuple) 110nf_ct_expect_find_get(struct net *net, u16 zone,
111 const struct nf_conntrack_tuple *tuple)
108{ 112{
109 struct nf_conntrack_expect *i; 113 struct nf_conntrack_expect *i;
110 114
111 rcu_read_lock(); 115 rcu_read_lock();
112 i = __nf_ct_expect_find(net, tuple); 116 i = __nf_ct_expect_find(net, zone, tuple);
113 if (i && !atomic_inc_not_zero(&i->use)) 117 if (i && !atomic_inc_not_zero(&i->use))
114 i = NULL; 118 i = NULL;
115 rcu_read_unlock(); 119 rcu_read_unlock();
@@ -121,7 +125,8 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_find_get);
121/* If an expectation for this connection is found, it gets delete from 125/* If an expectation for this connection is found, it gets delete from
122 * global list then returned. */ 126 * global list then returned. */
123struct nf_conntrack_expect * 127struct nf_conntrack_expect *
124nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple) 128nf_ct_find_expectation(struct net *net, u16 zone,
129 const struct nf_conntrack_tuple *tuple)
125{ 130{
126 struct nf_conntrack_expect *i, *exp = NULL; 131 struct nf_conntrack_expect *i, *exp = NULL;
127 struct hlist_node *n; 132 struct hlist_node *n;
@@ -133,7 +138,8 @@ nf_ct_find_expectation(struct net *net, const struct nf_conntrack_tuple *tuple)
133 h = nf_ct_expect_dst_hash(tuple); 138 h = nf_ct_expect_dst_hash(tuple);
134 hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { 139 hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) {
135 if (!(i->flags & NF_CT_EXPECT_INACTIVE) && 140 if (!(i->flags & NF_CT_EXPECT_INACTIVE) &&
136 nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask)) { 141 nf_ct_tuple_mask_cmp(tuple, &i->tuple, &i->mask) &&
142 nf_ct_zone(i->master) == zone) {
137 exp = i; 143 exp = i;
138 break; 144 break;
139 } 145 }
@@ -204,7 +210,8 @@ static inline int expect_matches(const struct nf_conntrack_expect *a,
204{ 210{
205 return a->master == b->master && a->class == b->class && 211 return a->master == b->master && a->class == b->class &&
206 nf_ct_tuple_equal(&a->tuple, &b->tuple) && 212 nf_ct_tuple_equal(&a->tuple, &b->tuple) &&
207 nf_ct_tuple_mask_equal(&a->mask, &b->mask); 213 nf_ct_tuple_mask_equal(&a->mask, &b->mask) &&
214 nf_ct_zone(a->master) == nf_ct_zone(b->master);
208} 215}
209 216
210/* Generally a bad idea to call this: could have matched already. */ 217/* Generally a bad idea to call this: could have matched already. */
@@ -232,7 +239,6 @@ struct nf_conntrack_expect *nf_ct_expect_alloc(struct nf_conn *me)
232 239
233 new->master = me; 240 new->master = me;
234 atomic_set(&new->use, 1); 241 atomic_set(&new->use, 1);
235 INIT_RCU_HEAD(&new->rcu);
236 return new; 242 return new;
237} 243}
238EXPORT_SYMBOL_GPL(nf_ct_expect_alloc); 244EXPORT_SYMBOL_GPL(nf_ct_expect_alloc);
@@ -500,6 +506,7 @@ static void exp_seq_stop(struct seq_file *seq, void *v)
500static int exp_seq_show(struct seq_file *s, void *v) 506static int exp_seq_show(struct seq_file *s, void *v)
501{ 507{
502 struct nf_conntrack_expect *expect; 508 struct nf_conntrack_expect *expect;
509 struct nf_conntrack_helper *helper;
503 struct hlist_node *n = v; 510 struct hlist_node *n = v;
504 char *delim = ""; 511 char *delim = "";
505 512
@@ -525,6 +532,14 @@ static int exp_seq_show(struct seq_file *s, void *v)
525 if (expect->flags & NF_CT_EXPECT_INACTIVE) 532 if (expect->flags & NF_CT_EXPECT_INACTIVE)
526 seq_printf(s, "%sINACTIVE", delim); 533 seq_printf(s, "%sINACTIVE", delim);
527 534
535 helper = rcu_dereference(nfct_help(expect->master)->helper);
536 if (helper) {
537 seq_printf(s, "%s%s", expect->flags ? " " : "", helper->name);
538 if (helper->expect_policy[expect->class].name)
539 seq_printf(s, "/%s",
540 helper->expect_policy[expect->class].name);
541 }
542
528 return seq_putc(s, '\n'); 543 return seq_putc(s, '\n');
529} 544}
530 545
diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c
index fef95be334bd..fdc8fb4ae10f 100644
--- a/net/netfilter/nf_conntrack_extend.c
+++ b/net/netfilter/nf_conntrack_extend.c
@@ -59,7 +59,6 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp)
59 if (!*ext) 59 if (!*ext)
60 return NULL; 60 return NULL;
61 61
62 INIT_RCU_HEAD(&(*ext)->rcu);
63 (*ext)->offset[id] = off; 62 (*ext)->offset[id] = off;
64 (*ext)->len = len; 63 (*ext)->len = len;
65 64
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c
index 66369490230e..a1c8dd917e12 100644
--- a/net/netfilter/nf_conntrack_h323_main.c
+++ b/net/netfilter/nf_conntrack_h323_main.c
@@ -29,6 +29,7 @@
29#include <net/netfilter/nf_conntrack_expect.h> 29#include <net/netfilter/nf_conntrack_expect.h>
30#include <net/netfilter/nf_conntrack_ecache.h> 30#include <net/netfilter/nf_conntrack_ecache.h>
31#include <net/netfilter/nf_conntrack_helper.h> 31#include <net/netfilter/nf_conntrack_helper.h>
32#include <net/netfilter/nf_conntrack_zones.h>
32#include <linux/netfilter/nf_conntrack_h323.h> 33#include <linux/netfilter/nf_conntrack_h323.h>
33 34
34/* Parameters */ 35/* Parameters */
@@ -1216,7 +1217,7 @@ static struct nf_conntrack_expect *find_expect(struct nf_conn *ct,
1216 tuple.dst.u.tcp.port = port; 1217 tuple.dst.u.tcp.port = port;
1217 tuple.dst.protonum = IPPROTO_TCP; 1218 tuple.dst.protonum = IPPROTO_TCP;
1218 1219
1219 exp = __nf_ct_expect_find(net, &tuple); 1220 exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
1220 if (exp && exp->master == ct) 1221 if (exp && exp->master == ct)
1221 return exp; 1222 return exp;
1222 return NULL; 1223 return NULL;
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index 4b1a56bd074c..4509fa6726f8 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -65,7 +65,7 @@ __nf_ct_helper_find(const struct nf_conntrack_tuple *tuple)
65} 65}
66 66
67struct nf_conntrack_helper * 67struct nf_conntrack_helper *
68__nf_conntrack_helper_find_byname(const char *name) 68__nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
69{ 69{
70 struct nf_conntrack_helper *h; 70 struct nf_conntrack_helper *h;
71 struct hlist_node *n; 71 struct hlist_node *n;
@@ -73,13 +73,34 @@ __nf_conntrack_helper_find_byname(const char *name)
73 73
74 for (i = 0; i < nf_ct_helper_hsize; i++) { 74 for (i = 0; i < nf_ct_helper_hsize; i++) {
75 hlist_for_each_entry_rcu(h, n, &nf_ct_helper_hash[i], hnode) { 75 hlist_for_each_entry_rcu(h, n, &nf_ct_helper_hash[i], hnode) {
76 if (!strcmp(h->name, name)) 76 if (!strcmp(h->name, name) &&
77 h->tuple.src.l3num == l3num &&
78 h->tuple.dst.protonum == protonum)
77 return h; 79 return h;
78 } 80 }
79 } 81 }
80 return NULL; 82 return NULL;
81} 83}
82EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find_byname); 84EXPORT_SYMBOL_GPL(__nf_conntrack_helper_find);
85
86struct nf_conntrack_helper *
87nf_conntrack_helper_try_module_get(const char *name, u16 l3num, u8 protonum)
88{
89 struct nf_conntrack_helper *h;
90
91 h = __nf_conntrack_helper_find(name, l3num, protonum);
92#ifdef CONFIG_MODULES
93 if (h == NULL) {
94 if (request_module("nfct-helper-%s", name) == 0)
95 h = __nf_conntrack_helper_find(name, l3num, protonum);
96 }
97#endif
98 if (h != NULL && !try_module_get(h->me))
99 h = NULL;
100
101 return h;
102}
103EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
83 104
84struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp) 105struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
85{ 106{
@@ -94,13 +115,22 @@ struct nf_conn_help *nf_ct_helper_ext_add(struct nf_conn *ct, gfp_t gfp)
94} 115}
95EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add); 116EXPORT_SYMBOL_GPL(nf_ct_helper_ext_add);
96 117
97int __nf_ct_try_assign_helper(struct nf_conn *ct, gfp_t flags) 118int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl,
119 gfp_t flags)
98{ 120{
121 struct nf_conntrack_helper *helper = NULL;
122 struct nf_conn_help *help;
99 int ret = 0; 123 int ret = 0;
100 struct nf_conntrack_helper *helper;
101 struct nf_conn_help *help = nfct_help(ct);
102 124
103 helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple); 125 if (tmpl != NULL) {
126 help = nfct_help(tmpl);
127 if (help != NULL)
128 helper = help->helper;
129 }
130
131 help = nfct_help(ct);
132 if (helper == NULL)
133 helper = __nf_ct_helper_find(&ct->tuplehash[IP_CT_DIR_REPLY].tuple);
104 if (helper == NULL) { 134 if (helper == NULL) {
105 if (help) 135 if (help)
106 rcu_assign_pointer(help->helper, NULL); 136 rcu_assign_pointer(help->helper, NULL);
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c
index 0ffe689dfe97..8b05f364b2f2 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -30,6 +30,7 @@
30 30
31#include <linux/netfilter.h> 31#include <linux/netfilter.h>
32#include <net/netlink.h> 32#include <net/netlink.h>
33#include <net/sock.h>
33#include <net/netfilter/nf_conntrack.h> 34#include <net/netfilter/nf_conntrack.h>
34#include <net/netfilter/nf_conntrack_core.h> 35#include <net/netfilter/nf_conntrack_core.h>
35#include <net/netfilter/nf_conntrack_expect.h> 36#include <net/netfilter/nf_conntrack_expect.h>
@@ -38,6 +39,7 @@
38#include <net/netfilter/nf_conntrack_l4proto.h> 39#include <net/netfilter/nf_conntrack_l4proto.h>
39#include <net/netfilter/nf_conntrack_tuple.h> 40#include <net/netfilter/nf_conntrack_tuple.h>
40#include <net/netfilter/nf_conntrack_acct.h> 41#include <net/netfilter/nf_conntrack_acct.h>
42#include <net/netfilter/nf_conntrack_zones.h>
41#ifdef CONFIG_NF_NAT_NEEDED 43#ifdef CONFIG_NF_NAT_NEEDED
42#include <net/netfilter/nf_nat_core.h> 44#include <net/netfilter/nf_nat_core.h>
43#include <net/netfilter/nf_nat_protocol.h> 45#include <net/netfilter/nf_nat_protocol.h>
@@ -378,6 +380,9 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq,
378 goto nla_put_failure; 380 goto nla_put_failure;
379 nla_nest_end(skb, nest_parms); 381 nla_nest_end(skb, nest_parms);
380 382
383 if (nf_ct_zone(ct))
384 NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct)));
385
381 if (ctnetlink_dump_status(skb, ct) < 0 || 386 if (ctnetlink_dump_status(skb, ct) < 0 ||
382 ctnetlink_dump_timeout(skb, ct) < 0 || 387 ctnetlink_dump_timeout(skb, ct) < 0 ||
383 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || 388 ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 ||
@@ -456,6 +461,7 @@ ctnetlink_nlmsg_size(const struct nf_conn *ct)
456static int 461static int
457ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) 462ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
458{ 463{
464 struct net *net;
459 struct nlmsghdr *nlh; 465 struct nlmsghdr *nlh;
460 struct nfgenmsg *nfmsg; 466 struct nfgenmsg *nfmsg;
461 struct nlattr *nest_parms; 467 struct nlattr *nest_parms;
@@ -482,7 +488,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
482 } else 488 } else
483 return 0; 489 return 0;
484 490
485 if (!item->report && !nfnetlink_has_listeners(group)) 491 net = nf_ct_net(ct);
492 if (!item->report && !nfnetlink_has_listeners(net, group))
486 return 0; 493 return 0;
487 494
488 skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC); 495 skb = nlmsg_new(ctnetlink_nlmsg_size(ct), GFP_ATOMIC);
@@ -514,6 +521,9 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
514 goto nla_put_failure; 521 goto nla_put_failure;
515 nla_nest_end(skb, nest_parms); 522 nla_nest_end(skb, nest_parms);
516 523
524 if (nf_ct_zone(ct))
525 NLA_PUT_BE16(skb, CTA_ZONE, htons(nf_ct_zone(ct)));
526
517 if (ctnetlink_dump_id(skb, ct) < 0) 527 if (ctnetlink_dump_id(skb, ct) < 0)
518 goto nla_put_failure; 528 goto nla_put_failure;
519 529
@@ -559,7 +569,8 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item)
559 rcu_read_unlock(); 569 rcu_read_unlock();
560 570
561 nlmsg_end(skb, nlh); 571 nlmsg_end(skb, nlh);
562 err = nfnetlink_send(skb, item->pid, group, item->report, GFP_ATOMIC); 572 err = nfnetlink_send(skb, net, item->pid, group, item->report,
573 GFP_ATOMIC);
563 if (err == -ENOBUFS || err == -EAGAIN) 574 if (err == -ENOBUFS || err == -EAGAIN)
564 return -ENOBUFS; 575 return -ENOBUFS;
565 576
@@ -571,7 +582,7 @@ nla_put_failure:
571nlmsg_failure: 582nlmsg_failure:
572 kfree_skb(skb); 583 kfree_skb(skb);
573errout: 584errout:
574 nfnetlink_set_err(0, group, -ENOBUFS); 585 nfnetlink_set_err(net, 0, group, -ENOBUFS);
575 return 0; 586 return 0;
576} 587}
577#endif /* CONFIG_NF_CONNTRACK_EVENTS */ 588#endif /* CONFIG_NF_CONNTRACK_EVENTS */
@@ -586,6 +597,7 @@ static int ctnetlink_done(struct netlink_callback *cb)
586static int 597static int
587ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) 598ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
588{ 599{
600 struct net *net = sock_net(skb->sk);
589 struct nf_conn *ct, *last; 601 struct nf_conn *ct, *last;
590 struct nf_conntrack_tuple_hash *h; 602 struct nf_conntrack_tuple_hash *h;
591 struct hlist_nulls_node *n; 603 struct hlist_nulls_node *n;
@@ -594,9 +606,9 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
594 606
595 rcu_read_lock(); 607 rcu_read_lock();
596 last = (struct nf_conn *)cb->args[1]; 608 last = (struct nf_conn *)cb->args[1];
597 for (; cb->args[0] < init_net.ct.htable_size; cb->args[0]++) { 609 for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) {
598restart: 610restart:
599 hlist_nulls_for_each_entry_rcu(h, n, &init_net.ct.hash[cb->args[0]], 611 hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[cb->args[0]],
600 hnnode) { 612 hnnode) {
601 if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) 613 if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL)
602 continue; 614 continue;
@@ -703,6 +715,11 @@ ctnetlink_parse_tuple_proto(struct nlattr *attr,
703 return ret; 715 return ret;
704} 716}
705 717
718static const struct nla_policy tuple_nla_policy[CTA_TUPLE_MAX+1] = {
719 [CTA_TUPLE_IP] = { .type = NLA_NESTED },
720 [CTA_TUPLE_PROTO] = { .type = NLA_NESTED },
721};
722
706static int 723static int
707ctnetlink_parse_tuple(const struct nlattr * const cda[], 724ctnetlink_parse_tuple(const struct nlattr * const cda[],
708 struct nf_conntrack_tuple *tuple, 725 struct nf_conntrack_tuple *tuple,
@@ -713,7 +730,7 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[],
713 730
714 memset(tuple, 0, sizeof(*tuple)); 731 memset(tuple, 0, sizeof(*tuple));
715 732
716 nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], NULL); 733 nla_parse_nested(tb, CTA_TUPLE_MAX, cda[type], tuple_nla_policy);
717 734
718 if (!tb[CTA_TUPLE_IP]) 735 if (!tb[CTA_TUPLE_IP])
719 return -EINVAL; 736 return -EINVAL;
@@ -740,12 +757,31 @@ ctnetlink_parse_tuple(const struct nlattr * const cda[],
740 return 0; 757 return 0;
741} 758}
742 759
760static int
761ctnetlink_parse_zone(const struct nlattr *attr, u16 *zone)
762{
763 if (attr)
764#ifdef CONFIG_NF_CONNTRACK_ZONES
765 *zone = ntohs(nla_get_be16(attr));
766#else
767 return -EOPNOTSUPP;
768#endif
769 else
770 *zone = 0;
771
772 return 0;
773}
774
775static const struct nla_policy help_nla_policy[CTA_HELP_MAX+1] = {
776 [CTA_HELP_NAME] = { .type = NLA_NUL_STRING },
777};
778
743static inline int 779static inline int
744ctnetlink_parse_help(const struct nlattr *attr, char **helper_name) 780ctnetlink_parse_help(const struct nlattr *attr, char **helper_name)
745{ 781{
746 struct nlattr *tb[CTA_HELP_MAX+1]; 782 struct nlattr *tb[CTA_HELP_MAX+1];
747 783
748 nla_parse_nested(tb, CTA_HELP_MAX, attr, NULL); 784 nla_parse_nested(tb, CTA_HELP_MAX, attr, help_nla_policy);
749 785
750 if (!tb[CTA_HELP_NAME]) 786 if (!tb[CTA_HELP_NAME])
751 return -EINVAL; 787 return -EINVAL;
@@ -756,11 +792,18 @@ ctnetlink_parse_help(const struct nlattr *attr, char **helper_name)
756} 792}
757 793
758static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { 794static const struct nla_policy ct_nla_policy[CTA_MAX+1] = {
795 [CTA_TUPLE_ORIG] = { .type = NLA_NESTED },
796 [CTA_TUPLE_REPLY] = { .type = NLA_NESTED },
759 [CTA_STATUS] = { .type = NLA_U32 }, 797 [CTA_STATUS] = { .type = NLA_U32 },
798 [CTA_PROTOINFO] = { .type = NLA_NESTED },
799 [CTA_HELP] = { .type = NLA_NESTED },
800 [CTA_NAT_SRC] = { .type = NLA_NESTED },
760 [CTA_TIMEOUT] = { .type = NLA_U32 }, 801 [CTA_TIMEOUT] = { .type = NLA_U32 },
761 [CTA_MARK] = { .type = NLA_U32 }, 802 [CTA_MARK] = { .type = NLA_U32 },
762 [CTA_USE] = { .type = NLA_U32 },
763 [CTA_ID] = { .type = NLA_U32 }, 803 [CTA_ID] = { .type = NLA_U32 },
804 [CTA_NAT_DST] = { .type = NLA_NESTED },
805 [CTA_TUPLE_MASTER] = { .type = NLA_NESTED },
806 [CTA_ZONE] = { .type = NLA_U16 },
764}; 807};
765 808
766static int 809static int
@@ -768,12 +811,18 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
768 const struct nlmsghdr *nlh, 811 const struct nlmsghdr *nlh,
769 const struct nlattr * const cda[]) 812 const struct nlattr * const cda[])
770{ 813{
814 struct net *net = sock_net(ctnl);
771 struct nf_conntrack_tuple_hash *h; 815 struct nf_conntrack_tuple_hash *h;
772 struct nf_conntrack_tuple tuple; 816 struct nf_conntrack_tuple tuple;
773 struct nf_conn *ct; 817 struct nf_conn *ct;
774 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 818 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
775 u_int8_t u3 = nfmsg->nfgen_family; 819 u_int8_t u3 = nfmsg->nfgen_family;
776 int err = 0; 820 u16 zone;
821 int err;
822
823 err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
824 if (err < 0)
825 return err;
777 826
778 if (cda[CTA_TUPLE_ORIG]) 827 if (cda[CTA_TUPLE_ORIG])
779 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); 828 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
@@ -781,7 +830,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
781 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3); 830 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_REPLY, u3);
782 else { 831 else {
783 /* Flush the whole table */ 832 /* Flush the whole table */
784 nf_conntrack_flush_report(&init_net, 833 nf_conntrack_flush_report(net,
785 NETLINK_CB(skb).pid, 834 NETLINK_CB(skb).pid,
786 nlmsg_report(nlh)); 835 nlmsg_report(nlh));
787 return 0; 836 return 0;
@@ -790,7 +839,7 @@ ctnetlink_del_conntrack(struct sock *ctnl, struct sk_buff *skb,
790 if (err < 0) 839 if (err < 0)
791 return err; 840 return err;
792 841
793 h = nf_conntrack_find_get(&init_net, &tuple); 842 h = nf_conntrack_find_get(net, zone, &tuple);
794 if (!h) 843 if (!h)
795 return -ENOENT; 844 return -ENOENT;
796 845
@@ -828,18 +877,24 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
828 const struct nlmsghdr *nlh, 877 const struct nlmsghdr *nlh,
829 const struct nlattr * const cda[]) 878 const struct nlattr * const cda[])
830{ 879{
880 struct net *net = sock_net(ctnl);
831 struct nf_conntrack_tuple_hash *h; 881 struct nf_conntrack_tuple_hash *h;
832 struct nf_conntrack_tuple tuple; 882 struct nf_conntrack_tuple tuple;
833 struct nf_conn *ct; 883 struct nf_conn *ct;
834 struct sk_buff *skb2 = NULL; 884 struct sk_buff *skb2 = NULL;
835 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 885 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
836 u_int8_t u3 = nfmsg->nfgen_family; 886 u_int8_t u3 = nfmsg->nfgen_family;
837 int err = 0; 887 u16 zone;
888 int err;
838 889
839 if (nlh->nlmsg_flags & NLM_F_DUMP) 890 if (nlh->nlmsg_flags & NLM_F_DUMP)
840 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table, 891 return netlink_dump_start(ctnl, skb, nlh, ctnetlink_dump_table,
841 ctnetlink_done); 892 ctnetlink_done);
842 893
894 err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
895 if (err < 0)
896 return err;
897
843 if (cda[CTA_TUPLE_ORIG]) 898 if (cda[CTA_TUPLE_ORIG])
844 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3); 899 err = ctnetlink_parse_tuple(cda, &tuple, CTA_TUPLE_ORIG, u3);
845 else if (cda[CTA_TUPLE_REPLY]) 900 else if (cda[CTA_TUPLE_REPLY])
@@ -850,7 +905,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb,
850 if (err < 0) 905 if (err < 0)
851 return err; 906 return err;
852 907
853 h = nf_conntrack_find_get(&init_net, &tuple); 908 h = nf_conntrack_find_get(net, zone, &tuple);
854 if (!h) 909 if (!h)
855 return -ENOENT; 910 return -ENOENT;
856 911
@@ -994,7 +1049,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
994 return 0; 1049 return 0;
995 } 1050 }
996 1051
997 helper = __nf_conntrack_helper_find_byname(helpname); 1052 helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
1053 nf_ct_protonum(ct));
998 if (helper == NULL) { 1054 if (helper == NULL) {
999#ifdef CONFIG_MODULES 1055#ifdef CONFIG_MODULES
1000 spin_unlock_bh(&nf_conntrack_lock); 1056 spin_unlock_bh(&nf_conntrack_lock);
@@ -1005,7 +1061,8 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[])
1005 } 1061 }
1006 1062
1007 spin_lock_bh(&nf_conntrack_lock); 1063 spin_lock_bh(&nf_conntrack_lock);
1008 helper = __nf_conntrack_helper_find_byname(helpname); 1064 helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
1065 nf_ct_protonum(ct));
1009 if (helper) 1066 if (helper)
1010 return -EAGAIN; 1067 return -EAGAIN;
1011#endif 1068#endif
@@ -1044,6 +1101,12 @@ ctnetlink_change_timeout(struct nf_conn *ct, const struct nlattr * const cda[])
1044 return 0; 1101 return 0;
1045} 1102}
1046 1103
1104static const struct nla_policy protoinfo_policy[CTA_PROTOINFO_MAX+1] = {
1105 [CTA_PROTOINFO_TCP] = { .type = NLA_NESTED },
1106 [CTA_PROTOINFO_DCCP] = { .type = NLA_NESTED },
1107 [CTA_PROTOINFO_SCTP] = { .type = NLA_NESTED },
1108};
1109
1047static inline int 1110static inline int
1048ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]) 1111ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[])
1049{ 1112{
@@ -1052,7 +1115,7 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]
1052 struct nf_conntrack_l4proto *l4proto; 1115 struct nf_conntrack_l4proto *l4proto;
1053 int err = 0; 1116 int err = 0;
1054 1117
1055 nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, NULL); 1118 nla_parse_nested(tb, CTA_PROTOINFO_MAX, attr, protoinfo_policy);
1056 1119
1057 rcu_read_lock(); 1120 rcu_read_lock();
1058 l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); 1121 l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct));
@@ -1064,12 +1127,18 @@ ctnetlink_change_protoinfo(struct nf_conn *ct, const struct nlattr * const cda[]
1064} 1127}
1065 1128
1066#ifdef CONFIG_NF_NAT_NEEDED 1129#ifdef CONFIG_NF_NAT_NEEDED
1130static const struct nla_policy nat_seq_policy[CTA_NAT_SEQ_MAX+1] = {
1131 [CTA_NAT_SEQ_CORRECTION_POS] = { .type = NLA_U32 },
1132 [CTA_NAT_SEQ_OFFSET_BEFORE] = { .type = NLA_U32 },
1133 [CTA_NAT_SEQ_OFFSET_AFTER] = { .type = NLA_U32 },
1134};
1135
1067static inline int 1136static inline int
1068change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr) 1137change_nat_seq_adj(struct nf_nat_seq *natseq, const struct nlattr * const attr)
1069{ 1138{
1070 struct nlattr *cda[CTA_NAT_SEQ_MAX+1]; 1139 struct nlattr *cda[CTA_NAT_SEQ_MAX+1];
1071 1140
1072 nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, NULL); 1141 nla_parse_nested(cda, CTA_NAT_SEQ_MAX, attr, nat_seq_policy);
1073 1142
1074 if (!cda[CTA_NAT_SEQ_CORRECTION_POS]) 1143 if (!cda[CTA_NAT_SEQ_CORRECTION_POS])
1075 return -EINVAL; 1144 return -EINVAL;
@@ -1175,7 +1244,8 @@ ctnetlink_change_conntrack(struct nf_conn *ct,
1175} 1244}
1176 1245
1177static struct nf_conn * 1246static struct nf_conn *
1178ctnetlink_create_conntrack(const struct nlattr * const cda[], 1247ctnetlink_create_conntrack(struct net *net, u16 zone,
1248 const struct nlattr * const cda[],
1179 struct nf_conntrack_tuple *otuple, 1249 struct nf_conntrack_tuple *otuple,
1180 struct nf_conntrack_tuple *rtuple, 1250 struct nf_conntrack_tuple *rtuple,
1181 u8 u3) 1251 u8 u3)
@@ -1184,7 +1254,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1184 int err = -EINVAL; 1254 int err = -EINVAL;
1185 struct nf_conntrack_helper *helper; 1255 struct nf_conntrack_helper *helper;
1186 1256
1187 ct = nf_conntrack_alloc(&init_net, otuple, rtuple, GFP_ATOMIC); 1257 ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC);
1188 if (IS_ERR(ct)) 1258 if (IS_ERR(ct))
1189 return ERR_PTR(-ENOMEM); 1259 return ERR_PTR(-ENOMEM);
1190 1260
@@ -1203,7 +1273,8 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1203 if (err < 0) 1273 if (err < 0)
1204 goto err2; 1274 goto err2;
1205 1275
1206 helper = __nf_conntrack_helper_find_byname(helpname); 1276 helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct),
1277 nf_ct_protonum(ct));
1207 if (helper == NULL) { 1278 if (helper == NULL) {
1208 rcu_read_unlock(); 1279 rcu_read_unlock();
1209#ifdef CONFIG_MODULES 1280#ifdef CONFIG_MODULES
@@ -1213,7 +1284,9 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1213 } 1284 }
1214 1285
1215 rcu_read_lock(); 1286 rcu_read_lock();
1216 helper = __nf_conntrack_helper_find_byname(helpname); 1287 helper = __nf_conntrack_helper_find(helpname,
1288 nf_ct_l3num(ct),
1289 nf_ct_protonum(ct));
1217 if (helper) { 1290 if (helper) {
1218 err = -EAGAIN; 1291 err = -EAGAIN;
1219 goto err2; 1292 goto err2;
@@ -1236,7 +1309,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1236 } 1309 }
1237 } else { 1310 } else {
1238 /* try an implicit helper assignation */ 1311 /* try an implicit helper assignation */
1239 err = __nf_ct_try_assign_helper(ct, GFP_ATOMIC); 1312 err = __nf_ct_try_assign_helper(ct, NULL, GFP_ATOMIC);
1240 if (err < 0) 1313 if (err < 0)
1241 goto err2; 1314 goto err2;
1242 } 1315 }
@@ -1268,7 +1341,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1268 } 1341 }
1269 1342
1270 nf_ct_acct_ext_add(ct, GFP_ATOMIC); 1343 nf_ct_acct_ext_add(ct, GFP_ATOMIC);
1271 nf_ct_ecache_ext_add(ct, GFP_ATOMIC); 1344 nf_ct_ecache_ext_add(ct, 0, 0, GFP_ATOMIC);
1272 1345
1273#if defined(CONFIG_NF_CONNTRACK_MARK) 1346#if defined(CONFIG_NF_CONNTRACK_MARK)
1274 if (cda[CTA_MARK]) 1347 if (cda[CTA_MARK])
@@ -1285,7 +1358,7 @@ ctnetlink_create_conntrack(const struct nlattr * const cda[],
1285 if (err < 0) 1358 if (err < 0)
1286 goto err2; 1359 goto err2;
1287 1360
1288 master_h = nf_conntrack_find_get(&init_net, &master); 1361 master_h = nf_conntrack_find_get(net, zone, &master);
1289 if (master_h == NULL) { 1362 if (master_h == NULL) {
1290 err = -ENOENT; 1363 err = -ENOENT;
1291 goto err2; 1364 goto err2;
@@ -1313,11 +1386,17 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1313 const struct nlmsghdr *nlh, 1386 const struct nlmsghdr *nlh,
1314 const struct nlattr * const cda[]) 1387 const struct nlattr * const cda[])
1315{ 1388{
1389 struct net *net = sock_net(ctnl);
1316 struct nf_conntrack_tuple otuple, rtuple; 1390 struct nf_conntrack_tuple otuple, rtuple;
1317 struct nf_conntrack_tuple_hash *h = NULL; 1391 struct nf_conntrack_tuple_hash *h = NULL;
1318 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1392 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1319 u_int8_t u3 = nfmsg->nfgen_family; 1393 u_int8_t u3 = nfmsg->nfgen_family;
1320 int err = 0; 1394 u16 zone;
1395 int err;
1396
1397 err = ctnetlink_parse_zone(cda[CTA_ZONE], &zone);
1398 if (err < 0)
1399 return err;
1321 1400
1322 if (cda[CTA_TUPLE_ORIG]) { 1401 if (cda[CTA_TUPLE_ORIG]) {
1323 err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3); 1402 err = ctnetlink_parse_tuple(cda, &otuple, CTA_TUPLE_ORIG, u3);
@@ -1333,9 +1412,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1333 1412
1334 spin_lock_bh(&nf_conntrack_lock); 1413 spin_lock_bh(&nf_conntrack_lock);
1335 if (cda[CTA_TUPLE_ORIG]) 1414 if (cda[CTA_TUPLE_ORIG])
1336 h = __nf_conntrack_find(&init_net, &otuple); 1415 h = __nf_conntrack_find(net, zone, &otuple);
1337 else if (cda[CTA_TUPLE_REPLY]) 1416 else if (cda[CTA_TUPLE_REPLY])
1338 h = __nf_conntrack_find(&init_net, &rtuple); 1417 h = __nf_conntrack_find(net, zone, &rtuple);
1339 1418
1340 if (h == NULL) { 1419 if (h == NULL) {
1341 err = -ENOENT; 1420 err = -ENOENT;
@@ -1343,7 +1422,7 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1343 struct nf_conn *ct; 1422 struct nf_conn *ct;
1344 enum ip_conntrack_events events; 1423 enum ip_conntrack_events events;
1345 1424
1346 ct = ctnetlink_create_conntrack(cda, &otuple, 1425 ct = ctnetlink_create_conntrack(net, zone, cda, &otuple,
1347 &rtuple, u3); 1426 &rtuple, u3);
1348 if (IS_ERR(ct)) { 1427 if (IS_ERR(ct)) {
1349 err = PTR_ERR(ct); 1428 err = PTR_ERR(ct);
@@ -1357,7 +1436,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1357 else 1436 else
1358 events = IPCT_NEW; 1437 events = IPCT_NEW;
1359 1438
1360 nf_conntrack_eventmask_report((1 << IPCT_STATUS) | 1439 nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
1440 (1 << IPCT_ASSURED) |
1361 (1 << IPCT_HELPER) | 1441 (1 << IPCT_HELPER) |
1362 (1 << IPCT_PROTOINFO) | 1442 (1 << IPCT_PROTOINFO) |
1363 (1 << IPCT_NATSEQADJ) | 1443 (1 << IPCT_NATSEQADJ) |
@@ -1382,7 +1462,8 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb,
1382 if (err == 0) { 1462 if (err == 0) {
1383 nf_conntrack_get(&ct->ct_general); 1463 nf_conntrack_get(&ct->ct_general);
1384 spin_unlock_bh(&nf_conntrack_lock); 1464 spin_unlock_bh(&nf_conntrack_lock);
1385 nf_conntrack_eventmask_report((1 << IPCT_STATUS) | 1465 nf_conntrack_eventmask_report((1 << IPCT_REPLY) |
1466 (1 << IPCT_ASSURED) |
1386 (1 << IPCT_HELPER) | 1467 (1 << IPCT_HELPER) |
1387 (1 << IPCT_PROTOINFO) | 1468 (1 << IPCT_PROTOINFO) |
1388 (1 << IPCT_NATSEQADJ) | 1469 (1 << IPCT_NATSEQADJ) |
@@ -1469,6 +1550,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1469 const struct nf_conntrack_expect *exp) 1550 const struct nf_conntrack_expect *exp)
1470{ 1551{
1471 struct nf_conn *master = exp->master; 1552 struct nf_conn *master = exp->master;
1553 struct nf_conntrack_helper *helper;
1472 long timeout = (exp->timeout.expires - jiffies) / HZ; 1554 long timeout = (exp->timeout.expires - jiffies) / HZ;
1473 1555
1474 if (timeout < 0) 1556 if (timeout < 0)
@@ -1485,6 +1567,9 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
1485 1567
1486 NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout)); 1568 NLA_PUT_BE32(skb, CTA_EXPECT_TIMEOUT, htonl(timeout));
1487 NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp)); 1569 NLA_PUT_BE32(skb, CTA_EXPECT_ID, htonl((unsigned long)exp));
1570 helper = rcu_dereference(nfct_help(master)->helper);
1571 if (helper)
1572 NLA_PUT_STRING(skb, CTA_EXPECT_HELP_NAME, helper->name);
1488 1573
1489 return 0; 1574 return 0;
1490 1575
@@ -1526,9 +1611,10 @@ nla_put_failure:
1526static int 1611static int
1527ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item) 1612ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
1528{ 1613{
1614 struct nf_conntrack_expect *exp = item->exp;
1615 struct net *net = nf_ct_exp_net(exp);
1529 struct nlmsghdr *nlh; 1616 struct nlmsghdr *nlh;
1530 struct nfgenmsg *nfmsg; 1617 struct nfgenmsg *nfmsg;
1531 struct nf_conntrack_expect *exp = item->exp;
1532 struct sk_buff *skb; 1618 struct sk_buff *skb;
1533 unsigned int type; 1619 unsigned int type;
1534 int flags = 0; 1620 int flags = 0;
@@ -1540,7 +1626,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
1540 return 0; 1626 return 0;
1541 1627
1542 if (!item->report && 1628 if (!item->report &&
1543 !nfnetlink_has_listeners(NFNLGRP_CONNTRACK_EXP_NEW)) 1629 !nfnetlink_has_listeners(net, NFNLGRP_CONNTRACK_EXP_NEW))
1544 return 0; 1630 return 0;
1545 1631
1546 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC); 1632 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
@@ -1563,7 +1649,7 @@ ctnetlink_expect_event(unsigned int events, struct nf_exp_event *item)
1563 rcu_read_unlock(); 1649 rcu_read_unlock();
1564 1650
1565 nlmsg_end(skb, nlh); 1651 nlmsg_end(skb, nlh);
1566 nfnetlink_send(skb, item->pid, NFNLGRP_CONNTRACK_EXP_NEW, 1652 nfnetlink_send(skb, net, item->pid, NFNLGRP_CONNTRACK_EXP_NEW,
1567 item->report, GFP_ATOMIC); 1653 item->report, GFP_ATOMIC);
1568 return 0; 1654 return 0;
1569 1655
@@ -1573,7 +1659,7 @@ nla_put_failure:
1573nlmsg_failure: 1659nlmsg_failure:
1574 kfree_skb(skb); 1660 kfree_skb(skb);
1575errout: 1661errout:
1576 nfnetlink_set_err(0, 0, -ENOBUFS); 1662 nfnetlink_set_err(net, 0, 0, -ENOBUFS);
1577 return 0; 1663 return 0;
1578} 1664}
1579#endif 1665#endif
@@ -1587,7 +1673,7 @@ static int ctnetlink_exp_done(struct netlink_callback *cb)
1587static int 1673static int
1588ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb) 1674ctnetlink_exp_dump_table(struct sk_buff *skb, struct netlink_callback *cb)
1589{ 1675{
1590 struct net *net = &init_net; 1676 struct net *net = sock_net(skb->sk);
1591 struct nf_conntrack_expect *exp, *last; 1677 struct nf_conntrack_expect *exp, *last;
1592 struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); 1678 struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh);
1593 struct hlist_node *n; 1679 struct hlist_node *n;
@@ -1631,8 +1717,12 @@ out:
1631} 1717}
1632 1718
1633static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = { 1719static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {
1720 [CTA_EXPECT_MASTER] = { .type = NLA_NESTED },
1721 [CTA_EXPECT_TUPLE] = { .type = NLA_NESTED },
1722 [CTA_EXPECT_MASK] = { .type = NLA_NESTED },
1634 [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 }, 1723 [CTA_EXPECT_TIMEOUT] = { .type = NLA_U32 },
1635 [CTA_EXPECT_ID] = { .type = NLA_U32 }, 1724 [CTA_EXPECT_ID] = { .type = NLA_U32 },
1725 [CTA_EXPECT_HELP_NAME] = { .type = NLA_NUL_STRING },
1636}; 1726};
1637 1727
1638static int 1728static int
@@ -1640,12 +1730,14 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1640 const struct nlmsghdr *nlh, 1730 const struct nlmsghdr *nlh,
1641 const struct nlattr * const cda[]) 1731 const struct nlattr * const cda[])
1642{ 1732{
1733 struct net *net = sock_net(ctnl);
1643 struct nf_conntrack_tuple tuple; 1734 struct nf_conntrack_tuple tuple;
1644 struct nf_conntrack_expect *exp; 1735 struct nf_conntrack_expect *exp;
1645 struct sk_buff *skb2; 1736 struct sk_buff *skb2;
1646 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1737 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1647 u_int8_t u3 = nfmsg->nfgen_family; 1738 u_int8_t u3 = nfmsg->nfgen_family;
1648 int err = 0; 1739 u16 zone;
1740 int err;
1649 1741
1650 if (nlh->nlmsg_flags & NLM_F_DUMP) { 1742 if (nlh->nlmsg_flags & NLM_F_DUMP) {
1651 return netlink_dump_start(ctnl, skb, nlh, 1743 return netlink_dump_start(ctnl, skb, nlh,
@@ -1653,6 +1745,10 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1653 ctnetlink_exp_done); 1745 ctnetlink_exp_done);
1654 } 1746 }
1655 1747
1748 err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
1749 if (err < 0)
1750 return err;
1751
1656 if (cda[CTA_EXPECT_MASTER]) 1752 if (cda[CTA_EXPECT_MASTER])
1657 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3); 1753 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3);
1658 else 1754 else
@@ -1661,7 +1757,7 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb,
1661 if (err < 0) 1757 if (err < 0)
1662 return err; 1758 return err;
1663 1759
1664 exp = nf_ct_expect_find_get(&init_net, &tuple); 1760 exp = nf_ct_expect_find_get(net, zone, &tuple);
1665 if (!exp) 1761 if (!exp)
1666 return -ENOENT; 1762 return -ENOENT;
1667 1763
@@ -1701,23 +1797,28 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1701 const struct nlmsghdr *nlh, 1797 const struct nlmsghdr *nlh,
1702 const struct nlattr * const cda[]) 1798 const struct nlattr * const cda[])
1703{ 1799{
1800 struct net *net = sock_net(ctnl);
1704 struct nf_conntrack_expect *exp; 1801 struct nf_conntrack_expect *exp;
1705 struct nf_conntrack_tuple tuple; 1802 struct nf_conntrack_tuple tuple;
1706 struct nf_conntrack_helper *h;
1707 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1803 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1708 struct hlist_node *n, *next; 1804 struct hlist_node *n, *next;
1709 u_int8_t u3 = nfmsg->nfgen_family; 1805 u_int8_t u3 = nfmsg->nfgen_family;
1710 unsigned int i; 1806 unsigned int i;
1807 u16 zone;
1711 int err; 1808 int err;
1712 1809
1713 if (cda[CTA_EXPECT_TUPLE]) { 1810 if (cda[CTA_EXPECT_TUPLE]) {
1714 /* delete a single expect by tuple */ 1811 /* delete a single expect by tuple */
1812 err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
1813 if (err < 0)
1814 return err;
1815
1715 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); 1816 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1716 if (err < 0) 1817 if (err < 0)
1717 return err; 1818 return err;
1718 1819
1719 /* bump usage count to 2 */ 1820 /* bump usage count to 2 */
1720 exp = nf_ct_expect_find_get(&init_net, &tuple); 1821 exp = nf_ct_expect_find_get(net, zone, &tuple);
1721 if (!exp) 1822 if (!exp)
1722 return -ENOENT; 1823 return -ENOENT;
1723 1824
@@ -1740,18 +1841,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1740 1841
1741 /* delete all expectations for this helper */ 1842 /* delete all expectations for this helper */
1742 spin_lock_bh(&nf_conntrack_lock); 1843 spin_lock_bh(&nf_conntrack_lock);
1743 h = __nf_conntrack_helper_find_byname(name);
1744 if (!h) {
1745 spin_unlock_bh(&nf_conntrack_lock);
1746 return -EOPNOTSUPP;
1747 }
1748 for (i = 0; i < nf_ct_expect_hsize; i++) { 1844 for (i = 0; i < nf_ct_expect_hsize; i++) {
1749 hlist_for_each_entry_safe(exp, n, next, 1845 hlist_for_each_entry_safe(exp, n, next,
1750 &init_net.ct.expect_hash[i], 1846 &net->ct.expect_hash[i],
1751 hnode) { 1847 hnode) {
1752 m_help = nfct_help(exp->master); 1848 m_help = nfct_help(exp->master);
1753 if (m_help->helper == h 1849 if (!strcmp(m_help->helper->name, name) &&
1754 && del_timer(&exp->timeout)) { 1850 del_timer(&exp->timeout)) {
1755 nf_ct_unlink_expect(exp); 1851 nf_ct_unlink_expect(exp);
1756 nf_ct_expect_put(exp); 1852 nf_ct_expect_put(exp);
1757 } 1853 }
@@ -1763,7 +1859,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb,
1763 spin_lock_bh(&nf_conntrack_lock); 1859 spin_lock_bh(&nf_conntrack_lock);
1764 for (i = 0; i < nf_ct_expect_hsize; i++) { 1860 for (i = 0; i < nf_ct_expect_hsize; i++) {
1765 hlist_for_each_entry_safe(exp, n, next, 1861 hlist_for_each_entry_safe(exp, n, next,
1766 &init_net.ct.expect_hash[i], 1862 &net->ct.expect_hash[i],
1767 hnode) { 1863 hnode) {
1768 if (del_timer(&exp->timeout)) { 1864 if (del_timer(&exp->timeout)) {
1769 nf_ct_unlink_expect(exp); 1865 nf_ct_unlink_expect(exp);
@@ -1784,7 +1880,9 @@ ctnetlink_change_expect(struct nf_conntrack_expect *x,
1784} 1880}
1785 1881
1786static int 1882static int
1787ctnetlink_create_expect(const struct nlattr * const cda[], u_int8_t u3, 1883ctnetlink_create_expect(struct net *net, u16 zone,
1884 const struct nlattr * const cda[],
1885 u_int8_t u3,
1788 u32 pid, int report) 1886 u32 pid, int report)
1789{ 1887{
1790 struct nf_conntrack_tuple tuple, mask, master_tuple; 1888 struct nf_conntrack_tuple tuple, mask, master_tuple;
@@ -1806,7 +1904,7 @@ ctnetlink_create_expect(const struct nlattr * const cda[], u_int8_t u3,
1806 return err; 1904 return err;
1807 1905
1808 /* Look for master conntrack of this expectation */ 1906 /* Look for master conntrack of this expectation */
1809 h = nf_conntrack_find_get(&init_net, &master_tuple); 1907 h = nf_conntrack_find_get(net, zone, &master_tuple);
1810 if (!h) 1908 if (!h)
1811 return -ENOENT; 1909 return -ENOENT;
1812 ct = nf_ct_tuplehash_to_ctrack(h); 1910 ct = nf_ct_tuplehash_to_ctrack(h);
@@ -1846,29 +1944,35 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb,
1846 const struct nlmsghdr *nlh, 1944 const struct nlmsghdr *nlh,
1847 const struct nlattr * const cda[]) 1945 const struct nlattr * const cda[])
1848{ 1946{
1947 struct net *net = sock_net(ctnl);
1849 struct nf_conntrack_tuple tuple; 1948 struct nf_conntrack_tuple tuple;
1850 struct nf_conntrack_expect *exp; 1949 struct nf_conntrack_expect *exp;
1851 struct nfgenmsg *nfmsg = nlmsg_data(nlh); 1950 struct nfgenmsg *nfmsg = nlmsg_data(nlh);
1852 u_int8_t u3 = nfmsg->nfgen_family; 1951 u_int8_t u3 = nfmsg->nfgen_family;
1853 int err = 0; 1952 u16 zone;
1953 int err;
1854 1954
1855 if (!cda[CTA_EXPECT_TUPLE] 1955 if (!cda[CTA_EXPECT_TUPLE]
1856 || !cda[CTA_EXPECT_MASK] 1956 || !cda[CTA_EXPECT_MASK]
1857 || !cda[CTA_EXPECT_MASTER]) 1957 || !cda[CTA_EXPECT_MASTER])
1858 return -EINVAL; 1958 return -EINVAL;
1859 1959
1960 err = ctnetlink_parse_zone(cda[CTA_EXPECT_ZONE], &zone);
1961 if (err < 0)
1962 return err;
1963
1860 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); 1964 err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3);
1861 if (err < 0) 1965 if (err < 0)
1862 return err; 1966 return err;
1863 1967
1864 spin_lock_bh(&nf_conntrack_lock); 1968 spin_lock_bh(&nf_conntrack_lock);
1865 exp = __nf_ct_expect_find(&init_net, &tuple); 1969 exp = __nf_ct_expect_find(net, zone, &tuple);
1866 1970
1867 if (!exp) { 1971 if (!exp) {
1868 spin_unlock_bh(&nf_conntrack_lock); 1972 spin_unlock_bh(&nf_conntrack_lock);
1869 err = -ENOENT; 1973 err = -ENOENT;
1870 if (nlh->nlmsg_flags & NLM_F_CREATE) { 1974 if (nlh->nlmsg_flags & NLM_F_CREATE) {
1871 err = ctnetlink_create_expect(cda, 1975 err = ctnetlink_create_expect(net, zone, cda,
1872 u3, 1976 u3,
1873 NETLINK_CB(skb).pid, 1977 NETLINK_CB(skb).pid,
1874 nlmsg_report(nlh)); 1978 nlmsg_report(nlh));
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c
index 3807ac7faf4c..088944824e13 100644
--- a/net/netfilter/nf_conntrack_pptp.c
+++ b/net/netfilter/nf_conntrack_pptp.c
@@ -28,6 +28,7 @@
28#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack.h>
29#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_core.h>
30#include <net/netfilter/nf_conntrack_helper.h> 30#include <net/netfilter/nf_conntrack_helper.h>
31#include <net/netfilter/nf_conntrack_zones.h>
31#include <linux/netfilter/nf_conntrack_proto_gre.h> 32#include <linux/netfilter/nf_conntrack_proto_gre.h>
32#include <linux/netfilter/nf_conntrack_pptp.h> 33#include <linux/netfilter/nf_conntrack_pptp.h>
33 34
@@ -123,7 +124,7 @@ static void pptp_expectfn(struct nf_conn *ct,
123 pr_debug("trying to unexpect other dir: "); 124 pr_debug("trying to unexpect other dir: ");
124 nf_ct_dump_tuple(&inv_t); 125 nf_ct_dump_tuple(&inv_t);
125 126
126 exp_other = nf_ct_expect_find_get(net, &inv_t); 127 exp_other = nf_ct_expect_find_get(net, nf_ct_zone(ct), &inv_t);
127 if (exp_other) { 128 if (exp_other) {
128 /* delete other expectation. */ 129 /* delete other expectation. */
129 pr_debug("found\n"); 130 pr_debug("found\n");
@@ -136,17 +137,18 @@ static void pptp_expectfn(struct nf_conn *ct,
136 rcu_read_unlock(); 137 rcu_read_unlock();
137} 138}
138 139
139static int destroy_sibling_or_exp(struct net *net, 140static int destroy_sibling_or_exp(struct net *net, struct nf_conn *ct,
140 const struct nf_conntrack_tuple *t) 141 const struct nf_conntrack_tuple *t)
141{ 142{
142 const struct nf_conntrack_tuple_hash *h; 143 const struct nf_conntrack_tuple_hash *h;
143 struct nf_conntrack_expect *exp; 144 struct nf_conntrack_expect *exp;
144 struct nf_conn *sibling; 145 struct nf_conn *sibling;
146 u16 zone = nf_ct_zone(ct);
145 147
146 pr_debug("trying to timeout ct or exp for tuple "); 148 pr_debug("trying to timeout ct or exp for tuple ");
147 nf_ct_dump_tuple(t); 149 nf_ct_dump_tuple(t);
148 150
149 h = nf_conntrack_find_get(net, t); 151 h = nf_conntrack_find_get(net, zone, t);
150 if (h) { 152 if (h) {
151 sibling = nf_ct_tuplehash_to_ctrack(h); 153 sibling = nf_ct_tuplehash_to_ctrack(h);
152 pr_debug("setting timeout of conntrack %p to 0\n", sibling); 154 pr_debug("setting timeout of conntrack %p to 0\n", sibling);
@@ -157,7 +159,7 @@ static int destroy_sibling_or_exp(struct net *net,
157 nf_ct_put(sibling); 159 nf_ct_put(sibling);
158 return 1; 160 return 1;
159 } else { 161 } else {
160 exp = nf_ct_expect_find_get(net, t); 162 exp = nf_ct_expect_find_get(net, zone, t);
161 if (exp) { 163 if (exp) {
162 pr_debug("unexpect_related of expect %p\n", exp); 164 pr_debug("unexpect_related of expect %p\n", exp);
163 nf_ct_unexpect_related(exp); 165 nf_ct_unexpect_related(exp);
@@ -182,7 +184,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
182 t.dst.protonum = IPPROTO_GRE; 184 t.dst.protonum = IPPROTO_GRE;
183 t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id; 185 t.src.u.gre.key = help->help.ct_pptp_info.pns_call_id;
184 t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id; 186 t.dst.u.gre.key = help->help.ct_pptp_info.pac_call_id;
185 if (!destroy_sibling_or_exp(net, &t)) 187 if (!destroy_sibling_or_exp(net, ct, &t))
186 pr_debug("failed to timeout original pns->pac ct/exp\n"); 188 pr_debug("failed to timeout original pns->pac ct/exp\n");
187 189
188 /* try reply (pac->pns) tuple */ 190 /* try reply (pac->pns) tuple */
@@ -190,7 +192,7 @@ static void pptp_destroy_siblings(struct nf_conn *ct)
190 t.dst.protonum = IPPROTO_GRE; 192 t.dst.protonum = IPPROTO_GRE;
191 t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id; 193 t.src.u.gre.key = help->help.ct_pptp_info.pac_call_id;
192 t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id; 194 t.dst.u.gre.key = help->help.ct_pptp_info.pns_call_id;
193 if (!destroy_sibling_or_exp(net, &t)) 195 if (!destroy_sibling_or_exp(net, ct, &t))
194 pr_debug("failed to timeout reply pac->pns ct/exp\n"); 196 pr_debug("failed to timeout reply pac->pns ct/exp\n");
195} 197}
196 198
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c
index dd375500dccc..9a2815549375 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -561,8 +561,9 @@ static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
561 return NF_ACCEPT; 561 return NF_ACCEPT;
562} 562}
563 563
564static int dccp_error(struct net *net, struct sk_buff *skb, 564static int dccp_error(struct net *net, struct nf_conn *tmpl,
565 unsigned int dataoff, enum ip_conntrack_info *ctinfo, 565 struct sk_buff *skb, unsigned int dataoff,
566 enum ip_conntrack_info *ctinfo,
566 u_int8_t pf, unsigned int hooknum) 567 u_int8_t pf, unsigned int hooknum)
567{ 568{
568 struct dccp_hdr _dh, *dh; 569 struct dccp_hdr _dh, *dh;
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c
index c99cfba64ddc..d899b1a69940 100644
--- a/net/netfilter/nf_conntrack_proto_gre.c
+++ b/net/netfilter/nf_conntrack_proto_gre.c
@@ -241,7 +241,7 @@ static int gre_packet(struct nf_conn *ct,
241 ct->proto.gre.stream_timeout); 241 ct->proto.gre.stream_timeout);
242 /* Also, more likely to be important, and not a probe. */ 242 /* Also, more likely to be important, and not a probe. */
243 set_bit(IPS_ASSURED_BIT, &ct->status); 243 set_bit(IPS_ASSURED_BIT, &ct->status);
244 nf_conntrack_event_cache(IPCT_STATUS, ct); 244 nf_conntrack_event_cache(IPCT_ASSURED, ct);
245 } else 245 } else
246 nf_ct_refresh_acct(ct, ctinfo, skb, 246 nf_ct_refresh_acct(ct, ctinfo, skb,
247 ct->proto.gre.timeout); 247 ct->proto.gre.timeout);
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c
index f9d930f80276..b68ff15ed979 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -377,7 +377,7 @@ static int sctp_packet(struct nf_conn *ct,
377 new_state == SCTP_CONNTRACK_ESTABLISHED) { 377 new_state == SCTP_CONNTRACK_ESTABLISHED) {
378 pr_debug("Setting assured bit\n"); 378 pr_debug("Setting assured bit\n");
379 set_bit(IPS_ASSURED_BIT, &ct->status); 379 set_bit(IPS_ASSURED_BIT, &ct->status);
380 nf_conntrack_event_cache(IPCT_STATUS, ct); 380 nf_conntrack_event_cache(IPCT_ASSURED, ct);
381 } 381 }
382 382
383 return NF_ACCEPT; 383 return NF_ACCEPT;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c
index 3c96437b45ad..9dd8cd4fb6e6 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -760,7 +760,7 @@ static const u8 tcp_valid_flags[(TH_FIN|TH_SYN|TH_RST|TH_ACK|TH_URG) + 1] =
760}; 760};
761 761
762/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */ 762/* Protect conntrack agaist broken packets. Code taken from ipt_unclean.c. */
763static int tcp_error(struct net *net, 763static int tcp_error(struct net *net, struct nf_conn *tmpl,
764 struct sk_buff *skb, 764 struct sk_buff *skb,
765 unsigned int dataoff, 765 unsigned int dataoff,
766 enum ip_conntrack_info *ctinfo, 766 enum ip_conntrack_info *ctinfo,
@@ -1045,7 +1045,7 @@ static int tcp_packet(struct nf_conn *ct,
1045 after SYN_RECV or a valid answer for a picked up 1045 after SYN_RECV or a valid answer for a picked up
1046 connection. */ 1046 connection. */
1047 set_bit(IPS_ASSURED_BIT, &ct->status); 1047 set_bit(IPS_ASSURED_BIT, &ct->status);
1048 nf_conntrack_event_cache(IPCT_STATUS, ct); 1048 nf_conntrack_event_cache(IPCT_ASSURED, ct);
1049 } 1049 }
1050 nf_ct_refresh_acct(ct, ctinfo, skb, timeout); 1050 nf_ct_refresh_acct(ct, ctinfo, skb, timeout);
1051 1051
diff --git a/net/netfilter/nf_conntrack_proto_udp.c b/net/netfilter/nf_conntrack_proto_udp.c
index 5c5518bedb4b..8289088b8218 100644
--- a/net/netfilter/nf_conntrack_proto_udp.c
+++ b/net/netfilter/nf_conntrack_proto_udp.c
@@ -77,7 +77,7 @@ static int udp_packet(struct nf_conn *ct,
77 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream); 77 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout_stream);
78 /* Also, more likely to be important, and not a probe */ 78 /* Also, more likely to be important, and not a probe */
79 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) 79 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
80 nf_conntrack_event_cache(IPCT_STATUS, ct); 80 nf_conntrack_event_cache(IPCT_ASSURED, ct);
81 } else 81 } else
82 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout); 82 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udp_timeout);
83 83
@@ -91,8 +91,8 @@ static bool udp_new(struct nf_conn *ct, const struct sk_buff *skb,
91 return true; 91 return true;
92} 92}
93 93
94static int udp_error(struct net *net, struct sk_buff *skb, unsigned int dataoff, 94static int udp_error(struct net *net, struct nf_conn *tmpl, struct sk_buff *skb,
95 enum ip_conntrack_info *ctinfo, 95 unsigned int dataoff, enum ip_conntrack_info *ctinfo,
96 u_int8_t pf, 96 u_int8_t pf,
97 unsigned int hooknum) 97 unsigned int hooknum)
98{ 98{
diff --git a/net/netfilter/nf_conntrack_proto_udplite.c b/net/netfilter/nf_conntrack_proto_udplite.c
index 458655bb2106..263b5a72588d 100644
--- a/net/netfilter/nf_conntrack_proto_udplite.c
+++ b/net/netfilter/nf_conntrack_proto_udplite.c
@@ -75,7 +75,7 @@ static int udplite_packet(struct nf_conn *ct,
75 nf_ct_udplite_timeout_stream); 75 nf_ct_udplite_timeout_stream);
76 /* Also, more likely to be important, and not a probe */ 76 /* Also, more likely to be important, and not a probe */
77 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status)) 77 if (!test_and_set_bit(IPS_ASSURED_BIT, &ct->status))
78 nf_conntrack_event_cache(IPCT_STATUS, ct); 78 nf_conntrack_event_cache(IPCT_ASSURED, ct);
79 } else 79 } else
80 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout); 80 nf_ct_refresh_acct(ct, ctinfo, skb, nf_ct_udplite_timeout);
81 81
@@ -89,7 +89,7 @@ static bool udplite_new(struct nf_conn *ct, const struct sk_buff *skb,
89 return true; 89 return true;
90} 90}
91 91
92static int udplite_error(struct net *net, 92static int udplite_error(struct net *net, struct nf_conn *tmpl,
93 struct sk_buff *skb, 93 struct sk_buff *skb,
94 unsigned int dataoff, 94 unsigned int dataoff,
95 enum ip_conntrack_info *ctinfo, 95 enum ip_conntrack_info *ctinfo,
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c
index 023966b569bf..8dd75d90efc0 100644
--- a/net/netfilter/nf_conntrack_sip.c
+++ b/net/netfilter/nf_conntrack_sip.c
@@ -16,12 +16,14 @@
16#include <linux/inet.h> 16#include <linux/inet.h>
17#include <linux/in.h> 17#include <linux/in.h>
18#include <linux/udp.h> 18#include <linux/udp.h>
19#include <linux/tcp.h>
19#include <linux/netfilter.h> 20#include <linux/netfilter.h>
20 21
21#include <net/netfilter/nf_conntrack.h> 22#include <net/netfilter/nf_conntrack.h>
22#include <net/netfilter/nf_conntrack_core.h> 23#include <net/netfilter/nf_conntrack_core.h>
23#include <net/netfilter/nf_conntrack_expect.h> 24#include <net/netfilter/nf_conntrack_expect.h>
24#include <net/netfilter/nf_conntrack_helper.h> 25#include <net/netfilter/nf_conntrack_helper.h>
26#include <net/netfilter/nf_conntrack_zones.h>
25#include <linux/netfilter/nf_conntrack_sip.h> 27#include <linux/netfilter/nf_conntrack_sip.h>
26 28
27MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
@@ -50,12 +52,16 @@ module_param(sip_direct_media, int, 0600);
50MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " 52MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling "
51 "endpoints only (default 1)"); 53 "endpoints only (default 1)");
52 54
53unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, 55unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff,
54 const char **dptr, 56 const char **dptr,
55 unsigned int *datalen) __read_mostly; 57 unsigned int *datalen) __read_mostly;
56EXPORT_SYMBOL_GPL(nf_nat_sip_hook); 58EXPORT_SYMBOL_GPL(nf_nat_sip_hook);
57 59
60void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly;
61EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook);
62
58unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, 63unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
64 unsigned int dataoff,
59 const char **dptr, 65 const char **dptr,
60 unsigned int *datalen, 66 unsigned int *datalen,
61 struct nf_conntrack_expect *exp, 67 struct nf_conntrack_expect *exp,
@@ -63,17 +69,17 @@ unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
63 unsigned int matchlen) __read_mostly; 69 unsigned int matchlen) __read_mostly;
64EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); 70EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook);
65 71
66unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, 72unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff,
67 const char **dptr, 73 const char **dptr,
68 unsigned int dataoff,
69 unsigned int *datalen, 74 unsigned int *datalen,
75 unsigned int sdpoff,
70 enum sdp_header_types type, 76 enum sdp_header_types type,
71 enum sdp_header_types term, 77 enum sdp_header_types term,
72 const union nf_inet_addr *addr) 78 const union nf_inet_addr *addr)
73 __read_mostly; 79 __read_mostly;
74EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); 80EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook);
75 81
76unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, 82unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff,
77 const char **dptr, 83 const char **dptr,
78 unsigned int *datalen, 84 unsigned int *datalen,
79 unsigned int matchoff, 85 unsigned int matchoff,
@@ -82,14 +88,15 @@ unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
82EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); 88EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook);
83 89
84unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, 90unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
85 const char **dptr,
86 unsigned int dataoff, 91 unsigned int dataoff,
92 const char **dptr,
87 unsigned int *datalen, 93 unsigned int *datalen,
94 unsigned int sdpoff,
88 const union nf_inet_addr *addr) 95 const union nf_inet_addr *addr)
89 __read_mostly; 96 __read_mostly;
90EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); 97EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook);
91 98
92unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, 99unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff,
93 const char **dptr, 100 const char **dptr,
94 unsigned int *datalen, 101 unsigned int *datalen,
95 struct nf_conntrack_expect *rtp_exp, 102 struct nf_conntrack_expect *rtp_exp,
@@ -236,12 +243,13 @@ int ct_sip_parse_request(const struct nf_conn *ct,
236 return 0; 243 return 0;
237 244
238 /* Find SIP URI */ 245 /* Find SIP URI */
239 limit -= strlen("sip:"); 246 for (; dptr < limit - strlen("sip:"); dptr++) {
240 for (; dptr < limit; dptr++) {
241 if (*dptr == '\r' || *dptr == '\n') 247 if (*dptr == '\r' || *dptr == '\n')
242 return -1; 248 return -1;
243 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) 249 if (strnicmp(dptr, "sip:", strlen("sip:")) == 0) {
250 dptr += strlen("sip:");
244 break; 251 break;
252 }
245 } 253 }
246 if (!skp_epaddr_len(ct, dptr, limit, &shift)) 254 if (!skp_epaddr_len(ct, dptr, limit, &shift))
247 return 0; 255 return 0;
@@ -284,7 +292,8 @@ static const struct sip_header ct_sip_hdrs[] = {
284 [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len), 292 [SIP_HDR_FROM] = SIP_HDR("From", "f", "sip:", skp_epaddr_len),
285 [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len), 293 [SIP_HDR_TO] = SIP_HDR("To", "t", "sip:", skp_epaddr_len),
286 [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len), 294 [SIP_HDR_CONTACT] = SIP_HDR("Contact", "m", "sip:", skp_epaddr_len),
287 [SIP_HDR_VIA] = SIP_HDR("Via", "v", "UDP ", epaddr_len), 295 [SIP_HDR_VIA_UDP] = SIP_HDR("Via", "v", "UDP ", epaddr_len),
296 [SIP_HDR_VIA_TCP] = SIP_HDR("Via", "v", "TCP ", epaddr_len),
288 [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len), 297 [SIP_HDR_EXPIRES] = SIP_HDR("Expires", NULL, NULL, digits_len),
289 [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len), 298 [SIP_HDR_CONTENT_LENGTH] = SIP_HDR("Content-Length", "l", NULL, digits_len),
290}; 299};
@@ -516,6 +525,33 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr,
516} 525}
517EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri); 526EXPORT_SYMBOL_GPL(ct_sip_parse_header_uri);
518 527
528static int ct_sip_parse_param(const struct nf_conn *ct, const char *dptr,
529 unsigned int dataoff, unsigned int datalen,
530 const char *name,
531 unsigned int *matchoff, unsigned int *matchlen)
532{
533 const char *limit = dptr + datalen;
534 const char *start;
535 const char *end;
536
537 limit = ct_sip_header_search(dptr + dataoff, limit, ",", strlen(","));
538 if (!limit)
539 limit = dptr + datalen;
540
541 start = ct_sip_header_search(dptr + dataoff, limit, name, strlen(name));
542 if (!start)
543 return 0;
544 start += strlen(name);
545
546 end = ct_sip_header_search(start, limit, ";", strlen(";"));
547 if (!end)
548 end = limit;
549
550 *matchoff = start - dptr;
551 *matchlen = end - start;
552 return 1;
553}
554
519/* Parse address from header parameter and return address, offset and length */ 555/* Parse address from header parameter and return address, offset and length */
520int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, 556int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr,
521 unsigned int dataoff, unsigned int datalen, 557 unsigned int dataoff, unsigned int datalen,
@@ -574,6 +610,29 @@ int ct_sip_parse_numerical_param(const struct nf_conn *ct, const char *dptr,
574} 610}
575EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param); 611EXPORT_SYMBOL_GPL(ct_sip_parse_numerical_param);
576 612
613static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr,
614 unsigned int dataoff, unsigned int datalen,
615 u8 *proto)
616{
617 unsigned int matchoff, matchlen;
618
619 if (ct_sip_parse_param(ct, dptr, dataoff, datalen, "transport=",
620 &matchoff, &matchlen)) {
621 if (!strnicmp(dptr + matchoff, "TCP", strlen("TCP")))
622 *proto = IPPROTO_TCP;
623 else if (!strnicmp(dptr + matchoff, "UDP", strlen("UDP")))
624 *proto = IPPROTO_UDP;
625 else
626 return 0;
627
628 if (*proto != nf_ct_protonum(ct))
629 return 0;
630 } else
631 *proto = nf_ct_protonum(ct);
632
633 return 1;
634}
635
577/* SDP header parsing: a SDP session description contains an ordered set of 636/* SDP header parsing: a SDP session description contains an ordered set of
578 * headers, starting with a section containing general session parameters, 637 * headers, starting with a section containing general session parameters,
579 * optionally followed by multiple media descriptions. 638 * optionally followed by multiple media descriptions.
@@ -682,7 +741,7 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr,
682 741
683static int refresh_signalling_expectation(struct nf_conn *ct, 742static int refresh_signalling_expectation(struct nf_conn *ct,
684 union nf_inet_addr *addr, 743 union nf_inet_addr *addr,
685 __be16 port, 744 u8 proto, __be16 port,
686 unsigned int expires) 745 unsigned int expires)
687{ 746{
688 struct nf_conn_help *help = nfct_help(ct); 747 struct nf_conn_help *help = nfct_help(ct);
@@ -694,6 +753,7 @@ static int refresh_signalling_expectation(struct nf_conn *ct,
694 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) { 753 hlist_for_each_entry_safe(exp, n, next, &help->expectations, lnode) {
695 if (exp->class != SIP_EXPECT_SIGNALLING || 754 if (exp->class != SIP_EXPECT_SIGNALLING ||
696 !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) || 755 !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) ||
756 exp->tuple.dst.protonum != proto ||
697 exp->tuple.dst.u.udp.port != port) 757 exp->tuple.dst.u.udp.port != port)
698 continue; 758 continue;
699 if (!del_timer(&exp->timeout)) 759 if (!del_timer(&exp->timeout))
@@ -728,7 +788,7 @@ static void flush_expectations(struct nf_conn *ct, bool media)
728 spin_unlock_bh(&nf_conntrack_lock); 788 spin_unlock_bh(&nf_conntrack_lock);
729} 789}
730 790
731static int set_expected_rtp_rtcp(struct sk_buff *skb, 791static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff,
732 const char **dptr, unsigned int *datalen, 792 const char **dptr, unsigned int *datalen,
733 union nf_inet_addr *daddr, __be16 port, 793 union nf_inet_addr *daddr, __be16 port,
734 enum sip_expectation_classes class, 794 enum sip_expectation_classes class,
@@ -777,7 +837,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
777 837
778 rcu_read_lock(); 838 rcu_read_lock();
779 do { 839 do {
780 exp = __nf_ct_expect_find(net, &tuple); 840 exp = __nf_ct_expect_find(net, nf_ct_zone(ct), &tuple);
781 841
782 if (!exp || exp->master == ct || 842 if (!exp || exp->master == ct ||
783 nfct_help(exp->master)->helper != nfct_help(ct)->helper || 843 nfct_help(exp->master)->helper != nfct_help(ct)->helper ||
@@ -805,7 +865,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
805 if (direct_rtp) { 865 if (direct_rtp) {
806 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); 866 nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook);
807 if (nf_nat_sdp_port && 867 if (nf_nat_sdp_port &&
808 !nf_nat_sdp_port(skb, dptr, datalen, 868 !nf_nat_sdp_port(skb, dataoff, dptr, datalen,
809 mediaoff, medialen, ntohs(rtp_port))) 869 mediaoff, medialen, ntohs(rtp_port)))
810 goto err1; 870 goto err1;
811 } 871 }
@@ -827,7 +887,8 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb,
827 887
828 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); 888 nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook);
829 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) 889 if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp)
830 ret = nf_nat_sdp_media(skb, dptr, datalen, rtp_exp, rtcp_exp, 890 ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen,
891 rtp_exp, rtcp_exp,
831 mediaoff, medialen, daddr); 892 mediaoff, medialen, daddr);
832 else { 893 else {
833 if (nf_ct_expect_related(rtp_exp) == 0) { 894 if (nf_ct_expect_related(rtp_exp) == 0) {
@@ -847,6 +908,7 @@ err1:
847static const struct sdp_media_type sdp_media_types[] = { 908static const struct sdp_media_type sdp_media_types[] = {
848 SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO), 909 SDP_MEDIA_TYPE("audio ", SIP_EXPECT_AUDIO),
849 SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO), 910 SDP_MEDIA_TYPE("video ", SIP_EXPECT_VIDEO),
911 SDP_MEDIA_TYPE("image ", SIP_EXPECT_IMAGE),
850}; 912};
851 913
852static const struct sdp_media_type *sdp_media_type(const char *dptr, 914static const struct sdp_media_type *sdp_media_type(const char *dptr,
@@ -866,13 +928,12 @@ static const struct sdp_media_type *sdp_media_type(const char *dptr,
866 return NULL; 928 return NULL;
867} 929}
868 930
869static int process_sdp(struct sk_buff *skb, 931static int process_sdp(struct sk_buff *skb, unsigned int dataoff,
870 const char **dptr, unsigned int *datalen, 932 const char **dptr, unsigned int *datalen,
871 unsigned int cseq) 933 unsigned int cseq)
872{ 934{
873 enum ip_conntrack_info ctinfo; 935 enum ip_conntrack_info ctinfo;
874 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 936 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
875 struct nf_conn_help *help = nfct_help(ct);
876 unsigned int matchoff, matchlen; 937 unsigned int matchoff, matchlen;
877 unsigned int mediaoff, medialen; 938 unsigned int mediaoff, medialen;
878 unsigned int sdpoff; 939 unsigned int sdpoff;
@@ -941,7 +1002,7 @@ static int process_sdp(struct sk_buff *skb,
941 else 1002 else
942 return NF_DROP; 1003 return NF_DROP;
943 1004
944 ret = set_expected_rtp_rtcp(skb, dptr, datalen, 1005 ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen,
945 &rtp_addr, htons(port), t->class, 1006 &rtp_addr, htons(port), t->class,
946 mediaoff, medialen); 1007 mediaoff, medialen);
947 if (ret != NF_ACCEPT) 1008 if (ret != NF_ACCEPT)
@@ -949,8 +1010,9 @@ static int process_sdp(struct sk_buff *skb,
949 1010
950 /* Update media connection address if present */ 1011 /* Update media connection address if present */
951 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { 1012 if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) {
952 ret = nf_nat_sdp_addr(skb, dptr, mediaoff, datalen, 1013 ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen,
953 c_hdr, SDP_HDR_MEDIA, &rtp_addr); 1014 mediaoff, c_hdr, SDP_HDR_MEDIA,
1015 &rtp_addr);
954 if (ret != NF_ACCEPT) 1016 if (ret != NF_ACCEPT)
955 return ret; 1017 return ret;
956 } 1018 }
@@ -960,14 +1022,12 @@ static int process_sdp(struct sk_buff *skb,
960 /* Update session connection and owner addresses */ 1022 /* Update session connection and owner addresses */
961 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); 1023 nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook);
962 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) 1024 if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK)
963 ret = nf_nat_sdp_session(skb, dptr, sdpoff, datalen, &rtp_addr); 1025 ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff,
964 1026 &rtp_addr);
965 if (ret == NF_ACCEPT && i > 0)
966 help->help.ct_sip_info.invite_cseq = cseq;
967 1027
968 return ret; 1028 return ret;
969} 1029}
970static int process_invite_response(struct sk_buff *skb, 1030static int process_invite_response(struct sk_buff *skb, unsigned int dataoff,
971 const char **dptr, unsigned int *datalen, 1031 const char **dptr, unsigned int *datalen,
972 unsigned int cseq, unsigned int code) 1032 unsigned int cseq, unsigned int code)
973{ 1033{
@@ -977,13 +1037,13 @@ static int process_invite_response(struct sk_buff *skb,
977 1037
978 if ((code >= 100 && code <= 199) || 1038 if ((code >= 100 && code <= 199) ||
979 (code >= 200 && code <= 299)) 1039 (code >= 200 && code <= 299))
980 return process_sdp(skb, dptr, datalen, cseq); 1040 return process_sdp(skb, dataoff, dptr, datalen, cseq);
981 else if (help->help.ct_sip_info.invite_cseq == cseq) 1041 else if (help->help.ct_sip_info.invite_cseq == cseq)
982 flush_expectations(ct, true); 1042 flush_expectations(ct, true);
983 return NF_ACCEPT; 1043 return NF_ACCEPT;
984} 1044}
985 1045
986static int process_update_response(struct sk_buff *skb, 1046static int process_update_response(struct sk_buff *skb, unsigned int dataoff,
987 const char **dptr, unsigned int *datalen, 1047 const char **dptr, unsigned int *datalen,
988 unsigned int cseq, unsigned int code) 1048 unsigned int cseq, unsigned int code)
989{ 1049{
@@ -993,13 +1053,13 @@ static int process_update_response(struct sk_buff *skb,
993 1053
994 if ((code >= 100 && code <= 199) || 1054 if ((code >= 100 && code <= 199) ||
995 (code >= 200 && code <= 299)) 1055 (code >= 200 && code <= 299))
996 return process_sdp(skb, dptr, datalen, cseq); 1056 return process_sdp(skb, dataoff, dptr, datalen, cseq);
997 else if (help->help.ct_sip_info.invite_cseq == cseq) 1057 else if (help->help.ct_sip_info.invite_cseq == cseq)
998 flush_expectations(ct, true); 1058 flush_expectations(ct, true);
999 return NF_ACCEPT; 1059 return NF_ACCEPT;
1000} 1060}
1001 1061
1002static int process_prack_response(struct sk_buff *skb, 1062static int process_prack_response(struct sk_buff *skb, unsigned int dataoff,
1003 const char **dptr, unsigned int *datalen, 1063 const char **dptr, unsigned int *datalen,
1004 unsigned int cseq, unsigned int code) 1064 unsigned int cseq, unsigned int code)
1005{ 1065{
@@ -1009,13 +1069,29 @@ static int process_prack_response(struct sk_buff *skb,
1009 1069
1010 if ((code >= 100 && code <= 199) || 1070 if ((code >= 100 && code <= 199) ||
1011 (code >= 200 && code <= 299)) 1071 (code >= 200 && code <= 299))
1012 return process_sdp(skb, dptr, datalen, cseq); 1072 return process_sdp(skb, dataoff, dptr, datalen, cseq);
1013 else if (help->help.ct_sip_info.invite_cseq == cseq) 1073 else if (help->help.ct_sip_info.invite_cseq == cseq)
1014 flush_expectations(ct, true); 1074 flush_expectations(ct, true);
1015 return NF_ACCEPT; 1075 return NF_ACCEPT;
1016} 1076}
1017 1077
1018static int process_bye_request(struct sk_buff *skb, 1078static int process_invite_request(struct sk_buff *skb, unsigned int dataoff,
1079 const char **dptr, unsigned int *datalen,
1080 unsigned int cseq)
1081{
1082 enum ip_conntrack_info ctinfo;
1083 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1084 struct nf_conn_help *help = nfct_help(ct);
1085 unsigned int ret;
1086
1087 flush_expectations(ct, true);
1088 ret = process_sdp(skb, dataoff, dptr, datalen, cseq);
1089 if (ret == NF_ACCEPT)
1090 help->help.ct_sip_info.invite_cseq = cseq;
1091 return ret;
1092}
1093
1094static int process_bye_request(struct sk_buff *skb, unsigned int dataoff,
1019 const char **dptr, unsigned int *datalen, 1095 const char **dptr, unsigned int *datalen,
1020 unsigned int cseq) 1096 unsigned int cseq)
1021{ 1097{
@@ -1030,7 +1106,7 @@ static int process_bye_request(struct sk_buff *skb,
1030 * signalling connections. The expectation is marked inactive and is activated 1106 * signalling connections. The expectation is marked inactive and is activated
1031 * when receiving a response indicating success from the registrar. 1107 * when receiving a response indicating success from the registrar.
1032 */ 1108 */
1033static int process_register_request(struct sk_buff *skb, 1109static int process_register_request(struct sk_buff *skb, unsigned int dataoff,
1034 const char **dptr, unsigned int *datalen, 1110 const char **dptr, unsigned int *datalen,
1035 unsigned int cseq) 1111 unsigned int cseq)
1036{ 1112{
@@ -1042,6 +1118,7 @@ static int process_register_request(struct sk_buff *skb,
1042 struct nf_conntrack_expect *exp; 1118 struct nf_conntrack_expect *exp;
1043 union nf_inet_addr *saddr, daddr; 1119 union nf_inet_addr *saddr, daddr;
1044 __be16 port; 1120 __be16 port;
1121 u8 proto;
1045 unsigned int expires = 0; 1122 unsigned int expires = 0;
1046 int ret; 1123 int ret;
1047 typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect; 1124 typeof(nf_nat_sip_expect_hook) nf_nat_sip_expect;
@@ -1074,6 +1151,10 @@ static int process_register_request(struct sk_buff *skb,
1074 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr)) 1151 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, &daddr))
1075 return NF_ACCEPT; 1152 return NF_ACCEPT;
1076 1153
1154 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen, *datalen,
1155 &proto) == 0)
1156 return NF_ACCEPT;
1157
1077 if (ct_sip_parse_numerical_param(ct, *dptr, 1158 if (ct_sip_parse_numerical_param(ct, *dptr,
1078 matchoff + matchlen, *datalen, 1159 matchoff + matchlen, *datalen,
1079 "expires=", NULL, NULL, &expires) < 0) 1160 "expires=", NULL, NULL, &expires) < 0)
@@ -1093,14 +1174,14 @@ static int process_register_request(struct sk_buff *skb,
1093 saddr = &ct->tuplehash[!dir].tuple.src.u3; 1174 saddr = &ct->tuplehash[!dir].tuple.src.u3;
1094 1175
1095 nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct), 1176 nf_ct_expect_init(exp, SIP_EXPECT_SIGNALLING, nf_ct_l3num(ct),
1096 saddr, &daddr, IPPROTO_UDP, NULL, &port); 1177 saddr, &daddr, proto, NULL, &port);
1097 exp->timeout.expires = sip_timeout * HZ; 1178 exp->timeout.expires = sip_timeout * HZ;
1098 exp->helper = nfct_help(ct)->helper; 1179 exp->helper = nfct_help(ct)->helper;
1099 exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE; 1180 exp->flags = NF_CT_EXPECT_PERMANENT | NF_CT_EXPECT_INACTIVE;
1100 1181
1101 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); 1182 nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook);
1102 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) 1183 if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK)
1103 ret = nf_nat_sip_expect(skb, dptr, datalen, exp, 1184 ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp,
1104 matchoff, matchlen); 1185 matchoff, matchlen);
1105 else { 1186 else {
1106 if (nf_ct_expect_related(exp) != 0) 1187 if (nf_ct_expect_related(exp) != 0)
@@ -1116,7 +1197,7 @@ store_cseq:
1116 return ret; 1197 return ret;
1117} 1198}
1118 1199
1119static int process_register_response(struct sk_buff *skb, 1200static int process_register_response(struct sk_buff *skb, unsigned int dataoff,
1120 const char **dptr, unsigned int *datalen, 1201 const char **dptr, unsigned int *datalen,
1121 unsigned int cseq, unsigned int code) 1202 unsigned int cseq, unsigned int code)
1122{ 1203{
@@ -1126,7 +1207,8 @@ static int process_register_response(struct sk_buff *skb,
1126 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); 1207 enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
1127 union nf_inet_addr addr; 1208 union nf_inet_addr addr;
1128 __be16 port; 1209 __be16 port;
1129 unsigned int matchoff, matchlen, dataoff = 0; 1210 u8 proto;
1211 unsigned int matchoff, matchlen, coff = 0;
1130 unsigned int expires = 0; 1212 unsigned int expires = 0;
1131 int in_contact = 0, ret; 1213 int in_contact = 0, ret;
1132 1214
@@ -1153,7 +1235,7 @@ static int process_register_response(struct sk_buff *skb,
1153 while (1) { 1235 while (1) {
1154 unsigned int c_expires = expires; 1236 unsigned int c_expires = expires;
1155 1237
1156 ret = ct_sip_parse_header_uri(ct, *dptr, &dataoff, *datalen, 1238 ret = ct_sip_parse_header_uri(ct, *dptr, &coff, *datalen,
1157 SIP_HDR_CONTACT, &in_contact, 1239 SIP_HDR_CONTACT, &in_contact,
1158 &matchoff, &matchlen, 1240 &matchoff, &matchlen,
1159 &addr, &port); 1241 &addr, &port);
@@ -1166,6 +1248,10 @@ static int process_register_response(struct sk_buff *skb,
1166 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr)) 1248 if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, &addr))
1167 continue; 1249 continue;
1168 1250
1251 if (ct_sip_parse_transport(ct, *dptr, matchoff + matchlen,
1252 *datalen, &proto) == 0)
1253 continue;
1254
1169 ret = ct_sip_parse_numerical_param(ct, *dptr, 1255 ret = ct_sip_parse_numerical_param(ct, *dptr,
1170 matchoff + matchlen, 1256 matchoff + matchlen,
1171 *datalen, "expires=", 1257 *datalen, "expires=",
@@ -1174,7 +1260,8 @@ static int process_register_response(struct sk_buff *skb,
1174 return NF_DROP; 1260 return NF_DROP;
1175 if (c_expires == 0) 1261 if (c_expires == 0)
1176 break; 1262 break;
1177 if (refresh_signalling_expectation(ct, &addr, port, c_expires)) 1263 if (refresh_signalling_expectation(ct, &addr, proto, port,
1264 c_expires))
1178 return NF_ACCEPT; 1265 return NF_ACCEPT;
1179 } 1266 }
1180 1267
@@ -1184,7 +1271,7 @@ flush:
1184} 1271}
1185 1272
1186static const struct sip_handler sip_handlers[] = { 1273static const struct sip_handler sip_handlers[] = {
1187 SIP_HANDLER("INVITE", process_sdp, process_invite_response), 1274 SIP_HANDLER("INVITE", process_invite_request, process_invite_response),
1188 SIP_HANDLER("UPDATE", process_sdp, process_update_response), 1275 SIP_HANDLER("UPDATE", process_sdp, process_update_response),
1189 SIP_HANDLER("ACK", process_sdp, NULL), 1276 SIP_HANDLER("ACK", process_sdp, NULL),
1190 SIP_HANDLER("PRACK", process_sdp, process_prack_response), 1277 SIP_HANDLER("PRACK", process_sdp, process_prack_response),
@@ -1192,13 +1279,13 @@ static const struct sip_handler sip_handlers[] = {
1192 SIP_HANDLER("REGISTER", process_register_request, process_register_response), 1279 SIP_HANDLER("REGISTER", process_register_request, process_register_response),
1193}; 1280};
1194 1281
1195static int process_sip_response(struct sk_buff *skb, 1282static int process_sip_response(struct sk_buff *skb, unsigned int dataoff,
1196 const char **dptr, unsigned int *datalen) 1283 const char **dptr, unsigned int *datalen)
1197{ 1284{
1198 enum ip_conntrack_info ctinfo; 1285 enum ip_conntrack_info ctinfo;
1199 struct nf_conn *ct = nf_ct_get(skb, &ctinfo); 1286 struct nf_conn *ct = nf_ct_get(skb, &ctinfo);
1200 unsigned int matchoff, matchlen; 1287 unsigned int matchoff, matchlen, matchend;
1201 unsigned int code, cseq, dataoff, i; 1288 unsigned int code, cseq, i;
1202 1289
1203 if (*datalen < strlen("SIP/2.0 200")) 1290 if (*datalen < strlen("SIP/2.0 200"))
1204 return NF_ACCEPT; 1291 return NF_ACCEPT;
@@ -1212,7 +1299,7 @@ static int process_sip_response(struct sk_buff *skb,
1212 cseq = simple_strtoul(*dptr + matchoff, NULL, 10); 1299 cseq = simple_strtoul(*dptr + matchoff, NULL, 10);
1213 if (!cseq) 1300 if (!cseq)
1214 return NF_DROP; 1301 return NF_DROP;
1215 dataoff = matchoff + matchlen + 1; 1302 matchend = matchoff + matchlen + 1;
1216 1303
1217 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) { 1304 for (i = 0; i < ARRAY_SIZE(sip_handlers); i++) {
1218 const struct sip_handler *handler; 1305 const struct sip_handler *handler;
@@ -1220,15 +1307,16 @@ static int process_sip_response(struct sk_buff *skb,
1220 handler = &sip_handlers[i]; 1307 handler = &sip_handlers[i];
1221 if (handler->response == NULL) 1308 if (handler->response == NULL)
1222 continue; 1309 continue;
1223 if (*datalen < dataoff + handler->len || 1310 if (*datalen < matchend + handler->len ||
1224 strnicmp(*dptr + dataoff, handler->method, handler->len)) 1311 strnicmp(*dptr + matchend, handler->method, handler->len))
1225 continue; 1312 continue;
1226 return handler->response(skb, dptr, datalen, cseq, code); 1313 return handler->response(skb, dataoff, dptr, datalen,
1314 cseq, code);
1227 } 1315 }
1228 return NF_ACCEPT; 1316 return NF_ACCEPT;
1229} 1317}
1230 1318
1231static int process_sip_request(struct sk_buff *skb, 1319static int process_sip_request(struct sk_buff *skb, unsigned int dataoff,
1232 const char **dptr, unsigned int *datalen) 1320 const char **dptr, unsigned int *datalen)
1233{ 1321{
1234 enum ip_conntrack_info ctinfo; 1322 enum ip_conntrack_info ctinfo;
@@ -1253,69 +1341,157 @@ static int process_sip_request(struct sk_buff *skb,
1253 if (!cseq) 1341 if (!cseq)
1254 return NF_DROP; 1342 return NF_DROP;
1255 1343
1256 return handler->request(skb, dptr, datalen, cseq); 1344 return handler->request(skb, dataoff, dptr, datalen, cseq);
1257 } 1345 }
1258 return NF_ACCEPT; 1346 return NF_ACCEPT;
1259} 1347}
1260 1348
1261static int sip_help(struct sk_buff *skb, 1349static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct,
1262 unsigned int protoff, 1350 unsigned int dataoff, const char **dptr,
1263 struct nf_conn *ct, 1351 unsigned int *datalen)
1264 enum ip_conntrack_info ctinfo) 1352{
1353 typeof(nf_nat_sip_hook) nf_nat_sip;
1354 int ret;
1355
1356 if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0)
1357 ret = process_sip_request(skb, dataoff, dptr, datalen);
1358 else
1359 ret = process_sip_response(skb, dataoff, dptr, datalen);
1360
1361 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
1362 nf_nat_sip = rcu_dereference(nf_nat_sip_hook);
1363 if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen))
1364 ret = NF_DROP;
1365 }
1366
1367 return ret;
1368}
1369
1370static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,
1371 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1265{ 1372{
1373 struct tcphdr *th, _tcph;
1266 unsigned int dataoff, datalen; 1374 unsigned int dataoff, datalen;
1267 const char *dptr; 1375 unsigned int matchoff, matchlen, clen;
1376 unsigned int msglen, origlen;
1377 const char *dptr, *end;
1378 s16 diff, tdiff = 0;
1268 int ret; 1379 int ret;
1269 typeof(nf_nat_sip_hook) nf_nat_sip; 1380 typeof(nf_nat_sip_seq_adjust_hook) nf_nat_sip_seq_adjust;
1381
1382 if (ctinfo != IP_CT_ESTABLISHED &&
1383 ctinfo != IP_CT_ESTABLISHED + IP_CT_IS_REPLY)
1384 return NF_ACCEPT;
1270 1385
1271 /* No Data ? */ 1386 /* No Data ? */
1272 dataoff = protoff + sizeof(struct udphdr); 1387 th = skb_header_pointer(skb, protoff, sizeof(_tcph), &_tcph);
1388 if (th == NULL)
1389 return NF_ACCEPT;
1390 dataoff = protoff + th->doff * 4;
1273 if (dataoff >= skb->len) 1391 if (dataoff >= skb->len)
1274 return NF_ACCEPT; 1392 return NF_ACCEPT;
1275 1393
1276 nf_ct_refresh(ct, skb, sip_timeout * HZ); 1394 nf_ct_refresh(ct, skb, sip_timeout * HZ);
1277 1395
1278 if (!skb_is_nonlinear(skb)) 1396 if (skb_is_nonlinear(skb)) {
1279 dptr = skb->data + dataoff;
1280 else {
1281 pr_debug("Copy of skbuff not supported yet.\n"); 1397 pr_debug("Copy of skbuff not supported yet.\n");
1282 return NF_ACCEPT; 1398 return NF_ACCEPT;
1283 } 1399 }
1284 1400
1401 dptr = skb->data + dataoff;
1285 datalen = skb->len - dataoff; 1402 datalen = skb->len - dataoff;
1286 if (datalen < strlen("SIP/2.0 200")) 1403 if (datalen < strlen("SIP/2.0 200"))
1287 return NF_ACCEPT; 1404 return NF_ACCEPT;
1288 1405
1289 if (strnicmp(dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) 1406 while (1) {
1290 ret = process_sip_request(skb, &dptr, &datalen); 1407 if (ct_sip_get_header(ct, dptr, 0, datalen,
1291 else 1408 SIP_HDR_CONTENT_LENGTH,
1292 ret = process_sip_response(skb, &dptr, &datalen); 1409 &matchoff, &matchlen) <= 0)
1410 break;
1411
1412 clen = simple_strtoul(dptr + matchoff, (char **)&end, 10);
1413 if (dptr + matchoff == end)
1414 break;
1415
1416 if (end + strlen("\r\n\r\n") > dptr + datalen)
1417 break;
1418 if (end[0] != '\r' || end[1] != '\n' ||
1419 end[2] != '\r' || end[3] != '\n')
1420 break;
1421 end += strlen("\r\n\r\n") + clen;
1422
1423 msglen = origlen = end - dptr;
1424
1425 ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen);
1426 if (ret != NF_ACCEPT)
1427 break;
1428 diff = msglen - origlen;
1429 tdiff += diff;
1430
1431 dataoff += msglen;
1432 dptr += msglen;
1433 datalen = datalen + diff - msglen;
1434 }
1293 1435
1294 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { 1436 if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) {
1295 nf_nat_sip = rcu_dereference(nf_nat_sip_hook); 1437 nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook);
1296 if (nf_nat_sip && !nf_nat_sip(skb, &dptr, &datalen)) 1438 if (nf_nat_sip_seq_adjust)
1297 ret = NF_DROP; 1439 nf_nat_sip_seq_adjust(skb, tdiff);
1298 } 1440 }
1299 1441
1300 return ret; 1442 return ret;
1301} 1443}
1302 1444
1303static struct nf_conntrack_helper sip[MAX_PORTS][2] __read_mostly; 1445static int sip_help_udp(struct sk_buff *skb, unsigned int protoff,
1304static char sip_names[MAX_PORTS][2][sizeof("sip-65535")] __read_mostly; 1446 struct nf_conn *ct, enum ip_conntrack_info ctinfo)
1447{
1448 unsigned int dataoff, datalen;
1449 const char *dptr;
1450
1451 /* No Data ? */
1452 dataoff = protoff + sizeof(struct udphdr);
1453 if (dataoff >= skb->len)
1454 return NF_ACCEPT;
1455
1456 nf_ct_refresh(ct, skb, sip_timeout * HZ);
1457
1458 if (skb_is_nonlinear(skb)) {
1459 pr_debug("Copy of skbuff not supported yet.\n");
1460 return NF_ACCEPT;
1461 }
1462
1463 dptr = skb->data + dataoff;
1464 datalen = skb->len - dataoff;
1465 if (datalen < strlen("SIP/2.0 200"))
1466 return NF_ACCEPT;
1467
1468 return process_sip_msg(skb, ct, dataoff, &dptr, &datalen);
1469}
1470
1471static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly;
1472static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly;
1305 1473
1306static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { 1474static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = {
1307 [SIP_EXPECT_SIGNALLING] = { 1475 [SIP_EXPECT_SIGNALLING] = {
1476 .name = "signalling",
1308 .max_expected = 1, 1477 .max_expected = 1,
1309 .timeout = 3 * 60, 1478 .timeout = 3 * 60,
1310 }, 1479 },
1311 [SIP_EXPECT_AUDIO] = { 1480 [SIP_EXPECT_AUDIO] = {
1481 .name = "audio",
1312 .max_expected = 2 * IP_CT_DIR_MAX, 1482 .max_expected = 2 * IP_CT_DIR_MAX,
1313 .timeout = 3 * 60, 1483 .timeout = 3 * 60,
1314 }, 1484 },
1315 [SIP_EXPECT_VIDEO] = { 1485 [SIP_EXPECT_VIDEO] = {
1486 .name = "video",
1316 .max_expected = 2 * IP_CT_DIR_MAX, 1487 .max_expected = 2 * IP_CT_DIR_MAX,
1317 .timeout = 3 * 60, 1488 .timeout = 3 * 60,
1318 }, 1489 },
1490 [SIP_EXPECT_IMAGE] = {
1491 .name = "image",
1492 .max_expected = IP_CT_DIR_MAX,
1493 .timeout = 3 * 60,
1494 },
1319}; 1495};
1320 1496
1321static void nf_conntrack_sip_fini(void) 1497static void nf_conntrack_sip_fini(void)
@@ -1323,7 +1499,7 @@ static void nf_conntrack_sip_fini(void)
1323 int i, j; 1499 int i, j;
1324 1500
1325 for (i = 0; i < ports_c; i++) { 1501 for (i = 0; i < ports_c; i++) {
1326 for (j = 0; j < 2; j++) { 1502 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) {
1327 if (sip[i][j].me == NULL) 1503 if (sip[i][j].me == NULL)
1328 continue; 1504 continue;
1329 nf_conntrack_helper_unregister(&sip[i][j]); 1505 nf_conntrack_helper_unregister(&sip[i][j]);
@@ -1343,14 +1519,24 @@ static int __init nf_conntrack_sip_init(void)
1343 memset(&sip[i], 0, sizeof(sip[i])); 1519 memset(&sip[i], 0, sizeof(sip[i]));
1344 1520
1345 sip[i][0].tuple.src.l3num = AF_INET; 1521 sip[i][0].tuple.src.l3num = AF_INET;
1346 sip[i][1].tuple.src.l3num = AF_INET6; 1522 sip[i][0].tuple.dst.protonum = IPPROTO_UDP;
1347 for (j = 0; j < 2; j++) { 1523 sip[i][0].help = sip_help_udp;
1348 sip[i][j].tuple.dst.protonum = IPPROTO_UDP; 1524 sip[i][1].tuple.src.l3num = AF_INET;
1525 sip[i][1].tuple.dst.protonum = IPPROTO_TCP;
1526 sip[i][1].help = sip_help_tcp;
1527
1528 sip[i][2].tuple.src.l3num = AF_INET6;
1529 sip[i][2].tuple.dst.protonum = IPPROTO_UDP;
1530 sip[i][2].help = sip_help_udp;
1531 sip[i][3].tuple.src.l3num = AF_INET6;
1532 sip[i][3].tuple.dst.protonum = IPPROTO_TCP;
1533 sip[i][3].help = sip_help_tcp;
1534
1535 for (j = 0; j < ARRAY_SIZE(sip[i]); j++) {
1349 sip[i][j].tuple.src.u.udp.port = htons(ports[i]); 1536 sip[i][j].tuple.src.u.udp.port = htons(ports[i]);
1350 sip[i][j].expect_policy = sip_exp_policy; 1537 sip[i][j].expect_policy = sip_exp_policy;
1351 sip[i][j].expect_class_max = SIP_EXPECT_MAX; 1538 sip[i][j].expect_class_max = SIP_EXPECT_MAX;
1352 sip[i][j].me = THIS_MODULE; 1539 sip[i][j].me = THIS_MODULE;
1353 sip[i][j].help = sip_help;
1354 1540
1355 tmpname = &sip_names[i][j][0]; 1541 tmpname = &sip_names[i][j][0];
1356 if (ports[i] == SIP_PORT) 1542 if (ports[i] == SIP_PORT)
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index e310f1561bb2..24a42efe62ef 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -26,6 +26,7 @@
26#include <net/netfilter/nf_conntrack_expect.h> 26#include <net/netfilter/nf_conntrack_expect.h>
27#include <net/netfilter/nf_conntrack_helper.h> 27#include <net/netfilter/nf_conntrack_helper.h>
28#include <net/netfilter/nf_conntrack_acct.h> 28#include <net/netfilter/nf_conntrack_acct.h>
29#include <net/netfilter/nf_conntrack_zones.h>
29 30
30MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
31 32
@@ -171,6 +172,11 @@ static int ct_seq_show(struct seq_file *s, void *v)
171 goto release; 172 goto release;
172#endif 173#endif
173 174
175#ifdef CONFIG_NF_CONNTRACK_ZONES
176 if (seq_printf(s, "zone=%u ", nf_ct_zone(ct)))
177 goto release;
178#endif
179
174 if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use))) 180 if (seq_printf(s, "use=%u\n", atomic_read(&ct->ct_general.use)))
175 goto release; 181 goto release;
176 182
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index eedc0c1ac7a4..8eb0cc23ada3 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -40,7 +40,6 @@ MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NETFILTER);
40 40
41static char __initdata nfversion[] = "0.30"; 41static char __initdata nfversion[] = "0.30";
42 42
43static struct sock *nfnl = NULL;
44static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT]; 43static const struct nfnetlink_subsystem *subsys_table[NFNL_SUBSYS_COUNT];
45static DEFINE_MUTEX(nfnl_mutex); 44static DEFINE_MUTEX(nfnl_mutex);
46 45
@@ -101,34 +100,35 @@ nfnetlink_find_client(u_int16_t type, const struct nfnetlink_subsystem *ss)
101 return &ss->cb[cb_id]; 100 return &ss->cb[cb_id];
102} 101}
103 102
104int nfnetlink_has_listeners(unsigned int group) 103int nfnetlink_has_listeners(struct net *net, unsigned int group)
105{ 104{
106 return netlink_has_listeners(nfnl, group); 105 return netlink_has_listeners(net->nfnl, group);
107} 106}
108EXPORT_SYMBOL_GPL(nfnetlink_has_listeners); 107EXPORT_SYMBOL_GPL(nfnetlink_has_listeners);
109 108
110int nfnetlink_send(struct sk_buff *skb, u32 pid, 109int nfnetlink_send(struct sk_buff *skb, struct net *net, u32 pid,
111 unsigned group, int echo, gfp_t flags) 110 unsigned group, int echo, gfp_t flags)
112{ 111{
113 return nlmsg_notify(nfnl, skb, pid, group, echo, flags); 112 return nlmsg_notify(net->nfnl, skb, pid, group, echo, flags);
114} 113}
115EXPORT_SYMBOL_GPL(nfnetlink_send); 114EXPORT_SYMBOL_GPL(nfnetlink_send);
116 115
117void nfnetlink_set_err(u32 pid, u32 group, int error) 116void nfnetlink_set_err(struct net *net, u32 pid, u32 group, int error)
118{ 117{
119 netlink_set_err(nfnl, pid, group, error); 118 netlink_set_err(net->nfnl, pid, group, error);
120} 119}
121EXPORT_SYMBOL_GPL(nfnetlink_set_err); 120EXPORT_SYMBOL_GPL(nfnetlink_set_err);
122 121
123int nfnetlink_unicast(struct sk_buff *skb, u_int32_t pid, int flags) 122int nfnetlink_unicast(struct sk_buff *skb, struct net *net, u_int32_t pid, int flags)
124{ 123{
125 return netlink_unicast(nfnl, skb, pid, flags); 124 return netlink_unicast(net->nfnl, skb, pid, flags);
126} 125}
127EXPORT_SYMBOL_GPL(nfnetlink_unicast); 126EXPORT_SYMBOL_GPL(nfnetlink_unicast);
128 127
129/* Process one complete nfnetlink message. */ 128/* Process one complete nfnetlink message. */
130static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) 129static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
131{ 130{
131 struct net *net = sock_net(skb->sk);
132 const struct nfnl_callback *nc; 132 const struct nfnl_callback *nc;
133 const struct nfnetlink_subsystem *ss; 133 const struct nfnetlink_subsystem *ss;
134 int type, err; 134 int type, err;
@@ -170,7 +170,7 @@ replay:
170 if (err < 0) 170 if (err < 0)
171 return err; 171 return err;
172 172
173 err = nc->call(nfnl, skb, nlh, (const struct nlattr **)cda); 173 err = nc->call(net->nfnl, skb, nlh, (const struct nlattr **)cda);
174 if (err == -EAGAIN) 174 if (err == -EAGAIN)
175 goto replay; 175 goto replay;
176 return err; 176 return err;
@@ -184,26 +184,45 @@ static void nfnetlink_rcv(struct sk_buff *skb)
184 nfnl_unlock(); 184 nfnl_unlock();
185} 185}
186 186
187static void __exit nfnetlink_exit(void) 187static int __net_init nfnetlink_net_init(struct net *net)
188{ 188{
189 printk("Removing netfilter NETLINK layer.\n"); 189 struct sock *nfnl;
190 netlink_kernel_release(nfnl); 190
191 return; 191 nfnl = netlink_kernel_create(net, NETLINK_NETFILTER, NFNLGRP_MAX,
192 nfnetlink_rcv, NULL, THIS_MODULE);
193 if (!nfnl)
194 return -ENOMEM;
195 net->nfnl_stash = nfnl;
196 rcu_assign_pointer(net->nfnl, nfnl);
197 return 0;
192} 198}
193 199
194static int __init nfnetlink_init(void) 200static void __net_exit nfnetlink_net_exit_batch(struct list_head *net_exit_list)
195{ 201{
196 printk("Netfilter messages via NETLINK v%s.\n", nfversion); 202 struct net *net;
197 203
198 nfnl = netlink_kernel_create(&init_net, NETLINK_NETFILTER, NFNLGRP_MAX, 204 list_for_each_entry(net, net_exit_list, exit_list)
199 nfnetlink_rcv, NULL, THIS_MODULE); 205 rcu_assign_pointer(net->nfnl, NULL);
200 if (!nfnl) { 206 synchronize_net();
201 printk(KERN_ERR "cannot initialize nfnetlink!\n"); 207 list_for_each_entry(net, net_exit_list, exit_list)
202 return -ENOMEM; 208 netlink_kernel_release(net->nfnl_stash);
203 } 209}
204 210
205 return 0; 211static struct pernet_operations nfnetlink_net_ops = {
212 .init = nfnetlink_net_init,
213 .exit_batch = nfnetlink_net_exit_batch,
214};
215
216static int __init nfnetlink_init(void)
217{
218 printk("Netfilter messages via NETLINK v%s.\n", nfversion);
219 return register_pernet_subsys(&nfnetlink_net_ops);
206} 220}
207 221
222static void __exit nfnetlink_exit(void)
223{
224 printk("Removing netfilter NETLINK layer.\n");
225 unregister_pernet_subsys(&nfnetlink_net_ops);
226}
208module_init(nfnetlink_init); 227module_init(nfnetlink_init);
209module_exit(nfnetlink_exit); 228module_exit(nfnetlink_exit);
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c
index 9de0470d557e..285e9029a9ff 100644
--- a/net/netfilter/nfnetlink_log.c
+++ b/net/netfilter/nfnetlink_log.c
@@ -323,7 +323,8 @@ __nfulnl_send(struct nfulnl_instance *inst)
323 NLMSG_DONE, 323 NLMSG_DONE,
324 sizeof(struct nfgenmsg)); 324 sizeof(struct nfgenmsg));
325 325
326 status = nfnetlink_unicast(inst->skb, inst->peer_pid, MSG_DONTWAIT); 326 status = nfnetlink_unicast(inst->skb, &init_net, inst->peer_pid,
327 MSG_DONTWAIT);
327 328
328 inst->qlen = 0; 329 inst->qlen = 0;
329 inst->skb = NULL; 330 inst->skb = NULL;
diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c
index 7e3fa410641e..7ba4abc405c9 100644
--- a/net/netfilter/nfnetlink_queue.c
+++ b/net/netfilter/nfnetlink_queue.c
@@ -112,7 +112,6 @@ instance_create(u_int16_t queue_num, int pid)
112 inst->copy_mode = NFQNL_COPY_NONE; 112 inst->copy_mode = NFQNL_COPY_NONE;
113 spin_lock_init(&inst->lock); 113 spin_lock_init(&inst->lock);
114 INIT_LIST_HEAD(&inst->queue_list); 114 INIT_LIST_HEAD(&inst->queue_list);
115 INIT_RCU_HEAD(&inst->rcu);
116 115
117 if (!try_module_get(THIS_MODULE)) { 116 if (!try_module_get(THIS_MODULE)) {
118 err = -EAGAIN; 117 err = -EAGAIN;
@@ -414,13 +413,13 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
414 queue->queue_dropped++; 413 queue->queue_dropped++;
415 if (net_ratelimit()) 414 if (net_ratelimit())
416 printk(KERN_WARNING "nf_queue: full at %d entries, " 415 printk(KERN_WARNING "nf_queue: full at %d entries, "
417 "dropping packets(s). Dropped: %d\n", 416 "dropping packets(s).\n",
418 queue->queue_total, queue->queue_dropped); 417 queue->queue_total);
419 goto err_out_free_nskb; 418 goto err_out_free_nskb;
420 } 419 }
421 420
422 /* nfnetlink_unicast will either free the nskb or add it to a socket */ 421 /* nfnetlink_unicast will either free the nskb or add it to a socket */
423 err = nfnetlink_unicast(nskb, queue->peer_pid, MSG_DONTWAIT); 422 err = nfnetlink_unicast(nskb, &init_net, queue->peer_pid, MSG_DONTWAIT);
424 if (err < 0) { 423 if (err < 0) {
425 queue->queue_user_dropped++; 424 queue->queue_user_dropped++;
426 goto err_out_unlock; 425 goto err_out_unlock;
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index f01955cce314..0a12cedfe9e3 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -26,7 +26,9 @@
26 26
27#include <linux/netfilter/x_tables.h> 27#include <linux/netfilter/x_tables.h>
28#include <linux/netfilter_arp.h> 28#include <linux/netfilter_arp.h>
29 29#include <linux/netfilter_ipv4/ip_tables.h>
30#include <linux/netfilter_ipv6/ip6_tables.h>
31#include <linux/netfilter_arp/arp_tables.h>
30 32
31MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); 34MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>");
@@ -37,7 +39,7 @@ MODULE_DESCRIPTION("{ip,ip6,arp,eb}_tables backend module");
37struct compat_delta { 39struct compat_delta {
38 struct compat_delta *next; 40 struct compat_delta *next;
39 unsigned int offset; 41 unsigned int offset;
40 short delta; 42 int delta;
41}; 43};
42 44
43struct xt_af { 45struct xt_af {
@@ -364,8 +366,10 @@ int xt_check_match(struct xt_mtchk_param *par,
364 * ebt_among is exempt from centralized matchsize checking 366 * ebt_among is exempt from centralized matchsize checking
365 * because it uses a dynamic-size data set. 367 * because it uses a dynamic-size data set.
366 */ 368 */
367 pr_err("%s_tables: %s match: invalid size %Zu != %u\n", 369 pr_err("%s_tables: %s.%u match: invalid size "
370 "%u (kernel) != (user) %u\n",
368 xt_prefix[par->family], par->match->name, 371 xt_prefix[par->family], par->match->name,
372 par->match->revision,
369 XT_ALIGN(par->match->matchsize), size); 373 XT_ALIGN(par->match->matchsize), size);
370 return -EINVAL; 374 return -EINVAL;
371 } 375 }
@@ -435,10 +439,10 @@ void xt_compat_flush_offsets(u_int8_t af)
435} 439}
436EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); 440EXPORT_SYMBOL_GPL(xt_compat_flush_offsets);
437 441
438short xt_compat_calc_jump(u_int8_t af, unsigned int offset) 442int xt_compat_calc_jump(u_int8_t af, unsigned int offset)
439{ 443{
440 struct compat_delta *tmp; 444 struct compat_delta *tmp;
441 short delta; 445 int delta;
442 446
443 for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next) 447 for (tmp = xt[af].compat_offsets, delta = 0; tmp; tmp = tmp->next)
444 if (tmp->offset < offset) 448 if (tmp->offset < offset)
@@ -481,8 +485,8 @@ int xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr,
481} 485}
482EXPORT_SYMBOL_GPL(xt_compat_match_from_user); 486EXPORT_SYMBOL_GPL(xt_compat_match_from_user);
483 487
484int xt_compat_match_to_user(struct xt_entry_match *m, void __user **dstptr, 488int xt_compat_match_to_user(const struct xt_entry_match *m,
485 unsigned int *size) 489 void __user **dstptr, unsigned int *size)
486{ 490{
487 const struct xt_match *match = m->u.kernel.match; 491 const struct xt_match *match = m->u.kernel.match;
488 struct compat_xt_entry_match __user *cm = *dstptr; 492 struct compat_xt_entry_match __user *cm = *dstptr;
@@ -514,8 +518,10 @@ int xt_check_target(struct xt_tgchk_param *par,
514 unsigned int size, u_int8_t proto, bool inv_proto) 518 unsigned int size, u_int8_t proto, bool inv_proto)
515{ 519{
516 if (XT_ALIGN(par->target->targetsize) != size) { 520 if (XT_ALIGN(par->target->targetsize) != size) {
517 pr_err("%s_tables: %s target: invalid size %Zu != %u\n", 521 pr_err("%s_tables: %s.%u target: invalid size "
522 "%u (kernel) != (user) %u\n",
518 xt_prefix[par->family], par->target->name, 523 xt_prefix[par->family], par->target->name,
524 par->target->revision,
519 XT_ALIGN(par->target->targetsize), size); 525 XT_ALIGN(par->target->targetsize), size);
520 return -EINVAL; 526 return -EINVAL;
521 } 527 }
@@ -582,8 +588,8 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr,
582} 588}
583EXPORT_SYMBOL_GPL(xt_compat_target_from_user); 589EXPORT_SYMBOL_GPL(xt_compat_target_from_user);
584 590
585int xt_compat_target_to_user(struct xt_entry_target *t, void __user **dstptr, 591int xt_compat_target_to_user(const struct xt_entry_target *t,
586 unsigned int *size) 592 void __user **dstptr, unsigned int *size)
587{ 593{
588 const struct xt_target *target = t->u.kernel.target; 594 const struct xt_target *target = t->u.kernel.target;
589 struct compat_xt_entry_target __user *ct = *dstptr; 595 struct compat_xt_entry_target __user *ct = *dstptr;
@@ -1091,6 +1097,60 @@ static const struct file_operations xt_target_ops = {
1091 1097
1092#endif /* CONFIG_PROC_FS */ 1098#endif /* CONFIG_PROC_FS */
1093 1099
1100/**
1101 * xt_hook_link - set up hooks for a new table
1102 * @table: table with metadata needed to set up hooks
1103 * @fn: Hook function
1104 *
1105 * This function will take care of creating and registering the necessary
1106 * Netfilter hooks for XT tables.
1107 */
1108struct nf_hook_ops *xt_hook_link(const struct xt_table *table, nf_hookfn *fn)
1109{
1110 unsigned int hook_mask = table->valid_hooks;
1111 uint8_t i, num_hooks = hweight32(hook_mask);
1112 uint8_t hooknum;
1113 struct nf_hook_ops *ops;
1114 int ret;
1115
1116 ops = kmalloc(sizeof(*ops) * num_hooks, GFP_KERNEL);
1117 if (ops == NULL)
1118 return ERR_PTR(-ENOMEM);
1119
1120 for (i = 0, hooknum = 0; i < num_hooks && hook_mask != 0;
1121 hook_mask >>= 1, ++hooknum) {
1122 if (!(hook_mask & 1))
1123 continue;
1124 ops[i].hook = fn;
1125 ops[i].owner = table->me;
1126 ops[i].pf = table->af;
1127 ops[i].hooknum = hooknum;
1128 ops[i].priority = table->priority;
1129 ++i;
1130 }
1131
1132 ret = nf_register_hooks(ops, num_hooks);
1133 if (ret < 0) {
1134 kfree(ops);
1135 return ERR_PTR(ret);
1136 }
1137
1138 return ops;
1139}
1140EXPORT_SYMBOL_GPL(xt_hook_link);
1141
1142/**
1143 * xt_hook_unlink - remove hooks for a table
1144 * @ops: nf_hook_ops array as returned by nf_hook_link
1145 * @hook_mask: the very same mask that was passed to nf_hook_link
1146 */
1147void xt_hook_unlink(const struct xt_table *table, struct nf_hook_ops *ops)
1148{
1149 nf_unregister_hooks(ops, hweight32(table->valid_hooks));
1150 kfree(ops);
1151}
1152EXPORT_SYMBOL_GPL(xt_hook_unlink);
1153
1094int xt_proto_init(struct net *net, u_int8_t af) 1154int xt_proto_init(struct net *net, u_int8_t af)
1095{ 1155{
1096#ifdef CONFIG_PROC_FS 1156#ifdef CONFIG_PROC_FS
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
new file mode 100644
index 000000000000..61c50fa84703
--- /dev/null
+++ b/net/netfilter/xt_CT.c
@@ -0,0 +1,164 @@
1/*
2 * Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#include <linux/module.h>
10#include <linux/skbuff.h>
11#include <linux/selinux.h>
12#include <linux/netfilter_ipv4/ip_tables.h>
13#include <linux/netfilter_ipv6/ip6_tables.h>
14#include <linux/netfilter/x_tables.h>
15#include <linux/netfilter/xt_CT.h>
16#include <net/netfilter/nf_conntrack.h>
17#include <net/netfilter/nf_conntrack_helper.h>
18#include <net/netfilter/nf_conntrack_ecache.h>
19#include <net/netfilter/nf_conntrack_zones.h>
20
21static unsigned int xt_ct_target(struct sk_buff *skb,
22 const struct xt_target_param *par)
23{
24 const struct xt_ct_target_info *info = par->targinfo;
25 struct nf_conn *ct = info->ct;
26
27 /* Previously seen (loopback)? Ignore. */
28 if (skb->nfct != NULL)
29 return XT_CONTINUE;
30
31 atomic_inc(&ct->ct_general.use);
32 skb->nfct = &ct->ct_general;
33 skb->nfctinfo = IP_CT_NEW;
34
35 return XT_CONTINUE;
36}
37
38static u8 xt_ct_find_proto(const struct xt_tgchk_param *par)
39{
40 if (par->family == AF_INET) {
41 const struct ipt_entry *e = par->entryinfo;
42
43 if (e->ip.invflags & IPT_INV_PROTO)
44 return 0;
45 return e->ip.proto;
46 } else if (par->family == AF_INET6) {
47 const struct ip6t_entry *e = par->entryinfo;
48
49 if (e->ipv6.invflags & IP6T_INV_PROTO)
50 return 0;
51 return e->ipv6.proto;
52 } else
53 return 0;
54}
55
56static bool xt_ct_tg_check(const struct xt_tgchk_param *par)
57{
58 struct xt_ct_target_info *info = par->targinfo;
59 struct nf_conntrack_tuple t;
60 struct nf_conn_help *help;
61 struct nf_conn *ct;
62 u8 proto;
63
64 if (info->flags & ~XT_CT_NOTRACK)
65 return false;
66
67 if (info->flags & XT_CT_NOTRACK) {
68 ct = &nf_conntrack_untracked;
69 atomic_inc(&ct->ct_general.use);
70 goto out;
71 }
72
73#ifndef CONFIG_NF_CONNTRACK_ZONES
74 if (info->zone)
75 goto err1;
76#endif
77
78 if (nf_ct_l3proto_try_module_get(par->family) < 0)
79 goto err1;
80
81 memset(&t, 0, sizeof(t));
82 ct = nf_conntrack_alloc(par->net, info->zone, &t, &t, GFP_KERNEL);
83 if (IS_ERR(ct))
84 goto err2;
85
86 if ((info->ct_events || info->exp_events) &&
87 !nf_ct_ecache_ext_add(ct, info->ct_events, info->exp_events,
88 GFP_KERNEL))
89 goto err3;
90
91 if (info->helper[0]) {
92 proto = xt_ct_find_proto(par);
93 if (!proto)
94 goto err3;
95
96 help = nf_ct_helper_ext_add(ct, GFP_KERNEL);
97 if (help == NULL)
98 goto err3;
99
100 help->helper = nf_conntrack_helper_try_module_get(info->helper,
101 par->family,
102 proto);
103 if (help->helper == NULL)
104 goto err3;
105 }
106
107 __set_bit(IPS_TEMPLATE_BIT, &ct->status);
108 __set_bit(IPS_CONFIRMED_BIT, &ct->status);
109out:
110 info->ct = ct;
111 return true;
112
113err3:
114 nf_conntrack_free(ct);
115err2:
116 nf_ct_l3proto_module_put(par->family);
117err1:
118 return false;
119}
120
121static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par)
122{
123 struct xt_ct_target_info *info = par->targinfo;
124 struct nf_conn *ct = info->ct;
125 struct nf_conn_help *help;
126
127 if (ct != &nf_conntrack_untracked) {
128 help = nfct_help(ct);
129 if (help)
130 module_put(help->helper->me);
131
132 nf_ct_l3proto_module_put(par->family);
133 }
134 nf_ct_put(info->ct);
135}
136
137static struct xt_target xt_ct_tg __read_mostly = {
138 .name = "CT",
139 .family = NFPROTO_UNSPEC,
140 .targetsize = XT_ALIGN(sizeof(struct xt_ct_target_info)),
141 .checkentry = xt_ct_tg_check,
142 .destroy = xt_ct_tg_destroy,
143 .target = xt_ct_target,
144 .table = "raw",
145 .me = THIS_MODULE,
146};
147
148static int __init xt_ct_tg_init(void)
149{
150 return xt_register_target(&xt_ct_tg);
151}
152
153static void __exit xt_ct_tg_exit(void)
154{
155 xt_unregister_target(&xt_ct_tg);
156}
157
158module_init(xt_ct_tg_init);
159module_exit(xt_ct_tg_exit);
160
161MODULE_LICENSE("GPL");
162MODULE_DESCRIPTION("Xtables: connection tracking target");
163MODULE_ALIAS("ipt_CT");
164MODULE_ALIAS("ip6t_CT");
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c
index f28f6a5fc02d..12dcd7007c3e 100644
--- a/net/netfilter/xt_NFQUEUE.c
+++ b/net/netfilter/xt_NFQUEUE.c
@@ -28,6 +28,7 @@ MODULE_ALIAS("ip6t_NFQUEUE");
28MODULE_ALIAS("arpt_NFQUEUE"); 28MODULE_ALIAS("arpt_NFQUEUE");
29 29
30static u32 jhash_initval __read_mostly; 30static u32 jhash_initval __read_mostly;
31static bool rnd_inited __read_mostly;
31 32
32static unsigned int 33static unsigned int
33nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par) 34nfqueue_tg(struct sk_buff *skb, const struct xt_target_param *par)
@@ -90,6 +91,10 @@ static bool nfqueue_tg_v1_check(const struct xt_tgchk_param *par)
90 const struct xt_NFQ_info_v1 *info = par->targinfo; 91 const struct xt_NFQ_info_v1 *info = par->targinfo;
91 u32 maxid; 92 u32 maxid;
92 93
94 if (unlikely(!rnd_inited)) {
95 get_random_bytes(&jhash_initval, sizeof(jhash_initval));
96 rnd_inited = true;
97 }
93 if (info->queues_total == 0) { 98 if (info->queues_total == 0) {
94 pr_err("NFQUEUE: number of total queues is 0\n"); 99 pr_err("NFQUEUE: number of total queues is 0\n");
95 return false; 100 return false;
@@ -135,7 +140,6 @@ static struct xt_target nfqueue_tg_reg[] __read_mostly = {
135 140
136static int __init nfqueue_tg_init(void) 141static int __init nfqueue_tg_init(void)
137{ 142{
138 get_random_bytes(&jhash_initval, sizeof(jhash_initval));
139 return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg)); 143 return xt_register_targets(nfqueue_tg_reg, ARRAY_SIZE(nfqueue_tg_reg));
140} 144}
141 145
diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c
index d80b8192e0d4..87ae97e5516f 100644
--- a/net/netfilter/xt_RATEEST.c
+++ b/net/netfilter/xt_RATEEST.c
@@ -23,6 +23,7 @@ static DEFINE_MUTEX(xt_rateest_mutex);
23#define RATEEST_HSIZE 16 23#define RATEEST_HSIZE 16
24static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly; 24static struct hlist_head rateest_hash[RATEEST_HSIZE] __read_mostly;
25static unsigned int jhash_rnd __read_mostly; 25static unsigned int jhash_rnd __read_mostly;
26static bool rnd_inited __read_mostly;
26 27
27static unsigned int xt_rateest_hash(const char *name) 28static unsigned int xt_rateest_hash(const char *name)
28{ 29{
@@ -93,6 +94,11 @@ static bool xt_rateest_tg_checkentry(const struct xt_tgchk_param *par)
93 struct gnet_estimator est; 94 struct gnet_estimator est;
94 } cfg; 95 } cfg;
95 96
97 if (unlikely(!rnd_inited)) {
98 get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
99 rnd_inited = true;
100 }
101
96 est = xt_rateest_lookup(info->name); 102 est = xt_rateest_lookup(info->name);
97 if (est) { 103 if (est) {
98 /* 104 /*
@@ -164,7 +170,6 @@ static int __init xt_rateest_tg_init(void)
164 for (i = 0; i < ARRAY_SIZE(rateest_hash); i++) 170 for (i = 0; i < ARRAY_SIZE(rateest_hash); i++)
165 INIT_HLIST_HEAD(&rateest_hash[i]); 171 INIT_HLIST_HEAD(&rateest_hash[i]);
166 172
167 get_random_bytes(&jhash_rnd, sizeof(jhash_rnd));
168 return xt_register_target(&xt_rateest_tg_reg); 173 return xt_register_target(&xt_rateest_tg_reg);
169} 174}
170 175
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c
index eda64c1cb1e5..6f21b4377dbb 100644
--- a/net/netfilter/xt_TCPMSS.c
+++ b/net/netfilter/xt_TCPMSS.c
@@ -60,17 +60,9 @@ tcpmss_mangle_packet(struct sk_buff *skb,
60 tcplen = skb->len - tcphoff; 60 tcplen = skb->len - tcphoff;
61 tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff); 61 tcph = (struct tcphdr *)(skb_network_header(skb) + tcphoff);
62 62
63 /* Since it passed flags test in tcp match, we know it is is 63 /* Header cannot be larger than the packet */
64 not a fragment, and has data >= tcp header length. SYN 64 if (tcplen < tcph->doff*4)
65 packets should not contain data: if they did, then we risk
66 running over MTU, sending Frag Needed and breaking things
67 badly. --RR */
68 if (tcplen != tcph->doff*4) {
69 if (net_ratelimit())
70 printk(KERN_ERR "xt_TCPMSS: bad length (%u bytes)\n",
71 skb->len);
72 return -1; 65 return -1;
73 }
74 66
75 if (info->mss == XT_TCPMSS_CLAMP_PMTU) { 67 if (info->mss == XT_TCPMSS_CLAMP_PMTU) {
76 if (dst_mtu(skb_dst(skb)) <= minlen) { 68 if (dst_mtu(skb_dst(skb)) <= minlen) {
@@ -115,6 +107,12 @@ tcpmss_mangle_packet(struct sk_buff *skb,
115 } 107 }
116 } 108 }
117 109
110 /* There is data after the header so the option can't be added
111 without moving it, and doing so may make the SYN packet
112 itself too large. Accept the packet unmodified instead. */
113 if (tcplen > tcph->doff*4)
114 return 0;
115
118 /* 116 /*
119 * MSS Option not found ?! add it.. 117 * MSS Option not found ?! add it..
120 */ 118 */
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c
index 38f03f75a636..26997ce90e48 100644
--- a/net/netfilter/xt_connlimit.c
+++ b/net/netfilter/xt_connlimit.c
@@ -28,6 +28,7 @@
28#include <net/netfilter/nf_conntrack.h> 28#include <net/netfilter/nf_conntrack.h>
29#include <net/netfilter/nf_conntrack_core.h> 29#include <net/netfilter/nf_conntrack_core.h>
30#include <net/netfilter/nf_conntrack_tuple.h> 30#include <net/netfilter/nf_conntrack_tuple.h>
31#include <net/netfilter/nf_conntrack_zones.h>
31 32
32/* we will save the tuples of all connections we care about */ 33/* we will save the tuples of all connections we care about */
33struct xt_connlimit_conn { 34struct xt_connlimit_conn {
@@ -40,15 +41,11 @@ struct xt_connlimit_data {
40 spinlock_t lock; 41 spinlock_t lock;
41}; 42};
42 43
43static u_int32_t connlimit_rnd; 44static u_int32_t connlimit_rnd __read_mostly;
44static bool connlimit_rnd_inited; 45static bool connlimit_rnd_inited __read_mostly;
45 46
46static inline unsigned int connlimit_iphash(__be32 addr) 47static inline unsigned int connlimit_iphash(__be32 addr)
47{ 48{
48 if (unlikely(!connlimit_rnd_inited)) {
49 get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
50 connlimit_rnd_inited = true;
51 }
52 return jhash_1word((__force __u32)addr, connlimit_rnd) & 0xFF; 49 return jhash_1word((__force __u32)addr, connlimit_rnd) & 0xFF;
53} 50}
54 51
@@ -59,11 +56,6 @@ connlimit_iphash6(const union nf_inet_addr *addr,
59 union nf_inet_addr res; 56 union nf_inet_addr res;
60 unsigned int i; 57 unsigned int i;
61 58
62 if (unlikely(!connlimit_rnd_inited)) {
63 get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
64 connlimit_rnd_inited = true;
65 }
66
67 for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) 59 for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i)
68 res.ip6[i] = addr->ip6[i] & mask->ip6[i]; 60 res.ip6[i] = addr->ip6[i] & mask->ip6[i];
69 61
@@ -99,7 +91,8 @@ same_source_net(const union nf_inet_addr *addr,
99 } 91 }
100} 92}
101 93
102static int count_them(struct xt_connlimit_data *data, 94static int count_them(struct net *net,
95 struct xt_connlimit_data *data,
103 const struct nf_conntrack_tuple *tuple, 96 const struct nf_conntrack_tuple *tuple,
104 const union nf_inet_addr *addr, 97 const union nf_inet_addr *addr,
105 const union nf_inet_addr *mask, 98 const union nf_inet_addr *mask,
@@ -122,7 +115,8 @@ static int count_them(struct xt_connlimit_data *data,
122 115
123 /* check the saved connections */ 116 /* check the saved connections */
124 list_for_each_entry_safe(conn, tmp, hash, list) { 117 list_for_each_entry_safe(conn, tmp, hash, list) {
125 found = nf_conntrack_find_get(&init_net, &conn->tuple); 118 found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE,
119 &conn->tuple);
126 found_ct = NULL; 120 found_ct = NULL;
127 121
128 if (found != NULL) 122 if (found != NULL)
@@ -180,6 +174,7 @@ static int count_them(struct xt_connlimit_data *data,
180static bool 174static bool
181connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par) 175connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
182{ 176{
177 struct net *net = dev_net(par->in ? par->in : par->out);
183 const struct xt_connlimit_info *info = par->matchinfo; 178 const struct xt_connlimit_info *info = par->matchinfo;
184 union nf_inet_addr addr; 179 union nf_inet_addr addr;
185 struct nf_conntrack_tuple tuple; 180 struct nf_conntrack_tuple tuple;
@@ -204,7 +199,7 @@ connlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
204 } 199 }
205 200
206 spin_lock_bh(&info->data->lock); 201 spin_lock_bh(&info->data->lock);
207 connections = count_them(info->data, tuple_ptr, &addr, 202 connections = count_them(net, info->data, tuple_ptr, &addr,
208 &info->mask, par->family); 203 &info->mask, par->family);
209 spin_unlock_bh(&info->data->lock); 204 spin_unlock_bh(&info->data->lock);
210 205
@@ -226,6 +221,10 @@ static bool connlimit_mt_check(const struct xt_mtchk_param *par)
226 struct xt_connlimit_info *info = par->matchinfo; 221 struct xt_connlimit_info *info = par->matchinfo;
227 unsigned int i; 222 unsigned int i;
228 223
224 if (unlikely(!connlimit_rnd_inited)) {
225 get_random_bytes(&connlimit_rnd, sizeof(connlimit_rnd));
226 connlimit_rnd_inited = true;
227 }
229 if (nf_ct_l3proto_try_module_get(par->family) < 0) { 228 if (nf_ct_l3proto_try_module_get(par->family) < 0) {
230 printk(KERN_WARNING "cannot load conntrack support for " 229 printk(KERN_WARNING "cannot load conntrack support for "
231 "address family %u\n", par->family); 230 "address family %u\n", par->family);
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c
index dd16e404424f..e47fb805ffb4 100644
--- a/net/netfilter/xt_hashlimit.c
+++ b/net/netfilter/xt_hashlimit.c
@@ -26,6 +26,7 @@
26#endif 26#endif
27 27
28#include <net/net_namespace.h> 28#include <net/net_namespace.h>
29#include <net/netns/generic.h>
29 30
30#include <linux/netfilter/x_tables.h> 31#include <linux/netfilter/x_tables.h>
31#include <linux/netfilter_ipv4/ip_tables.h> 32#include <linux/netfilter_ipv4/ip_tables.h>
@@ -40,9 +41,19 @@ MODULE_DESCRIPTION("Xtables: per hash-bucket rate-limit match");
40MODULE_ALIAS("ipt_hashlimit"); 41MODULE_ALIAS("ipt_hashlimit");
41MODULE_ALIAS("ip6t_hashlimit"); 42MODULE_ALIAS("ip6t_hashlimit");
42 43
44struct hashlimit_net {
45 struct hlist_head htables;
46 struct proc_dir_entry *ipt_hashlimit;
47 struct proc_dir_entry *ip6t_hashlimit;
48};
49
50static int hashlimit_net_id;
51static inline struct hashlimit_net *hashlimit_pernet(struct net *net)
52{
53 return net_generic(net, hashlimit_net_id);
54}
55
43/* need to declare this at the top */ 56/* need to declare this at the top */
44static struct proc_dir_entry *hashlimit_procdir4;
45static struct proc_dir_entry *hashlimit_procdir6;
46static const struct file_operations dl_file_ops; 57static const struct file_operations dl_file_ops;
47 58
48/* hash table crap */ 59/* hash table crap */
@@ -79,27 +90,26 @@ struct dsthash_ent {
79 90
80struct xt_hashlimit_htable { 91struct xt_hashlimit_htable {
81 struct hlist_node node; /* global list of all htables */ 92 struct hlist_node node; /* global list of all htables */
82 atomic_t use; 93 int use;
83 u_int8_t family; 94 u_int8_t family;
95 bool rnd_initialized;
84 96
85 struct hashlimit_cfg1 cfg; /* config */ 97 struct hashlimit_cfg1 cfg; /* config */
86 98
87 /* used internally */ 99 /* used internally */
88 spinlock_t lock; /* lock for list_head */ 100 spinlock_t lock; /* lock for list_head */
89 u_int32_t rnd; /* random seed for hash */ 101 u_int32_t rnd; /* random seed for hash */
90 int rnd_initialized;
91 unsigned int count; /* number entries in table */ 102 unsigned int count; /* number entries in table */
92 struct timer_list timer; /* timer for gc */ 103 struct timer_list timer; /* timer for gc */
93 104
94 /* seq_file stuff */ 105 /* seq_file stuff */
95 struct proc_dir_entry *pde; 106 struct proc_dir_entry *pde;
107 struct net *net;
96 108
97 struct hlist_head hash[0]; /* hashtable itself */ 109 struct hlist_head hash[0]; /* hashtable itself */
98}; 110};
99 111
100static DEFINE_SPINLOCK(hashlimit_lock); /* protects htables list */ 112static DEFINE_MUTEX(hashlimit_mutex); /* protects htables list */
101static DEFINE_MUTEX(hlimit_mutex); /* additional checkentry protection */
102static HLIST_HEAD(hashlimit_htables);
103static struct kmem_cache *hashlimit_cachep __read_mostly; 113static struct kmem_cache *hashlimit_cachep __read_mostly;
104 114
105static inline bool dst_cmp(const struct dsthash_ent *ent, 115static inline bool dst_cmp(const struct dsthash_ent *ent,
@@ -150,7 +160,7 @@ dsthash_alloc_init(struct xt_hashlimit_htable *ht,
150 * the first hashtable entry */ 160 * the first hashtable entry */
151 if (!ht->rnd_initialized) { 161 if (!ht->rnd_initialized) {
152 get_random_bytes(&ht->rnd, sizeof(ht->rnd)); 162 get_random_bytes(&ht->rnd, sizeof(ht->rnd));
153 ht->rnd_initialized = 1; 163 ht->rnd_initialized = true;
154 } 164 }
155 165
156 if (ht->cfg.max && ht->count >= ht->cfg.max) { 166 if (ht->cfg.max && ht->count >= ht->cfg.max) {
@@ -185,8 +195,9 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent)
185} 195}
186static void htable_gc(unsigned long htlong); 196static void htable_gc(unsigned long htlong);
187 197
188static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family) 198static int htable_create_v0(struct net *net, struct xt_hashlimit_info *minfo, u_int8_t family)
189{ 199{
200 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
190 struct xt_hashlimit_htable *hinfo; 201 struct xt_hashlimit_htable *hinfo;
191 unsigned int size; 202 unsigned int size;
192 unsigned int i; 203 unsigned int i;
@@ -232,33 +243,36 @@ static int htable_create_v0(struct xt_hashlimit_info *minfo, u_int8_t family)
232 for (i = 0; i < hinfo->cfg.size; i++) 243 for (i = 0; i < hinfo->cfg.size; i++)
233 INIT_HLIST_HEAD(&hinfo->hash[i]); 244 INIT_HLIST_HEAD(&hinfo->hash[i]);
234 245
235 atomic_set(&hinfo->use, 1); 246 hinfo->use = 1;
236 hinfo->count = 0; 247 hinfo->count = 0;
237 hinfo->family = family; 248 hinfo->family = family;
238 hinfo->rnd_initialized = 0; 249 hinfo->rnd_initialized = false;
239 spin_lock_init(&hinfo->lock); 250 spin_lock_init(&hinfo->lock);
240 hinfo->pde = proc_create_data(minfo->name, 0, 251 hinfo->pde = proc_create_data(minfo->name, 0,
241 (family == NFPROTO_IPV4) ? 252 (family == NFPROTO_IPV4) ?
242 hashlimit_procdir4 : hashlimit_procdir6, 253 hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
243 &dl_file_ops, hinfo); 254 &dl_file_ops, hinfo);
244 if (!hinfo->pde) { 255 if (!hinfo->pde) {
245 vfree(hinfo); 256 vfree(hinfo);
246 return -1; 257 return -1;
247 } 258 }
259 hinfo->net = net;
248 260
249 setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo); 261 setup_timer(&hinfo->timer, htable_gc, (unsigned long )hinfo);
250 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); 262 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
251 add_timer(&hinfo->timer); 263 add_timer(&hinfo->timer);
252 264
253 spin_lock_bh(&hashlimit_lock); 265 mutex_lock(&hashlimit_mutex);
254 hlist_add_head(&hinfo->node, &hashlimit_htables); 266 hlist_add_head(&hinfo->node, &hashlimit_net->htables);
255 spin_unlock_bh(&hashlimit_lock); 267 mutex_unlock(&hashlimit_mutex);
256 268
257 return 0; 269 return 0;
258} 270}
259 271
260static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family) 272static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo,
273 u_int8_t family)
261{ 274{
275 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
262 struct xt_hashlimit_htable *hinfo; 276 struct xt_hashlimit_htable *hinfo;
263 unsigned int size; 277 unsigned int size;
264 unsigned int i; 278 unsigned int i;
@@ -293,28 +307,29 @@ static int htable_create(struct xt_hashlimit_mtinfo1 *minfo, u_int8_t family)
293 for (i = 0; i < hinfo->cfg.size; i++) 307 for (i = 0; i < hinfo->cfg.size; i++)
294 INIT_HLIST_HEAD(&hinfo->hash[i]); 308 INIT_HLIST_HEAD(&hinfo->hash[i]);
295 309
296 atomic_set(&hinfo->use, 1); 310 hinfo->use = 1;
297 hinfo->count = 0; 311 hinfo->count = 0;
298 hinfo->family = family; 312 hinfo->family = family;
299 hinfo->rnd_initialized = 0; 313 hinfo->rnd_initialized = false;
300 spin_lock_init(&hinfo->lock); 314 spin_lock_init(&hinfo->lock);
301 315
302 hinfo->pde = proc_create_data(minfo->name, 0, 316 hinfo->pde = proc_create_data(minfo->name, 0,
303 (family == NFPROTO_IPV4) ? 317 (family == NFPROTO_IPV4) ?
304 hashlimit_procdir4 : hashlimit_procdir6, 318 hashlimit_net->ipt_hashlimit : hashlimit_net->ip6t_hashlimit,
305 &dl_file_ops, hinfo); 319 &dl_file_ops, hinfo);
306 if (hinfo->pde == NULL) { 320 if (hinfo->pde == NULL) {
307 vfree(hinfo); 321 vfree(hinfo);
308 return -1; 322 return -1;
309 } 323 }
324 hinfo->net = net;
310 325
311 setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); 326 setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo);
312 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); 327 hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval);
313 add_timer(&hinfo->timer); 328 add_timer(&hinfo->timer);
314 329
315 spin_lock_bh(&hashlimit_lock); 330 mutex_lock(&hashlimit_mutex);
316 hlist_add_head(&hinfo->node, &hashlimit_htables); 331 hlist_add_head(&hinfo->node, &hashlimit_net->htables);
317 spin_unlock_bh(&hashlimit_lock); 332 mutex_unlock(&hashlimit_mutex);
318 333
319 return 0; 334 return 0;
320} 335}
@@ -364,43 +379,46 @@ static void htable_gc(unsigned long htlong)
364 379
365static void htable_destroy(struct xt_hashlimit_htable *hinfo) 380static void htable_destroy(struct xt_hashlimit_htable *hinfo)
366{ 381{
382 struct hashlimit_net *hashlimit_net = hashlimit_pernet(hinfo->net);
383 struct proc_dir_entry *parent;
384
367 del_timer_sync(&hinfo->timer); 385 del_timer_sync(&hinfo->timer);
368 386
369 /* remove proc entry */ 387 if (hinfo->family == NFPROTO_IPV4)
370 remove_proc_entry(hinfo->pde->name, 388 parent = hashlimit_net->ipt_hashlimit;
371 hinfo->family == NFPROTO_IPV4 ? hashlimit_procdir4 : 389 else
372 hashlimit_procdir6); 390 parent = hashlimit_net->ip6t_hashlimit;
391 remove_proc_entry(hinfo->pde->name, parent);
373 htable_selective_cleanup(hinfo, select_all); 392 htable_selective_cleanup(hinfo, select_all);
374 vfree(hinfo); 393 vfree(hinfo);
375} 394}
376 395
377static struct xt_hashlimit_htable *htable_find_get(const char *name, 396static struct xt_hashlimit_htable *htable_find_get(struct net *net,
397 const char *name,
378 u_int8_t family) 398 u_int8_t family)
379{ 399{
400 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
380 struct xt_hashlimit_htable *hinfo; 401 struct xt_hashlimit_htable *hinfo;
381 struct hlist_node *pos; 402 struct hlist_node *pos;
382 403
383 spin_lock_bh(&hashlimit_lock); 404 hlist_for_each_entry(hinfo, pos, &hashlimit_net->htables, node) {
384 hlist_for_each_entry(hinfo, pos, &hashlimit_htables, node) {
385 if (!strcmp(name, hinfo->pde->name) && 405 if (!strcmp(name, hinfo->pde->name) &&
386 hinfo->family == family) { 406 hinfo->family == family) {
387 atomic_inc(&hinfo->use); 407 hinfo->use++;
388 spin_unlock_bh(&hashlimit_lock);
389 return hinfo; 408 return hinfo;
390 } 409 }
391 } 410 }
392 spin_unlock_bh(&hashlimit_lock);
393 return NULL; 411 return NULL;
394} 412}
395 413
396static void htable_put(struct xt_hashlimit_htable *hinfo) 414static void htable_put(struct xt_hashlimit_htable *hinfo)
397{ 415{
398 if (atomic_dec_and_test(&hinfo->use)) { 416 mutex_lock(&hashlimit_mutex);
399 spin_lock_bh(&hashlimit_lock); 417 if (--hinfo->use == 0) {
400 hlist_del(&hinfo->node); 418 hlist_del(&hinfo->node);
401 spin_unlock_bh(&hashlimit_lock);
402 htable_destroy(hinfo); 419 htable_destroy(hinfo);
403 } 420 }
421 mutex_unlock(&hashlimit_mutex);
404} 422}
405 423
406/* The algorithm used is the Simple Token Bucket Filter (TBF) 424/* The algorithm used is the Simple Token Bucket Filter (TBF)
@@ -665,6 +683,7 @@ hashlimit_mt(const struct sk_buff *skb, const struct xt_match_param *par)
665 683
666static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par) 684static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
667{ 685{
686 struct net *net = par->net;
668 struct xt_hashlimit_info *r = par->matchinfo; 687 struct xt_hashlimit_info *r = par->matchinfo;
669 688
670 /* Check for overflow. */ 689 /* Check for overflow. */
@@ -687,25 +706,20 @@ static bool hashlimit_mt_check_v0(const struct xt_mtchk_param *par)
687 if (r->name[sizeof(r->name) - 1] != '\0') 706 if (r->name[sizeof(r->name) - 1] != '\0')
688 return false; 707 return false;
689 708
690 /* This is the best we've got: We cannot release and re-grab lock, 709 mutex_lock(&hashlimit_mutex);
691 * since checkentry() is called before x_tables.c grabs xt_mutex. 710 r->hinfo = htable_find_get(net, r->name, par->match->family);
692 * We also cannot grab the hashtable spinlock, since htable_create will 711 if (!r->hinfo && htable_create_v0(net, r, par->match->family) != 0) {
693 * call vmalloc, and that can sleep. And we cannot just re-search 712 mutex_unlock(&hashlimit_mutex);
694 * the list of htable's in htable_create(), since then we would
695 * create duplicate proc files. -HW */
696 mutex_lock(&hlimit_mutex);
697 r->hinfo = htable_find_get(r->name, par->match->family);
698 if (!r->hinfo && htable_create_v0(r, par->match->family) != 0) {
699 mutex_unlock(&hlimit_mutex);
700 return false; 713 return false;
701 } 714 }
702 mutex_unlock(&hlimit_mutex); 715 mutex_unlock(&hashlimit_mutex);
703 716
704 return true; 717 return true;
705} 718}
706 719
707static bool hashlimit_mt_check(const struct xt_mtchk_param *par) 720static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
708{ 721{
722 struct net *net = par->net;
709 struct xt_hashlimit_mtinfo1 *info = par->matchinfo; 723 struct xt_hashlimit_mtinfo1 *info = par->matchinfo;
710 724
711 /* Check for overflow. */ 725 /* Check for overflow. */
@@ -728,19 +742,13 @@ static bool hashlimit_mt_check(const struct xt_mtchk_param *par)
728 return false; 742 return false;
729 } 743 }
730 744
731 /* This is the best we've got: We cannot release and re-grab lock, 745 mutex_lock(&hashlimit_mutex);
732 * since checkentry() is called before x_tables.c grabs xt_mutex. 746 info->hinfo = htable_find_get(net, info->name, par->match->family);
733 * We also cannot grab the hashtable spinlock, since htable_create will 747 if (!info->hinfo && htable_create(net, info, par->match->family) != 0) {
734 * call vmalloc, and that can sleep. And we cannot just re-search 748 mutex_unlock(&hashlimit_mutex);
735 * the list of htable's in htable_create(), since then we would
736 * create duplicate proc files. -HW */
737 mutex_lock(&hlimit_mutex);
738 info->hinfo = htable_find_get(info->name, par->match->family);
739 if (!info->hinfo && htable_create(info, par->match->family) != 0) {
740 mutex_unlock(&hlimit_mutex);
741 return false; 749 return false;
742 } 750 }
743 mutex_unlock(&hlimit_mutex); 751 mutex_unlock(&hashlimit_mutex);
744 return true; 752 return true;
745} 753}
746 754
@@ -767,7 +775,7 @@ struct compat_xt_hashlimit_info {
767 compat_uptr_t master; 775 compat_uptr_t master;
768}; 776};
769 777
770static void hashlimit_mt_compat_from_user(void *dst, void *src) 778static void hashlimit_mt_compat_from_user(void *dst, const void *src)
771{ 779{
772 int off = offsetof(struct compat_xt_hashlimit_info, hinfo); 780 int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
773 781
@@ -775,7 +783,7 @@ static void hashlimit_mt_compat_from_user(void *dst, void *src)
775 memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off); 783 memset(dst + off, 0, sizeof(struct compat_xt_hashlimit_info) - off);
776} 784}
777 785
778static int hashlimit_mt_compat_to_user(void __user *dst, void *src) 786static int hashlimit_mt_compat_to_user(void __user *dst, const void *src)
779{ 787{
780 int off = offsetof(struct compat_xt_hashlimit_info, hinfo); 788 int off = offsetof(struct compat_xt_hashlimit_info, hinfo);
781 789
@@ -841,8 +849,7 @@ static struct xt_match hashlimit_mt_reg[] __read_mostly = {
841static void *dl_seq_start(struct seq_file *s, loff_t *pos) 849static void *dl_seq_start(struct seq_file *s, loff_t *pos)
842 __acquires(htable->lock) 850 __acquires(htable->lock)
843{ 851{
844 struct proc_dir_entry *pde = s->private; 852 struct xt_hashlimit_htable *htable = s->private;
845 struct xt_hashlimit_htable *htable = pde->data;
846 unsigned int *bucket; 853 unsigned int *bucket;
847 854
848 spin_lock_bh(&htable->lock); 855 spin_lock_bh(&htable->lock);
@@ -859,8 +866,7 @@ static void *dl_seq_start(struct seq_file *s, loff_t *pos)
859 866
860static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos) 867static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
861{ 868{
862 struct proc_dir_entry *pde = s->private; 869 struct xt_hashlimit_htable *htable = s->private;
863 struct xt_hashlimit_htable *htable = pde->data;
864 unsigned int *bucket = (unsigned int *)v; 870 unsigned int *bucket = (unsigned int *)v;
865 871
866 *pos = ++(*bucket); 872 *pos = ++(*bucket);
@@ -874,8 +880,7 @@ static void *dl_seq_next(struct seq_file *s, void *v, loff_t *pos)
874static void dl_seq_stop(struct seq_file *s, void *v) 880static void dl_seq_stop(struct seq_file *s, void *v)
875 __releases(htable->lock) 881 __releases(htable->lock)
876{ 882{
877 struct proc_dir_entry *pde = s->private; 883 struct xt_hashlimit_htable *htable = s->private;
878 struct xt_hashlimit_htable *htable = pde->data;
879 unsigned int *bucket = (unsigned int *)v; 884 unsigned int *bucket = (unsigned int *)v;
880 885
881 kfree(bucket); 886 kfree(bucket);
@@ -917,8 +922,7 @@ static int dl_seq_real_show(struct dsthash_ent *ent, u_int8_t family,
917 922
918static int dl_seq_show(struct seq_file *s, void *v) 923static int dl_seq_show(struct seq_file *s, void *v)
919{ 924{
920 struct proc_dir_entry *pde = s->private; 925 struct xt_hashlimit_htable *htable = s->private;
921 struct xt_hashlimit_htable *htable = pde->data;
922 unsigned int *bucket = (unsigned int *)v; 926 unsigned int *bucket = (unsigned int *)v;
923 struct dsthash_ent *ent; 927 struct dsthash_ent *ent;
924 struct hlist_node *pos; 928 struct hlist_node *pos;
@@ -944,7 +948,7 @@ static int dl_proc_open(struct inode *inode, struct file *file)
944 948
945 if (!ret) { 949 if (!ret) {
946 struct seq_file *sf = file->private_data; 950 struct seq_file *sf = file->private_data;
947 sf->private = PDE(inode); 951 sf->private = PDE(inode)->data;
948 } 952 }
949 return ret; 953 return ret;
950} 954}
@@ -957,10 +961,61 @@ static const struct file_operations dl_file_ops = {
957 .release = seq_release 961 .release = seq_release
958}; 962};
959 963
964static int __net_init hashlimit_proc_net_init(struct net *net)
965{
966 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
967
968 hashlimit_net->ipt_hashlimit = proc_mkdir("ipt_hashlimit", net->proc_net);
969 if (!hashlimit_net->ipt_hashlimit)
970 return -ENOMEM;
971#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
972 hashlimit_net->ip6t_hashlimit = proc_mkdir("ip6t_hashlimit", net->proc_net);
973 if (!hashlimit_net->ip6t_hashlimit) {
974 proc_net_remove(net, "ipt_hashlimit");
975 return -ENOMEM;
976 }
977#endif
978 return 0;
979}
980
981static void __net_exit hashlimit_proc_net_exit(struct net *net)
982{
983 proc_net_remove(net, "ipt_hashlimit");
984#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
985 proc_net_remove(net, "ip6t_hashlimit");
986#endif
987}
988
989static int __net_init hashlimit_net_init(struct net *net)
990{
991 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
992
993 INIT_HLIST_HEAD(&hashlimit_net->htables);
994 return hashlimit_proc_net_init(net);
995}
996
997static void __net_exit hashlimit_net_exit(struct net *net)
998{
999 struct hashlimit_net *hashlimit_net = hashlimit_pernet(net);
1000
1001 BUG_ON(!hlist_empty(&hashlimit_net->htables));
1002 hashlimit_proc_net_exit(net);
1003}
1004
1005static struct pernet_operations hashlimit_net_ops = {
1006 .init = hashlimit_net_init,
1007 .exit = hashlimit_net_exit,
1008 .id = &hashlimit_net_id,
1009 .size = sizeof(struct hashlimit_net),
1010};
1011
960static int __init hashlimit_mt_init(void) 1012static int __init hashlimit_mt_init(void)
961{ 1013{
962 int err; 1014 int err;
963 1015
1016 err = register_pernet_subsys(&hashlimit_net_ops);
1017 if (err < 0)
1018 return err;
964 err = xt_register_matches(hashlimit_mt_reg, 1019 err = xt_register_matches(hashlimit_mt_reg,
965 ARRAY_SIZE(hashlimit_mt_reg)); 1020 ARRAY_SIZE(hashlimit_mt_reg));
966 if (err < 0) 1021 if (err < 0)
@@ -974,41 +1029,21 @@ static int __init hashlimit_mt_init(void)
974 printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n"); 1029 printk(KERN_ERR "xt_hashlimit: unable to create slab cache\n");
975 goto err2; 1030 goto err2;
976 } 1031 }
977 hashlimit_procdir4 = proc_mkdir("ipt_hashlimit", init_net.proc_net); 1032 return 0;
978 if (!hashlimit_procdir4) { 1033
979 printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
980 "entry\n");
981 goto err3;
982 }
983 err = 0;
984#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
985 hashlimit_procdir6 = proc_mkdir("ip6t_hashlimit", init_net.proc_net);
986 if (!hashlimit_procdir6) {
987 printk(KERN_ERR "xt_hashlimit: unable to create proc dir "
988 "entry\n");
989 err = -ENOMEM;
990 }
991#endif
992 if (!err)
993 return 0;
994 remove_proc_entry("ipt_hashlimit", init_net.proc_net);
995err3:
996 kmem_cache_destroy(hashlimit_cachep);
997err2: 1034err2:
998 xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); 1035 xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
999err1: 1036err1:
1037 unregister_pernet_subsys(&hashlimit_net_ops);
1000 return err; 1038 return err;
1001 1039
1002} 1040}
1003 1041
1004static void __exit hashlimit_mt_exit(void) 1042static void __exit hashlimit_mt_exit(void)
1005{ 1043{
1006 remove_proc_entry("ipt_hashlimit", init_net.proc_net);
1007#if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE)
1008 remove_proc_entry("ip6t_hashlimit", init_net.proc_net);
1009#endif
1010 kmem_cache_destroy(hashlimit_cachep); 1044 kmem_cache_destroy(hashlimit_cachep);
1011 xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg)); 1045 xt_unregister_matches(hashlimit_mt_reg, ARRAY_SIZE(hashlimit_mt_reg));
1046 unregister_pernet_subsys(&hashlimit_net_ops);
1012} 1047}
1013 1048
1014module_init(hashlimit_mt_init); 1049module_init(hashlimit_mt_init);
diff --git a/net/netfilter/xt_limit.c b/net/netfilter/xt_limit.c
index 2773be6a71dd..a0ca5339af41 100644
--- a/net/netfilter/xt_limit.c
+++ b/net/netfilter/xt_limit.c
@@ -148,7 +148,7 @@ struct compat_xt_rateinfo {
148 148
149/* To keep the full "prev" timestamp, the upper 32 bits are stored in the 149/* To keep the full "prev" timestamp, the upper 32 bits are stored in the
150 * master pointer, which does not need to be preserved. */ 150 * master pointer, which does not need to be preserved. */
151static void limit_mt_compat_from_user(void *dst, void *src) 151static void limit_mt_compat_from_user(void *dst, const void *src)
152{ 152{
153 const struct compat_xt_rateinfo *cm = src; 153 const struct compat_xt_rateinfo *cm = src;
154 struct xt_rateinfo m = { 154 struct xt_rateinfo m = {
@@ -162,7 +162,7 @@ static void limit_mt_compat_from_user(void *dst, void *src)
162 memcpy(dst, &m, sizeof(m)); 162 memcpy(dst, &m, sizeof(m));
163} 163}
164 164
165static int limit_mt_compat_to_user(void __user *dst, void *src) 165static int limit_mt_compat_to_user(void __user *dst, const void *src)
166{ 166{
167 const struct xt_rateinfo *m = src; 167 const struct xt_rateinfo *m = src;
168 struct compat_xt_rateinfo cm = { 168 struct compat_xt_rateinfo cm = {
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c
index 4d1a41bbd5d7..4169e200588d 100644
--- a/net/netfilter/xt_osf.c
+++ b/net/netfilter/xt_osf.c
@@ -334,7 +334,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
334 if (info->flags & XT_OSF_LOG) 334 if (info->flags & XT_OSF_LOG)
335 nf_log_packet(p->family, p->hooknum, skb, 335 nf_log_packet(p->family, p->hooknum, skb,
336 p->in, p->out, NULL, 336 p->in, p->out, NULL,
337 "%s [%s:%s] : %pi4:%d -> %pi4:%d hops=%d\n", 337 "%s [%s:%s] : %pI4:%d -> %pI4:%d hops=%d\n",
338 f->genre, f->version, f->subtype, 338 f->genre, f->version, f->subtype,
339 &ip->saddr, ntohs(tcp->source), 339 &ip->saddr, ntohs(tcp->source),
340 &ip->daddr, ntohs(tcp->dest), 340 &ip->daddr, ntohs(tcp->dest),
@@ -349,7 +349,7 @@ static bool xt_osf_match_packet(const struct sk_buff *skb,
349 349
350 if (!fcount && (info->flags & XT_OSF_LOG)) 350 if (!fcount && (info->flags & XT_OSF_LOG))
351 nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL, 351 nf_log_packet(p->family, p->hooknum, skb, p->in, p->out, NULL,
352 "Remote OS is not known: %pi4:%u -> %pi4:%u\n", 352 "Remote OS is not known: %pI4:%u -> %pI4:%u\n",
353 &ip->saddr, ntohs(tcp->source), 353 &ip->saddr, ntohs(tcp->source),
354 &ip->daddr, ntohs(tcp->dest)); 354 &ip->daddr, ntohs(tcp->dest));
355 355
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c
index fc70a49c0afd..132cfaa84cdc 100644
--- a/net/netfilter/xt_recent.c
+++ b/net/netfilter/xt_recent.c
@@ -28,6 +28,7 @@
28#include <linux/skbuff.h> 28#include <linux/skbuff.h>
29#include <linux/inet.h> 29#include <linux/inet.h>
30#include <net/net_namespace.h> 30#include <net/net_namespace.h>
31#include <net/netns/generic.h>
31 32
32#include <linux/netfilter/x_tables.h> 33#include <linux/netfilter/x_tables.h>
33#include <linux/netfilter/xt_recent.h> 34#include <linux/netfilter/xt_recent.h>
@@ -52,7 +53,7 @@ module_param(ip_list_perms, uint, 0400);
52module_param(ip_list_uid, uint, 0400); 53module_param(ip_list_uid, uint, 0400);
53module_param(ip_list_gid, uint, 0400); 54module_param(ip_list_gid, uint, 0400);
54MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list"); 55MODULE_PARM_DESC(ip_list_tot, "number of IPs to remember per list");
55MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP to remember (max. 255)"); 56MODULE_PARM_DESC(ip_pkt_list_tot, "number of packets per IP address to remember (max. 255)");
56MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs"); 57MODULE_PARM_DESC(ip_list_hash_size, "size of hash table used to look up IPs");
57MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files"); 58MODULE_PARM_DESC(ip_list_perms, "permissions on /proc/net/xt_recent/* files");
58MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files"); 59MODULE_PARM_DESC(ip_list_uid,"owner of /proc/net/xt_recent/* files");
@@ -78,37 +79,40 @@ struct recent_table {
78 struct list_head iphash[0]; 79 struct list_head iphash[0];
79}; 80};
80 81
81static LIST_HEAD(tables); 82struct recent_net {
83 struct list_head tables;
84#ifdef CONFIG_PROC_FS
85 struct proc_dir_entry *xt_recent;
86#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
87 struct proc_dir_entry *ipt_recent;
88#endif
89#endif
90};
91
92static int recent_net_id;
93static inline struct recent_net *recent_pernet(struct net *net)
94{
95 return net_generic(net, recent_net_id);
96}
97
82static DEFINE_SPINLOCK(recent_lock); 98static DEFINE_SPINLOCK(recent_lock);
83static DEFINE_MUTEX(recent_mutex); 99static DEFINE_MUTEX(recent_mutex);
84 100
85#ifdef CONFIG_PROC_FS 101#ifdef CONFIG_PROC_FS
86#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
87static struct proc_dir_entry *proc_old_dir;
88#endif
89static struct proc_dir_entry *recent_proc_dir;
90static const struct file_operations recent_old_fops, recent_mt_fops; 102static const struct file_operations recent_old_fops, recent_mt_fops;
91#endif 103#endif
92 104
93static u_int32_t hash_rnd; 105static u_int32_t hash_rnd __read_mostly;
94static bool hash_rnd_initted; 106static bool hash_rnd_inited __read_mostly;
95 107
96static unsigned int recent_entry_hash4(const union nf_inet_addr *addr) 108static inline unsigned int recent_entry_hash4(const union nf_inet_addr *addr)
97{ 109{
98 if (!hash_rnd_initted) {
99 get_random_bytes(&hash_rnd, sizeof(hash_rnd));
100 hash_rnd_initted = true;
101 }
102 return jhash_1word((__force u32)addr->ip, hash_rnd) & 110 return jhash_1word((__force u32)addr->ip, hash_rnd) &
103 (ip_list_hash_size - 1); 111 (ip_list_hash_size - 1);
104} 112}
105 113
106static unsigned int recent_entry_hash6(const union nf_inet_addr *addr) 114static inline unsigned int recent_entry_hash6(const union nf_inet_addr *addr)
107{ 115{
108 if (!hash_rnd_initted) {
109 get_random_bytes(&hash_rnd, sizeof(hash_rnd));
110 hash_rnd_initted = true;
111 }
112 return jhash2((u32 *)addr->ip6, ARRAY_SIZE(addr->ip6), hash_rnd) & 116 return jhash2((u32 *)addr->ip6, ARRAY_SIZE(addr->ip6), hash_rnd) &
113 (ip_list_hash_size - 1); 117 (ip_list_hash_size - 1);
114} 118}
@@ -180,11 +184,12 @@ static void recent_entry_update(struct recent_table *t, struct recent_entry *e)
180 list_move_tail(&e->lru_list, &t->lru_list); 184 list_move_tail(&e->lru_list, &t->lru_list);
181} 185}
182 186
183static struct recent_table *recent_table_lookup(const char *name) 187static struct recent_table *recent_table_lookup(struct recent_net *recent_net,
188 const char *name)
184{ 189{
185 struct recent_table *t; 190 struct recent_table *t;
186 191
187 list_for_each_entry(t, &tables, list) 192 list_for_each_entry(t, &recent_net->tables, list)
188 if (!strcmp(t->name, name)) 193 if (!strcmp(t->name, name))
189 return t; 194 return t;
190 return NULL; 195 return NULL;
@@ -203,6 +208,8 @@ static void recent_table_flush(struct recent_table *t)
203static bool 208static bool
204recent_mt(const struct sk_buff *skb, const struct xt_match_param *par) 209recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)
205{ 210{
211 struct net *net = dev_net(par->in ? par->in : par->out);
212 struct recent_net *recent_net = recent_pernet(net);
206 const struct xt_recent_mtinfo *info = par->matchinfo; 213 const struct xt_recent_mtinfo *info = par->matchinfo;
207 struct recent_table *t; 214 struct recent_table *t;
208 struct recent_entry *e; 215 struct recent_entry *e;
@@ -235,7 +242,7 @@ recent_mt(const struct sk_buff *skb, const struct xt_match_param *par)
235 ttl++; 242 ttl++;
236 243
237 spin_lock_bh(&recent_lock); 244 spin_lock_bh(&recent_lock);
238 t = recent_table_lookup(info->name); 245 t = recent_table_lookup(recent_net, info->name);
239 e = recent_entry_lookup(t, &addr, par->match->family, 246 e = recent_entry_lookup(t, &addr, par->match->family,
240 (info->check_set & XT_RECENT_TTL) ? ttl : 0); 247 (info->check_set & XT_RECENT_TTL) ? ttl : 0);
241 if (e == NULL) { 248 if (e == NULL) {
@@ -279,6 +286,7 @@ out:
279 286
280static bool recent_mt_check(const struct xt_mtchk_param *par) 287static bool recent_mt_check(const struct xt_mtchk_param *par)
281{ 288{
289 struct recent_net *recent_net = recent_pernet(par->net);
282 const struct xt_recent_mtinfo *info = par->matchinfo; 290 const struct xt_recent_mtinfo *info = par->matchinfo;
283 struct recent_table *t; 291 struct recent_table *t;
284#ifdef CONFIG_PROC_FS 292#ifdef CONFIG_PROC_FS
@@ -287,6 +295,10 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
287 unsigned i; 295 unsigned i;
288 bool ret = false; 296 bool ret = false;
289 297
298 if (unlikely(!hash_rnd_inited)) {
299 get_random_bytes(&hash_rnd, sizeof(hash_rnd));
300 hash_rnd_inited = true;
301 }
290 if (hweight8(info->check_set & 302 if (hweight8(info->check_set &
291 (XT_RECENT_SET | XT_RECENT_REMOVE | 303 (XT_RECENT_SET | XT_RECENT_REMOVE |
292 XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1) 304 XT_RECENT_CHECK | XT_RECENT_UPDATE)) != 1)
@@ -294,14 +306,18 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
294 if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) && 306 if ((info->check_set & (XT_RECENT_SET | XT_RECENT_REMOVE)) &&
295 (info->seconds || info->hit_count)) 307 (info->seconds || info->hit_count))
296 return false; 308 return false;
297 if (info->hit_count > ip_pkt_list_tot) 309 if (info->hit_count > ip_pkt_list_tot) {
310 pr_info(KBUILD_MODNAME ": hitcount (%u) is larger than "
311 "packets to be remembered (%u)\n",
312 info->hit_count, ip_pkt_list_tot);
298 return false; 313 return false;
314 }
299 if (info->name[0] == '\0' || 315 if (info->name[0] == '\0' ||
300 strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN) 316 strnlen(info->name, XT_RECENT_NAME_LEN) == XT_RECENT_NAME_LEN)
301 return false; 317 return false;
302 318
303 mutex_lock(&recent_mutex); 319 mutex_lock(&recent_mutex);
304 t = recent_table_lookup(info->name); 320 t = recent_table_lookup(recent_net, info->name);
305 if (t != NULL) { 321 if (t != NULL) {
306 t->refcnt++; 322 t->refcnt++;
307 ret = true; 323 ret = true;
@@ -318,7 +334,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
318 for (i = 0; i < ip_list_hash_size; i++) 334 for (i = 0; i < ip_list_hash_size; i++)
319 INIT_LIST_HEAD(&t->iphash[i]); 335 INIT_LIST_HEAD(&t->iphash[i]);
320#ifdef CONFIG_PROC_FS 336#ifdef CONFIG_PROC_FS
321 pde = proc_create_data(t->name, ip_list_perms, recent_proc_dir, 337 pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent,
322 &recent_mt_fops, t); 338 &recent_mt_fops, t);
323 if (pde == NULL) { 339 if (pde == NULL) {
324 kfree(t); 340 kfree(t);
@@ -327,10 +343,10 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
327 pde->uid = ip_list_uid; 343 pde->uid = ip_list_uid;
328 pde->gid = ip_list_gid; 344 pde->gid = ip_list_gid;
329#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT 345#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
330 pde = proc_create_data(t->name, ip_list_perms, proc_old_dir, 346 pde = proc_create_data(t->name, ip_list_perms, recent_net->ipt_recent,
331 &recent_old_fops, t); 347 &recent_old_fops, t);
332 if (pde == NULL) { 348 if (pde == NULL) {
333 remove_proc_entry(t->name, proc_old_dir); 349 remove_proc_entry(t->name, recent_net->xt_recent);
334 kfree(t); 350 kfree(t);
335 goto out; 351 goto out;
336 } 352 }
@@ -339,7 +355,7 @@ static bool recent_mt_check(const struct xt_mtchk_param *par)
339#endif 355#endif
340#endif 356#endif
341 spin_lock_bh(&recent_lock); 357 spin_lock_bh(&recent_lock);
342 list_add_tail(&t->list, &tables); 358 list_add_tail(&t->list, &recent_net->tables);
343 spin_unlock_bh(&recent_lock); 359 spin_unlock_bh(&recent_lock);
344 ret = true; 360 ret = true;
345out: 361out:
@@ -349,20 +365,21 @@ out:
349 365
350static void recent_mt_destroy(const struct xt_mtdtor_param *par) 366static void recent_mt_destroy(const struct xt_mtdtor_param *par)
351{ 367{
368 struct recent_net *recent_net = recent_pernet(par->net);
352 const struct xt_recent_mtinfo *info = par->matchinfo; 369 const struct xt_recent_mtinfo *info = par->matchinfo;
353 struct recent_table *t; 370 struct recent_table *t;
354 371
355 mutex_lock(&recent_mutex); 372 mutex_lock(&recent_mutex);
356 t = recent_table_lookup(info->name); 373 t = recent_table_lookup(recent_net, info->name);
357 if (--t->refcnt == 0) { 374 if (--t->refcnt == 0) {
358 spin_lock_bh(&recent_lock); 375 spin_lock_bh(&recent_lock);
359 list_del(&t->list); 376 list_del(&t->list);
360 spin_unlock_bh(&recent_lock); 377 spin_unlock_bh(&recent_lock);
361#ifdef CONFIG_PROC_FS 378#ifdef CONFIG_PROC_FS
362#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT 379#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
363 remove_proc_entry(t->name, proc_old_dir); 380 remove_proc_entry(t->name, recent_net->ipt_recent);
364#endif 381#endif
365 remove_proc_entry(t->name, recent_proc_dir); 382 remove_proc_entry(t->name, recent_net->xt_recent);
366#endif 383#endif
367 recent_table_flush(t); 384 recent_table_flush(t);
368 kfree(t); 385 kfree(t);
@@ -611,8 +628,65 @@ static const struct file_operations recent_mt_fops = {
611 .release = seq_release_private, 628 .release = seq_release_private,
612 .owner = THIS_MODULE, 629 .owner = THIS_MODULE,
613}; 630};
631
632static int __net_init recent_proc_net_init(struct net *net)
633{
634 struct recent_net *recent_net = recent_pernet(net);
635
636 recent_net->xt_recent = proc_mkdir("xt_recent", net->proc_net);
637 if (!recent_net->xt_recent)
638 return -ENOMEM;
639#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
640 recent_net->ipt_recent = proc_mkdir("ipt_recent", net->proc_net);
641 if (!recent_net->ipt_recent) {
642 proc_net_remove(net, "xt_recent");
643 return -ENOMEM;
644 }
645#endif
646 return 0;
647}
648
649static void __net_exit recent_proc_net_exit(struct net *net)
650{
651#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
652 proc_net_remove(net, "ipt_recent");
653#endif
654 proc_net_remove(net, "xt_recent");
655}
656#else
657static inline int recent_proc_net_init(struct net *net)
658{
659 return 0;
660}
661
662static inline void recent_proc_net_exit(struct net *net)
663{
664}
614#endif /* CONFIG_PROC_FS */ 665#endif /* CONFIG_PROC_FS */
615 666
667static int __net_init recent_net_init(struct net *net)
668{
669 struct recent_net *recent_net = recent_pernet(net);
670
671 INIT_LIST_HEAD(&recent_net->tables);
672 return recent_proc_net_init(net);
673}
674
675static void __net_exit recent_net_exit(struct net *net)
676{
677 struct recent_net *recent_net = recent_pernet(net);
678
679 BUG_ON(!list_empty(&recent_net->tables));
680 recent_proc_net_exit(net);
681}
682
683static struct pernet_operations recent_net_ops = {
684 .init = recent_net_init,
685 .exit = recent_net_exit,
686 .id = &recent_net_id,
687 .size = sizeof(struct recent_net),
688};
689
616static struct xt_match recent_mt_reg[] __read_mostly = { 690static struct xt_match recent_mt_reg[] __read_mostly = {
617 { 691 {
618 .name = "recent", 692 .name = "recent",
@@ -644,39 +718,19 @@ static int __init recent_mt_init(void)
644 return -EINVAL; 718 return -EINVAL;
645 ip_list_hash_size = 1 << fls(ip_list_tot); 719 ip_list_hash_size = 1 << fls(ip_list_tot);
646 720
647 err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); 721 err = register_pernet_subsys(&recent_net_ops);
648#ifdef CONFIG_PROC_FS
649 if (err) 722 if (err)
650 return err; 723 return err;
651 recent_proc_dir = proc_mkdir("xt_recent", init_net.proc_net); 724 err = xt_register_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
652 if (recent_proc_dir == NULL) { 725 if (err)
653 xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); 726 unregister_pernet_subsys(&recent_net_ops);
654 err = -ENOMEM;
655 }
656#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
657 if (err < 0)
658 return err;
659 proc_old_dir = proc_mkdir("ipt_recent", init_net.proc_net);
660 if (proc_old_dir == NULL) {
661 remove_proc_entry("xt_recent", init_net.proc_net);
662 xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
663 err = -ENOMEM;
664 }
665#endif
666#endif
667 return err; 727 return err;
668} 728}
669 729
670static void __exit recent_mt_exit(void) 730static void __exit recent_mt_exit(void)
671{ 731{
672 BUG_ON(!list_empty(&tables));
673 xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg)); 732 xt_unregister_matches(recent_mt_reg, ARRAY_SIZE(recent_mt_reg));
674#ifdef CONFIG_PROC_FS 733 unregister_pernet_subsys(&recent_net_ops);
675#ifdef CONFIG_NETFILTER_XT_MATCH_RECENT_PROC_COMPAT
676 remove_proc_entry("ipt_recent", init_net.proc_net);
677#endif
678 remove_proc_entry("xt_recent", init_net.proc_net);
679#endif
680} 734}
681 735
682module_init(recent_mt_init); 736module_init(recent_mt_init);
diff --git a/net/netfilter/xt_repldata.h b/net/netfilter/xt_repldata.h
new file mode 100644
index 000000000000..6efe4e5a81c6
--- /dev/null
+++ b/net/netfilter/xt_repldata.h
@@ -0,0 +1,35 @@
1/*
2 * Today's hack: quantum tunneling in structs
3 *
4 * 'entries' and 'term' are never anywhere referenced by word in code. In fact,
5 * they serve as the hanging-off data accessed through repl.data[].
6 */
7
8#define xt_alloc_initial_table(type, typ2) ({ \
9 unsigned int hook_mask = info->valid_hooks; \
10 unsigned int nhooks = hweight32(hook_mask); \
11 unsigned int bytes = 0, hooknum = 0, i = 0; \
12 struct { \
13 struct type##_replace repl; \
14 struct type##_standard entries[nhooks]; \
15 struct type##_error term; \
16 } *tbl = kzalloc(sizeof(*tbl), GFP_KERNEL); \
17 if (tbl == NULL) \
18 return NULL; \
19 strncpy(tbl->repl.name, info->name, sizeof(tbl->repl.name)); \
20 tbl->term = (struct type##_error)typ2##_ERROR_INIT; \
21 tbl->repl.valid_hooks = hook_mask; \
22 tbl->repl.num_entries = nhooks + 1; \
23 tbl->repl.size = nhooks * sizeof(struct type##_standard) + \
24 sizeof(struct type##_error); \
25 for (; hook_mask != 0; hook_mask >>= 1, ++hooknum) { \
26 if (!(hook_mask & 1)) \
27 continue; \
28 tbl->repl.hook_entry[hooknum] = bytes; \
29 tbl->repl.underflow[hooknum] = bytes; \
30 tbl->entries[i++] = (struct type##_standard) \
31 typ2##_STANDARD_INIT(NF_ACCEPT); \
32 bytes += sizeof(struct type##_standard); \
33 } \
34 tbl; \
35})