aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/netns/ipv4.h2
-rw-r--r--net/ipv4/icmp.c49
2 files changed, 34 insertions, 17 deletions
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index a9b4f6086294..504fde174525 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -26,6 +26,8 @@ struct netns_ipv4 {
26 struct hlist_head *fib_table_hash; 26 struct hlist_head *fib_table_hash;
27 struct sock *fibnl; 27 struct sock *fibnl;
28 28
29 struct sock **icmp_sk;
30
29 struct netns_frags frags; 31 struct netns_frags frags;
30#ifdef CONFIG_NETFILTER 32#ifdef CONFIG_NETFILTER
31 struct xt_table *iptable_filter; 33 struct xt_table *iptable_filter;
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 97d97ada4ce6..b51f4b0a3264 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -229,8 +229,10 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES+1];
229 * 229 *
230 * On SMP we have one ICMP socket per-cpu. 230 * On SMP we have one ICMP socket per-cpu.
231 */ 231 */
232static struct sock **__icmp_sk = NULL; 232static struct sock *icmp_sk(struct net *net)
233#define icmp_sk (__icmp_sk[smp_processor_id()]) 233{
234 return net->ipv4.icmp_sk[smp_processor_id()];
235}
234 236
235static inline int icmp_xmit_lock(struct sock *sk) 237static inline int icmp_xmit_lock(struct sock *sk)
236{ 238{
@@ -349,7 +351,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
349 struct sock *sk; 351 struct sock *sk;
350 struct sk_buff *skb; 352 struct sk_buff *skb;
351 353
352 sk = icmp_sk; 354 sk = icmp_sk(rt->u.dst.dev->nd_net);
353 if (ip_append_data(sk, icmp_glue_bits, icmp_param, 355 if (ip_append_data(sk, icmp_glue_bits, icmp_param,
354 icmp_param->data_len+icmp_param->head_len, 356 icmp_param->data_len+icmp_param->head_len,
355 icmp_param->head_len, 357 icmp_param->head_len,
@@ -378,10 +380,11 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param,
378 380
379static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) 381static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
380{ 382{
381 struct sock *sk = icmp_sk;
382 struct inet_sock *inet = inet_sk(sk);
383 struct ipcm_cookie ipc; 383 struct ipcm_cookie ipc;
384 struct rtable *rt = (struct rtable *)skb->dst; 384 struct rtable *rt = (struct rtable *)skb->dst;
385 struct net *net = rt->u.dst.dev->nd_net;
386 struct sock *sk = icmp_sk(net);
387 struct inet_sock *inet = inet_sk(sk);
385 __be32 daddr; 388 __be32 daddr;
386 389
387 if (ip_options_echo(&icmp_param->replyopts, skb)) 390 if (ip_options_echo(&icmp_param->replyopts, skb))
@@ -407,7 +410,7 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb)
407 .tos = RT_TOS(ip_hdr(skb)->tos) } }, 410 .tos = RT_TOS(ip_hdr(skb)->tos) } },
408 .proto = IPPROTO_ICMP }; 411 .proto = IPPROTO_ICMP };
409 security_skb_classify_flow(skb, &fl); 412 security_skb_classify_flow(skb, &fl);
410 if (ip_route_output_key(rt->u.dst.dev->nd_net, &rt, &fl)) 413 if (ip_route_output_key(net, &rt, &fl))
411 goto out_unlock; 414 goto out_unlock;
412 } 415 }
413 if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type, 416 if (icmpv4_xrlim_allow(rt, icmp_param->data.icmph.type,
@@ -440,11 +443,12 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
440 __be32 saddr; 443 __be32 saddr;
441 u8 tos; 444 u8 tos;
442 struct net *net; 445 struct net *net;
443 struct sock *sk = icmp_sk; 446 struct sock *sk;
444 447
445 if (!rt) 448 if (!rt)
446 goto out; 449 goto out;
447 net = rt->u.dst.dev->nd_net; 450 net = rt->u.dst.dev->nd_net;
451 sk = icmp_sk(net);
448 452
449 /* 453 /*
450 * Find the original header. It is expected to be valid, of course. 454 * Find the original header. It is expected to be valid, of course.
@@ -1142,22 +1146,23 @@ static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = {
1142 }, 1146 },
1143}; 1147};
1144 1148
1145static void __exit icmp_exit(void) 1149static void __net_exit icmp_sk_exit(struct net *net)
1146{ 1150{
1147 int i; 1151 int i;
1148 1152
1149 for_each_possible_cpu(i) 1153 for_each_possible_cpu(i)
1150 sk_release_kernel(__icmp_sk[i]); 1154 sk_release_kernel(net->ipv4.icmp_sk[i]);
1151 kfree(__icmp_sk); 1155 kfree(net->ipv4.icmp_sk);
1152 __icmp_sk = NULL; 1156 net->ipv4.icmp_sk = NULL;
1153} 1157}
1154 1158
1155int __init icmp_init(void) 1159int __net_init icmp_sk_init(struct net *net)
1156{ 1160{
1157 int i, err; 1161 int i, err;
1158 1162
1159 __icmp_sk = kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL); 1163 net->ipv4.icmp_sk =
1160 if (__icmp_sk == NULL) 1164 kzalloc(nr_cpu_ids * sizeof(struct sock *), GFP_KERNEL);
1165 if (net->ipv4.icmp_sk == NULL)
1161 return -ENOMEM; 1166 return -ENOMEM;
1162 1167
1163 for_each_possible_cpu(i) { 1168 for_each_possible_cpu(i) {
@@ -1169,8 +1174,8 @@ int __init icmp_init(void)
1169 if (err < 0) 1174 if (err < 0)
1170 goto fail; 1175 goto fail;
1171 1176
1172 __icmp_sk[i] = sk = sock->sk; 1177 net->ipv4.icmp_sk[i] = sk = sock->sk;
1173 sk_change_net(sk, &init_net); 1178 sk_change_net(sk, net);
1174 1179
1175 sk->sk_allocation = GFP_ATOMIC; 1180 sk->sk_allocation = GFP_ATOMIC;
1176 1181
@@ -1193,10 +1198,20 @@ int __init icmp_init(void)
1193 return 0; 1198 return 0;
1194 1199
1195fail: 1200fail:
1196 icmp_exit(); 1201 icmp_sk_exit(net);
1197 return err; 1202 return err;
1198} 1203}
1199 1204
1205static struct pernet_operations __net_initdata icmp_sk_ops = {
1206 .init = icmp_sk_init,
1207 .exit = icmp_sk_exit,
1208};
1209
1210int __init icmp_init(void)
1211{
1212 return register_pernet_device(&icmp_sk_ops);
1213}
1214
1200EXPORT_SYMBOL(icmp_err_convert); 1215EXPORT_SYMBOL(icmp_err_convert);
1201EXPORT_SYMBOL(icmp_send); 1216EXPORT_SYMBOL(icmp_send);
1202EXPORT_SYMBOL(icmp_statistics); 1217EXPORT_SYMBOL(icmp_statistics);