aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6/udp.c')
-rw-r--r--net/ipv6/udp.c89
1 files changed, 78 insertions, 11 deletions
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index c55698d19d68..1216c920f945 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -462,6 +462,61 @@ csum_copy_err:
462 goto try_again; 462 goto try_again;
463} 463}
464 464
465DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
466void udpv6_encap_enable(void)
467{
468 static_branch_enable(&udpv6_encap_needed_key);
469}
470EXPORT_SYMBOL(udpv6_encap_enable);
471
472/* Try to match ICMP errors to UDP tunnels by looking up a socket without
473 * reversing source and destination port: this will match tunnels that force the
474 * same destination port on both endpoints (e.g. VXLAN, GENEVE). Note that
475 * lwtunnels might actually break this assumption by being configured with
476 * different destination ports on endpoints, in this case we won't be able to
477 * trace ICMP messages back to them.
478 *
479 * Then ask the tunnel implementation to match the error against a valid
480 * association.
481 *
482 * Return the socket if we have a match.
483 */
484static struct sock *__udp6_lib_err_encap(struct net *net,
485 const struct ipv6hdr *hdr, int offset,
486 struct udphdr *uh,
487 struct udp_table *udptable,
488 struct sk_buff *skb)
489{
490 int (*lookup)(struct sock *sk, struct sk_buff *skb);
491 int network_offset, transport_offset;
492 struct udp_sock *up;
493 struct sock *sk;
494
495 sk = __udp6_lib_lookup(net, &hdr->daddr, uh->source,
496 &hdr->saddr, uh->dest,
497 inet6_iif(skb), 0, udptable, skb);
498 if (!sk)
499 return NULL;
500
501 network_offset = skb_network_offset(skb);
502 transport_offset = skb_transport_offset(skb);
503
504 /* Network header needs to point to the outer IPv6 header inside ICMP */
505 skb_reset_network_header(skb);
506
507 /* Transport header needs to point to the UDP header */
508 skb_set_transport_header(skb, offset);
509
510 up = udp_sk(sk);
511 lookup = READ_ONCE(up->encap_err_lookup);
512 if (!lookup || lookup(sk, skb))
513 sk = NULL;
514
515 skb_set_transport_header(skb, transport_offset);
516 skb_set_network_header(skb, network_offset);
517 return sk;
518}
519
465void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, 520void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
466 u8 type, u8 code, int offset, __be32 info, 521 u8 type, u8 code, int offset, __be32 info,
467 struct udp_table *udptable) 522 struct udp_table *udptable)
@@ -471,6 +526,7 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
471 const struct in6_addr *saddr = &hdr->saddr; 526 const struct in6_addr *saddr = &hdr->saddr;
472 const struct in6_addr *daddr = &hdr->daddr; 527 const struct in6_addr *daddr = &hdr->daddr;
473 struct udphdr *uh = (struct udphdr *)(skb->data+offset); 528 struct udphdr *uh = (struct udphdr *)(skb->data+offset);
529 bool tunnel = false;
474 struct sock *sk; 530 struct sock *sk;
475 int harderr; 531 int harderr;
476 int err; 532 int err;
@@ -479,9 +535,18 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
479 sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source, 535 sk = __udp6_lib_lookup(net, daddr, uh->dest, saddr, uh->source,
480 inet6_iif(skb), inet6_sdif(skb), udptable, skb); 536 inet6_iif(skb), inet6_sdif(skb), udptable, skb);
481 if (!sk) { 537 if (!sk) {
482 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev), 538 /* No socket for error: try tunnels before discarding */
483 ICMP6_MIB_INERRORS); 539 if (static_branch_unlikely(&udpv6_encap_needed_key)) {
484 return; 540 sk = __udp6_lib_err_encap(net, hdr, offset, uh,
541 udptable, skb);
542 }
543
544 if (!sk) {
545 __ICMP6_INC_STATS(net, __in6_dev_get(skb->dev),
546 ICMP6_MIB_INERRORS);
547 return;
548 }
549 tunnel = true;
485 } 550 }
486 551
487 harderr = icmpv6_err_convert(type, code, &err); 552 harderr = icmpv6_err_convert(type, code, &err);
@@ -495,10 +560,19 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
495 harderr = 1; 560 harderr = 1;
496 } 561 }
497 if (type == NDISC_REDIRECT) { 562 if (type == NDISC_REDIRECT) {
498 ip6_sk_redirect(skb, sk); 563 if (tunnel) {
564 ip6_redirect(skb, sock_net(sk), inet6_iif(skb),
565 sk->sk_mark, sk->sk_uid);
566 } else {
567 ip6_sk_redirect(skb, sk);
568 }
499 goto out; 569 goto out;
500 } 570 }
501 571
572 /* Tunnels don't have an application socket: don't pass errors back */
573 if (tunnel)
574 goto out;
575
502 if (!np->recverr) { 576 if (!np->recverr) {
503 if (!harderr || sk->sk_state != TCP_ESTABLISHED) 577 if (!harderr || sk->sk_state != TCP_ESTABLISHED)
504 goto out; 578 goto out;
@@ -547,13 +621,6 @@ static __inline__ void udpv6_err(struct sk_buff *skb,
547 __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table); 621 __udp6_lib_err(skb, opt, type, code, offset, info, &udp_table);
548} 622}
549 623
550DEFINE_STATIC_KEY_FALSE(udpv6_encap_needed_key);
551void udpv6_encap_enable(void)
552{
553 static_branch_enable(&udpv6_encap_needed_key);
554}
555EXPORT_SYMBOL(udpv6_encap_enable);
556
557static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb) 624static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
558{ 625{
559 struct udp_sock *up = udp_sk(sk); 626 struct udp_sock *up = udp_sk(sk);