Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[platform/kernel/linux-starfive.git] / net / ipv4 / udp.c
index 1976fdd..aff2a8e 100644 (file)
 #include <net/net_namespace.h>
 #include <net/icmp.h>
 #include <net/inet_hashtables.h>
+#include <net/ip_tunnels.h>
 #include <net/route.h>
 #include <net/checksum.h>
 #include <net/xfrm.h>
 #include "udp_impl.h"
 #include <net/sock_reuseport.h>
 #include <net/addrconf.h>
+#include <net/udp_tunnel.h>
 
 struct udp_table udp_table __read_mostly;
 EXPORT_SYMBOL(udp_table);
@@ -371,6 +373,7 @@ static int compute_score(struct sock *sk, struct net *net,
 {
        int score;
        struct inet_sock *inet;
+       bool dev_match;
 
        if (!net_eq(sock_net(sk), net) ||
            udp_sk(sk)->udp_port_hash != hnum ||
@@ -398,15 +401,11 @@ static int compute_score(struct sock *sk, struct net *net,
                score += 4;
        }
 
-       if (sk->sk_bound_dev_if || exact_dif) {
-               bool dev_match = (sk->sk_bound_dev_if == dif ||
-                                 sk->sk_bound_dev_if == sdif);
-
-               if (!dev_match)
-                       return -1;
-               if (sk->sk_bound_dev_if)
-                       score += 4;
-       }
+       dev_match = udp_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
+                                       dif, sdif);
+       if (!dev_match)
+               return -1;
+       score += 4;
 
        if (sk->sk_incoming_cpu == raw_smp_processor_id())
                score++;
@@ -585,6 +584,89 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
        return true;
 }
 
+DEFINE_STATIC_KEY_FALSE(udp_encap_needed_key);
+void udp_encap_enable(void)
+{
+       static_branch_inc(&udp_encap_needed_key);
+}
+EXPORT_SYMBOL(udp_encap_enable);
+
+/* Handler for tunnels with arbitrary destination ports: no socket lookup, go
+ * through error handlers in encapsulations looking for a match.
+ */
+static int __udp4_lib_err_encap_no_sk(struct sk_buff *skb, u32 info)
+{
+       int i;
+
+       for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
+               int (*handler)(struct sk_buff *skb, u32 info);
+
+               if (!iptun_encaps[i])
+                       continue;
+               handler = rcu_dereference(iptun_encaps[i]->err_handler);
+               if (handler && !handler(skb, info))
+                       return 0;
+       }
+
+       return -ENOENT;
+}
+
+/* Try to match ICMP errors to UDP tunnels by looking up a socket without
+ * reversing source and destination port: this will match tunnels that force the
+ * same destination port on both endpoints (e.g. VXLAN, GENEVE). Note that
+ * lwtunnels might actually break this assumption by being configured with
+ * different destination ports on endpoints, in this case we won't be able to
+ * trace ICMP messages back to them.
+ *
+ * If this doesn't match any socket, probe tunnels with arbitrary destination
+ * ports (e.g. FoU, GUE): there, the receiving socket is useless, as the port
+ * we've sent packets to won't necessarily match the local destination port.
+ *
+ * Then ask the tunnel implementation to match the error against a valid
+ * association.
+ *
+ * Return an error if we can't find a match, the socket if we need further
+ * processing, zero otherwise.
+ */
+static struct sock *__udp4_lib_err_encap(struct net *net,
+                                        const struct iphdr *iph,
+                                        struct udphdr *uh,
+                                        struct udp_table *udptable,
+                                        struct sk_buff *skb, u32 info)
+{
+       int network_offset, transport_offset;
+       struct sock *sk;
+
+       network_offset = skb_network_offset(skb);
+       transport_offset = skb_transport_offset(skb);
+
+       /* Network header needs to point to the outer IPv4 header inside ICMP */
+       skb_reset_network_header(skb);
+
+       /* Transport header needs to point to the UDP header */
+       skb_set_transport_header(skb, iph->ihl << 2);
+
+       sk = __udp4_lib_lookup(net, iph->daddr, uh->source,
+                              iph->saddr, uh->dest, skb->dev->ifindex, 0,
+                              udptable, NULL);
+       if (sk) {
+               int (*lookup)(struct sock *sk, struct sk_buff *skb);
+               struct udp_sock *up = udp_sk(sk);
+
+               lookup = READ_ONCE(up->encap_err_lookup);
+               if (!lookup || lookup(sk, skb))
+                       sk = NULL;
+       }
+
+       if (!sk)
+               sk = ERR_PTR(__udp4_lib_err_encap_no_sk(skb, info));
+
+       skb_set_transport_header(skb, transport_offset);
+       skb_set_network_header(skb, network_offset);
+
+       return sk;
+}
+
 /*
  * This routine is called by the ICMP module when it gets some
  * sort of error condition.  If err < 0 then the socket should
@@ -596,13 +678,14 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk,
  * to find the appropriate port.
  */
 
-void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
+int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
 {
        struct inet_sock *inet;
        const struct iphdr *iph = (const struct iphdr *)skb->data;
        struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2));
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
+       bool tunnel = false;
        struct sock *sk;
        int harderr;
        int err;
@@ -612,8 +695,21 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
                               iph->saddr, uh->source, skb->dev->ifindex,
                               inet_sdif(skb), udptable, NULL);
        if (!sk) {
-               __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
-               return; /* No socket for error */
+               /* No socket for error: try tunnels before discarding */
+               sk = ERR_PTR(-ENOENT);
+               if (static_branch_unlikely(&udp_encap_needed_key)) {
+                       sk = __udp4_lib_err_encap(net, iph, uh, udptable, skb,
+                                                 info);
+                       if (!sk)
+                               return 0;
+               }
+
+               if (IS_ERR(sk)) {
+                       __ICMP_INC_STATS(net, ICMP_MIB_INERRORS);
+                       return PTR_ERR(sk);
+               }
+
+               tunnel = true;
        }
 
        err = 0;
@@ -656,6 +752,10 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
         *      RFC1122: OK.  Passes ICMP errors back to application, as per
         *      4.1.3.3.
         */
+       if (tunnel) {
+               /* ...not for tunnels though: we don't have a sending socket */
+               goto out;
+       }
        if (!inet->recverr) {
                if (!harderr || sk->sk_state != TCP_ESTABLISHED)
                        goto out;
@@ -665,12 +765,12 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        sk->sk_err = err;
        sk->sk_error_report(sk);
 out:
-       return;
+       return 0;
 }
 
-void udp_err(struct sk_buff *skb, u32 info)
+int udp_err(struct sk_buff *skb, u32 info)
 {
-       __udp4_lib_err(skb, info, &udp_table);
+       return __udp4_lib_err(skb, info, &udp_table);
 }
 
 /*
@@ -1713,6 +1813,10 @@ try_again:
                memset(sin->sin_zero, 0, sizeof(sin->sin_zero));
                *addr_len = sizeof(*sin);
        }
+
+       if (udp_sk(sk)->gro_enabled)
+               udp_cmsg_recv(msg, sk, skb);
+
        if (inet->cmsg_flags)
                ip_cmsg_recv_offset(msg, sk, skb, sizeof(struct udphdr), off);
 
@@ -1889,13 +1993,6 @@ static int __udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
        return 0;
 }
 
-DEFINE_STATIC_KEY_FALSE(udp_encap_needed_key);
-void udp_encap_enable(void)
-{
-       static_branch_enable(&udp_encap_needed_key);
-}
-EXPORT_SYMBOL(udp_encap_enable);
-
 /* returns:
  *  -1: error
  *   0: success
@@ -1904,7 +2001,7 @@ EXPORT_SYMBOL(udp_encap_enable);
  * Note that in the success and error cases, the skb is assumed to
  * have either been requeued or freed.
  */
-static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb)
 {
        struct udp_sock *up = udp_sk(sk);
        int is_udplite = IS_UDPLITE(sk);
@@ -2007,6 +2104,27 @@ drop:
        return -1;
 }
 
+static int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb)
+{
+       struct sk_buff *next, *segs;
+       int ret;
+
+       if (likely(!udp_unexpected_gso(sk, skb)))
+               return udp_queue_rcv_one_skb(sk, skb);
+
+       BUILD_BUG_ON(sizeof(struct udp_skb_cb) > SKB_SGO_CB_OFFSET);
+       __skb_push(skb, -skb_mac_offset(skb));
+       segs = udp_rcv_segment(sk, skb, true);
+       for (skb = segs; skb; skb = next) {
+               next = skb->next;
+               __skb_pull(skb, skb_transport_offset(skb));
+               ret = udp_queue_rcv_one_skb(sk, skb);
+               if (ret > 0)
+                       ip_protocol_deliver_rcu(dev_net(skb->dev), skb, -ret);
+       }
+       return 0;
+}
+
 /* For TCP sockets, sk_rx_dst is protected by socket lock
  * For UDP, we use xchg() to guard against concurrent changes.
  */
@@ -2398,11 +2516,15 @@ void udp_destroy_sock(struct sock *sk)
        bool slow = lock_sock_fast(sk);
        udp_flush_pending_frames(sk);
        unlock_sock_fast(sk, slow);
-       if (static_branch_unlikely(&udp_encap_needed_key) && up->encap_type) {
-               void (*encap_destroy)(struct sock *sk);
-               encap_destroy = READ_ONCE(up->encap_destroy);
-               if (encap_destroy)
-                       encap_destroy(sk);
+       if (static_branch_unlikely(&udp_encap_needed_key)) {
+               if (up->encap_type) {
+                       void (*encap_destroy)(struct sock *sk);
+                       encap_destroy = READ_ONCE(up->encap_destroy);
+                       if (encap_destroy)
+                               encap_destroy(sk);
+               }
+               if (up->encap_enabled)
+                       static_branch_dec(&udp_encap_needed_key);
        }
 }
 
@@ -2447,7 +2569,9 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                        /* FALLTHROUGH */
                case UDP_ENCAP_L2TPINUDP:
                        up->encap_type = val;
-                       udp_encap_enable();
+                       lock_sock(sk);
+                       udp_tunnel_encap_enable(sk->sk_socket);
+                       release_sock(sk);
                        break;
                default:
                        err = -ENOPROTOOPT;
@@ -2469,6 +2593,14 @@ int udp_lib_setsockopt(struct sock *sk, int level, int optname,
                up->gso_size = val;
                break;
 
+       case UDP_GRO:
+               lock_sock(sk);
+               if (valbool)
+                       udp_tunnel_encap_enable(sk->sk_socket);
+               up->gro_enabled = valbool;
+               release_sock(sk);
+               break;
+
        /*
         *      UDP-Lite's partial checksum coverage (RFC 3828).
         */