[Bug 8332] Applications and games using ICMP ping request report 'no connection to internet' (Wine 32-bit/64-bit preloader requires CAP_NET_RAW to create raw sockets)
"WineHQ Bugzilla" <[email protected]> Sun, 13 Jun 2021 23:24:04 +0000
| Newsgroups | gmane.comp.emulators.wine.bugs |
|---|---|
| Message-ID | <[email protected]/> |
https://bugs.winehq.org/show_bug.cgi?id=3D8332 Damjan Jovanovic <[email protected]> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |[email protected], | |[email protected] --- Comment #31 from Damjan Jovanovic <[email protected]> --- Falling back to calling the "ping" command line tool shouldn't ever be necessary on MacOS and Linux. When creating a raw socket fails, Wine tries to fall back to using an unprivileged ICMP socket, which is a non-standard socket type present on Ma= cOS and Linux: ---snip--- int sid=3Dsocket(AF_INET,SOCK_RAW,IPPROTO_ICMP); if (sid < 0) { /* Some systems (e.g. Linux 3.0+ and Mac OS X) support non-privileged ICMP via SOCK_DGRAM type. */ sid=3Dsocket(AF_INET,SOCK_DGRAM,IPPROTO_ICMP); } ---snip--- Documentation: Linux: https://lwn.net/Articles/420800/ MacOS: http://www.manpagez.com/man/4/icmp/ On MacOS, I think that work fine. Linux however is currently completely broken, and pinging always fail, beca= use: 1. This socket type does not return the IP header as expected from the recvfrom() system call in the icmp_get_reply() function, causing the reply = to be parsed incorrectly in that function. On Linux, the reply immediately beg= ins with the ICMP header instead. 2. Even when that is somewhat fixed (it's long and painful to fix fully), it still breaks, because Linux overwrites the ICMP header field "icmp_id" with= its own value, ie. this value is later overwritten by the kernel: ---snip--- icmp_header->icmp_id=3Did; ---snip--- causing this check in icmp_get_reply() to always fail: ---snip--- if ((icmp_header->icmp_id=3D=3Did) && (icmp_header->icmp_se= q=3D=3Dseq)) ---snip--- and the reply thus falsely never matches the request, so pinging still fail= s. The "icmp_id" is overwritten by the socket's port number, which can be set through bind(). It cannot be queried by getsockname() which always returns = port 0, even after bind(). However it seems best not to set it, let the kernel p= ick a free port, and then skip the icmp_id check above instead, as the kernel already filters replies by their icmp_id. Fixing (2) is easy, but (1) really needs to use recvmsg() instead, with IP_RECVTTL, IP_RECVTOS, IP_RETOPTS, IP_RECVERR and other ancillary data, on= ly on Linux and only for these unprivileged ICMP sockets. Then this alternative source of IP header data needs to be integrated into icmp_get_reply(). I don't know how Gabriel ever said that this works on Linux. Either he never tested, only tested pinging an invalid address, or Linux changed how unprivileged ICMP sockets work between then and now: ---snip--- commit e6d9aaeb67172dd0ba1e73f34c7f0cad36ed43ff Author: Gabriel Iv=EF=BF=BD=EF=BF=BDncescu <[email protected]> Date: Mon Aug 3 16:15:52 2020 +0300 iphlpapi: Update comment for SOCK_DGRAM since Linux also supports it fr= om 3.0. Linux does require the user to be in the range specified by /proc/sys/net/ipv4/ping_group_range though, but otherwise works fine. Signed-off-by: Gabriel Iv=EF=BF=BD=EF=BF=BDncescu <gabrielopcode@gmail.= com> Signed-off-by: Alexandre Julliard <[email protected]> ---snip--- --=20 Do not reply to this email, post in Bugzilla using the above URL to reply. You are receiving this mail because: You are watching all bug changes.=