diff options
-rw-r--r-- | include/net/netns/ipv4.h | 2 | ||||
-rw-r--r-- | net/ipv4/icmp.c | 49 |
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 | */ |
232 | static struct sock **__icmp_sk = NULL; | 232 | static 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 | ||
235 | static inline int icmp_xmit_lock(struct sock *sk) | 237 | static 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 | ||
379 | static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | 381 | static 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 | ||
1145 | static void __exit icmp_exit(void) | 1149 | static 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 | ||
1155 | int __init icmp_init(void) | 1159 | int __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 | ||
1195 | fail: | 1200 | fail: |
1196 | icmp_exit(); | 1201 | icmp_sk_exit(net); |
1197 | return err; | 1202 | return err; |
1198 | } | 1203 | } |
1199 | 1204 | ||
1205 | static struct pernet_operations __net_initdata icmp_sk_ops = { | ||
1206 | .init = icmp_sk_init, | ||
1207 | .exit = icmp_sk_exit, | ||
1208 | }; | ||
1209 | |||
1210 | int __init icmp_init(void) | ||
1211 | { | ||
1212 | return register_pernet_device(&icmp_sk_ops); | ||
1213 | } | ||
1214 | |||
1200 | EXPORT_SYMBOL(icmp_err_convert); | 1215 | EXPORT_SYMBOL(icmp_err_convert); |
1201 | EXPORT_SYMBOL(icmp_send); | 1216 | EXPORT_SYMBOL(icmp_send); |
1202 | EXPORT_SYMBOL(icmp_statistics); | 1217 | EXPORT_SYMBOL(icmp_statistics); |