.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * IPv6 input |
---|
3 | 4 | * Linux INET6 implementation |
---|
.. | .. |
---|
7 | 8 | * Ian P. Morris <I.P.Morris@soton.ac.uk> |
---|
8 | 9 | * |
---|
9 | 10 | * 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 | 11 | */ |
---|
16 | 12 | /* Changes |
---|
17 | 13 | * |
---|
.. | .. |
---|
29 | 25 | #include <linux/icmpv6.h> |
---|
30 | 26 | #include <linux/mroute6.h> |
---|
31 | 27 | #include <linux/slab.h> |
---|
| 28 | +#include <linux/indirect_call_wrapper.h> |
---|
32 | 29 | |
---|
33 | 30 | #include <linux/netfilter.h> |
---|
34 | 31 | #include <linux/netfilter_ipv6.h> |
---|
.. | .. |
---|
47 | 44 | #include <net/inet_ecn.h> |
---|
48 | 45 | #include <net/dst_metadata.h> |
---|
49 | 46 | |
---|
| 47 | +void udp_v6_early_demux(struct sk_buff *); |
---|
| 48 | +void tcp_v6_early_demux(struct sk_buff *); |
---|
50 | 49 | static void ip6_rcv_finish_core(struct net *net, struct sock *sk, |
---|
51 | 50 | struct sk_buff *skb) |
---|
52 | 51 | { |
---|
53 | | - void (*edemux)(struct sk_buff *skb); |
---|
54 | | - |
---|
55 | | - if (net->ipv4.sysctl_ip_early_demux && !skb_dst(skb) && skb->sk == NULL) { |
---|
56 | | - const struct inet6_protocol *ipprot; |
---|
57 | | - |
---|
58 | | - ipprot = rcu_dereference(inet6_protos[ipv6_hdr(skb)->nexthdr]); |
---|
59 | | - if (ipprot && (edemux = READ_ONCE(ipprot->early_demux))) |
---|
60 | | - edemux(skb); |
---|
| 52 | + if (READ_ONCE(net->ipv4.sysctl_ip_early_demux) && |
---|
| 53 | + !skb_dst(skb) && !skb->sk) { |
---|
| 54 | + switch (ipv6_hdr(skb)->nexthdr) { |
---|
| 55 | + case IPPROTO_TCP: |
---|
| 56 | + if (READ_ONCE(net->ipv4.sysctl_tcp_early_demux)) |
---|
| 57 | + tcp_v6_early_demux(skb); |
---|
| 58 | + break; |
---|
| 59 | + case IPPROTO_UDP: |
---|
| 60 | + if (READ_ONCE(net->ipv4.sysctl_udp_early_demux)) |
---|
| 61 | + udp_v6_early_demux(skb); |
---|
| 62 | + break; |
---|
| 63 | + } |
---|
61 | 64 | } |
---|
| 65 | + |
---|
62 | 66 | if (!skb_valid_dst(skb)) |
---|
63 | 67 | ip6_route_input(skb); |
---|
64 | 68 | } |
---|
.. | .. |
---|
86 | 90 | } |
---|
87 | 91 | } |
---|
88 | 92 | |
---|
| 93 | +static bool ip6_can_use_hint(const struct sk_buff *skb, |
---|
| 94 | + const struct sk_buff *hint) |
---|
| 95 | +{ |
---|
| 96 | + return hint && !skb_dst(skb) && |
---|
| 97 | + ipv6_addr_equal(&ipv6_hdr(hint)->daddr, &ipv6_hdr(skb)->daddr); |
---|
| 98 | +} |
---|
| 99 | + |
---|
| 100 | +static struct sk_buff *ip6_extract_route_hint(const struct net *net, |
---|
| 101 | + struct sk_buff *skb) |
---|
| 102 | +{ |
---|
| 103 | + if (fib6_routes_require_src(net) || fib6_has_custom_rules(net)) |
---|
| 104 | + return NULL; |
---|
| 105 | + |
---|
| 106 | + return skb; |
---|
| 107 | +} |
---|
| 108 | + |
---|
89 | 109 | static void ip6_list_rcv_finish(struct net *net, struct sock *sk, |
---|
90 | 110 | struct list_head *head) |
---|
91 | 111 | { |
---|
| 112 | + struct sk_buff *skb, *next, *hint = NULL; |
---|
92 | 113 | struct dst_entry *curr_dst = NULL; |
---|
93 | | - struct sk_buff *skb, *next; |
---|
94 | 114 | struct list_head sublist; |
---|
95 | 115 | |
---|
96 | 116 | INIT_LIST_HEAD(&sublist); |
---|
.. | .. |
---|
104 | 124 | skb = l3mdev_ip6_rcv(skb); |
---|
105 | 125 | if (!skb) |
---|
106 | 126 | continue; |
---|
107 | | - ip6_rcv_finish_core(net, sk, skb); |
---|
| 127 | + |
---|
| 128 | + if (ip6_can_use_hint(skb, hint)) |
---|
| 129 | + skb_dst_copy(skb, hint); |
---|
| 130 | + else |
---|
| 131 | + ip6_rcv_finish_core(net, sk, skb); |
---|
108 | 132 | dst = skb_dst(skb); |
---|
109 | 133 | if (curr_dst != dst) { |
---|
| 134 | + hint = ip6_extract_route_hint(net, skb); |
---|
| 135 | + |
---|
110 | 136 | /* dispatch old sublist */ |
---|
111 | 137 | if (!list_empty(&sublist)) |
---|
112 | 138 | ip6_sublist_rcv_finish(&sublist); |
---|
.. | .. |
---|
180 | 206 | */ |
---|
181 | 207 | if ((ipv6_addr_loopback(&hdr->saddr) || |
---|
182 | 208 | ipv6_addr_loopback(&hdr->daddr)) && |
---|
183 | | - !(dev->flags & IFF_LOOPBACK)) |
---|
| 209 | + !(dev->flags & IFF_LOOPBACK) && |
---|
| 210 | + !netif_is_l3_master(dev)) |
---|
184 | 211 | goto err; |
---|
185 | 212 | |
---|
186 | 213 | /* RFC4291 Errata ID: 3480 |
---|
.. | .. |
---|
252 | 279 | rcu_read_unlock(); |
---|
253 | 280 | |
---|
254 | 281 | /* Must drop socket now because of tproxy. */ |
---|
255 | | - skb_orphan(skb); |
---|
| 282 | + if (!skb_sk_is_prefetched(skb)) |
---|
| 283 | + skb_orphan(skb); |
---|
256 | 284 | |
---|
257 | 285 | return skb; |
---|
258 | 286 | err: |
---|
.. | .. |
---|
314 | 342 | list_add_tail(&skb->list, &sublist); |
---|
315 | 343 | } |
---|
316 | 344 | /* dispatch final sublist */ |
---|
317 | | - ip6_sublist_rcv(&sublist, curr_dev, curr_net); |
---|
| 345 | + if (!list_empty(&sublist)) |
---|
| 346 | + ip6_sublist_rcv(&sublist, curr_dev, curr_net); |
---|
318 | 347 | } |
---|
| 348 | + |
---|
| 349 | +INDIRECT_CALLABLE_DECLARE(int udpv6_rcv(struct sk_buff *)); |
---|
| 350 | +INDIRECT_CALLABLE_DECLARE(int tcp_v6_rcv(struct sk_buff *)); |
---|
319 | 351 | |
---|
320 | 352 | /* |
---|
321 | 353 | * Deliver the packet to the host |
---|
322 | 354 | */ |
---|
323 | | - |
---|
324 | | - |
---|
325 | | -static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb) |
---|
| 355 | +void ip6_protocol_deliver_rcu(struct net *net, struct sk_buff *skb, int nexthdr, |
---|
| 356 | + bool have_final) |
---|
326 | 357 | { |
---|
327 | 358 | const struct inet6_protocol *ipprot; |
---|
328 | 359 | struct inet6_dev *idev; |
---|
329 | 360 | unsigned int nhoff; |
---|
330 | | - int nexthdr; |
---|
331 | 361 | bool raw; |
---|
332 | | - bool have_final = false; |
---|
333 | 362 | |
---|
334 | 363 | /* |
---|
335 | 364 | * Parse extension headers |
---|
336 | 365 | */ |
---|
337 | 366 | |
---|
338 | | - rcu_read_lock(); |
---|
339 | 367 | resubmit: |
---|
340 | 368 | idev = ip6_dst_idev(skb_dst(skb)); |
---|
341 | | - if (!pskb_pull(skb, skb_transport_offset(skb))) |
---|
342 | | - goto discard; |
---|
343 | 369 | nhoff = IP6CB(skb)->nhoff; |
---|
344 | | - nexthdr = skb_network_header(skb)[nhoff]; |
---|
| 370 | + if (!have_final) { |
---|
| 371 | + if (!pskb_pull(skb, skb_transport_offset(skb))) |
---|
| 372 | + goto discard; |
---|
| 373 | + nexthdr = skb_network_header(skb)[nhoff]; |
---|
| 374 | + } |
---|
345 | 375 | |
---|
346 | 376 | resubmit_final: |
---|
347 | 377 | raw = raw6_local_deliver(skb, nexthdr); |
---|
.. | .. |
---|
360 | 390 | } |
---|
361 | 391 | } else if (ipprot->flags & INET6_PROTO_FINAL) { |
---|
362 | 392 | const struct ipv6hdr *hdr; |
---|
| 393 | + int sdif = inet6_sdif(skb); |
---|
| 394 | + struct net_device *dev; |
---|
363 | 395 | |
---|
364 | 396 | /* Only do this once for first final protocol */ |
---|
365 | 397 | have_final = true; |
---|
.. | .. |
---|
367 | 399 | /* Free reference early: we don't need it any more, |
---|
368 | 400 | and it may hold ip_conntrack module loaded |
---|
369 | 401 | indefinitely. */ |
---|
370 | | - nf_reset(skb); |
---|
| 402 | + nf_reset_ct(skb); |
---|
371 | 403 | |
---|
372 | 404 | skb_postpull_rcsum(skb, skb_network_header(skb), |
---|
373 | 405 | skb_network_header_len(skb)); |
---|
374 | 406 | hdr = ipv6_hdr(skb); |
---|
| 407 | + |
---|
| 408 | + /* skb->dev passed may be master dev for vrfs. */ |
---|
| 409 | + if (sdif) { |
---|
| 410 | + dev = dev_get_by_index_rcu(net, sdif); |
---|
| 411 | + if (!dev) |
---|
| 412 | + goto discard; |
---|
| 413 | + } else { |
---|
| 414 | + dev = skb->dev; |
---|
| 415 | + } |
---|
| 416 | + |
---|
375 | 417 | if (ipv6_addr_is_multicast(&hdr->daddr) && |
---|
376 | | - !ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, |
---|
377 | | - &hdr->saddr) && |
---|
| 418 | + !ipv6_chk_mcast_addr(dev, &hdr->daddr, |
---|
| 419 | + &hdr->saddr) && |
---|
378 | 420 | !ipv6_is_mld(skb, nexthdr, skb_network_header_len(skb))) |
---|
379 | 421 | goto discard; |
---|
380 | 422 | } |
---|
.. | .. |
---|
382 | 424 | !xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) |
---|
383 | 425 | goto discard; |
---|
384 | 426 | |
---|
385 | | - ret = ipprot->handler(skb); |
---|
| 427 | + ret = INDIRECT_CALL_2(ipprot->handler, tcp_v6_rcv, udpv6_rcv, |
---|
| 428 | + skb); |
---|
386 | 429 | if (ret > 0) { |
---|
387 | 430 | if (ipprot->flags & INET6_PROTO_FINAL) { |
---|
388 | 431 | /* Not an extension header, most likely UDP |
---|
.. | .. |
---|
412 | 455 | consume_skb(skb); |
---|
413 | 456 | } |
---|
414 | 457 | } |
---|
415 | | - rcu_read_unlock(); |
---|
416 | | - return 0; |
---|
| 458 | + return; |
---|
417 | 459 | |
---|
418 | 460 | discard: |
---|
419 | 461 | __IP6_INC_STATS(net, idev, IPSTATS_MIB_INDISCARDS); |
---|
420 | | - rcu_read_unlock(); |
---|
421 | 462 | kfree_skb(skb); |
---|
| 463 | +} |
---|
| 464 | + |
---|
| 465 | +static int ip6_input_finish(struct net *net, struct sock *sk, struct sk_buff *skb) |
---|
| 466 | +{ |
---|
| 467 | + rcu_read_lock(); |
---|
| 468 | + ip6_protocol_deliver_rcu(net, skb, 0, false); |
---|
| 469 | + rcu_read_unlock(); |
---|
| 470 | + |
---|
422 | 471 | return 0; |
---|
423 | 472 | } |
---|
424 | 473 | |
---|
.. | .. |
---|
433 | 482 | |
---|
434 | 483 | int ip6_mc_input(struct sk_buff *skb) |
---|
435 | 484 | { |
---|
| 485 | + int sdif = inet6_sdif(skb); |
---|
436 | 486 | const struct ipv6hdr *hdr; |
---|
| 487 | + struct net_device *dev; |
---|
437 | 488 | bool deliver; |
---|
438 | 489 | |
---|
439 | 490 | __IP6_UPD_PO_STATS(dev_net(skb_dst(skb)->dev), |
---|
440 | 491 | __in6_dev_get_safely(skb->dev), IPSTATS_MIB_INMCAST, |
---|
441 | 492 | skb->len); |
---|
442 | 493 | |
---|
| 494 | + /* skb->dev passed may be master dev for vrfs. */ |
---|
| 495 | + if (sdif) { |
---|
| 496 | + rcu_read_lock(); |
---|
| 497 | + dev = dev_get_by_index_rcu(dev_net(skb->dev), sdif); |
---|
| 498 | + if (!dev) { |
---|
| 499 | + rcu_read_unlock(); |
---|
| 500 | + kfree_skb(skb); |
---|
| 501 | + return -ENODEV; |
---|
| 502 | + } |
---|
| 503 | + } else { |
---|
| 504 | + dev = skb->dev; |
---|
| 505 | + } |
---|
| 506 | + |
---|
443 | 507 | hdr = ipv6_hdr(skb); |
---|
444 | | - deliver = ipv6_chk_mcast_addr(skb->dev, &hdr->daddr, NULL); |
---|
| 508 | + deliver = ipv6_chk_mcast_addr(dev, &hdr->daddr, NULL); |
---|
| 509 | + if (sdif) |
---|
| 510 | + rcu_read_unlock(); |
---|
445 | 511 | |
---|
446 | 512 | #ifdef CONFIG_IPV6_MROUTE |
---|
447 | 513 | /* |
---|
448 | 514 | * IPv6 multicast router mode is now supported ;) |
---|
449 | 515 | */ |
---|
450 | | - if (dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding && |
---|
| 516 | + if (atomic_read(&dev_net(skb->dev)->ipv6.devconf_all->mc_forwarding) && |
---|
451 | 517 | !(ipv6_addr_type(&hdr->daddr) & |
---|
452 | 518 | (IPV6_ADDR_LOOPBACK|IPV6_ADDR_LINKLOCAL)) && |
---|
453 | 519 | likely(!(IP6CB(skb)->flags & IP6SKB_FORWARDED))) { |
---|