The ICMP RFC says that identifier and sequence number may be zero.
Having them zero for a Echo message, along with a data of zero:s
as well will result in a Echo reply message with only zero:s.

Some NAT implementations seem to get the checksum wrong on these
packages. Setting a checksum of 0x0 instead of 0xffff.

Through NAT:
  Internet Control Message Protocol
      Type: 0 (Echo (ping) reply)
      Code: 0
      Checksum: 0x0000 [incorrect, should be 0xffff]
      Identifier (BE): 0 (0x0000)
      Identifier (LE): 0 (0x0000)
      Sequence number (BE): 0 (0x0000)
      Sequence number (LE): 0 (0x0000)
      Data (56 bytes)
          Data: 000000000000000000000000000000000000000000000000...
          [Length: 56]

Without NAT:
  Internet Control Message Protocol
      Type: 0 (Echo (ping) reply)
      Code: 0
      Checksum: 0xffff [correct]
      Identifier (BE): 0 (0x0000)
      Identifier (LE): 0 (0x0000)
      Sequence number (BE): 0 (0x0000)
      Sequence number (LE): 0 (0x0000)
      [Request frame: 189]
      [Response time: 0.024 ms]
      Data (56 bytes)
          Data: 000000000000000000000000000000000000000000000000...
          [Length: 56]

And this in turn will make some hardware MAC checksum offloading
engines drop the packet.

This change can be seen as a workaround for bugs in other layers.
But just setting an identifier for the Echo message packet will
avoid prodding the hornets nest.

Signed-off-by: Jonas Danielsson <[email protected]>
---
 networking/ping.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/networking/ping.c b/networking/ping.c
index 5d71fe8..35ceec7 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -196,6 +196,7 @@ create_icmp_socket(void)
 struct globals {
        char *hostname;
        char packet[DEFDATALEN + MAXIPLEN + MAXICMPLEN];
+       uint16_t myid;
 } FIX_ALIASING;
 #define G (*(struct globals*)&bb_common_bufsiz1)
 #define INIT_G() do { } while (0)
@@ -214,6 +215,7 @@ static void ping4(len_and_sockaddr *lsa)
        pkt = (struct icmp *) G.packet;
        /*memset(pkt, 0, sizeof(G.packet)); already is */
        pkt->icmp_type = ICMP_ECHO;
+       pkt->icmp_id = G.myid;
        pkt->icmp_cksum = inet_cksum((uint16_t *) pkt, sizeof(G.packet));
 
        xsendto(pingsock, G.packet, DEFDATALEN + ICMP_MINLEN, &lsa->u.sa, 
lsa->len);
@@ -238,6 +240,9 @@ static void ping4(len_and_sockaddr *lsa)
                        struct iphdr *iphdr = (struct iphdr *) G.packet;
 
                        pkt = (struct icmp *) (G.packet + (iphdr->ihl << 2));   
/* skip ip hdr */
+                       if (pkt->icmp_id != G.myid)
+                               continue; /* not our ping */
+
                        if (pkt->icmp_type == ICMP_ECHOREPLY)
                                break;
                }
@@ -317,6 +322,7 @@ static int common_ping_main(sa_family_t af, char **argv)
        if (!G.hostname)
                bb_show_usage();
 
+       G.myid = (uint16_t) getpid();
 #if ENABLE_PING6
        lsa = xhost_and_af2sockaddr(G.hostname, 0, af);
 #else
-- 
2.1.4

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to