Skip to content

icmp: Handle ICMP packets as IPPROTO_IP on BSD

In macOS, as already commented in this source file as well, packets from SOCK_DGRAM + IPPROTO_ICMP sockets include IP header while Linux doesn't not prepend the header.

Due to the discrepancy, in macOS, we need to handle received ICMP packets as if they are IP packets so that its IPv4 header gets stripped.

As pointed out in review comments, it appears CONFIG_BSD is no longer propagated from QEMU. This patch fixes the issue by detecting BSD (including macOS) by ourselves.

How I tested

You can easily reproduce the issue by pinging from QEMU with user networking on macOS. Here's an example using lima:

$ limactl start default # use default (broken) QEMU
$ limactl shell default ping -c 4 8.8.8.8                                       
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=0 ttl=255 time=914914384133207 ms
wrong data byte #16 should be 0x10 but was 0x0
#16	0 1 0 1 b6 c1 8e 64 0 0 0 0 27 9e e 0 0 0 0 0 10 11 12 13 14 15 16 17 18 19 1a 1b 
#48	1c 1d 1e 1f 20 21 22 23 
64 bytes from 8.8.8.8: icmp_seq=0 ttl=255 time=2761390231356143 ms (DUP!)
wrong data byte #16 should be 0x10 but was 0x0
#16	0 1 0 2 b7 c1 8e 64 0 0 0 0 c6 b6 e 0 0 0 0 0 10 11 12 13 14 15 16 17 18 19 1a 1b 
#48	1c 1d 1e 1f 20 21 22 23 
64 bytes from 8.8.8.8: icmp_seq=0 ttl=255 time=3313081185710003 ms (DUP!)
wrong data byte #16 should be 0x10 but was 0x0
#16	0 1 0 3 b8 c1 8e 64 0 0 0 0 6d bd e 0 0 0 0 0 10 11 12 13 14 15 16 17 18 19 1a 1b 
#48	1c 1d 1e 1f 20 21 22 23 
64 bytes from 8.8.8.8: icmp_seq=0 ttl=255 time=4561985657376191 ms (DUP!)
wrong data byte #16 should be 0x10 but was 0x0
#16	0 1 0 4 b9 c1 8e 64 0 0 0 0 c1 cd e 0 0 0 0 0 10 11 12 13 14 15 16 17 18 19 1a 1b 
#48	1c 1d 1e 1f 20 21 22 23 
^C
--- 8.8.8.8 ping statistics ---
4 packets transmitted, 1 received, +3 duplicates, 75% packet loss, time 3008ms
rtt min/avg/max/mdev = 914914384133207.147/2887842864643886.080/4561985657376190.676/2509448.035 ms, pipe 5

As you can see ping complains about corrupted ICMP payload and reports incorrect RTTs. With this patch, ping will work as normal:

$ QEMU_SYSTEM_AARCH64=~/src/qemu/build/qemu-system-aarch64 limactl start default  # Use my own build w/ this fix
$ limactl shell default ping -c 4 8.8.8.8                                       
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=255 time=13.2 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=255 time=10.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=255 time=9.50 ms
64 bytes from 8.8.8.8: icmp_seq=4 ttl=255 time=9.03 ms

--- 8.8.8.8 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 2997ms
rtt min/avg/max/mdev = 9.028/10.460/13.200/1.627 ms
Edited by Seiya Nuta

Merge request reports

Loading