Commit 42fb06b3 authored by David Howells's avatar David Howells

net: Change the udp encap_err_rcv to allow use of {ip,ipv6}_icmp_error()

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: default avatarDavid Howells <dhowells@redhat.com>
cc: Marc Dionne <marc.dionne@auristor.com>
cc: linux-afs@lists.infradead.org
cc: netdev@vger.kernel.org
parent 8889a711
...@@ -70,7 +70,8 @@ struct udp_sock { ...@@ -70,7 +70,8 @@ struct udp_sock {
* For encapsulation sockets. * For encapsulation sockets.
*/ */
int (*encap_rcv)(struct sock *sk, struct sk_buff *skb); 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); int (*encap_err_lookup)(struct sock *sk, struct sk_buff *skb);
void (*encap_destroy)(struct sock *sk); void (*encap_destroy)(struct sock *sk);
......
...@@ -68,8 +68,8 @@ typedef int (*udp_tunnel_encap_rcv_t)(struct sock *sk, struct sk_buff *skb); ...@@ -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, typedef int (*udp_tunnel_encap_err_lookup_t)(struct sock *sk,
struct sk_buff *skb); struct sk_buff *skb);
typedef void (*udp_tunnel_encap_err_rcv_t)(struct sock *sk, typedef void (*udp_tunnel_encap_err_rcv_t)(struct sock *sk,
struct sk_buff *skb, struct sk_buff *skb, int err,
unsigned int udp_offset); __be16 port, u32 info, u8 *payload);
typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk); typedef void (*udp_tunnel_encap_destroy_t)(struct sock *sk);
typedef struct sk_buff *(*udp_tunnel_gro_receive_t)(struct sock *sk, typedef struct sk_buff *(*udp_tunnel_gro_receive_t)(struct sock *sk,
struct list_head *head, struct list_head *head,
......
...@@ -433,6 +433,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err, ...@@ -433,6 +433,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
} }
kfree_skb(skb); kfree_skb(skb);
} }
EXPORT_SYMBOL_GPL(ip_icmp_error);
void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info) void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
{ {
......
...@@ -784,7 +784,8 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) ...@@ -784,7 +784,8 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)
if (tunnel) { if (tunnel) {
/* ...not for tunnels though: we don't have a sending socket */ /* ...not for tunnels though: we don't have a sending socket */
if (udp_sk(sk)->encap_err_rcv) 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; goto out;
} }
if (!inet->recverr) { if (!inet->recverr) {
......
...@@ -334,6 +334,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err, ...@@ -334,6 +334,7 @@ void ipv6_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
if (sock_queue_err_skb(sk, skb)) if (sock_queue_err_skb(sk, skb))
kfree_skb(skb); kfree_skb(skb);
} }
EXPORT_SYMBOL_GPL(ipv6_icmp_error);
void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info) void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
{ {
......
...@@ -631,7 +631,8 @@ int __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, ...@@ -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 */ /* Tunnels don't have an application socket: don't pass errors back */
if (tunnel) { if (tunnel) {
if (udp_sk(sk)->encap_err_rcv) 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; goto out;
} }
......
...@@ -998,7 +998,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *); ...@@ -998,7 +998,7 @@ void rxrpc_send_keepalive(struct rxrpc_peer *);
/* /*
* peer_event.c * 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_error_report(struct sock *);
void rxrpc_peer_keepalive_worker(struct work_struct *); void rxrpc_peer_keepalive_worker(struct work_struct *);
......
...@@ -29,20 +29,16 @@ static void rxrpc_distribute_error(struct rxrpc_peer *, int, ...@@ -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, static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int udp_offset, __be16 udp_port,
unsigned int *info,
struct sockaddr_rxrpc *srx) struct sockaddr_rxrpc *srx)
{ {
struct iphdr *ip, *ip0 = ip_hdr(skb); struct iphdr *ip, *ip0 = ip_hdr(skb);
struct icmphdr *icmp = icmp_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); _enter("%u,%u,%u", ip0->protocol, icmp->type, icmp->code);
switch (icmp->type) { switch (icmp->type) {
case ICMP_DEST_UNREACH: case ICMP_DEST_UNREACH:
*info = ntohs(icmp->un.frag.mtu);
fallthrough;
case ICMP_TIME_EXCEEDED: case ICMP_TIME_EXCEEDED:
case ICMP_PARAMETERPROB: case ICMP_PARAMETERPROB:
ip = (struct iphdr *)((void *)icmp + 8); ip = (struct iphdr *)((void *)icmp + 8);
...@@ -63,7 +59,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, ...@@ -63,7 +59,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
case AF_INET: case AF_INET:
srx->transport_len = sizeof(srx->transport.sin); srx->transport_len = sizeof(srx->transport.sin);
srx->transport.family = AF_INET; 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, memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
...@@ -72,7 +68,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, ...@@ -72,7 +68,7 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local,
case AF_INET6: case AF_INET6:
srx->transport_len = sizeof(srx->transport.sin); srx->transport_len = sizeof(srx->transport.sin);
srx->transport.family = AF_INET; 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, memcpy(&srx->transport.sin.sin_addr, &ip->daddr,
sizeof(struct in_addr)); sizeof(struct in_addr));
break; break;
...@@ -93,20 +89,16 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp_rcu(struct rxrpc_local *local, ...@@ -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, static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
struct sk_buff *skb, struct sk_buff *skb,
unsigned int udp_offset, __be16 udp_port,
unsigned int *info,
struct sockaddr_rxrpc *srx) struct sockaddr_rxrpc *srx)
{ {
struct icmp6hdr *icmp = icmp6_hdr(skb); struct icmp6hdr *icmp = icmp6_hdr(skb);
struct ipv6hdr *ip, *ip0 = ipv6_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); _enter("%u,%u,%u", ip0->nexthdr, icmp->icmp6_type, icmp->icmp6_code);
switch (icmp->icmp6_type) { switch (icmp->icmp6_type) {
case ICMPV6_DEST_UNREACH: case ICMPV6_DEST_UNREACH:
*info = ntohl(icmp->icmp6_mtu);
fallthrough;
case ICMPV6_PKT_TOOBIG: case ICMPV6_PKT_TOOBIG:
case ICMPV6_TIME_EXCEED: case ICMPV6_TIME_EXCEED:
case ICMPV6_PARAMPROB: case ICMPV6_PARAMPROB:
...@@ -129,13 +121,13 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local, ...@@ -129,13 +121,13 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local,
_net("Rx ICMP6 on v4 sock"); _net("Rx ICMP6 on v4 sock");
srx->transport_len = sizeof(srx->transport.sin); srx->transport_len = sizeof(srx->transport.sin);
srx->transport.family = AF_INET; 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, memcpy(&srx->transport.sin.sin_addr,
&ip->daddr.s6_addr32[3], sizeof(struct in_addr)); &ip->daddr.s6_addr32[3], sizeof(struct in_addr));
break; break;
case AF_INET6: case AF_INET6:
_net("Rx ICMP6"); _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, memcpy(&srx->transport.sin6.sin6_addr, &ip->daddr,
sizeof(struct in6_addr)); sizeof(struct in6_addr));
break; break;
...@@ -152,15 +144,13 @@ static struct rxrpc_peer *rxrpc_lookup_peer_icmp6_rcu(struct rxrpc_local *local, ...@@ -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. * Handle an error received on the local endpoint as a tunnel.
*/ */
void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, int err,
unsigned int udp_offset) __be16 port, u32 info, u8 *payload)
{ {
struct sock_extended_err ee; struct sock_extended_err ee;
struct sockaddr_rxrpc srx; struct sockaddr_rxrpc srx;
struct rxrpc_local *local; struct rxrpc_local *local;
struct rxrpc_peer *peer; struct rxrpc_peer *peer;
unsigned int info = 0;
int err;
u8 version = ip_hdr(skb)->version; u8 version = ip_hdr(skb)->version;
u8 type = icmp_hdr(skb)->type; u8 type = icmp_hdr(skb)->type;
u8 code = icmp_hdr(skb)->code; u8 code = icmp_hdr(skb)->code;
...@@ -176,13 +166,11 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, ...@@ -176,13 +166,11 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
switch (ip_hdr(skb)->version) { switch (ip_hdr(skb)->version) {
case IPVERSION: case IPVERSION:
peer = rxrpc_lookup_peer_icmp_rcu(local, skb, udp_offset, peer = rxrpc_lookup_peer_icmp_rcu(local, skb, port, &srx);
&info, &srx);
break; break;
#ifdef CONFIG_AF_RXRPC_IPV6 #ifdef CONFIG_AF_RXRPC_IPV6
case 6: case 6:
peer = rxrpc_lookup_peer_icmp6_rcu(local, skb, udp_offset, peer = rxrpc_lookup_peer_icmp6_rcu(local, skb, port, &srx);
&info, &srx);
break; break;
#endif #endif
default: default:
...@@ -201,34 +189,12 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, ...@@ -201,34 +189,12 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
switch (version) { switch (version) {
case IPVERSION: case IPVERSION:
switch (type) { if (type == ICMP_DEST_UNREACH &&
case ICMP_DEST_UNREACH: code == ICMP_FRAG_NEEDED) {
switch (code) {
case ICMP_FRAG_NEEDED:
rxrpc_adjust_mtu(peer, info); rxrpc_adjust_mtu(peer, info);
rcu_read_unlock(); rcu_read_unlock();
rxrpc_put_peer(peer); rxrpc_put_peer(peer);
return; 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;
} }
ee.ee_origin = SO_EE_ORIGIN_ICMP; ee.ee_origin = SO_EE_ORIGIN_ICMP;
...@@ -239,16 +205,13 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb, ...@@ -239,16 +205,13 @@ void rxrpc_encap_err_rcv(struct sock *sk, struct sk_buff *skb,
#ifdef CONFIG_AF_RXRPC_IPV6 #ifdef CONFIG_AF_RXRPC_IPV6
case 6: case 6:
switch (type) { if (type == ICMPV6_PKT_TOOBIG) {
case ICMPV6_PKT_TOOBIG:
rxrpc_adjust_mtu(peer, info); rxrpc_adjust_mtu(peer, info);
rcu_read_unlock(); rcu_read_unlock();
rxrpc_put_peer(peer); rxrpc_put_peer(peer);
return; return;
} }
icmpv6_err_convert(type, code, &err);
if (err == EACCES) if (err == EACCES)
err = EHOSTUNREACH; err = EHOSTUNREACH;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment