Chris Friesen <cfriesen@xxxxxxxxxx> Subject: UDP error handling inconsistencies. Hi, [sorry if you receive this email twice, the subject line disappeared from the first version due to a stupid mistake on my part] according to the documentation (man 7 udp): "All fatal errors will be passed to the user as an error return even when the socket is not connected. This includes asynchronous errors received from the network." and experience shows that it is wrong (simply sending a packet to a non existing port on another host). The error disappeared for some reason in 2.3.41, which was released in January 2000 (yeah, almost 8 years ago, I've been doing some kernel paleontology). I found this when upgrading a machine, which has been running almost nonstop since 1999. Not only the code for ipv4 does not match the documentation but it seems that the ipv6 behaviour is subtly different from ipv4, which I try to resume in the following table (which may be wrong, as my head spins with all the negatives in the logic): connected recverr Error reported? socket? set ? Doc. IPv4 IPv6 No No Hard No No No Yes Yes Yes Yes Yes No Yes No Hard Yes Yes Yes Yes Yes A patch to restore pre-2.3.41 behaviour for IPv4 follows (and the logic becomes much clearer IMO, not only because it avoids a goto), but I'm not sure that it should be applied. I've been running it for 24 hours without ill effects (my test program reacts much faster when the other end is not running instead of waiting for a timeout in poll(2)), but I'm afraid that existing applications might break when confronted with a sedimented bug/feature which has been the behaviour against which they have been tested. On the other hand, I feel that subtle corner cases differences between IPv4 and IPv6 should not be allowed. I could produce a patch for IPv6 but I don't have any IPv6 environment nor the time to set one up for testing. BTW, I've been trying to follow UDP's sendmsg paths and I still have not found where the check for sk->sk_err (or the call to sock_error() actually) is done. I have also found at least a reference to a similar problem on lkml by Chris Friesen: http://www.ussg.iu.edu/hypermail/linux/kernel/0308.3/0259.html but there are exactly zero replies to this post. Regards, Gabriel P.S.: if inet->recverr is the unfrequent case, the first if in the patch should become if (unlikely(inet->recverr)). I have no idea of how frequently RECVERR option is set. diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 2835535..bca532c 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -380,14 +380,13 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[]) * RFC1122: OK. Passes ICMP errors back to application, as per * 4.1.3.3. */ - if (!inet->recverr) { - if (!harderr || sk->sk_state != TCP_ESTABLISHED) - goto out; - } else { + if (inet->recverr) { ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1)); } - sk->sk_err = err; - sk->sk_error_report(sk); + if (harderr || sk->sk_state == TCP_ESTABLISHED) { + sk->sk_err = err; + sk->sk_error_report(sk); + } out: sock_put(sk); } ----- End forwarded message ----- - To unsubscribe from this list: send the line "unsubscribe linux-net" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html