1616#include <net/sock.h>
1717#include <net/af_rxrpc.h>
1818#include <net/ip.h>
19- #include <net/icmp.h>
2019#include "ar-internal.h"
2120
22- static void rxrpc_adjust_mtu (struct rxrpc_peer * , unsigned int );
2321static void rxrpc_store_error (struct rxrpc_peer * , struct sock_exterr_skb * );
2422static void rxrpc_distribute_error (struct rxrpc_peer * , int ,
2523 enum rxrpc_call_completion );
2624
27- /*
28- * Find the peer associated with an ICMPv4 packet.
29- */
30- static struct rxrpc_peer * rxrpc_lookup_peer_icmp_rcu (struct rxrpc_local * local ,
31- struct sk_buff * skb ,
32- __be16 udp_port ,
33- struct sockaddr_rxrpc * srx )
34- {
35- struct iphdr * ip , * ip0 = ip_hdr (skb );
36- struct icmphdr * icmp = icmp_hdr (skb );
37-
38- _enter ("%u,%u,%u" , ip0 -> protocol , icmp -> type , icmp -> code );
39-
40- switch (icmp -> type ) {
41- case ICMP_DEST_UNREACH :
42- case ICMP_TIME_EXCEEDED :
43- case ICMP_PARAMETERPROB :
44- ip = (struct iphdr * )((void * )icmp + 8 );
45- break ;
46- default :
47- return NULL ;
48- }
49-
50- memset (srx , 0 , sizeof (* srx ));
51- srx -> transport_type = local -> srx .transport_type ;
52- srx -> transport_len = local -> srx .transport_len ;
53- srx -> transport .family = local -> srx .transport .family ;
54-
55- /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
56- * versa?
57- */
58- switch (srx -> transport .family ) {
59- case AF_INET :
60- srx -> transport_len = sizeof (srx -> transport .sin );
61- srx -> transport .family = AF_INET ;
62- srx -> transport .sin .sin_port = udp_port ;
63- memcpy (& srx -> transport .sin .sin_addr , & ip -> daddr ,
64- sizeof (struct in_addr ));
65- break ;
66-
67- #ifdef CONFIG_AF_RXRPC_IPV6
68- case AF_INET6 :
69- srx -> transport_len = sizeof (srx -> transport .sin );
70- srx -> transport .family = AF_INET ;
71- srx -> transport .sin .sin_port = udp_port ;
72- memcpy (& srx -> transport .sin .sin_addr , & ip -> daddr ,
73- sizeof (struct in_addr ));
74- break ;
75- #endif
76-
77- default :
78- WARN_ON_ONCE (1 );
79- return NULL ;
80- }
81-
82- _net ("ICMP {%pISp}" , & srx -> transport );
83- return rxrpc_lookup_peer_rcu (local , srx );
84- }
85-
86- #ifdef CONFIG_AF_RXRPC_IPV6
87- /*
88- * Find the peer associated with an ICMPv6 packet.
89- */
90- static struct rxrpc_peer * rxrpc_lookup_peer_icmp6_rcu (struct rxrpc_local * local ,
91- struct sk_buff * skb ,
92- __be16 udp_port ,
93- struct sockaddr_rxrpc * srx )
94- {
95- struct icmp6hdr * icmp = icmp6_hdr (skb );
96- struct ipv6hdr * ip , * ip0 = ipv6_hdr (skb );
97-
98- _enter ("%u,%u,%u" , ip0 -> nexthdr , icmp -> icmp6_type , icmp -> icmp6_code );
99-
100- switch (icmp -> icmp6_type ) {
101- case ICMPV6_DEST_UNREACH :
102- case ICMPV6_PKT_TOOBIG :
103- case ICMPV6_TIME_EXCEED :
104- case ICMPV6_PARAMPROB :
105- ip = (struct ipv6hdr * )((void * )icmp + 8 );
106- break ;
107- default :
108- return NULL ;
109- }
110-
111- memset (srx , 0 , sizeof (* srx ));
112- srx -> transport_type = local -> srx .transport_type ;
113- srx -> transport_len = local -> srx .transport_len ;
114- srx -> transport .family = local -> srx .transport .family ;
115-
116- /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
117- * versa?
118- */
119- switch (srx -> transport .family ) {
120- case AF_INET :
121- _net ("Rx ICMP6 on v4 sock" );
122- srx -> transport_len = sizeof (srx -> transport .sin );
123- srx -> transport .family = AF_INET ;
124- srx -> transport .sin .sin_port = udp_port ;
125- memcpy (& srx -> transport .sin .sin_addr ,
126- & ip -> daddr .s6_addr32 [3 ], sizeof (struct in_addr ));
127- break ;
128- case AF_INET6 :
129- _net ("Rx ICMP6" );
130- srx -> transport .sin .sin_port = udp_port ;
131- memcpy (& srx -> transport .sin6 .sin6_addr , & ip -> daddr ,
132- sizeof (struct in6_addr ));
133- break ;
134- default :
135- WARN_ON_ONCE (1 );
136- return NULL ;
137- }
138-
139- _net ("ICMP {%pISp}" , & srx -> transport );
140- return rxrpc_lookup_peer_rcu (local , srx );
141- }
142- #endif /* CONFIG_AF_RXRPC_IPV6 */
143-
144- /*
145- * Handle an error received on the local endpoint as a tunnel.
146- */
147- void rxrpc_encap_err_rcv (struct sock * sk , struct sk_buff * skb , int err ,
148- __be16 port , u32 info , u8 * payload )
149- {
150- struct sock_extended_err ee ;
151- struct sockaddr_rxrpc srx ;
152- struct rxrpc_local * local ;
153- struct rxrpc_peer * peer ;
154- u8 version = ip_hdr (skb )-> version ;
155- u8 type = icmp_hdr (skb )-> type ;
156- u8 code = icmp_hdr (skb )-> code ;
157-
158- rcu_read_lock ();
159- local = rcu_dereference_sk_user_data (sk );
160- if (unlikely (!local )) {
161- rcu_read_unlock ();
162- return ;
163- }
164-
165- rxrpc_new_skb (skb , rxrpc_skb_received );
166-
167- switch (ip_hdr (skb )-> version ) {
168- case IPVERSION :
169- peer = rxrpc_lookup_peer_icmp_rcu (local , skb , port , & srx );
170- break ;
171- #ifdef CONFIG_AF_RXRPC_IPV6
172- case 6 :
173- peer = rxrpc_lookup_peer_icmp6_rcu (local , skb , port , & srx );
174- break ;
175- #endif
176- default :
177- rcu_read_unlock ();
178- return ;
179- }
180-
181- if (peer && !rxrpc_get_peer_maybe (peer ))
182- peer = NULL ;
183- if (!peer ) {
184- rcu_read_unlock ();
185- return ;
186- }
187-
188- memset (& ee , 0 , sizeof (ee ));
189-
190- switch (version ) {
191- case IPVERSION :
192- if (type == ICMP_DEST_UNREACH &&
193- code == ICMP_FRAG_NEEDED ) {
194- rxrpc_adjust_mtu (peer , info );
195- rcu_read_unlock ();
196- rxrpc_put_peer (peer );
197- return ;
198- }
199-
200- ee .ee_origin = SO_EE_ORIGIN_ICMP ;
201- ee .ee_type = type ;
202- ee .ee_code = code ;
203- ee .ee_errno = err ;
204- break ;
205-
206- #ifdef CONFIG_AF_RXRPC_IPV6
207- case 6 :
208- if (type == ICMPV6_PKT_TOOBIG ) {
209- rxrpc_adjust_mtu (peer , info );
210- rcu_read_unlock ();
211- rxrpc_put_peer (peer );
212- return ;
213- }
214-
215- if (err == EACCES )
216- err = EHOSTUNREACH ;
217-
218- ee .ee_origin = SO_EE_ORIGIN_ICMP6 ;
219- ee .ee_type = type ;
220- ee .ee_code = code ;
221- ee .ee_errno = err ;
222- break ;
223- #endif
224- }
225-
226- trace_rxrpc_rx_icmp (peer , & ee , & srx );
227-
228- rxrpc_distribute_error (peer , err , RXRPC_CALL_NETWORK_ERROR );
229- rcu_read_unlock ();
230- rxrpc_put_peer (peer );
231- }
232-
23325/*
23426 * Find the peer associated with a local error.
23527 */
@@ -246,6 +38,9 @@ static struct rxrpc_peer *rxrpc_lookup_peer_local_rcu(struct rxrpc_local *local,
24638 srx -> transport_len = local -> srx .transport_len ;
24739 srx -> transport .family = local -> srx .transport .family ;
24840
41+ /* Can we see an ICMP4 packet on an ICMP6 listening socket? and vice
42+ * versa?
43+ */
24944 switch (srx -> transport .family ) {
25045 case AF_INET :
25146 srx -> transport_len = sizeof (srx -> transport .sin );
@@ -375,20 +170,38 @@ void rxrpc_error_report(struct sock *sk)
375170 }
376171 rxrpc_new_skb (skb , rxrpc_skb_received );
377172 serr = SKB_EXT_ERR (skb );
173+ if (!skb -> len && serr -> ee .ee_origin == SO_EE_ORIGIN_TIMESTAMPING ) {
174+ _leave ("UDP empty message" );
175+ rcu_read_unlock ();
176+ rxrpc_free_skb (skb , rxrpc_skb_freed );
177+ return ;
178+ }
378179
379- if ( serr -> ee . ee_origin == SO_EE_ORIGIN_LOCAL ) {
380- peer = rxrpc_lookup_peer_local_rcu ( local , skb , & srx );
381- if ( peer && ! rxrpc_get_peer_maybe ( peer ))
382- peer = NULL ;
383- if ( peer ) {
384- trace_rxrpc_rx_icmp ( peer , & serr -> ee , & srx );
385- rxrpc_store_error ( peer , serr );
386- }
180+ peer = rxrpc_lookup_peer_local_rcu ( local , skb , & srx );
181+ if ( peer && ! rxrpc_get_peer_maybe ( peer ))
182+ peer = NULL ;
183+ if (! peer ) {
184+ rcu_read_unlock ();
185+ rxrpc_free_skb ( skb , rxrpc_skb_freed );
186+ _leave ( " [no peer]" );
187+ return ;
387188 }
388189
190+ trace_rxrpc_rx_icmp (peer , & serr -> ee , & srx );
191+
192+ if ((serr -> ee .ee_origin == SO_EE_ORIGIN_ICMP &&
193+ serr -> ee .ee_type == ICMP_DEST_UNREACH &&
194+ serr -> ee .ee_code == ICMP_FRAG_NEEDED )) {
195+ rxrpc_adjust_mtu (peer , serr -> ee .ee_info );
196+ goto out ;
197+ }
198+
199+ rxrpc_store_error (peer , serr );
200+ out :
389201 rcu_read_unlock ();
390202 rxrpc_free_skb (skb , rxrpc_skb_freed );
391203 rxrpc_put_peer (peer );
204+
392205 _leave ("" );
393206}
394207
0 commit comments