1 /* Error message handling (ICMP)
3 * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
12 #include <linux/module.h>
13 #include <linux/net.h>
14 #include <linux/skbuff.h>
15 #include <linux/errqueue.h>
16 #include <linux/udp.h>
18 #include <linux/in6.h>
19 #include <linux/icmp.h>
21 #include <net/af_rxrpc.h>
23 #include "ar-internal.h"
26 * handle an error received on the local endpoint
28 void rxrpc_UDP_error_report(struct sock
*sk
)
30 struct sock_exterr_skb
*serr
;
31 struct rxrpc_transport
*trans
;
32 struct rxrpc_local
*local
= sk
->sk_user_data
;
33 struct rxrpc_peer
*peer
;
38 _enter("%p{%d}", sk
, local
->debug_id
);
40 skb
= skb_dequeue(&sk
->sk_error_queue
);
42 _leave("UDP socket errqueue empty");
48 serr
= SKB_EXT_ERR(skb
);
49 addr
= *(__be32
*)(skb_network_header(skb
) + serr
->addr_offset
);
52 _net("Rx UDP Error from %pI4:%hu", &addr
, ntohs(port
));
53 _debug("Msg l:%d d:%d", skb
->len
, skb
->data_len
);
55 peer
= rxrpc_find_peer(local
, addr
, port
);
62 trans
= rxrpc_find_transport(local
, peer
);
66 _leave(" [no trans]");
70 if (serr
->ee
.ee_origin
== SO_EE_ORIGIN_ICMP
&&
71 serr
->ee
.ee_type
== ICMP_DEST_UNREACH
&&
72 serr
->ee
.ee_code
== ICMP_FRAG_NEEDED
74 u32 mtu
= serr
->ee
.ee_info
;
76 _net("Rx Received ICMP Fragmentation Needed (%d)", mtu
);
78 /* wind down the local interface MTU */
79 if (mtu
> 0 && peer
->if_mtu
== 65535 && mtu
< peer
->if_mtu
) {
81 _net("I/F MTU %u", mtu
);
84 /* ip_rt_frag_needed() may have eaten the info */
86 mtu
= ntohs(icmp_hdr(skb
)->un
.frag
.mtu
);
89 /* they didn't give us a size, estimate one */
96 if (mtu
< peer
->hdrsize
)
97 mtu
= peer
->hdrsize
+ 4;
101 if (mtu
< peer
->mtu
) {
102 spin_lock_bh(&peer
->lock
);
104 peer
->maxdata
= peer
->mtu
- peer
->hdrsize
;
105 spin_unlock_bh(&peer
->lock
);
106 _net("Net MTU %u (maxdata %u)",
107 peer
->mtu
, peer
->maxdata
);
111 rxrpc_put_peer(peer
);
113 /* pass the transport ref to error_handler to release */
114 skb_queue_tail(&trans
->error_queue
, skb
);
115 rxrpc_queue_work(&trans
->error_handler
);
117 /* reset and regenerate socket error */
118 spin_lock_bh(&sk
->sk_error_queue
.lock
);
120 skb
= skb_peek(&sk
->sk_error_queue
);
122 sk
->sk_err
= SKB_EXT_ERR(skb
)->ee
.ee_errno
;
123 spin_unlock_bh(&sk
->sk_error_queue
.lock
);
124 sk
->sk_error_report(sk
);
126 spin_unlock_bh(&sk
->sk_error_queue
.lock
);
133 * deal with UDP error messages
135 void rxrpc_UDP_error_handler(struct work_struct
*work
)
137 struct sock_extended_err
*ee
;
138 struct sock_exterr_skb
*serr
;
139 struct rxrpc_transport
*trans
=
140 container_of(work
, struct rxrpc_transport
, error_handler
);
146 skb
= skb_dequeue(&trans
->error_queue
);
150 serr
= SKB_EXT_ERR(skb
);
153 _net("Rx Error o=%d t=%d c=%d e=%d",
154 ee
->ee_origin
, ee
->ee_type
, ee
->ee_code
, ee
->ee_errno
);
158 switch (ee
->ee_origin
) {
159 case SO_EE_ORIGIN_ICMP
:
161 switch (ee
->ee_type
) {
162 case ICMP_DEST_UNREACH
:
163 switch (ee
->ee_code
) {
164 case ICMP_NET_UNREACH
:
165 _net("Rx Received ICMP Network Unreachable");
168 case ICMP_HOST_UNREACH
:
169 _net("Rx Received ICMP Host Unreachable");
172 case ICMP_PORT_UNREACH
:
173 _net("Rx Received ICMP Port Unreachable");
176 case ICMP_FRAG_NEEDED
:
177 _net("Rx Received ICMP Fragmentation Needed (%d)",
179 err
= 0; /* dealt with elsewhere */
181 case ICMP_NET_UNKNOWN
:
182 _net("Rx Received ICMP Unknown Network");
185 case ICMP_HOST_UNKNOWN
:
186 _net("Rx Received ICMP Unknown Host");
190 _net("Rx Received ICMP DestUnreach code=%u",
196 case ICMP_TIME_EXCEEDED
:
197 _net("Rx Received ICMP TTL Exceeded");
201 _proto("Rx Received ICMP error { type=%u code=%u }",
202 ee
->ee_type
, ee
->ee_code
);
207 case SO_EE_ORIGIN_LOCAL
:
208 _proto("Rx Received local error { error=%d }",
213 case SO_EE_ORIGIN_NONE
:
214 case SO_EE_ORIGIN_ICMP6
:
216 _proto("Rx Received error report { orig=%u }",
222 /* terminate all the affected calls if there's an unrecoverable
225 struct rxrpc_call
*call
, *_n
;
227 _debug("ISSUE ERROR %d", err
);
229 spin_lock_bh(&trans
->peer
->lock
);
230 trans
->peer
->net_error
= err
;
232 list_for_each_entry_safe(call
, _n
, &trans
->peer
->error_targets
,
234 write_lock(&call
->state_lock
);
235 if (call
->state
!= RXRPC_CALL_COMPLETE
&&
236 call
->state
< RXRPC_CALL_NETWORK_ERROR
) {
237 call
->state
= RXRPC_CALL_NETWORK_ERROR
;
238 set_bit(RXRPC_CALL_RCVD_ERROR
, &call
->events
);
239 rxrpc_queue_call(call
);
241 write_unlock(&call
->state_lock
);
242 list_del_init(&call
->error_link
);
245 spin_unlock_bh(&trans
->peer
->lock
);
248 if (!skb_queue_empty(&trans
->error_queue
))
249 rxrpc_queue_work(&trans
->error_handler
);
252 rxrpc_put_transport(trans
);
This page took 0.034375 seconds and 5 git commands to generate.