This is not really elegant and I didn't try to display with vertical
bars like it should be done when no additional IP info is requested,
but the code already has many branches with very similar code and I
didn't want to add even more complexity to it.
Vincent Bernat [Tue, 9 Mar 2021 21:46:47 +0000 (22:46 +0100)]
net: fix MPLS display for curses and report
After #364, MPLS labels were not displayed anymore due to a logic
invertion. Previously, the addr/mpls fields were populated first and
addrs[i]/mplss[i] copied from these values. After the patch, the
reverse is happening but populating addrs[i] and mpls[i] was still
done by copying the value from addr/mpls. This was not a problem for
displaying addresses as addr was used however for mpls labels, this is
mplss which is used exclusively (net_mpls() is not using mpls field,
but mplss field).
After #364, hosts position is changing depending on the most recent
paths. I didn't fix that as it may be seen as a feature but this can
be a bit disturbing.
Also, unrelated, but the unnecessary/unsafe casts to void pointer are
removed for net_addr(), net_addrs(), net_mpls() and net_mplss(). Also,
net_mpls() is using mpls field instead of mplss as this seems more
correct.
This has been tested with curses and report. Also, raw is still
working.
Vincent Bernat [Mon, 8 Mar 2021 07:29:53 +0000 (08:29 +0100)]
ui: don't cast to void* when calling display_rawhost()
The provided types are compatible with the function signature.
Moreover, this seems to hide a bug where `display_rawhost()` is called
with an address instead of an MPLS struct.
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.