diff --git a/ChangeLog b/ChangeLog index 746be8fb7feb57eac0c461ed33cf179f69c84cb1..2245ad3a08245635a124c24dacce59c736e09d2f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -657,3 +657,4 @@ * examples/nsh: A debug option was left on that can (and does) cause infinite loops and stack overflows. + * net/uip: Correct calculation of checksum on ICMP ping response. diff --git a/Documentation/NuttX.html b/Documentation/NuttX.html index 7d565de74b407bc7f09c43ee967ba8aee3c8e210..ff04cad7f7ab541498d68d64e86ed2ac5f6ecc59 100644 --- a/Documentation/NuttX.html +++ b/Documentation/NuttX.html @@ -1348,6 +1348,7 @@ nuttx-0.4.4 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> * examples/nsh: A debug option was left on that can (and does) cause infinite loops and stack overflows. + * net/uip: Correct calculation of checksum on ICMP ping response. pascal-0.1.3 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr> diff --git a/include/net/uip/uip-arch.h b/include/net/uip/uip-arch.h index 80e574efa5eceb0de5125ad78485b10ca8d201da..3409f1416393d0cd3247df1695312b3f67c9a762 100644 --- a/include/net/uip/uip-arch.h +++ b/include/net/uip/uip-arch.h @@ -366,7 +366,7 @@ extern uint16 uip_ipchksum(struct uip_driver_s *dev); extern uint16 uip_tcpchksum(struct uip_driver_s *dev); extern uint16 uip_udpchksum(struct uip_driver_s *dev); -extern uint16 uip_icmpchksum(struct uip_driver_s *dev); +extern uint16 uip_icmpchksum(struct uip_driver_s *dev, int len); #endif /* __UIP_ARCH_H */ diff --git a/include/net/uip/uip-icmp.h b/include/net/uip/uip-icmp.h index 67d6941d3856551cd359d585d0b2d95ebb2448ad..e6b52b07cb84b0f7ec4c36019358b5dd04b758de 100644 --- a/include/net/uip/uip-icmp.h +++ b/include/net/uip/uip-icmp.h @@ -2,7 +2,7 @@ * net/uip/uip-icmp.h * Header file for the uIP ICMP stack. * - * Copyright (C) 2007, 2008 Gregory Nutt. All rights reserved. + * Copyright (C) 2007-2009 Gregory Nutt. All rights reserved. * Author: Gregory Nutt <spudmonkey@racsa.co.cr> * * This logic was leveraged from uIP which also has a BSD-style license: diff --git a/net/uip/uip_chksum.c b/net/uip/uip_chksum.c index defb5b4791844c3148f966365c4c64f245af6a74..45e8894b37d8bd33b2ec4351899a77ca76629693 100644 --- a/net/uip/uip_chksum.c +++ b/net/uip/uip_chksum.c @@ -229,11 +229,11 @@ uint16 uip_udpchksum(struct uip_driver_s *dev) /* Calculate the checksum of the ICMP message */ -#if defined(CONFIG_NET_ICMP) && defined(CONFIG_NET_ICMP_PING) -uint16 uip_icmpchksum(struct uip_driver_s *dev) +#if defined(CONFIG_NET_ICMP) +uint16 uip_icmpchksum(struct uip_driver_s *dev, int len) { struct uip_icmpip_hdr *picmp = ICMPBUF; - return uip_chksum((uint16*)&picmp->type, dev->d_sndlen); + return uip_chksum((uint16*)&picmp->type, len); } #endif diff --git a/net/uip/uip_icmpinput.c b/net/uip/uip_icmpinput.c index 52352c700fe37b551807a6d327072b336bd976c1..f2edcbcb5d7d69f3cdf27ec3f276f32f377c9bd6 100644 --- a/net/uip/uip_icmpinput.c +++ b/net/uip/uip_icmpinput.c @@ -131,22 +131,24 @@ void uip_icmpinput(struct uip_driver_s *dev) } #endif - picmp->type = ICMP_ECHO_REPLY; + /* Change the ICMP type */ - if (picmp->icmpchksum >= HTONS(0xffff - (ICMP_ECHO_REPLY << 8))) - { - picmp->icmpchksum += HTONS(ICMP_ECHO_REPLY << 8) + 1; - } - else - { - picmp->icmpchksum += HTONS(ICMP_ECHO_REPLY << 8); - } + picmp->type = ICMP_ECHO_REPLY; /* Swap IP addresses. */ uiphdr_ipaddr_copy(picmp->destipaddr, picmp->srcipaddr); uiphdr_ipaddr_copy(picmp->srcipaddr, &dev->d_ipaddr); + /* Recalculate the ICMP checksum */ + + picmp->icmpchksum = 0; + picmp->icmpchksum = ~uip_icmpchksum(dev, (((uint16)picmp->len[0] << 8) | (uint16)picmp->len[1]) - UIP_IPH_LEN); + if (picmp->icmpchksum == 0) + { + picmp->icmpchksum = 0xffff; + } + nvdbg("Outgoing ICMP packet length: %d (%d)\n", dev->d_len, (picmp->len[0] << 8) | picmp->len[1]); diff --git a/net/uip/uip_icmpsend.c b/net/uip/uip_icmpsend.c index 6acbf3176a2abb6c74d24fe77d3cf4446f952ab2..0c3784e951400d7619a95bb6915bc52c59994274 100644 --- a/net/uip/uip_icmpsend.c +++ b/net/uip/uip_icmpsend.c @@ -150,7 +150,7 @@ void uip_icmpsend(struct uip_driver_s *dev, uip_ipaddr_t *destaddr) /* Calculate the ICMP checksum. */ picmp->icmpchksum = 0; - picmp->icmpchksum = ~(uip_icmpchksum(dev)); + picmp->icmpchksum = ~(uip_icmpchksum(dev, dev->d_sndlen)); if (picmp->icmpchksum == 0) { picmp->icmpchksum = 0xffff;