Sami Kerola [Wed, 17 Jul 2019 19:17:56 +0000 (20:17 +0100)]
mtr-packet: make address-not-available errors less likely
Use MIN_PORT to MAX_PORT port range to avoid getting EADDRNOTAVAIL caused by
sockets in FIN-WAIT-1 state. This issue is easy to reproduce with following
loop (as root).
src="$(ip route | awk '/default/ {print $9}')"
while true; do
echo "6000 send-probe ip-4 1.1.1.1 local-ip-4 $src port 443 protocol tcp" |
./mtr-packet
done | head -n 10
6000 reply ip-4 1.1.1.1 round-trip-time 11306
6000 address-not-available
6000 address-not-available
[...]
Reported-by: Scott Pearson <scott@cloudflare.com> Reproeuced-by: Jarred Trainor <jarred@cloudflare.com> Signed-off-by: Sami Kerola <kerolasa@iki.fi> && <kerolasa@cloudflare.com>
Matt Kimball [Sun, 3 Mar 2019 16:00:55 +0000 (08:00 -0800)]
Rework Cygwin mtr-packet to respond to signals (such as SIGTERM)
The prior implementation of mtr-packet on Cygwin would
not respond to Unix-style signals sent from other processes.
It was unkillable from the Cygwin shell, even with SIGKILL,
and exiting mtr would sometimes stall for several seconds because
it would ignore the SIGTERM sent from the main mtr process.
It would then wait for all outstanding probes to timeout before
exiting.
Signals were ignored because they are implemented by the Cygwin
library at the user level, (i.e. not provided by the OS kernel),
and mtr-packet often bypassed Cygwin's I/O functions by calling
Win32 APIs directly.
With this rework, the Cygwin implementation uses an ICMP service
thread to call the Win32 ICMP functions, but the main thread
uses a POSIX-style select() loop, similar to the Unix version mtr.
I would have liked to avoid multithreading entirely, but here are
the constraints:
a) mtr was originally a Unix program which used "raw sockets"
b) In order to port mtr to Windows, Cygwin is used to get a
Unix-like environment
c) You can't use a raw socket to receive an ICMP reply on Windows.
However, Windows provides a separate API in the form of
ICMP.DLL for sending and receiving ICMP messages.
d) The ICMP API works asynchronously, and requires completion
through an asynchronous procedure call ("APC")
e) APCs are only delivered during blocking Win32 operations
which are flagged as "alertable." This prevents apps from
having APCs execute unexpectedly during an I/O operation.
f) Cygwin's implementation of POSIX functions does all I/O
through non-alertable I/O operations. This is reasonable
because APCs don't exist in the POSIX API.
g) Cygwin implements Unix-style signals at the application level,
since the Windows kernel doesn't have them. We want our
program to respond to SIGTERM and SIGKILL, at least.
h) Cygwin's signal implementation will deliver signals during
blocking I/O functions in the Cygwin library, but won't
respond to signals if the signal is sent while the application
is in a blocking Windows API call which Cygwin is not aware of.
i) Since we want to both send/receive ICMP probes and also respond
to Unix-style signals, we require two threads: one which
uses Cygwin's POSIX style blocking I/O and can respond to
signals, and one which uses alertable waits using Win32
blocking APIs.
The solution is to have the main thread using select() as the
blocking operation in its loop, and also to have an ICMP service
thread using WaitForSingleObjectEx() as its blocking operation.
The main thread will respond to signals. The ICMP service thread
will run the APCs completing ICMP.DLL requests.
This change doesn't affect non-Windows versions of mtr, other than
moving the code from command_unix.c back into command.c,
since it can now be shared between Unix-like systems and Windows.
Change 817f171d converted the error reporting in mtr-packet from
perror() to error(). That's fine, but error() is missing on MacOS.
We already had portability/error.c for this reason, but that was
previously only linked into the mtr binary, not mtr-packet.
This change also links portability/error.c with mtr-packet, when
error() is missing from the OS.
Rationale is that error(...) will prefix the error message with the
program name which is useful information now that mtr is split into
two executables (mtr and mtr-packet.)
Markus Kötter [Thu, 1 Nov 2018 10:34:25 +0000 (11:34 +0100)]
probe - extend matching to src/dst host&port
Running multiple instances of mtr in udp mode will lead to incorrect
response pick ups due to sequence number re-use.
The changes address the issue by using more values to prevent incorrect
probe matches.
Markus Kötter [Mon, 29 Oct 2018 10:29:22 +0000 (11:29 +0100)]
set udp checksum
in case the checksum field is used fpr the sequence number,
calculate the checksum and write to the udp payload field so the seq no
matches the checksum
In mtr 0.87 it was possible to start mtr against unreachable
host (that local kernel already knew that it is unreachable).
Later it was broken. Make such tracing possible again.
Under Linux Vserver SOCK_RAW is quite limited. Only IPPROTO_ICMP works,
so try to use it.
check_length_order() also doesn't work because sendto is also limited.
Fortunately under linux check_length_order is not needed as described
in comment around check_length_order.
Chonggang Li [Mon, 21 Aug 2017 20:34:45 +0000 (13:34 -0700)]
mtr-packet: fix compilation on OS X
Error queue is not supported by OS X, use AC_CHECK_HEADERS to introduce
a compilation flag called HAVE_LINUX_ERRQUEUE_H to skip compiling errqueue
related code.
Chonggang Li [Thu, 13 Jul 2017 23:17:08 +0000 (16:17 -0700)]
mtr-packet: use ICMP and UDP without privilege on linux
This commit enables non-privileged users to use mtr on linux without
setuid. Currently ICMP and UDP protocols are supported in this commit.
Previously, to use mtr on linux with protocol ICMP and UDP, RAW sockets
have to be opened to send out packets and receive ICMP errors, so users
must have RAW socket permission to use this program. The goal of this
commit is to make mtr usable for normal users without RAW socket
permission. The changes include:
(1) The origianl logic is not changed, but instead, when the program
fails to open RAW sockets, it will fallback to opening DGRAM scoekts.
(2) A new flag is created to indicate whether RAW socket is used for
IPv4 and IPv6 respectively.
(3) When using DGRAM sockets to send out packets, receive sockets are
not required. Instead, IP_RECVERR is enabled to receive ICMP errors.
(4) Packet receiving function is changed from recvfrom() to recvmsg() to
retrieve more information.
(5) When error is indicated, the program will check the error type and
read from the error queue of the socket. Original payload causing the
error will be read out from the error queue to match for probe, and
additional data (e.g. source ip of ICMP error packets) will be retrieved
from CMSG.
(6) Use a separate socket to probe byter order if raw socket creation
fails, to avoid double bind issue.
(7) Also a few tweaks are added to make non-RAW socket working.
Matt Kimball [Sun, 16 Jul 2017 17:19:32 +0000 (10:19 -0700)]
commandline: Added --interface for using a named network interface
Using '--interface' on the commandline (or '-I') will specify
a network interface by name. This is sometimes a more convenient
alternative to using '--address' for specifying a source address
from which to send probes.
This can be useful when you have both a wired ethernet connection
and WiFi connection, and wish to use a specific connection for the
purposes of tracing.
This feature was requested in issue #207.
This change also cleans up main() slightly by factoring out the
hostent structure generation.
Matt Kimball [Wed, 12 Jul 2017 19:48:46 +0000 (12:48 -0700)]
json: Fix malformed json when the "hubs" list is empty
When generating JSON output, and when no hosts are found when
probing, the generated JSON was malformed. (i.e. when the "hubs" list
in the generated JSON is empty, there was no closing bracket.) This can
be reproduced by tracing to an unused host address on the local subnet.
Matt Kimball [Tue, 11 Jul 2017 21:55:40 +0000 (14:55 -0700)]
ui: display "no route to host" error as host entry rather than abort
When a host is reported as unreachable in response to a particular
network probe, the Windows version of the mtr UI had the unfortuante
behavior of exiting and and printing a terse message. This is
surprising to a user, who would expect mtr probes and reporting to
continue.
With this change, probing continues and a status reading
"no route to host" is displayed in the probe report.
This change will also improve the reporting of the Unix version of
mtr, now specifying "no route to host" instead of misleadingly
indicating that no reply has been received.