Branch data Line data Source code
1 : : /*
2 : : * IPv6 input
3 : : * Linux INET6 implementation
4 : : *
5 : : * Authors:
6 : : * Pedro Roque <roque@di.fc.ul.pt>
7 : : * Ian P. Morris <I.P.Morris@soton.ac.uk>
8 : : *
9 : : * Based in linux/net/ipv4/ip_input.c
10 : : *
11 : : * This program is free software; you can redistribute it and/or
12 : : * modify it under the terms of the GNU General Public License
13 : : * as published by the Free Software Foundation; either version
14 : : * 2 of the License, or (at your option) any later version.
15 : : */
16 : : /* Changes
17 : : *
18 : : * Mitsuru KANDA @USAGI and
19 : : * YOSHIFUJI Hideaki @USAGI: Remove ipv6_parse_exthdrs().
20 : : */
21 : :
22 : : #include <linux/errno.h>
23 : : #include <linux/types.h>
24 : : #include <linux/socket.h>
25 : : #include <linux/sockios.h>
26 : : #include <linux/net.h>
27 : : #include <linux/netdevice.h>
28 : : #include <linux/in6.h>
29 : : #include <linux/icmpv6.h>
30 : : #include <linux/mroute6.h>
31 : : #include <linux/slab.h>
32 : :
33 : : #include <linux/netfilter.h>
34 : : #include <linux/netfilter_ipv6.h>
35 : :
36 : : #include <net/sock.h>
37 : : #include <net/snmp.h>
38 : :
39 : : #include <net/ipv6.h>
40 : : #include <net/protocol.h>
41 : : #include <net/transp_v6.h>
42 : : #include <net/rawv6.h>
43 : : #include <net/ndisc.h>
44 : : #include <net/ip6_route.h>
45 : : #include <net/addrconf.h>
46 : : #include <net/xfrm.h>
47 : : #include <net/inet_ecn.h>
48 : :
49 : :
50 : 0 : int ip6_rcv_finish(struct sk_buff *skb)
51 : : {
52 [ + - ][ + - ]: 5 : if (sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) {
[ + - ]
53 : : const struct inet6_protocol *ipprot;
54 : :
55 : 5 : ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]);
56 [ + - ][ - + ]: 5 : if (ipprot && ipprot->early_demux)
57 : 0 : ipprot->early_demux(skb);
58 : : }
59 [ + - ]: 5 : if (!skb_dst(skb))
60 : 5 : ip6_route_input(skb);
61 : :
62 : 5 : return dst_input(skb);
63 : : }
64 : :
65 : 0 : int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
66 : : {
67 : : const struct ipv6hdr *hdr;
68 : : u32 pkt_len;
69 : : struct inet6_dev *idev;
70 : 5 : struct net *net = dev_net(skb->dev);
71 : :
72 [ - + ]: 5 : if (skb->pkt_type == PACKET_OTHERHOST) {
73 : 0 : kfree_skb(skb);
74 : 0 : return NET_RX_DROP;
75 : : }
76 : :
77 : : rcu_read_lock();
78 : :
79 : 5 : idev = __in6_dev_get(skb->dev);
80 : :
81 [ + - ]: 5 : IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_IN, skb->len);
82 : :
83 [ + - ][ + - ]: 5 : if ((skb = skb_share_check(skb, GFP_ATOMIC)) == NULL ||
84 [ - + ]: 5 : !idev || unlikely(idev->cnf.disable_ipv6)) {
85 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
86 : : goto drop;
87 : : }
88 : :
89 : 5 : memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
90 : :
91 : : /*
92 : : * Store incoming device index. When the packet will
93 : : * be queued, we cannot refer to skb->dev anymore.
94 : : *
95 : : * BTW, when we send a packet for our own local address on a
96 : : * non-loopback interface (e.g. ethX), it is being delivered
97 : : * via the loopback interface (lo) here; skb->dev = loopback_dev.
98 : : * It, however, should be considered as if it is being
99 : : * arrived via the sending interface (ethX), because of the
100 : : * nature of scoping architecture. --yoshfuji
101 : : */
102 [ - + ]: 5 : IP6CB(skb)->iif = skb_dst(skb) ? ip6_dst_idev(skb_dst(skb))->dev->ifindex : dev->ifindex;
103 : :
104 [ + - ]: 5 : if (unlikely(!pskb_may_pull(skb, sizeof(*hdr))))
105 : : goto err;
106 : :
107 : : hdr = ipv6_hdr(skb);
108 : :
109 [ + - ]: 5 : if (hdr->version != 6)
110 : : goto err;
111 : :
112 [ + - ][ - + ]: 15 : IP6_ADD_STATS_BH(dev_net(dev), idev,
[ - + ]
113 : : IPSTATS_MIB_NOECTPKTS +
114 : : (ipv6_get_dsfield(hdr) & INET_ECN_MASK),
115 : : max_t(unsigned short, 1, skb_shinfo(skb)->gso_segs));
116 : : /*
117 : : * RFC4291 2.5.3
118 : : * A packet received on an interface with a destination address
119 : : * of loopback must be dropped.
120 : : */
121 [ + - ][ + - ]: 5 : if (!(dev->flags & IFF_LOOPBACK) &&
122 : 10 : ipv6_addr_loopback(&hdr->daddr))
123 : : goto err;
124 : :
125 : : /* RFC4291 Errata ID: 3480
126 : : * Interface-Local scope spans only a single interface on a
127 : : * node and is useful only for loopback transmission of
128 : : * multicast. Packets with interface-local scope received
129 : : * from another node must be discarded.
130 : : */
131 [ + - ][ + - ]: 5 : if (!(skb->pkt_type == PACKET_LOOPBACK ||
132 [ + - ]: 5 : dev->flags & IFF_LOOPBACK) &&
133 [ + - ]: 5 : ipv6_addr_is_multicast(&hdr->daddr) &&
134 : 5 : IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 1)
135 : : goto err;
136 : :
137 : : /* RFC4291 2.7
138 : : * Nodes must not originate a packet to a multicast address whose scope
139 : : * field contains the reserved value 0; if such a packet is received, it
140 : : * must be silently dropped.
141 : : */
142 [ + - ][ + - ]: 5 : if (ipv6_addr_is_multicast(&hdr->daddr) &&
143 : 5 : IPV6_ADDR_MC_SCOPE(&hdr->daddr) == 0)
144 : : goto err;
145 : :
146 : : /*
147 : : * RFC4291 2.7
148 : : * Multicast addresses must not be used as source addresses in IPv6
149 : : * packets or appear in any Routing header.
150 : : */
151 [ + - ]: 5 : if (ipv6_addr_is_multicast(&hdr->saddr))
152 : : goto err;
153 : :
154 : 5 : skb->transport_header = skb->network_header + sizeof(*hdr);
155 : 5 : IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
156 : :
157 [ - + ]: 5 : pkt_len = ntohs(hdr->payload_len);
158 : :
159 : : /* pkt_len may be zero if Jumbo payload option is present */
160 [ - + ][ # # ]: 5 : if (pkt_len || hdr->nexthdr != NEXTHDR_HOP) {
161 [ - + ]: 5 : if (pkt_len + sizeof(struct ipv6hdr) > skb->len) {
162 [ # # ]: 0 : IP6_INC_STATS_BH(net,
163 : : idev, IPSTATS_MIB_INTRUNCATEDPKTS);
164 : : goto drop;
165 : : }
166 [ - + ]: 5 : if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) {
167 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
168 : : goto drop;
169 : : }
170 : : hdr = ipv6_hdr(skb);
171 : : }
172 : :
173 [ - + ]: 5 : if (hdr->nexthdr == NEXTHDR_HOP) {
174 [ # # ]: 0 : if (ipv6_parse_hopopts(skb) < 0) {
175 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
176 : : rcu_read_unlock();
177 : 0 : return NET_RX_DROP;
178 : : }
179 : : }
180 : :
181 : : rcu_read_unlock();
182 : :
183 : : /* Must drop socket now because of tproxy. */
184 : : skb_orphan(skb);
185 : :
186 : 5 : return NF_HOOK(NFPROTO_IPV6, NF_INET_PRE_ROUTING, skb, dev, NULL,
187 : : ip6_rcv_finish);
188 : : err:
189 [ - ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INHDRERRORS);
190 : : drop:
191 : : rcu_read_unlock();
192 : 0 : kfree_skb(skb);
193 : 0 : return NET_RX_DROP;
194 : : }
195 : :
196 : : /*
197 : : * Deliver the packet to the host
198 : : */
199 : :
200 : :
201 : 0 : static int ip6_input_finish(struct sk_buff *skb)
202 : : {
203 : : struct net *net = dev_net(skb_dst(skb)->dev);
204 : : const struct inet6_protocol *ipprot;
205 : : struct inet6_dev *idev;
206 : : unsigned int nhoff;
207 : : int nexthdr;
208 : : bool raw;
209 : :
210 : : /*
211 : : * Parse extension headers
212 : : */
213 : :
214 : : rcu_read_lock();
215 : : resubmit:
216 : : idev = ip6_dst_idev(skb_dst(skb));
217 [ + - ]: 5 : if (!pskb_pull(skb, skb_transport_offset(skb)))
218 : : goto discard;
219 : 5 : nhoff = IP6CB(skb)->nhoff;
220 : 5 : nexthdr = skb_network_header(skb)[nhoff];
221 : :
222 : 5 : raw = raw6_local_deliver(skb, nexthdr);
223 [ + - ]: 5 : if ((ipprot = rcu_dereference(inet6_protos[nexthdr])) != NULL) {
224 : : int ret;
225 : :
226 [ + - ]: 5 : if (ipprot->flags & INET6_PROTO_FINAL) {
227 : : const struct ipv6hdr *hdr;
228 : :
229 : : /* Free reference early: we don't need it any more,
230 : : and it may hold ip_conntrack module loaded
231 : : indefinitely. */
232 : : nf_reset(skb);
233 : :
234 : : skb_postpull_rcsum(skb, skb_network_header(skb),
235 : : skb_network_header_len(skb));
236 : : hdr = ipv6_hdr(skb);
237 [ + - - + ]: 10 : if (ipv6_addr_is_multicast(&hdr->daddr) &&
238 : 5 : !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr,
239 [ # # ]: 0 : &hdr->saddr) &&
240 : : !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb)))
241 : : goto discard;
242 : : }
243 [ - + ][ # # ]: 5 : if (!(ipprot->flags & INET6_PROTO_NOPOLICY) &&
244 : : !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb))
245 : : goto discard;
246 : :
247 : 5 : ret = ipprot->handler(skb);
248 [ - + ]: 5 : if (ret > 0)
249 : : goto resubmit;
250 [ + - ]: 5 : else if (ret == 0)
251 [ + - ]: 5 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
252 : : } else {
253 [ # # ]: 0 : if (!raw) {
254 [ # # ]: 0 : if (xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) {
255 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev,
256 : : IPSTATS_MIB_INUNKNOWNPROTOS);
257 : 0 : icmpv6_send(skb, ICMPV6_PARAMPROB,
258 : : ICMPV6_UNK_NEXTHDR, nhoff);
259 : : }
260 : 0 : kfree_skb(skb);
261 : : } else {
262 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDELIVERS);
263 : 0 : consume_skb(skb);
264 : : }
265 : : }
266 : : rcu_read_unlock();
267 : 5 : return 0;
268 : :
269 : : discard:
270 [ # # ]: 0 : IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_INDISCARDS);
271 : : rcu_read_unlock();
272 : 0 : kfree_skb(skb);
273 : 0 : return 0;
274 : : }
275 : :
276 : :
277 : 0 : int ip6_input(struct sk_buff *skb)
278 : : {
279 : 10 : return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_IN, skb, skb->dev, NULL,
280 : : ip6_input_finish);
281 : : }
282 : :
283 : 0 : int ip6_mc_input(struct sk_buff *skb)
284 : : {
285 : : const struct ipv6hdr *hdr;
286 : : bool deliver;
287 : :
288 [ + - ]: 5 : IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev),
289 : : ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INMCAST,
290 : : skb->len);
291 : :
292 : : hdr = ipv6_hdr(skb);
293 : 5 : deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL);
294 : :
295 : : #ifdef CONFIG_IPV6_MROUTE
296 : : /*
297 : : * IPv6 multicast router mode is now supported ;)
298 : : */
299 : : if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding &&
300 : : !(ipv6_addr_type(&hdr->daddr) &
301 : : (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) &&
302 : : likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) {
303 : : /*
304 : : * Okay, we try to forward - split and duplicate
305 : : * packets.
306 : : */
307 : : struct sk_buff *skb2;
308 : : struct inet6_skb_parm *opt = IP6CB(skb);
309 : :
310 : : /* Check for MLD */
311 : : if (unlikely(opt->flags & IP6SKB_ROUTERALERT)) {
312 : : /* Check if this is a mld message */
313 : : u8 nexthdr = hdr->nexthdr;
314 : : __be16 frag_off;
315 : : int offset;
316 : :
317 : : /* Check if the value of Router Alert
318 : : * is for MLD (0x0000).
319 : : */
320 : : if (opt->ra == htons(IPV6_OPT_ROUTERALERT_MLD)) {
321 : : deliver = false;
322 : :
323 : : if (!ipv6_ext_hdr(nexthdr)) {
324 : : /* BUG */
325 : : goto out;
326 : : }
327 : : offset = ipv6_skip_exthdr(skb, sizeof(*hdr),
328 : : &nexthdr, &frag_off);
329 : : if (offset < 0)
330 : : goto out;
331 : :
332 : : if (!ipv6_is_mld(skb, nexthdr, offset))
333 : : goto out;
334 : :
335 : : deliver = true;
336 : : }
337 : : /* unknown RA - process it normally */
338 : : }
339 : :
340 : : if (deliver)
341 : : skb2 = skb_clone(skb, GFP_ATOMIC);
342 : : else {
343 : : skb2 = skb;
344 : : skb = NULL;
345 : : }
346 : :
347 : : if (skb2) {
348 : : ip6_mr_input(skb2);
349 : : }
350 : : }
351 : : out:
352 : : #endif
353 [ + - ]: 5 : if (likely(deliver))
354 : 5 : ip6_input(skb);
355 : : else {
356 : : /* discard */
357 : 0 : kfree_skb(skb);
358 : : }
359 : :
360 : 5 : return 0;
361 : : }
|