Skip to content

usr: fix the ping build and its ICMP reply parsing - #321

Merged
daniel-rossier merged 3 commits into
mainfrom
fix/usr-ping-reply-parsing
Aug 23, 2026
Merged

usr: fix the ping build and its ICMP reply parsing#321
daniel-rossier merged 3 commits into
mainfrom
fix/usr-ping-reply-parsing

Conversation

@daniel-rossier

Copy link
Copy Markdown
Contributor

build.sh bsp-so3 was failing in usr-so3:do_build:

so3/usr/src/ping.c:39:10: fatal error: lwip/icmp.h: No such file or directory

Those lwIP headers are kernel-side (so3/so3/include/net/lwip/) and are not
on the user-space include path — nor needed: musl's <netinet/ip_icmp.h>
already provides ICMP_ECHO / ICMP_ECHOREPLY and struct iphdr.

Removing the includes alone would have left the reply check broken. The magic
69 the code compared against was not an ICMP type but 0x45, the first byte
of the IP header (version 4, IHL 5): a raw socket delivers the whole IP
datagram (lwIP calls the raw pcb's receive callback with the payload still on
the IP header, see net/lwip/core/raw.c:raw_input), so the ICMP message starts
at iphdr->ihl * 4. The reply is now parsed at that offset, the receive buffer
is sized for iphdr + PING_PKT_LEN (the old 64-byte one truncated the
payload), a too-short reply is rejected, and the TTL reported is the one that
came back rather than the one requested. rtt_total was also summed into
without being initialised, and close(s) was commented out under a dead label.

Two build-experience fixes ride along, one commit each:

  • the build container's banner, dbuild.sh's header/--help, docker/README.md,
    the Dockerfile header and the build-system chapter now lead with bsp-so3;
    this tree's default target is SO3, bsp-linux stays as the alternative;
  • tezi-feed-serve.sh --ensure runs after every build and deploy, including on
    soft/hard-storage platforms that never publish a TEZI feed, and printed
    "feed directory does not exist yet / run a deploy first" every single time.
    It is silent now when there is nothing to serve; the hint is kept for an
    explicit foreground invocation.

Testing

  • build.sh bsp-so3 and deploy.sh bsp-so3 on virt64, clean.
  • Booted under QEMU (st.sh) to the SO3 shell; ping.elf present in the rootfs.
  • clang-format --dry-run -Werror so3/usr/src/ping.c clean.

Note: ping cannot be exercised on virt32/virt64 as shipped — CONFIG_NET is
off in every defconfig and the only NIC driver is smc911x, which QEMU's
virt machine does not provide (doc/source/lwip.rst already documents this).
The fix is therefore verified by build and inspection, not by a live echo reply.

ping did not build any more: the kernel-side lwIP headers (lwip/icmp.h,
lwip/inet.h, lwip/netif.h) are not on the user-space include path, and
they are not needed either — musl's <netinet/ip_icmp.h> already provides
ICMP_ECHO/ICMP_ECHOREPLY and struct iphdr.

Dropping them alone would still have left the reply check wrong. The
magic 69 it used to compare against was never an ICMP type: it is 0x45,
the first byte of the IP header (version 4, IHL 5). A raw socket hands
over the whole IP datagram — lwIP delivers the pbuf to the raw pcb with
the payload still pointing at the IP header — so the ICMP message starts
at iphdr->ihl * 4, not at offset 0.

Parse the reply accordingly:

  - receive into a buffer sized for the IP header plus the ICMP message;
    the previous 64-byte buffer truncated the payload,
  - reject a reply too short to hold an ICMP header,
  - check type/code at the right offset, against ICMP_ECHOREPLY,
  - report the TTL that came back rather than the one we asked for.

While here, initialise rtt_total (it was summed into uninitialised) and
close the socket on the way out instead of leaving the close commented
out under a dead label.
This tree's default target is SO3, so the first thing the build
container suggests should be the SO3 BSP, not the Linux one. Switch the
examples in the container banner, in dbuild.sh's header and --help, in
docker/README.md, in the Dockerfile header and in the build-system
chapter; the bsp-linux mention stays as the alternative.
--ensure runs after every build and deploy, including on the soft- and
hard-storage platforms that never publish a TEZI feed, so an absent feed
directory is the normal case there — yet each command ended with a
"feed directory does not exist yet / run a deploy first" pair on stderr.

Test for the feed quietly in do_ensure and leave the explaining to
check_feed, which now only runs when the server is asked for explicitly
(foreground invocation), where the hint is what the user wants.
@daniel-rossier
daniel-rossier merged commit 90511ff into main Aug 23, 2026
6 checks passed
@daniel-rossier
daniel-rossier deleted the fix/usr-ping-reply-parsing branch August 23, 2026 13:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant