Blame view

net/ipv6/ip6_input.c 10.2 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
  /*
   *	IPv6 input
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
3
   *	Linux INET6 implementation
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
4
5
6
7
8
   *
   *	Authors:
   *	Pedro Roque		<roque@di.fc.ul.pt>
   *	Ian P. Morris		<I.P.Morris@soton.ac.uk>
   *
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
   *	Based in linux/net/ipv4/ip_input.c
   *
   *	This program is free software; you can redistribute it and/or
   *      modify it under the terms of the GNU General Public License
   *      as published by the Free Software Foundation; either version
   *      2 of the License, or (at your option) any later version.
   */
  /* Changes
   *
67ba4152e   Ian Morris   ipv6: White-space...
18
19
   *	Mitsuru KANDA @USAGI and
   *	YOSHIFUJI Hideaki @USAGI: Remove ipv6_parse_exthdrs().
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
20
21
22
23
24
25
   */
  
  #include <linux/errno.h>
  #include <linux/types.h>
  #include <linux/socket.h>
  #include <linux/sockios.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
26
27
28
29
  #include <linux/net.h>
  #include <linux/netdevice.h>
  #include <linux/in6.h>
  #include <linux/icmpv6.h>
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
30
  #include <linux/mroute6.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  
  #include <linux/netfilter.h>
  #include <linux/netfilter_ipv6.h>
  
  #include <net/sock.h>
  #include <net/snmp.h>
  
  #include <net/ipv6.h>
  #include <net/protocol.h>
  #include <net/transp_v6.h>
  #include <net/rawv6.h>
  #include <net/ndisc.h>
  #include <net/ip6_route.h>
  #include <net/addrconf.h>
  #include <net/xfrm.h>
1f07d03e2   Eric Dumazet   net: add SNMP cou...
47
  #include <net/inet_ecn.h>
48fb6b554   Wei-Chun Chao   ipv6: fix crash o...
48
  #include <net/dst_metadata.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
49

0c4b51f00   Eric W. Biederman   netfilter: Pass n...
50
  int ip6_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
51
  {
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
52
  	void (*edemux)(struct sk_buff *skb);
74b20582a   David Ahern   net: l3mdev: Add ...
53
54
55
56
57
58
  	/* if ingress device is enslaved to an L3 master device pass the
  	 * skb to its handler for processing
  	 */
  	skb = l3mdev_ip6_rcv(skb);
  	if (!skb)
  		return NET_RX_SUCCESS;
e21145a98   Nikolay Borisov   ipv4: namespacify...
59
  	if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
c7109986d   Eric Dumazet   ipv6: Early TCP s...
60
  		const struct inet6_protocol *ipprot;
c7109986d   Eric Dumazet   ipv6: Early TCP s...
61
  		ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
dddb64bcb   subashab@codeaurora.org   net: Add sysctl t...
62
63
  		if (ipprot && (edemux = READ_ONCE(ipprot->early_demux)))
  			edemux(skb);
c7109986d   Eric Dumazet   ipv6: Early TCP s...
64
  	}
48fb6b554   Wei-Chun Chao   ipv6: fix crash o...
65
  	if (!skb_valid_dst(skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
67
68
69
  		ip6_route_input(skb);
  
  	return dst_input(skb);
  }
f2ccd8fa0   David S. Miller   [NET]: Kill skb->...
70
  int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
71
  {
b71d1d426   Eric Dumazet   inet: constify ip...
72
  	const struct ipv6hdr *hdr;
67ba4152e   Ian Morris   ipv6: White-space...
73
  	u32 pkt_len;
a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
74
  	struct inet6_dev *idev;
483a47d2f   Denis V. Lunev   ipv6: added net a...
75
  	struct net *net = dev_net(skb->dev);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
76

a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
77
78
  	if (skb->pkt_type == PACKET_OTHERHOST) {
  		kfree_skb(skb);
5c91face5   Mark Smith   ipv6: correct ret...
79
  		return NET_RX_DROP;
a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
80
81
82
  	}
  
  	rcu_read_lock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83

a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
84
  	idev = __in6_dev_get(skb->dev);
c2005eb01   Eric Dumazet   ipv6: rename IP6_...
85
  	__IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_IN, skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86

778d80be5   YOSHIFUJI Hideaki   ipv6: Add disable...
87
88
  	if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
  	    !idev || unlikely(idev->cnf.disable_ipv6)) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
89
  		__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
71f6f6dfd   Jesper Nilsson   ipv6: Plug sk_buf...
90
  		goto drop;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
91
  	}
6b7fdc3ae   Guillaume Chazarain   [IPV6]: Clean skb...
92
  	memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
95
96
97
98
  	/*
  	 * Store incoming device index. When the packet will
  	 * be queued, we cannot refer to skb->dev anymore.
  	 *
  	 * BTW, when we send a packet for our own local address on a
  	 * non-loopback interface (e.g. ethX), it is being delivered
de3cb747f   Daniel Lezcano   [NET]: Dynamicall...
99
  	 * via the loopback interface (lo) here; skb->dev = loopback_dev.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
100
101
102
103
  	 * It, however, should be considered as if it is being
  	 * arrived via the sending interface (ethX), because of the
  	 * nature of scoping architecture. --yoshfuji
  	 */
48fb6b554   Wei-Chun Chao   ipv6: fix crash o...
104
  	IP6CB(skb)->iif = skb_valid_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
105

2889139a6   Herbert Xu   [IPV6]: Remove re...
106
  	if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
107
  		goto err;
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
108
  	hdr = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
109
110
111
  
  	if (hdr->version != 6)
  		goto err;
1d0155035   Eric Dumazet   ipv6: rename IP6_...
112
113
  	__IP6_ADD_STATS(net, idev,
  			IPSTATS_MIB_NOECTPKTS +
1f07d03e2   Eric Dumazet   net: add SNMP cou...
114
  				(ipv6_get_dsfield(hdr) & INET_ECN_MASK),
1d0155035   Eric Dumazet   ipv6: rename IP6_...
115
  			max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs));
f630e43a2   YOSHIFUJI Hideaki   ipv6: Drop packet...
116
117
  	/*
  	 * RFC4291 2.5.3
0aa8c13eb   Florian Westphal   ipv6: drop non lo...
118
119
  	 * The loopback address must not be used as the source address in IPv6
  	 * packets that are sent outside of a single node. [..]
f630e43a2   YOSHIFUJI Hideaki   ipv6: Drop packet...
120
121
122
  	 * A packet received on an interface with a destination address
  	 * of loopback must be dropped.
  	 */
0aa8c13eb   Florian Westphal   ipv6: drop non lo...
123
124
125
  	if ((ipv6_addr_loopback(&hdr->saddr) ||
  	     ipv6_addr_loopback(&hdr->daddr)) &&
  	     !(dev->flags & IFF_LOOPBACK))
f630e43a2   YOSHIFUJI Hideaki   ipv6: Drop packet...
126
  		goto err;
1c4a154e5   Hannes Frederic Sowa   ipv6: don't accep...
127
128
129
130
131
132
133
134
135
136
137
  	/* RFC4291 Errata ID: 3480
  	 * Interface-Local scope spans only a single interface on a
  	 * node and is useful only for loopback transmission of
  	 * multicast.  Packets with interface-local scope received
  	 * from another node must be discarded.
  	 */
  	if (!(skb->pkt_type == PACKET_LOOPBACK ||
  	      dev->flags & IFF_LOOPBACK) &&
  	    ipv6_addr_is_multicast(&hdr->daddr) &&
  	    IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
  		goto err;
abbc30436   Johannes Berg   ipv6: add option ...
138
139
140
141
142
143
144
145
146
  	/* If enabled, drop unicast packets that were encapsulated in link-layer
  	 * multicast or broadcast to protected against the so-called "hole-196"
  	 * attack in 802.11 wireless.
  	 */
  	if (!ipv6_addr_is_multicast(&hdr->daddr) &&
  	    (skb->pkt_type == PACKET_BROADCAST ||
  	     skb->pkt_type == PACKET_MULTICAST) &&
  	    idev->cnf.drop_unicast_in_l2_multicast)
  		goto err;
20314092c   Hannes Frederic Sowa   ipv6: don't accep...
147
148
149
150
151
152
153
154
  	/* RFC4291 2.7
  	 * Nodes must not originate a packet to a multicast address whose scope
  	 * field contains the reserved value 0; if such a packet is received, it
  	 * must be silently dropped.
  	 */
  	if (ipv6_addr_is_multicast(&hdr->daddr) &&
  	    IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
  		goto err;
c457338d7   Brian Haley   ipv6: drop packet...
155
156
157
158
159
160
161
  	/*
  	 * RFC4291 2.7
  	 * Multicast addresses must not be used as source addresses in IPv6
  	 * packets or appear in any Routing header.
  	 */
  	if (ipv6_addr_is_multicast(&hdr->saddr))
  		goto err;
b0e380b1d   Arnaldo Carvalho de Melo   [SK_BUFF]: unions...
162
  	skb->transport_header = skb->network_header + sizeof(*hdr);
951dbc8ac   Patrick McHardy   [IPV6]: Move next...
163
  	IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
  	pkt_len = ntohs(hdr->payload_len);
  
  	/* pkt_len may be zero if Jumbo payload option is present */
  	if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
60e5c1664   Mitsuru Chinen   [IPv6]: Exclude t...
168
  		if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
169
170
  			__IP6_INC_STATS(net,
  					idev, IPSTATS_MIB_INTRUNCATEDPKTS);
60e5c1664   Mitsuru Chinen   [IPv6]: Exclude t...
171
172
  			goto drop;
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
  		if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
174
  			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
175
176
  			goto drop;
  		}
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
177
  		hdr = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
178
179
180
  	}
  
  	if (hdr->nexthdr == NEXTHDR_HOP) {
e5bbef20e   Herbert Xu   [IPV6]: Replace s...
181
  		if (ipv6_parse_hopopts(skb) < 0) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
182
  			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
183
  			rcu_read_unlock();
5c91face5   Mark Smith   ipv6: correct ret...
184
  			return NET_RX_DROP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
186
  	}
a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
187
  	rcu_read_unlock();
71f9dacd2   Herbert Xu   inet: Call skb_or...
188
189
  	/* Must drop socket now because of tproxy. */
  	skb_orphan(skb);
29a26a568   Eric W. Biederman   netfilter: Pass s...
190
191
  	return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING,
  		       net, NULL, skb, dev, NULL,
6e23ae2a4   Patrick McHardy   [NETFILTER]: Intr...
192
  		       ip6_rcv_finish);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
193
  err:
1d0155035   Eric Dumazet   ipv6: rename IP6_...
194
  	__IP6_INC_STATS(net, idev, IPSTATS_MIB_INHDRERRORS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
195
  drop:
a11d206d0   YOSHIFUJI Hideaki   [IPV6]: Per-inter...
196
  	rcu_read_unlock();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
197
  	kfree_skb(skb);
5c91face5   Mark Smith   ipv6: correct ret...
198
  	return NET_RX_DROP;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
199
200
201
202
203
  }
  
  /*
   *	Deliver the packet to the host
   */
0c4b51f00   Eric W. Biederman   netfilter: Pass n...
204
  static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
205
  {
41135cc83   Alexey Dobriyan   net: constify str...
206
  	const struct inet6_protocol *ipprot;
f9242b6b2   David S. Miller   inet: Sanitize in...
207
  	struct inet6_dev *idev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
208
  	unsigned int nhoff;
a50feda54   Eric Dumazet   ipv6: bool/const ...
209
210
  	int nexthdr;
  	bool raw;
1da44f9c1   Tom Herbert   ipv6: Change "fin...
211
  	bool have_final = false;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
212

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
213
214
215
  	/*
  	 *	Parse extension headers
  	 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
216
  	rcu_read_lock();
1b0ccfe54   David S. Miller   Revert "ipv6: Fix...
217
  resubmit:
adf30907d   Eric Dumazet   net: skb->dst acc...
218
  	idev = ip6_dst_idev(skb_dst(skb));
ea2ae17d6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
219
  	if (!pskb_pull(skb, skb_transport_offset(skb)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
220
  		goto discard;
951dbc8ac   Patrick McHardy   [IPV6]: Move next...
221
  	nhoff = IP6CB(skb)->nhoff;
d56f90a7c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
222
  	nexthdr = skb_network_header(skb)[nhoff];
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
223

4c64242a9   Tom Herbert   ipv6: Fix nexthdr...
224
  resubmit_final:
69d6da0b0   Pavel Emelyanov   [IPv6] RAW: Compa...
225
  	raw = raw6_local_deliver(skb, nexthdr);
e5d08d718   Ian Morris   ipv6: coding styl...
226
  	ipprot = rcu_dereference(inet6_protos[nexthdr]);
53b24b8f9   Ian Morris   ipv6: coding styl...
227
  	if (ipprot) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
228
  		int ret;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
229

1da44f9c1   Tom Herbert   ipv6: Change "fin...
230
231
232
233
234
235
236
237
238
239
  		if (have_final) {
  			if (!(ipprot->flags & INET6_PROTO_FINAL)) {
  				/* Once we've seen a final protocol don't
  				 * allow encapsulation on any non-final
  				 * ones. This allows foo in UDP encapsulation
  				 * to work.
  				 */
  				goto discard;
  			}
  		} else if (ipprot->flags & INET6_PROTO_FINAL) {
b71d1d426   Eric Dumazet   inet: constify ip...
240
  			const struct ipv6hdr *hdr;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
241

1da44f9c1   Tom Herbert   ipv6: Change "fin...
242
243
  			/* Only do this once for first final protocol */
  			have_final = true;
9fb9cbb10   Yasuyuki Kozakai   [NETFILTER]: Add ...
244
245
246
247
  			/* Free reference early: we don't need it any more,
  			   and it may hold ip_conntrack module loaded
  			   indefinitely. */
  			nf_reset(skb);
d56f90a7c   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
248
  			skb_postpull_rcsum(skb, skb_network_header(skb),
cfe1fc775   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
249
  					   skb_network_header_len(skb));
0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
250
  			hdr = ipv6_hdr(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
251
252
253
  			if (ipv6_addr_is_multicast(&hdr->daddr) &&
  			    !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
  			    &hdr->saddr) &&
daad15126   YOSHIFUJI Hideaki / 吉藤英明   ipv6: Make ipv6_i...
254
  			    !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
255
256
257
  				goto discard;
  		}
  		if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
258
  		    !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
259
  			goto discard;
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
260

e5bbef20e   Herbert Xu   [IPV6]: Replace s...
261
  		ret = ipprot->handler(skb);
4c64242a9   Tom Herbert   ipv6: Fix nexthdr...
262
263
264
265
266
267
268
269
270
271
272
273
274
  		if (ret > 0) {
  			if (ipprot->flags & INET6_PROTO_FINAL) {
  				/* Not an extension header, most likely UDP
  				 * encapsulation. Use return value as nexthdr
  				 * protocol not nhoff (which presumably is
  				 * not set by handler).
  				 */
  				nexthdr = ret;
  				goto resubmit_final;
  			} else {
  				goto resubmit;
  			}
  		} else if (ret == 0) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
275
  			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS);
4c64242a9   Tom Herbert   ipv6: Fix nexthdr...
276
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
277
  	} else {
69d6da0b0   Pavel Emelyanov   [IPv6] RAW: Compa...
278
  		if (!raw) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
279
  			if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
280
281
  				__IP6_INC_STATS(net, idev,
  						IPSTATS_MIB_INUNKNOWNPROTOS);
fad87acae   Patrick McHardy   [IPV6]: Fix SKB l...
282
  				icmpv6_send(skb, ICMPV6_PARAMPROB,
3ffe533c8   Alexey Dobriyan   ipv6: drop unused...
283
  					    ICMPV6_UNK_NEXTHDR, nhoff);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
284
  			}
d8c6f4b9b   Neil Horman   ipv[4|6]: correct...
285
286
  			kfree_skb(skb);
  		} else {
1d0155035   Eric Dumazet   ipv6: rename IP6_...
287
  			__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDELIVERS);
d8c6f4b9b   Neil Horman   ipv[4|6]: correct...
288
289
  			consume_skb(skb);
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
290
291
292
293
294
  	}
  	rcu_read_unlock();
  	return 0;
  
  discard:
1d0155035   Eric Dumazet   ipv6: rename IP6_...
295
  	__IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
296
297
298
299
300
301
302
303
  	rcu_read_unlock();
  	kfree_skb(skb);
  	return 0;
  }
  
  
  int ip6_input(struct sk_buff *skb)
  {
29a26a568   Eric W. Biederman   netfilter: Pass s...
304
305
  	return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN,
  		       dev_net(skb->dev), NULL, skb, skb->dev, NULL,
6e23ae2a4   Patrick McHardy   [NETFILTER]: Intr...
306
  		       ip6_input_finish);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
307
  }
b4869aa2f   David Ahern   net: vrf: ipv6 su...
308
  EXPORT_SYMBOL_GPL(ip6_input);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
309
310
311
  
  int ip6_mc_input(struct sk_buff *skb)
  {
b71d1d426   Eric Dumazet   inet: constify ip...
312
  	const struct ipv6hdr *hdr;
a50feda54   Eric Dumazet   ipv6: bool/const ...
313
  	bool deliver;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
314

c2005eb01   Eric Dumazet   ipv6: rename IP6_...
315
  	__IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev),
adf30907d   Eric Dumazet   net: skb->dst acc...
316
  			 ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST,
edf391ff1   Neil Horman   snmp: add missing...
317
  			 skb->len);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
318

0660e03f6   Arnaldo Carvalho de Melo   [SK_BUFF]: Introd...
319
  	hdr = ipv6_hdr(skb);
4c7966b86   YOSHIFUJI Hideaki   [IPV6] MCAST: Ens...
320
  	deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
321

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
322
  #ifdef CONFIG_IPV6_MROUTE
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
323
  	/*
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
324
  	 *      IPv6 multicast router mode is now supported ;)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
325
  	 */
53b7997fd   YOSHIFUJI Hideaki   ipv6 netns: Make ...
326
  	if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
ddf64354a   Hannes Frederic Sowa   ipv6: stop multic...
327
328
  	    !(ipv6_addr_type(&hdr->daddr) &
  	      (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
329
330
331
332
333
334
335
336
337
  	    likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
  		/*
  		 * Okay, we try to forward - split and duplicate
  		 * packets.
  		 */
  		struct sk_buff *skb2;
  		struct inet6_skb_parm *opt = IP6CB(skb);
  
  		/* Check for MLD */
dd3332bfc   YOSHIFUJI Hideaki / 吉藤英明   ipv6: Store Route...
338
  		if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
339
  			/* Check if this is a mld message */
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
340
  			u8 nexthdr = hdr->nexthdr;
75f2811c6   Jesse Gross   ipv6: Add fragmen...
341
  			__be16 frag_off;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
342
343
344
345
346
  			int offset;
  
  			/* Check if the value of Router Alert
  			 * is for MLD (0x0000).
  			 */
dd3332bfc   YOSHIFUJI Hideaki / 吉藤英明   ipv6: Store Route...
347
  			if (opt->ra == htons(IPV6_OPT_ROUTERALERT_MLD)) {
a50feda54   Eric Dumazet   ipv6: bool/const ...
348
  				deliver = false;
aba6096b2   YOSHIFUJI Hideaki   [IPV6]: Kill seve...
349

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
350
351
  				if (!ipv6_ext_hdr(nexthdr)) {
  					/* BUG */
aba6096b2   YOSHIFUJI Hideaki   [IPV6]: Kill seve...
352
  					goto out;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
353
354
  				}
  				offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
75f2811c6   Jesse Gross   ipv6: Add fragmen...
355
  							  &nexthdr, &frag_off);
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
356
  				if (offset < 0)
aba6096b2   YOSHIFUJI Hideaki   [IPV6]: Kill seve...
357
  					goto out;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
358

4c938d22c   Angga   ipv6: Make MLD pa...
359
360
  				if (ipv6_is_mld(skb, nexthdr, offset))
  					deliver = true;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
361

4c938d22c   Angga   ipv6: Make MLD pa...
362
  				goto out;
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
363
364
365
  			}
  			/* unknown RA - process it normally */
  		}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
366

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
367
368
369
370
371
372
  		if (deliver)
  			skb2 = skb_clone(skb, GFP_ATOMIC);
  		else {
  			skb2 = skb;
  			skb = NULL;
  		}
1ab1457c4   YOSHIFUJI Hideaki   [NET] IPV6: Fix w...
373

7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
374
  		if (skb2) {
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
375
  			ip6_mr_input(skb2);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
376
377
  		}
  	}
7bc570c8b   YOSHIFUJI Hideaki   [IPV6] MROUTE: Su...
378
  out:
aba6096b2   YOSHIFUJI Hideaki   [IPV6]: Kill seve...
379
380
  #endif
  	if (likely(deliver))
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
381
  		ip6_input(skb);
aba6096b2   YOSHIFUJI Hideaki   [IPV6]: Kill seve...
382
383
384
  	else {
  		/* discard */
  		kfree_skb(skb);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
385
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
386
387
388
  
  	return 0;
  }