mirror of
https://github.com/tbsdtv/linux_media.git
synced 2025-07-23 04:33:26 +02:00
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: David Howells <dhowells@redhat.com> cc: Marc Dionne <marc.dionne@auristor.com> cc: linux-afs@lists.infradead.org cc: netdev@vger.kernel.org
This commit is contained in:
@@ -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);
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
/* 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 *);
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
_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,
|
|||||||
/*
|
/*
|
||||||
* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
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) {
|
rxrpc_adjust_mtu(peer, info);
|
||||||
case ICMP_FRAG_NEEDED:
|
rcu_read_unlock();
|
||||||
rxrpc_adjust_mtu(peer, info);
|
rxrpc_put_peer(peer);
|
||||||
rcu_read_unlock();
|
return;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
|||||||
|
|
||||||
#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;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user