]>
Commit | Line | Data |
---|---|---|
da495922 GKH |
1 | From foo@baz Fri Jul 3 19:59:52 PDT 2015 |
2 | From: Julian Anastasov <ja@ssi.bg> | |
3 | Date: Tue, 23 Jun 2015 08:34:39 +0300 | |
4 | Subject: ip: report the original address of ICMP messages | |
5 | ||
6 | From: Julian Anastasov <ja@ssi.bg> | |
7 | ||
8 | [ Upstream commit 34b99df4e6256ddafb663c6de0711dceceddfe0e ] | |
9 | ||
10 | ICMP messages can trigger ICMP and local errors. In this case | |
11 | serr->port is 0 and starting from Linux 4.0 we do not return | |
12 | the original target address to the error queue readers. | |
13 | Add function to define which errors provide addr_offset. | |
14 | With this fix my ping command is not silent anymore. | |
15 | ||
16 | Fixes: c247f0534cc5 ("ip: fix error queue empty skb handling") | |
17 | Signed-off-by: Julian Anastasov <ja@ssi.bg> | |
18 | Acked-by: Willem de Bruijn <willemb@google.com> | |
19 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
21 | --- | |
22 | net/ipv4/ip_sockglue.c | 11 ++++++++++- | |
23 | net/ipv6/datagram.c | 12 +++++++++++- | |
24 | 2 files changed, 21 insertions(+), 2 deletions(-) | |
25 | ||
26 | --- a/net/ipv4/ip_sockglue.c | |
27 | +++ b/net/ipv4/ip_sockglue.c | |
28 | @@ -432,6 +432,15 @@ void ip_local_error(struct sock *sk, int | |
29 | kfree_skb(skb); | |
30 | } | |
31 | ||
32 | +/* For some errors we have valid addr_offset even with zero payload and | |
33 | + * zero port. Also, addr_offset should be supported if port is set. | |
34 | + */ | |
35 | +static inline bool ipv4_datagram_support_addr(struct sock_exterr_skb *serr) | |
36 | +{ | |
37 | + return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | |
38 | + serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port; | |
39 | +} | |
40 | + | |
41 | /* IPv4 supports cmsg on all imcp errors and some timestamps | |
42 | * | |
43 | * Timestamp code paths do not initialize the fields expected by cmsg: | |
44 | @@ -498,7 +507,7 @@ int ip_recv_error(struct sock *sk, struc | |
45 | ||
46 | serr = SKB_EXT_ERR(skb); | |
47 | ||
48 | - if (sin && serr->port) { | |
49 | + if (sin && ipv4_datagram_support_addr(serr)) { | |
50 | sin->sin_family = AF_INET; | |
51 | sin->sin_addr.s_addr = *(__be32 *)(skb_network_header(skb) + | |
52 | serr->addr_offset); | |
53 | --- a/net/ipv6/datagram.c | |
54 | +++ b/net/ipv6/datagram.c | |
55 | @@ -325,6 +325,16 @@ void ipv6_local_rxpmtu(struct sock *sk, | |
56 | kfree_skb(skb); | |
57 | } | |
58 | ||
59 | +/* For some errors we have valid addr_offset even with zero payload and | |
60 | + * zero port. Also, addr_offset should be supported if port is set. | |
61 | + */ | |
62 | +static inline bool ipv6_datagram_support_addr(struct sock_exterr_skb *serr) | |
63 | +{ | |
64 | + return serr->ee.ee_origin == SO_EE_ORIGIN_ICMP6 || | |
65 | + serr->ee.ee_origin == SO_EE_ORIGIN_ICMP || | |
66 | + serr->ee.ee_origin == SO_EE_ORIGIN_LOCAL || serr->port; | |
67 | +} | |
68 | + | |
69 | /* IPv6 supports cmsg on all origins aside from SO_EE_ORIGIN_LOCAL. | |
70 | * | |
71 | * At one point, excluding local errors was a quick test to identify icmp/icmp6 | |
72 | @@ -389,7 +399,7 @@ int ipv6_recv_error(struct sock *sk, str | |
73 | ||
74 | serr = SKB_EXT_ERR(skb); | |
75 | ||
76 | - if (sin && serr->port) { | |
77 | + if (sin && ipv6_datagram_support_addr(serr)) { | |
78 | const unsigned char *nh = skb_network_header(skb); | |
79 | sin->sin6_family = AF_INET6; | |
80 | sin->sin6_flowinfo = 0; |