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