Chris Friesen <[EMAIL PROTECTED]>
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 [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to