Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later
2 : : /*
3 : : * Internet Control Message Protocol (ICMPv6)
4 : : * Linux INET6 implementation
5 : : *
6 : : * Authors:
7 : : * Pedro Roque <roque@di.fc.ul.pt>
8 : : *
9 : : * Based on net/ipv4/icmp.c
10 : : *
11 : : * RFC 1885
12 : : */
13 : :
14 : : /*
15 : : * Changes:
16 : : *
17 : : * Andi Kleen : exception handling
18 : : * Andi Kleen add rate limits. never reply to a icmp.
19 : : * add more length checks and other fixes.
20 : : * yoshfuji : ensure to sent parameter problem for
21 : : * fragments.
22 : : * YOSHIFUJI Hideaki @USAGI: added sysctl for icmp rate limit.
23 : : * Randy Dunlap and
24 : : * YOSHIFUJI Hideaki @USAGI: Per-interface statistics support
25 : : * Kazunori MIYAZAWA @USAGI: change output process to use ip6_append_data
26 : : */
27 : :
28 : : #define pr_fmt(fmt) "IPv6: " fmt
29 : :
30 : : #include <linux/module.h>
31 : : #include <linux/errno.h>
32 : : #include <linux/types.h>
33 : : #include <linux/socket.h>
34 : : #include <linux/in.h>
35 : : #include <linux/kernel.h>
36 : : #include <linux/sockios.h>
37 : : #include <linux/net.h>
38 : : #include <linux/skbuff.h>
39 : : #include <linux/init.h>
40 : : #include <linux/netfilter.h>
41 : : #include <linux/slab.h>
42 : :
43 : : #ifdef CONFIG_SYSCTL
44 : : #include <linux/sysctl.h>
45 : : #endif
46 : :
47 : : #include <linux/inet.h>
48 : : #include <linux/netdevice.h>
49 : : #include <linux/icmpv6.h>
50 : :
51 : : #include <net/ip.h>
52 : : #include <net/sock.h>
53 : :
54 : : #include <net/ipv6.h>
55 : : #include <net/ip6_checksum.h>
56 : : #include <net/ping.h>
57 : : #include <net/protocol.h>
58 : : #include <net/raw.h>
59 : : #include <net/rawv6.h>
60 : : #include <net/transp_v6.h>
61 : : #include <net/ip6_route.h>
62 : : #include <net/addrconf.h>
63 : : #include <net/icmp.h>
64 : : #include <net/xfrm.h>
65 : : #include <net/inet_common.h>
66 : : #include <net/dsfield.h>
67 : : #include <net/l3mdev.h>
68 : :
69 : : #include <linux/uaccess.h>
70 : :
71 : : /*
72 : : * The ICMP socket(s). This is the most convenient way to flow control
73 : : * our ICMP output as well as maintain a clean interface throughout
74 : : * all layers. All Socketless IP sends will soon be gone.
75 : : *
76 : : * On SMP we have one ICMP socket per-cpu.
77 : : */
78 : 0 : static struct sock *icmpv6_sk(struct net *net)
79 : : {
80 : 0 : return this_cpu_read(*net->ipv6.icmp_sk);
81 : : }
82 : :
83 : 0 : static int icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
84 : : u8 type, u8 code, int offset, __be32 info)
85 : : {
86 : : /* icmpv6_notify checks 8 bytes can be pulled, icmp6hdr is 8 bytes */
87 : 0 : struct icmp6hdr *icmp6 = (struct icmp6hdr *) (skb->data + offset);
88 [ # # ]: 0 : struct net *net = dev_net(skb->dev);
89 : :
90 [ # # ]: 0 : if (type == ICMPV6_PKT_TOOBIG)
91 : 0 : ip6_update_pmtu(skb, net, info, skb->dev->ifindex, 0, sock_net_uid(net, NULL));
92 [ # # ]: 0 : else if (type == NDISC_REDIRECT)
93 : 0 : ip6_redirect(skb, net, skb->dev->ifindex, 0,
94 : : sock_net_uid(net, NULL));
95 : :
96 [ # # ]: 0 : if (!(type & ICMPV6_INFOMSG_MASK))
97 [ # # ]: 0 : if (icmp6->icmp6_type == ICMPV6_ECHO_REQUEST)
98 : 0 : ping_err(skb, offset, ntohl(info));
99 : :
100 : 0 : return 0;
101 : : }
102 : :
103 : : static int icmpv6_rcv(struct sk_buff *skb);
104 : :
105 : : static const struct inet6_protocol icmpv6_protocol = {
106 : : .handler = icmpv6_rcv,
107 : : .err_handler = icmpv6_err,
108 : : .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
109 : : };
110 : :
111 : : /* Called with BH disabled */
112 : 0 : static __inline__ struct sock *icmpv6_xmit_lock(struct net *net)
113 : : {
114 : 0 : struct sock *sk;
115 : :
116 : 0 : sk = icmpv6_sk(net);
117 [ # # # # ]: 0 : if (unlikely(!spin_trylock(&sk->sk_lock.slock))) {
118 : : /* This can happen if the output path (f.e. SIT or
119 : : * ip6ip6 tunnel) signals dst_link_failure() for an
120 : : * outgoing ICMP6 packet.
121 : : */
122 : : return NULL;
123 : : }
124 : : return sk;
125 : : }
126 : :
127 : 0 : static __inline__ void icmpv6_xmit_unlock(struct sock *sk)
128 : : {
129 : 0 : spin_unlock(&sk->sk_lock.slock);
130 : 0 : }
131 : :
132 : : /*
133 : : * Figure out, may we reply to this packet with icmp error.
134 : : *
135 : : * We do not reply, if:
136 : : * - it was icmp error message.
137 : : * - it is truncated, so that it is known, that protocol is ICMPV6
138 : : * (i.e. in the middle of some exthdr)
139 : : *
140 : : * --ANK (980726)
141 : : */
142 : :
143 : 0 : static bool is_ineligible(const struct sk_buff *skb)
144 : : {
145 [ # # ]: 0 : int ptr = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
146 : 0 : int len = skb->len - ptr;
147 : 0 : __u8 nexthdr = ipv6_hdr(skb)->nexthdr;
148 : 0 : __be16 frag_off;
149 : :
150 [ # # ]: 0 : if (len < 0)
151 : : return true;
152 : :
153 : 0 : ptr = ipv6_skip_exthdr(skb, ptr, &nexthdr, &frag_off);
154 [ # # ]: 0 : if (ptr < 0)
155 : : return false;
156 [ # # ]: 0 : if (nexthdr == IPPROTO_ICMPV6) {
157 : 0 : u8 _type, *tp;
158 : 0 : tp = skb_header_pointer(skb,
159 : : ptr+offsetof(struct icmp6hdr, icmp6_type),
160 : : sizeof(_type), &_type);
161 [ # # # # ]: 0 : if (!tp || !(*tp & ICMPV6_INFOMSG_MASK))
162 : 0 : return true;
163 : : }
164 : : return false;
165 : : }
166 : :
167 : 0 : static bool icmpv6_mask_allow(struct net *net, int type)
168 : : {
169 : 0 : if (type > ICMPV6_MSG_MAX)
170 : : return true;
171 : :
172 : : /* Limit if icmp type is set in ratemask. */
173 [ # # # # ]: 0 : if (!test_bit(type, net->ipv6.sysctl.icmpv6_ratemask))
174 : : return true;
175 : :
176 : : return false;
177 : : }
178 : :
179 : 0 : static bool icmpv6_global_allow(struct net *net, int type)
180 : : {
181 [ # # ]: 0 : if (icmpv6_mask_allow(net, type))
182 : 0 : return true;
183 : :
184 [ # # ]: 0 : if (icmp_global_allow())
185 : 0 : return true;
186 : :
187 : : return false;
188 : : }
189 : :
190 : : /*
191 : : * Check the ICMP output rate limit
192 : : */
193 : 0 : static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
194 : : struct flowi6 *fl6)
195 : : {
196 : 0 : struct net *net = sock_net(sk);
197 : 0 : struct dst_entry *dst;
198 : 0 : bool res = false;
199 : :
200 : 0 : if (icmpv6_mask_allow(net, type))
201 : : return true;
202 : :
203 : : /*
204 : : * Look up the output route.
205 : : * XXX: perhaps the expire for routing entries cloned by
206 : : * this lookup should be more aggressive (not longer than timeout).
207 : : */
208 : 0 : dst = ip6_route_output(net, sk, fl6);
209 [ # # ]: 0 : if (dst->error) {
210 [ # # ]: 0 : IP6_INC_STATS(net, ip6_dst_idev(dst),
211 : : IPSTATS_MIB_OUTNOROUTES);
212 [ # # # # ]: 0 : } else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
213 : : res = true;
214 : : } else {
215 : 0 : struct rt6_info *rt = (struct rt6_info *)dst;
216 : 0 : int tmo = net->ipv6.sysctl.icmpv6_time;
217 : 0 : struct inet_peer *peer;
218 : :
219 : : /* Give more bandwidth to wider prefixes. */
220 [ # # ]: 0 : if (rt->rt6i_dst.plen < 128)
221 : 0 : tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
222 : :
223 : 0 : peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr, 1);
224 : 0 : res = inet_peer_xrlim_allow(peer, tmo);
225 [ # # ]: 0 : if (peer)
226 : 0 : inet_putpeer(peer);
227 : : }
228 : 0 : dst_release(dst);
229 : 0 : return res;
230 : : }
231 : :
232 : : /*
233 : : * an inline helper for the "simple" if statement below
234 : : * checks if parameter problem report is caused by an
235 : : * unrecognized IPv6 option that has the Option Type
236 : : * highest-order two bits set to 10
237 : : */
238 : :
239 : 0 : static bool opt_unrec(struct sk_buff *skb, __u32 offset)
240 : : {
241 : 0 : u8 _optval, *op;
242 : :
243 : 0 : offset += skb_network_offset(skb);
244 : 0 : op = skb_header_pointer(skb, offset, sizeof(_optval), &_optval);
245 [ # # ]: 0 : if (!op)
246 : : return true;
247 : 0 : return (*op & 0xC0) == 0x80;
248 : : }
249 : :
250 : 0 : void icmpv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6,
251 : : struct icmp6hdr *thdr, int len)
252 : : {
253 : 0 : struct sk_buff *skb;
254 : 0 : struct icmp6hdr *icmp6h;
255 : :
256 [ # # ]: 0 : skb = skb_peek(&sk->sk_write_queue);
257 [ # # ]: 0 : if (!skb)
258 : : return;
259 : :
260 [ # # ]: 0 : icmp6h = icmp6_hdr(skb);
261 : 0 : memcpy(icmp6h, thdr, sizeof(struct icmp6hdr));
262 : 0 : icmp6h->icmp6_cksum = 0;
263 : :
264 [ # # ]: 0 : if (skb_queue_len(&sk->sk_write_queue) == 1) {
265 : 0 : skb->csum = csum_partial(icmp6h,
266 : : sizeof(struct icmp6hdr), skb->csum);
267 : 0 : icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
268 : 0 : &fl6->daddr,
269 : 0 : len, fl6->flowi6_proto,
270 : : skb->csum);
271 : : } else {
272 : 0 : __wsum tmp_csum = 0;
273 : :
274 [ # # ]: 0 : skb_queue_walk(&sk->sk_write_queue, skb) {
275 : 0 : tmp_csum = csum_add(tmp_csum, skb->csum);
276 : : }
277 : :
278 : 0 : tmp_csum = csum_partial(icmp6h,
279 : : sizeof(struct icmp6hdr), tmp_csum);
280 : 0 : icmp6h->icmp6_cksum = csum_ipv6_magic(&fl6->saddr,
281 : 0 : &fl6->daddr,
282 : 0 : len, fl6->flowi6_proto,
283 : : tmp_csum);
284 : : }
285 : 0 : ip6_push_pending_frames(sk);
286 : : }
287 : :
288 : : struct icmpv6_msg {
289 : : struct sk_buff *skb;
290 : : int offset;
291 : : uint8_t type;
292 : : };
293 : :
294 : 0 : static int icmpv6_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
295 : : {
296 : 0 : struct icmpv6_msg *msg = (struct icmpv6_msg *) from;
297 : 0 : struct sk_buff *org_skb = msg->skb;
298 : 0 : __wsum csum = 0;
299 : :
300 : 0 : csum = skb_copy_and_csum_bits(org_skb, msg->offset + offset,
301 : : to, len, csum);
302 [ # # ]: 0 : skb->csum = csum_block_add(skb->csum, csum, odd);
303 [ # # ]: 0 : if (!(msg->type & ICMPV6_INFOMSG_MASK))
304 : 0 : nf_ct_attach(skb, org_skb);
305 : 0 : return 0;
306 : : }
307 : :
308 : : #if IS_ENABLED(CONFIG_IPV6_MIP6)
309 : : static void mip6_addr_swap(struct sk_buff *skb)
310 : : {
311 : : struct ipv6hdr *iph = ipv6_hdr(skb);
312 : : struct inet6_skb_parm *opt = IP6CB(skb);
313 : : struct ipv6_destopt_hao *hao;
314 : : struct in6_addr tmp;
315 : : int off;
316 : :
317 : : if (opt->dsthao) {
318 : : off = ipv6_find_tlv(skb, opt->dsthao, IPV6_TLV_HAO);
319 : : if (likely(off >= 0)) {
320 : : hao = (struct ipv6_destopt_hao *)
321 : : (skb_network_header(skb) + off);
322 : : tmp = iph->saddr;
323 : : iph->saddr = hao->addr;
324 : : hao->addr = tmp;
325 : : }
326 : : }
327 : : }
328 : : #else
329 : 0 : static inline void mip6_addr_swap(struct sk_buff *skb) {}
330 : : #endif
331 : :
332 : 0 : static struct dst_entry *icmpv6_route_lookup(struct net *net,
333 : : struct sk_buff *skb,
334 : : struct sock *sk,
335 : : struct flowi6 *fl6)
336 : : {
337 : 0 : struct dst_entry *dst, *dst2;
338 : 0 : struct flowi6 fl2;
339 : 0 : int err;
340 : :
341 : 0 : err = ip6_dst_lookup(net, sk, &dst, fl6);
342 [ # # ]: 0 : if (err)
343 : 0 : return ERR_PTR(err);
344 : :
345 : : /*
346 : : * We won't send icmp if the destination is known
347 : : * anycast.
348 : : */
349 [ # # # # ]: 0 : if (ipv6_anycast_destination(dst, &fl6->daddr)) {
350 : 0 : net_dbg_ratelimited("icmp6_send: acast source\n");
351 : 0 : dst_release(dst);
352 : 0 : return ERR_PTR(-EINVAL);
353 : : }
354 : :
355 : : /* No need to clone since we're just using its address. */
356 : 0 : dst2 = dst;
357 : :
358 : 0 : dst = xfrm_lookup(net, dst, flowi6_to_flowi(fl6), sk, 0);
359 [ # # ]: 0 : if (!IS_ERR(dst)) {
360 [ # # ]: 0 : if (dst != dst2)
361 : : return dst;
362 : : } else {
363 [ # # ]: 0 : if (PTR_ERR(dst) == -EPERM)
364 : 0 : dst = NULL;
365 : : else
366 : : return dst;
367 : : }
368 : :
369 : 0 : err = xfrm_decode_session_reverse(skb, flowi6_to_flowi(&fl2), AF_INET6);
370 [ # # ]: 0 : if (err)
371 : 0 : goto relookup_failed;
372 : :
373 : 0 : err = ip6_dst_lookup(net, sk, &dst2, &fl2);
374 [ # # ]: 0 : if (err)
375 : 0 : goto relookup_failed;
376 : :
377 : 0 : dst2 = xfrm_lookup(net, dst2, flowi6_to_flowi(&fl2), sk, XFRM_LOOKUP_ICMP);
378 [ # # ]: 0 : if (!IS_ERR(dst2)) {
379 : 0 : dst_release(dst);
380 : 0 : dst = dst2;
381 : : } else {
382 [ # # ]: 0 : err = PTR_ERR(dst2);
383 [ # # ]: 0 : if (err == -EPERM) {
384 : 0 : dst_release(dst);
385 : 0 : return dst2;
386 : : } else
387 : 0 : goto relookup_failed;
388 : : }
389 : :
390 : 0 : relookup_failed:
391 [ # # ]: 0 : if (dst)
392 : : return dst;
393 : 0 : return ERR_PTR(err);
394 : : }
395 : :
396 : 0 : static struct net_device *icmp6_dev(const struct sk_buff *skb)
397 : : {
398 : 0 : struct net_device *dev = skb->dev;
399 : :
400 : : /* for local traffic to local address, skb dev is the loopback
401 : : * device. Check if there is a dst attached to the skb and if so
402 : : * get the real device index. Same is needed for replies to a link
403 : : * local address on a device enslaved to an L3 master device
404 : : */
405 [ # # # # : 0 : if (unlikely(dev->ifindex == LOOPBACK_IFINDEX || netif_is_l3_master(skb->dev))) {
# # ]
406 [ # # # # : 0 : const struct rt6_info *rt6 = skb_rt6_info(skb);
# # ]
407 : :
408 [ # # # # : 0 : if (rt6)
# # ]
409 : 0 : dev = rt6->rt6i_idev->dev;
410 : : }
411 : :
412 : 0 : return dev;
413 : : }
414 : :
415 : 0 : static int icmp6_iif(const struct sk_buff *skb)
416 : : {
417 : 0 : return icmp6_dev(skb)->ifindex;
418 : : }
419 : :
420 : : /*
421 : : * Send an ICMP message in response to a packet in error
422 : : */
423 : 0 : static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
424 : : const struct in6_addr *force_saddr)
425 : : {
426 : 0 : struct inet6_dev *idev = NULL;
427 [ # # ]: 0 : struct ipv6hdr *hdr = ipv6_hdr(skb);
428 : 0 : struct sock *sk;
429 : 0 : struct net *net;
430 : 0 : struct ipv6_pinfo *np;
431 : 0 : const struct in6_addr *saddr = NULL;
432 : 0 : struct dst_entry *dst;
433 : 0 : struct icmp6hdr tmp_hdr;
434 : 0 : struct flowi6 fl6;
435 : 0 : struct icmpv6_msg msg;
436 : 0 : struct ipcm6_cookie ipc6;
437 : 0 : int iif = 0;
438 : 0 : int addr_type = 0;
439 : 0 : int len;
440 : 0 : u32 mark;
441 : :
442 [ # # # # ]: 0 : if ((u8 *)hdr < skb->head ||
443 [ # # ]: 0 : (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
444 : 0 : return;
445 : :
446 [ # # ]: 0 : if (!skb->dev)
447 : : return;
448 [ # # ]: 0 : net = dev_net(skb->dev);
449 [ # # ]: 0 : mark = IP6_REPLY_MARK(net, skb->mark);
450 : : /*
451 : : * Make sure we respect the rules
452 : : * i.e. RFC 1885 2.4(e)
453 : : * Rule (e.1) is enforced by not using icmp6_send
454 : : * in any code that processes icmp errors.
455 : : */
456 : 0 : addr_type = ipv6_addr_type(&hdr->daddr);
457 : :
458 [ # # # # ]: 0 : if (ipv6_chk_addr(net, &hdr->daddr, skb->dev, 0) ||
459 : 0 : ipv6_chk_acast_addr_src(net, skb->dev, &hdr->daddr))
460 : : saddr = &hdr->daddr;
461 : :
462 : : /*
463 : : * Dest addr check
464 : : */
465 : :
466 [ # # # # ]: 0 : if (addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST) {
467 [ # # ]: 0 : if (type != ICMPV6_PKT_TOOBIG &&
468 [ # # ]: 0 : !(type == ICMPV6_PARAMPROB &&
469 [ # # ]: 0 : code == ICMPV6_UNK_OPTION &&
470 : 0 : (opt_unrec(skb, info))))
471 : 0 : return;
472 : :
473 : : saddr = NULL;
474 : : }
475 : :
476 : 0 : addr_type = ipv6_addr_type(&hdr->saddr);
477 : :
478 : : /*
479 : : * Source addr check
480 : : */
481 : :
482 [ # # # # ]: 0 : if (__ipv6_addr_needs_scope_id(addr_type)) {
483 [ # # ]: 0 : iif = icmp6_iif(skb);
484 : : } else {
485 : 0 : dst = skb_dst(skb);
486 : 0 : iif = l3mdev_master_ifindex(dst ? dst->dev : skb->dev);
487 : : }
488 : :
489 : : /*
490 : : * Must not send error if the source does not uniquely
491 : : * identify a single node (RFC2463 Section 2.4).
492 : : * We check unspecified / multicast addresses here,
493 : : * and anycast addresses will be checked later.
494 : : */
495 [ # # # # ]: 0 : if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
496 : : net_dbg_ratelimited("icmp6_send: addr_any/mcast source [%pI6c > %pI6c]\n",
497 : : &hdr->saddr, &hdr->daddr);
498 : : return;
499 : : }
500 : :
501 : : /*
502 : : * Never answer to a ICMP packet.
503 : : */
504 [ # # ]: 0 : if (is_ineligible(skb)) {
505 : : net_dbg_ratelimited("icmp6_send: no reply to icmp error [%pI6c > %pI6c]\n",
506 : : &hdr->saddr, &hdr->daddr);
507 : : return;
508 : : }
509 : :
510 : : /* Needed by both icmp_global_allow and icmpv6_xmit_lock */
511 : 0 : local_bh_disable();
512 : :
513 : : /* Check global sysctl_icmp_msgs_per_sec ratelimit */
514 [ # # # # ]: 0 : if (!(skb->dev->flags & IFF_LOOPBACK) && !icmpv6_global_allow(net, type))
515 : 0 : goto out_bh_enable;
516 : :
517 : 0 : mip6_addr_swap(skb);
518 : :
519 : 0 : sk = icmpv6_xmit_lock(net);
520 [ # # ]: 0 : if (!sk)
521 : 0 : goto out_bh_enable;
522 : :
523 : 0 : memset(&fl6, 0, sizeof(fl6));
524 : 0 : fl6.flowi6_proto = IPPROTO_ICMPV6;
525 : 0 : fl6.daddr = hdr->saddr;
526 [ # # ]: 0 : if (force_saddr)
527 : 0 : saddr = force_saddr;
528 [ # # ]: 0 : if (saddr) {
529 : 0 : fl6.saddr = *saddr;
530 : : } else {
531 : : /* select a more meaningful saddr from input if */
532 : 0 : struct net_device *in_netdev;
533 : :
534 : 0 : in_netdev = dev_get_by_index(net, IP6CB(skb)->iif);
535 [ # # ]: 0 : if (in_netdev) {
536 [ # # ]: 0 : ipv6_dev_get_saddr(net, in_netdev, &fl6.daddr,
537 : 0 : inet6_sk(sk)->srcprefs,
538 : : &fl6.saddr);
539 : 0 : dev_put(in_netdev);
540 : : }
541 : : }
542 : 0 : fl6.flowi6_mark = mark;
543 : 0 : fl6.flowi6_oif = iif;
544 : 0 : fl6.fl6_icmp_type = type;
545 : 0 : fl6.fl6_icmp_code = code;
546 : 0 : fl6.flowi6_uid = sock_net_uid(net, NULL);
547 : 0 : fl6.mp_hash = rt6_multipath_hash(net, &fl6, skb, NULL);
548 [ # # ]: 0 : security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
549 : :
550 : 0 : sk->sk_mark = mark;
551 [ # # ]: 0 : np = inet6_sk(sk);
552 : :
553 [ # # ]: 0 : if (!icmpv6_xrlim_allow(sk, type, &fl6))
554 : 0 : goto out;
555 : :
556 : 0 : tmp_hdr.icmp6_type = type;
557 : 0 : tmp_hdr.icmp6_code = code;
558 : 0 : tmp_hdr.icmp6_cksum = 0;
559 : 0 : tmp_hdr.icmp6_pointer = htonl(info);
560 : :
561 [ # # # # ]: 0 : if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
562 : 0 : fl6.flowi6_oif = np->mcast_oif;
563 [ # # ]: 0 : else if (!fl6.flowi6_oif)
564 : 0 : fl6.flowi6_oif = np->ucast_oif;
565 : :
566 : 0 : ipcm6_init_sk(&ipc6, np);
567 : 0 : fl6.flowlabel = ip6_make_flowinfo(ipc6.tclass, fl6.flowlabel);
568 : :
569 : 0 : dst = icmpv6_route_lookup(net, skb, sk, &fl6);
570 [ # # ]: 0 : if (IS_ERR(dst))
571 : 0 : goto out;
572 : :
573 [ # # ]: 0 : ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
574 : :
575 : 0 : msg.skb = skb;
576 : 0 : msg.offset = skb_network_offset(skb);
577 : 0 : msg.type = type;
578 : :
579 : 0 : len = skb->len - msg.offset;
580 : 0 : len = min_t(unsigned int, len, IPV6_MIN_MTU - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr));
581 : 0 : if (len < 0) {
582 : : net_dbg_ratelimited("icmp: len problem [%pI6c > %pI6c]\n",
583 : : &hdr->saddr, &hdr->daddr);
584 : : goto out_dst_release;
585 : : }
586 : :
587 : 0 : rcu_read_lock();
588 : 0 : idev = __in6_dev_get(skb->dev);
589 : :
590 [ # # ]: 0 : if (ip6_append_data(sk, icmpv6_getfrag, &msg,
591 : 0 : len + sizeof(struct icmp6hdr),
592 : : sizeof(struct icmp6hdr),
593 : : &ipc6, &fl6, (struct rt6_info *)dst,
594 : : MSG_DONTWAIT)) {
595 [ # # ]: 0 : ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
596 : 0 : ip6_flush_pending_frames(sk);
597 : : } else {
598 : 0 : icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
599 : : len + sizeof(struct icmp6hdr));
600 : : }
601 : 0 : rcu_read_unlock();
602 : : out_dst_release:
603 : 0 : dst_release(dst);
604 : 0 : out:
605 : 0 : icmpv6_xmit_unlock(sk);
606 : 0 : out_bh_enable:
607 : 0 : local_bh_enable();
608 : : }
609 : :
610 : : /* Slightly more convenient version of icmp6_send.
611 : : */
612 : 0 : void icmpv6_param_prob(struct sk_buff *skb, u8 code, int pos)
613 : : {
614 : 0 : icmp6_send(skb, ICMPV6_PARAMPROB, code, pos, NULL);
615 : 0 : kfree_skb(skb);
616 : 0 : }
617 : :
618 : : /* Generate icmpv6 with type/code ICMPV6_DEST_UNREACH/ICMPV6_ADDR_UNREACH
619 : : * if sufficient data bytes are available
620 : : * @nhs is the size of the tunnel header(s) :
621 : : * Either an IPv4 header for SIT encap
622 : : * an IPv4 header + GRE header for GRE encap
623 : : */
624 : 0 : int ip6_err_gen_icmpv6_unreach(struct sk_buff *skb, int nhs, int type,
625 : : unsigned int data_len)
626 : : {
627 : 0 : struct in6_addr temp_saddr;
628 : 0 : struct rt6_info *rt;
629 : 0 : struct sk_buff *skb2;
630 : 0 : u32 info = 0;
631 : :
632 [ # # ]: 0 : if (!pskb_may_pull(skb, nhs + sizeof(struct ipv6hdr) + 8))
633 : : return 1;
634 : :
635 : : /* RFC 4884 (partial) support for ICMP extensions */
636 [ # # # # : 0 : if (data_len < 128 || (data_len & 7) || skb->len < data_len)
# # ]
637 : : data_len = 0;
638 : :
639 : 0 : skb2 = data_len ? skb_copy(skb, GFP_ATOMIC) : skb_clone(skb, GFP_ATOMIC);
640 : :
641 [ # # ]: 0 : if (!skb2)
642 : : return 1;
643 : :
644 [ # # ]: 0 : skb_dst_drop(skb2);
645 : 0 : skb_pull(skb2, nhs);
646 : 0 : skb_reset_network_header(skb2);
647 : :
648 : 0 : rt = rt6_lookup(dev_net(skb->dev), &ipv6_hdr(skb2)->saddr, NULL, 0,
649 : : skb, 0);
650 : :
651 [ # # # # ]: 0 : if (rt && rt->dst.dev)
652 : 0 : skb2->dev = rt->dst.dev;
653 : :
654 [ # # ]: 0 : ipv6_addr_set_v4mapped(ip_hdr(skb)->saddr, &temp_saddr);
655 : :
656 [ # # ]: 0 : if (data_len) {
657 : : /* RFC 4884 (partial) support :
658 : : * insert 0 padding at the end, before the extensions
659 : : */
660 : 0 : __skb_push(skb2, nhs);
661 : 0 : skb_reset_network_header(skb2);
662 : 0 : memmove(skb2->data, skb2->data + nhs, data_len - nhs);
663 : 0 : memset(skb2->data + data_len - nhs, 0, nhs);
664 : : /* RFC 4884 4.5 : Length is measured in 64-bit words,
665 : : * and stored in reserved[0]
666 : : */
667 : 0 : info = (data_len/8) << 24;
668 : : }
669 [ # # ]: 0 : if (type == ICMP_TIME_EXCEEDED)
670 : 0 : icmp6_send(skb2, ICMPV6_TIME_EXCEED, ICMPV6_EXC_HOPLIMIT,
671 : : info, &temp_saddr);
672 : : else
673 : 0 : icmp6_send(skb2, ICMPV6_DEST_UNREACH, ICMPV6_ADDR_UNREACH,
674 : : info, &temp_saddr);
675 [ # # ]: 0 : if (rt)
676 : 0 : ip6_rt_put(rt);
677 : :
678 : 0 : kfree_skb(skb2);
679 : :
680 : 0 : return 0;
681 : : }
682 : : EXPORT_SYMBOL(ip6_err_gen_icmpv6_unreach);
683 : :
684 : 0 : static void icmpv6_echo_reply(struct sk_buff *skb)
685 : : {
686 [ # # ]: 0 : struct net *net = dev_net(skb->dev);
687 : 0 : struct sock *sk;
688 : 0 : struct inet6_dev *idev;
689 : 0 : struct ipv6_pinfo *np;
690 : 0 : const struct in6_addr *saddr = NULL;
691 [ # # ]: 0 : struct icmp6hdr *icmph = icmp6_hdr(skb);
692 : 0 : struct icmp6hdr tmp_hdr;
693 : 0 : struct flowi6 fl6;
694 : 0 : struct icmpv6_msg msg;
695 : 0 : struct dst_entry *dst;
696 : 0 : struct ipcm6_cookie ipc6;
697 [ # # ]: 0 : u32 mark = IP6_REPLY_MARK(net, skb->mark);
698 : 0 : bool acast;
699 : :
700 [ # # ]: 0 : if (ipv6_addr_is_multicast(&ipv6_hdr(skb)->daddr) &&
701 [ # # ]: 0 : net->ipv6.sysctl.icmpv6_echo_ignore_multicast)
702 : 0 : return;
703 : :
704 [ # # ]: 0 : saddr = &ipv6_hdr(skb)->daddr;
705 : :
706 [ # # ]: 0 : acast = ipv6_anycast_destination(skb_dst(skb), saddr);
707 [ # # # # ]: 0 : if (acast && net->ipv6.sysctl.icmpv6_echo_ignore_anycast)
708 : : return;
709 : :
710 [ # # ]: 0 : if (!ipv6_unicast_destination(skb) &&
711 [ # # # # ]: 0 : !(net->ipv6.sysctl.anycast_src_echo_reply && acast))
712 : 0 : saddr = NULL;
713 : :
714 : 0 : memcpy(&tmp_hdr, icmph, sizeof(tmp_hdr));
715 : 0 : tmp_hdr.icmp6_type = ICMPV6_ECHO_REPLY;
716 : :
717 : 0 : memset(&fl6, 0, sizeof(fl6));
718 [ # # ]: 0 : if (net->ipv6.sysctl.flowlabel_reflect & FLOWLABEL_REFLECT_ICMPV6_ECHO_REPLIES)
719 : 0 : fl6.flowlabel = ip6_flowlabel(ipv6_hdr(skb));
720 : :
721 : 0 : fl6.flowi6_proto = IPPROTO_ICMPV6;
722 [ # # ]: 0 : fl6.daddr = ipv6_hdr(skb)->saddr;
723 [ # # ]: 0 : if (saddr)
724 : 0 : fl6.saddr = *saddr;
725 [ # # ]: 0 : fl6.flowi6_oif = icmp6_iif(skb);
726 : 0 : fl6.fl6_icmp_type = ICMPV6_ECHO_REPLY;
727 : 0 : fl6.flowi6_mark = mark;
728 : 0 : fl6.flowi6_uid = sock_net_uid(net, NULL);
729 : 0 : security_skb_classify_flow(skb, flowi6_to_flowi(&fl6));
730 : :
731 : 0 : local_bh_disable();
732 : 0 : sk = icmpv6_xmit_lock(net);
733 [ # # ]: 0 : if (!sk)
734 : 0 : goto out_bh_enable;
735 : 0 : sk->sk_mark = mark;
736 [ # # ]: 0 : np = inet6_sk(sk);
737 : :
738 [ # # # # ]: 0 : if (!fl6.flowi6_oif && ipv6_addr_is_multicast(&fl6.daddr))
739 : 0 : fl6.flowi6_oif = np->mcast_oif;
740 [ # # ]: 0 : else if (!fl6.flowi6_oif)
741 : 0 : fl6.flowi6_oif = np->ucast_oif;
742 : :
743 [ # # ]: 0 : if (ip6_dst_lookup(net, sk, &dst, &fl6))
744 : 0 : goto out;
745 : 0 : dst = xfrm_lookup(net, dst, flowi6_to_flowi(&fl6), sk, 0);
746 [ # # ]: 0 : if (IS_ERR(dst))
747 : 0 : goto out;
748 : :
749 : : /* Check the ratelimit */
750 [ # # # # : 0 : if ((!(skb->dev->flags & IFF_LOOPBACK) && !icmpv6_global_allow(net, ICMPV6_ECHO_REPLY)) ||
# # ]
751 : 0 : !icmpv6_xrlim_allow(sk, ICMPV6_ECHO_REPLY, &fl6))
752 : 0 : goto out_dst_release;
753 : :
754 [ # # ]: 0 : idev = __in6_dev_get(skb->dev);
755 : :
756 : 0 : msg.skb = skb;
757 : 0 : msg.offset = 0;
758 : 0 : msg.type = ICMPV6_ECHO_REPLY;
759 : :
760 [ # # ]: 0 : ipcm6_init_sk(&ipc6, np);
761 [ # # ]: 0 : ipc6.hlimit = ip6_sk_dst_hoplimit(np, &fl6, dst);
762 : 0 : ipc6.tclass = ipv6_get_dsfield(ipv6_hdr(skb));
763 : :
764 [ # # ]: 0 : if (ip6_append_data(sk, icmpv6_getfrag, &msg,
765 : 0 : skb->len + sizeof(struct icmp6hdr),
766 : : sizeof(struct icmp6hdr), &ipc6, &fl6,
767 : : (struct rt6_info *)dst, MSG_DONTWAIT)) {
768 [ # # ]: 0 : __ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS);
769 : 0 : ip6_flush_pending_frames(sk);
770 : : } else {
771 : 0 : icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr,
772 : 0 : skb->len + sizeof(struct icmp6hdr));
773 : : }
774 : 0 : out_dst_release:
775 : 0 : dst_release(dst);
776 : 0 : out:
777 : 0 : icmpv6_xmit_unlock(sk);
778 : 0 : out_bh_enable:
779 : 0 : local_bh_enable();
780 : : }
781 : :
782 : 0 : void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info)
783 : : {
784 : 0 : const struct inet6_protocol *ipprot;
785 : 0 : int inner_offset;
786 : 0 : __be16 frag_off;
787 : 0 : u8 nexthdr;
788 : 0 : struct net *net = dev_net(skb->dev);
789 : :
790 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
791 : 0 : goto out;
792 : :
793 : 0 : nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr;
794 [ # # ]: 0 : if (ipv6_ext_hdr(nexthdr)) {
795 : : /* now skip over extension headers */
796 : 0 : inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
797 : : &nexthdr, &frag_off);
798 [ # # ]: 0 : if (inner_offset < 0)
799 : 0 : goto out;
800 : : } else {
801 : : inner_offset = sizeof(struct ipv6hdr);
802 : : }
803 : :
804 : : /* Checkin header including 8 bytes of inner protocol header. */
805 [ # # ]: 0 : if (!pskb_may_pull(skb, inner_offset+8))
806 : 0 : goto out;
807 : :
808 : : /* BUGGG_FUTURE: we should try to parse exthdrs in this packet.
809 : : Without this we will not able f.e. to make source routed
810 : : pmtu discovery.
811 : : Corresponding argument (opt) to notifiers is already added.
812 : : --ANK (980726)
813 : : */
814 : :
815 [ # # ]: 0 : ipprot = rcu_dereference(inet6_protos[nexthdr]);
816 [ # # # # ]: 0 : if (ipprot && ipprot->err_handler)
817 : 0 : ipprot->err_handler(skb, NULL, type, code, inner_offset, info);
818 : :
819 : 0 : raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info);
820 : 0 : return;
821 : :
822 : 0 : out:
823 [ # # ]: 0 : __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS);
824 : : }
825 : :
826 : : /*
827 : : * Handle icmp messages
828 : : */
829 : :
830 : 0 : static int icmpv6_rcv(struct sk_buff *skb)
831 : : {
832 [ # # ]: 0 : struct net *net = dev_net(skb->dev);
833 [ # # ]: 0 : struct net_device *dev = icmp6_dev(skb);
834 : 0 : struct inet6_dev *idev = __in6_dev_get(dev);
835 : 0 : const struct in6_addr *saddr, *daddr;
836 : 0 : struct icmp6hdr *hdr;
837 : 0 : u8 type;
838 : 0 : bool success = false;
839 : :
840 [ # # ]: 0 : if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
841 [ # # ]: 0 : struct sec_path *sp = skb_sec_path(skb);
842 : 0 : int nh;
843 : :
844 [ # # # # ]: 0 : if (!(sp && sp->xvec[sp->len - 1]->props.flags &
845 : : XFRM_STATE_ICMP))
846 : 0 : goto drop_no_count;
847 : :
848 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(*hdr) + sizeof(struct ipv6hdr)))
849 : 0 : goto drop_no_count;
850 : :
851 : 0 : nh = skb_network_offset(skb);
852 : 0 : skb_set_network_header(skb, sizeof(*hdr));
853 : :
854 [ # # ]: 0 : if (!xfrm6_policy_check_reverse(NULL, XFRM_POLICY_IN, skb))
855 : 0 : goto drop_no_count;
856 : :
857 : 0 : skb_set_network_header(skb, nh);
858 : : }
859 : :
860 [ # # ]: 0 : __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INMSGS);
861 : :
862 : 0 : saddr = &ipv6_hdr(skb)->saddr;
863 : 0 : daddr = &ipv6_hdr(skb)->daddr;
864 : :
865 [ # # # # ]: 0 : if (skb_checksum_validate(skb, IPPROTO_ICMPV6, ip6_compute_pseudo)) {
866 : 0 : net_dbg_ratelimited("ICMPv6 checksum failed [%pI6c > %pI6c]\n",
867 : : saddr, daddr);
868 : 0 : goto csum_error;
869 : : }
870 : :
871 [ # # # # ]: 0 : if (!pskb_pull(skb, sizeof(*hdr)))
872 : 0 : goto discard_it;
873 : :
874 [ # # ]: 0 : hdr = icmp6_hdr(skb);
875 : :
876 : 0 : type = hdr->icmp6_type;
877 : :
878 [ # # ]: 0 : ICMP6MSGIN_INC_STATS(dev_net(dev), idev, type);
879 : :
880 [ # # # # : 0 : switch (type) {
# # # #
# ]
881 : 0 : case ICMPV6_ECHO_REQUEST:
882 [ # # ]: 0 : if (!net->ipv6.sysctl.icmpv6_echo_ignore_all)
883 : 0 : icmpv6_echo_reply(skb);
884 : : break;
885 : :
886 : 0 : case ICMPV6_ECHO_REPLY:
887 : 0 : success = ping_rcv(skb);
888 : 0 : break;
889 : :
890 : 0 : case ICMPV6_PKT_TOOBIG:
891 : : /* BUGGG_FUTURE: if packet contains rthdr, we cannot update
892 : : standard destination cache. Seems, only "advanced"
893 : : destination cache will allow to solve this problem
894 : : --ANK (980726)
895 : : */
896 [ # # ]: 0 : if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
897 : 0 : goto discard_it;
898 : 0 : hdr = icmp6_hdr(skb);
899 : :
900 : : /* to notify */
901 : : /* fall through */
902 : 0 : case ICMPV6_DEST_UNREACH:
903 : : case ICMPV6_TIME_EXCEED:
904 : : case ICMPV6_PARAMPROB:
905 : 0 : icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
906 : 0 : break;
907 : :
908 : 0 : case NDISC_ROUTER_SOLICITATION:
909 : : case NDISC_ROUTER_ADVERTISEMENT:
910 : : case NDISC_NEIGHBOUR_SOLICITATION:
911 : : case NDISC_NEIGHBOUR_ADVERTISEMENT:
912 : : case NDISC_REDIRECT:
913 : 0 : ndisc_rcv(skb);
914 : 0 : break;
915 : :
916 : 0 : case ICMPV6_MGM_QUERY:
917 : 0 : igmp6_event_query(skb);
918 : 0 : break;
919 : :
920 : 0 : case ICMPV6_MGM_REPORT:
921 : 0 : igmp6_event_report(skb);
922 : 0 : break;
923 : :
924 : : case ICMPV6_MGM_REDUCTION:
925 : : case ICMPV6_NI_QUERY:
926 : : case ICMPV6_NI_REPLY:
927 : : case ICMPV6_MLD2_REPORT:
928 : : case ICMPV6_DHAAD_REQUEST:
929 : : case ICMPV6_DHAAD_REPLY:
930 : : case ICMPV6_MOBILE_PREFIX_SOL:
931 : : case ICMPV6_MOBILE_PREFIX_ADV:
932 : : break;
933 : :
934 : 0 : default:
935 : : /* informational */
936 [ # # ]: 0 : if (type & ICMPV6_INFOMSG_MASK)
937 : : break;
938 : :
939 : 0 : net_dbg_ratelimited("icmpv6: msg of unknown type [%pI6c > %pI6c]\n",
940 : : saddr, daddr);
941 : :
942 : : /*
943 : : * error of unknown type.
944 : : * must pass to upper level
945 : : */
946 : :
947 : 0 : icmpv6_notify(skb, type, hdr->icmp6_code, hdr->icmp6_mtu);
948 : : }
949 : :
950 : : /* until the v6 path can be better sorted assume failure and
951 : : * preserve the status quo behaviour for the rest of the paths to here
952 : : */
953 [ # # ]: 0 : if (success)
954 : 0 : consume_skb(skb);
955 : : else
956 : 0 : kfree_skb(skb);
957 : :
958 : : return 0;
959 : :
960 : : csum_error:
961 [ # # ]: 0 : __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_CSUMERRORS);
962 : 0 : discard_it:
963 [ # # ]: 0 : __ICMP6_INC_STATS(dev_net(dev), idev, ICMP6_MIB_INERRORS);
964 : 0 : drop_no_count:
965 : 0 : kfree_skb(skb);
966 : 0 : return 0;
967 : : }
968 : :
969 : 0 : void icmpv6_flow_init(struct sock *sk, struct flowi6 *fl6,
970 : : u8 type,
971 : : const struct in6_addr *saddr,
972 : : const struct in6_addr *daddr,
973 : : int oif)
974 : : {
975 : 0 : memset(fl6, 0, sizeof(*fl6));
976 : 0 : fl6->saddr = *saddr;
977 : 0 : fl6->daddr = *daddr;
978 : 0 : fl6->flowi6_proto = IPPROTO_ICMPV6;
979 : 0 : fl6->fl6_icmp_type = type;
980 : 0 : fl6->fl6_icmp_code = 0;
981 : 0 : fl6->flowi6_oif = oif;
982 : 0 : security_sk_classify_flow(sk, flowi6_to_flowi(fl6));
983 : 0 : }
984 : :
985 : 0 : static void __net_exit icmpv6_sk_exit(struct net *net)
986 : : {
987 : 0 : int i;
988 : :
989 [ # # ]: 0 : for_each_possible_cpu(i)
990 [ # # ]: 0 : inet_ctl_sock_destroy(*per_cpu_ptr(net->ipv6.icmp_sk, i));
991 : 0 : free_percpu(net->ipv6.icmp_sk);
992 : 0 : }
993 : :
994 : 13 : static int __net_init icmpv6_sk_init(struct net *net)
995 : : {
996 : 13 : struct sock *sk;
997 : 13 : int err, i;
998 : :
999 : 13 : net->ipv6.icmp_sk = alloc_percpu(struct sock *);
1000 [ + - ]: 13 : if (!net->ipv6.icmp_sk)
1001 : : return -ENOMEM;
1002 : :
1003 [ + + ]: 26 : for_each_possible_cpu(i) {
1004 : 13 : err = inet_ctl_sock_create(&sk, PF_INET6,
1005 : : SOCK_RAW, IPPROTO_ICMPV6, net);
1006 [ - + ]: 13 : if (err < 0) {
1007 : 0 : pr_err("Failed to initialize the ICMP6 control socket (err %d)\n",
1008 : : err);
1009 : 0 : goto fail;
1010 : : }
1011 : :
1012 : 13 : *per_cpu_ptr(net->ipv6.icmp_sk, i) = sk;
1013 : :
1014 : : /* Enough space for 2 64K ICMP packets, including
1015 : : * sk_buff struct overhead.
1016 : : */
1017 : 13 : sk->sk_sndbuf = 2 * SKB_TRUESIZE(64 * 1024);
1018 : : }
1019 : : return 0;
1020 : :
1021 : : fail:
1022 : 0 : icmpv6_sk_exit(net);
1023 : 0 : return err;
1024 : : }
1025 : :
1026 : : static struct pernet_operations icmpv6_sk_ops = {
1027 : : .init = icmpv6_sk_init,
1028 : : .exit = icmpv6_sk_exit,
1029 : : };
1030 : :
1031 : 13 : int __init icmpv6_init(void)
1032 : : {
1033 : 13 : int err;
1034 : :
1035 : 13 : err = register_pernet_subsys(&icmpv6_sk_ops);
1036 [ + - ]: 13 : if (err < 0)
1037 : : return err;
1038 : :
1039 : 13 : err = -EAGAIN;
1040 [ - + ]: 13 : if (inet6_add_protocol(&icmpv6_protocol, IPPROTO_ICMPV6) < 0)
1041 : 0 : goto fail;
1042 : :
1043 : 13 : err = inet6_register_icmp_sender(icmp6_send);
1044 [ - + ]: 13 : if (err)
1045 : 0 : goto sender_reg_err;
1046 : : return 0;
1047 : :
1048 : : sender_reg_err:
1049 : 0 : inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
1050 : 0 : fail:
1051 : 0 : pr_err("Failed to register ICMP6 protocol\n");
1052 : 0 : unregister_pernet_subsys(&icmpv6_sk_ops);
1053 : 0 : return err;
1054 : : }
1055 : :
1056 : 0 : void icmpv6_cleanup(void)
1057 : : {
1058 : 0 : inet6_unregister_icmp_sender(icmp6_send);
1059 : 0 : unregister_pernet_subsys(&icmpv6_sk_ops);
1060 : 0 : inet6_del_protocol(&icmpv6_protocol, IPPROTO_ICMPV6);
1061 : 0 : }
1062 : :
1063 : :
1064 : : static const struct icmp6_err {
1065 : : int err;
1066 : : int fatal;
1067 : : } tab_unreach[] = {
1068 : : { /* NOROUTE */
1069 : : .err = ENETUNREACH,
1070 : : .fatal = 0,
1071 : : },
1072 : : { /* ADM_PROHIBITED */
1073 : : .err = EACCES,
1074 : : .fatal = 1,
1075 : : },
1076 : : { /* Was NOT_NEIGHBOUR, now reserved */
1077 : : .err = EHOSTUNREACH,
1078 : : .fatal = 0,
1079 : : },
1080 : : { /* ADDR_UNREACH */
1081 : : .err = EHOSTUNREACH,
1082 : : .fatal = 0,
1083 : : },
1084 : : { /* PORT_UNREACH */
1085 : : .err = ECONNREFUSED,
1086 : : .fatal = 1,
1087 : : },
1088 : : { /* POLICY_FAIL */
1089 : : .err = EACCES,
1090 : : .fatal = 1,
1091 : : },
1092 : : { /* REJECT_ROUTE */
1093 : : .err = EACCES,
1094 : : .fatal = 1,
1095 : : },
1096 : : };
1097 : :
1098 : 0 : int icmpv6_err_convert(u8 type, u8 code, int *err)
1099 : : {
1100 : 0 : int fatal = 0;
1101 : :
1102 : 0 : *err = EPROTO;
1103 : :
1104 [ # # # # : 0 : switch (type) {
# ]
1105 : 0 : case ICMPV6_DEST_UNREACH:
1106 : 0 : fatal = 1;
1107 [ # # ]: 0 : if (code < ARRAY_SIZE(tab_unreach)) {
1108 : 0 : *err = tab_unreach[code].err;
1109 : 0 : fatal = tab_unreach[code].fatal;
1110 : : }
1111 : : break;
1112 : :
1113 : 0 : case ICMPV6_PKT_TOOBIG:
1114 : 0 : *err = EMSGSIZE;
1115 : 0 : break;
1116 : :
1117 : 0 : case ICMPV6_PARAMPROB:
1118 : 0 : *err = EPROTO;
1119 : 0 : fatal = 1;
1120 : 0 : break;
1121 : :
1122 : 0 : case ICMPV6_TIME_EXCEED:
1123 : 0 : *err = EHOSTUNREACH;
1124 : 0 : break;
1125 : : }
1126 : :
1127 : 0 : return fatal;
1128 : : }
1129 : : EXPORT_SYMBOL(icmpv6_err_convert);
1130 : :
1131 : : #ifdef CONFIG_SYSCTL
1132 : : static struct ctl_table ipv6_icmp_table_template[] = {
1133 : : {
1134 : : .procname = "ratelimit",
1135 : : .data = &init_net.ipv6.sysctl.icmpv6_time,
1136 : : .maxlen = sizeof(int),
1137 : : .mode = 0644,
1138 : : .proc_handler = proc_dointvec_ms_jiffies,
1139 : : },
1140 : : {
1141 : : .procname = "echo_ignore_all",
1142 : : .data = &init_net.ipv6.sysctl.icmpv6_echo_ignore_all,
1143 : : .maxlen = sizeof(int),
1144 : : .mode = 0644,
1145 : : .proc_handler = proc_dointvec,
1146 : : },
1147 : : {
1148 : : .procname = "echo_ignore_multicast",
1149 : : .data = &init_net.ipv6.sysctl.icmpv6_echo_ignore_multicast,
1150 : : .maxlen = sizeof(int),
1151 : : .mode = 0644,
1152 : : .proc_handler = proc_dointvec,
1153 : : },
1154 : : {
1155 : : .procname = "echo_ignore_anycast",
1156 : : .data = &init_net.ipv6.sysctl.icmpv6_echo_ignore_anycast,
1157 : : .maxlen = sizeof(int),
1158 : : .mode = 0644,
1159 : : .proc_handler = proc_dointvec,
1160 : : },
1161 : : {
1162 : : .procname = "ratemask",
1163 : : .data = &init_net.ipv6.sysctl.icmpv6_ratemask_ptr,
1164 : : .maxlen = ICMPV6_MSG_MAX + 1,
1165 : : .mode = 0644,
1166 : : .proc_handler = proc_do_large_bitmap,
1167 : : },
1168 : : { },
1169 : : };
1170 : :
1171 : 13 : struct ctl_table * __net_init ipv6_icmp_sysctl_init(struct net *net)
1172 : : {
1173 : 13 : struct ctl_table *table;
1174 : :
1175 : 13 : table = kmemdup(ipv6_icmp_table_template,
1176 : : sizeof(ipv6_icmp_table_template),
1177 : : GFP_KERNEL);
1178 : :
1179 [ + - ]: 13 : if (table) {
1180 : 13 : table[0].data = &net->ipv6.sysctl.icmpv6_time;
1181 : 13 : table[1].data = &net->ipv6.sysctl.icmpv6_echo_ignore_all;
1182 : 13 : table[2].data = &net->ipv6.sysctl.icmpv6_echo_ignore_multicast;
1183 : 13 : table[3].data = &net->ipv6.sysctl.icmpv6_echo_ignore_anycast;
1184 : 13 : table[4].data = &net->ipv6.sysctl.icmpv6_ratemask_ptr;
1185 : : }
1186 : 13 : return table;
1187 : : }
1188 : : #endif
|