OSDN Git Service

net: Change the udp encap_err_rcv to allow use of {ip,ipv6}_icmp_error()
authorDavid Howells <dhowells@redhat.com>
Wed, 12 Oct 2022 07:49:29 +0000 (08:49 +0100)
committerDavid Howells <dhowells@redhat.com>
Tue, 8 Nov 2022 16:42:28 +0000 (16:42 +0000)
Change the udp encap_err_rcv signature to match ip_icmp_error() and
ipv6_icmp_error() so that those can be used from the called function and
export them.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org

include/linux/udp.h
include/net/udp_tunnel.h
net/ipv4/ip_sockglue.c
net/ipv4/udp.c
net/ipv6/datagram.c
net/ipv6/udp.c
net/rxrpc/ar-internal.h
net/rxrpc/peer_event.c

index 5cdba00..dea57aa 100644 (file)
@@ -70,7 +70,8 @@ struct udp_sock {
         * For encapsulation sockets.
         */
        int (*encap_rcv)(struct sock *sk, struct sk_buff *skb);
-       void (*encap_err_rcv)(struct sock *sk, struct sk_buff *skb, unsigned int udp_offset);
+       void (*encap_err_rcv)(struct sock *sk, struct sk_buff *skb, int err,
+                             __be16 port, u32 info, u8 *payload);
        int (*encap_err_lookup)(struct sock *sk, struct sk_buff *skb);
        void (*encap_destroy)(struct sock *sk);
 
index 72394f4..0ca9b7a 100644 (file)
@@ -68,8 +68,8 @@ typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb);
 typedef int (*udp_tunnel_encap_err_lookup_t)(struct sock *sk,
                                             struct sk_buff *skb);
 typedef void (*udp_tunnel_encap_err_rcv_t)(struct sock *sk,
-                                          struct sk_buff *skb,
-                                          unsigned int udp_offset);
+                                          struct sk_buff *skb, int err,
+                                          __be16 port, u32 info, u8 *payload);
 typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk);
 typedef struct sk_buff *(*udp_tunnel_gro_receive_t)(struct sock *sk,
                                                    struct list_head *head,
index 5f16807..9f92ae3 100644 (file)
@@ -433,6 +433,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
        }
        kfree_skb(skb);
 }
+EXPORT_SYMBOL_GPL(ip_icmp_error);
 
 void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
 {
index 89accc3..b859d6c 100644 (file)
@@ -784,7 +784,8 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
        if (tunnel) {
                /* ...not for tunnels though: we don't have a sending socket */
                if (udp_sk(sk)->encap_err_rcv)
-                       udp_sk(sk)->encap_err_rcv(sk, skb, iph->ihl << 2);
+                       udp_sk(sk)->encap_err_rcv(sk, skb, err, uh->dest, info,
+                                                 (u8 *)(uh+1));
                goto out;
        }
        if (!inet->recverr) {
index df7e032..7c7155b 100644 (file)
@@ -334,6 +334,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
        if (sock_queue_err_skb(sk, skb))
                kfree_skb(skb);
 }
+EXPORT_SYMBOL_GPL(ipv6_icmp_error);
 
 void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
 {
index 297f7cc..4bc3fc2 100644 (file)
@@ -631,7 +631,8 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        /* Tunnels don't have an application socket: don't pass errors back */
        if (tunnel) {
                if (udp_sk(sk)->encap_err_rcv)
-                       udp_sk(sk)->encap_err_rcv(sk, skb, offset);
+                       udp_sk(sk)->encap_err_rcv(sk, skb, err, uh->dest,
+                                                 ntohl(info), (u8 *)(uh+1));
                goto out;
        }
 
index 436a1e8..51270b2 100644 (file)
@@ -998,7 +998,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *);
 /*
  * peer_event.c
  */
-void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, unsigned int udp_offset);
+void rxrpc_encap_err_rcv(struct sock *, struct sk_buff *, int, __be16, u32, u8 *);
 void rxrpc_error_report(struct sock *);
 void rxrpc_peer_keepalive_worker(struct work_struct *);
 
index 32561e9..d7d6d7a 100644 (file)
@@ -29,20 +29,16 @@ static void rxrpc_distribute_error(struct rxrpc_peer *, int,
  */
 static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
                                                     struct sk_buff *skb,
-                                                    unsigned int udp_offset,
-                                                    unsigned int *info,
+                                                    __be16 udp_port,
                                                     struct sockaddr_rxrpc *srx)
 {
        struct iphdr *ip, *ip0 = ip_hdr(skb);
        struct icmphdr *icmp = icmp_hdr(skb);
-       struct udphdr *udp = (struct udphdr *)(skb->data + udp_offset);
 
        _enter("%u,%u,%u", ip0->protocol, icmp->type, icmp->code);
 
        switch (icmp->type) {
        case ICMP_DEST_UNREACH:
-               *info = ntohs(icmp->un.frag.mtu);
-               fallthrough;
        case ICMP_TIME_EXCEEDED:
        case ICMP_PARAMETERPROB:
                ip = (struct iphdr *)((void *)icmp + 8);
@@ -63,7 +59,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
        case AF_INET:
                srx->transport_len = sizeof(srx->transport.sin);
                srx->transport.family = AF_INET;
-               srx->transport.sin.sin_port = udp->dest;
+               srx->transport.sin.sin_port = udp_port;
                memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
                       sizeof(struct in_addr));
                break;
@@ -72,7 +68,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
        case AF_INET6:
                srx->transport_len = sizeof(srx->transport.sin);
                srx->transport.family = AF_INET;
-               srx->transport.sin.sin_port = udp->dest;
+               srx->transport.sin.sin_port = udp_port;
                memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
                       sizeof(struct in_addr));
                break;
@@ -93,20 +89,16 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
  */
 static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
                                                      struct sk_buff *skb,
-                                                     unsigned int udp_offset,
-                                                     unsigned int *info,
+                                                     __be16 udp_port,
                                                      struct sockaddr_rxrpc *srx)
 {
        struct icmp6hdr *icmp = icmp6_hdr(skb);
        struct ipv6hdr *ip, *ip0 = ipv6_hdr(skb);
-       struct udphdr *udp = (struct udphdr *)(skb->data + udp_offset);
 
        _enter("%u,%u,%u", ip0->nexthdr, icmp->icmp6_type, icmp->icmp6_code);
 
        switch (icmp->icmp6_type) {
        case ICMPV6_DEST_UNREACH:
-               *info = ntohl(icmp->icmp6_mtu);
-               fallthrough;
        case ICMPV6_PKT_TOOBIG:
        case ICMPV6_TIME_EXCEED:
        case ICMPV6_PARAMPROB:
@@ -129,13 +121,13 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
                _net("Rx ICMP6 on v4 sock");
                srx->transport_len = sizeof(srx->transport.sin);
                srx->transport.family = AF_INET;
-               srx->transport.sin.sin_port = udp->dest;
+               srx->transport.sin.sin_port = udp_port;
                memcpy(&srx->transport.sin.sin_addr,
                       &ip->daddr.s6_addr32[3], sizeof(struct in_addr));
                break;
        case AF_INET6:
                _net("Rx ICMP6");
-               srx->transport.sin.sin_port = udp->dest;
+               srx->transport.sin.sin_port = udp_port;
                memcpy(&srx->transport.sin6.sin6_addr, &ip->daddr,
                       sizeof(struct in6_addr));
                break;
@@ -152,15 +144,13 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
 /*
  * Handle an error received on the local endpoint as a tunnel.
  */
-void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
-                        unsigned int udp_offset)
+void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, int err,
+                        __be16 port, u32 info, u8 *payload)
 {
        struct sock_extended_err ee;
        struct sockaddr_rxrpc srx;
        struct rxrpc_local *local;
        struct rxrpc_peer *peer;
-       unsigned int info = 0;
-       int err;
        u8 version = ip_hdr(skb)->version;
        u8 type = icmp_hdr(skb)->type;
        u8 code = icmp_hdr(skb)->code;
@@ -176,13 +166,11 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
 
        switch (ip_hdr(skb)->version) {
        case IPVERSION:
-               peer = rxrpc_lookup_peer_icmp_rcu(local, skb, udp_offset,
-                                                 &info, &srx);
+               peer = rxrpc_lookup_peer_icmp_rcu(local, skb, port, &srx);
                break;
 #ifdef CONFIG_AF_RXRPC_IPV6
        case 6:
-               peer = rxrpc_lookup_peer_icmp6_rcu(local, skb, udp_offset,
-                                                  &info, &srx);
+               peer = rxrpc_lookup_peer_icmp6_rcu(local, skb, port, &srx);
                break;
 #endif
        default:
@@ -201,34 +189,12 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
 
        switch (version) {
        case IPVERSION:
-               switch (type) {
-               case ICMP_DEST_UNREACH:
-                       switch (code) {
-                       case ICMP_FRAG_NEEDED:
-                               rxrpc_adjust_mtu(peer, info);
-                               rcu_read_unlock();
-                               rxrpc_put_peer(peer);
-                               return;
-                       default:
-                               break;
-                       }
-
-                       err = EHOSTUNREACH;
-                       if (code <= NR_ICMP_UNREACH) {
-                               /* Might want to do something different with
-                                * non-fatal errors
-                                */
-                               //harderr = icmp_err_convert[code].fatal;
-                               err = icmp_err_convert[code].errno;
-                       }
-                       break;
-
-               case ICMP_TIME_EXCEEDED:
-                       err = EHOSTUNREACH;
-                       break;
-               default:
-                       err = EPROTO;
-                       break;
+               if (type == ICMP_DEST_UNREACH &&
+                   code == ICMP_FRAG_NEEDED) {
+                       rxrpc_adjust_mtu(peer, info);
+                       rcu_read_unlock();
+                       rxrpc_put_peer(peer);
+                       return;
                }
 
                ee.ee_origin = SO_EE_ORIGIN_ICMP;
@@ -239,16 +205,13 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
 
 #ifdef CONFIG_AF_RXRPC_IPV6
        case 6:
-               switch (type) {
-               case ICMPV6_PKT_TOOBIG:
+               if (type == ICMPV6_PKT_TOOBIG) {
                        rxrpc_adjust_mtu(peer, info);
                        rcu_read_unlock();
                        rxrpc_put_peer(peer);
                        return;
                }
 
-               icmpv6_err_convert(type, code, &err);
-
                if (err == EACCES)
                        err = EHOSTUNREACH;