Skip to content

Commit

Permalink
Utilities/nc: Add an option to test a TCP-listening service
Browse files Browse the repository at this point in the history
Similarly to OpenBSD nc, an option to just connect without transmitting
any actual data is added.

However, we don't allow UDP-mode when testing a remote service, as it
will always succeed and has no technical meaning for the user if they're
not able to view the traffic on the remote machine.
  • Loading branch information
supercomputer7 authored and nico committed Jun 28, 2024
1 parent dcf7296 commit 972f758
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 0 deletions.
1 change: 1 addition & 0 deletions Base/usr/share/man/man1/nc.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Network cat: Connect to network sockets as if it were a file.
* `-u`, `--udp`: UDP mode
* `-p port`: Local port for remote connections
* `-v`, `--verbose`: Log everything that's happening
* `-z`, `--test-listening-service`: Test a TCP-listening service

## Arguments

Expand Down
18 changes: 18 additions & 0 deletions Userland/Utilities/nc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
bool should_close = false;
bool udp_mode = false;
bool numeric_mode = false;
bool test_listening_daemons = false;
ByteString target;
u16 port = 0;
u16 local_port = 0;
Expand All @@ -60,6 +61,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.set_general_help("Network cat: Connect to network sockets as if it were a file.");
args_parser.add_option(maximum_tcp_receive_buffer_size_input, "Set maximum tcp receive buffer size", "length", 'I', nullptr);
args_parser.add_option(should_listen, "Listen instead of connecting", "listen", 'l');
args_parser.add_option(test_listening_daemons, "Test a TCP-listening service", "test-listening-service", 'z');
args_parser.add_option(should_close, "Close connection after reading stdin to the end", nullptr, 'N');
args_parser.add_option(numeric_mode, "Suppress name resolution", nullptr, 'n');
args_parser.add_option(udp_mode, "UDP mode", "udp", 'u');
Expand All @@ -69,6 +71,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
args_parser.add_positional_argument(port, "Port to connect to or listen on", "port", Core::ArgsParser::Required::No);
args_parser.parse(arguments);

if (test_listening_daemons && (udp_mode || should_listen)) {
warnln("listening/udp-mode while testing TCP services is not supported");
return 1;
}

if (udp_mode) {
if (should_listen) {
warnln("listening on UDP not yet supported");
Expand Down Expand Up @@ -171,6 +178,17 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
warnln("connecting to {}:{}", inet_ntop(dst_addr.sin_family, &dst_addr.sin_addr, addr_str, sizeof(addr_str)), ntohs(dst_addr.sin_port));
}

if (test_listening_daemons) {
auto connect_or_error = Core::System::connect(fd, (struct sockaddr*)&dst_addr, sizeof(dst_addr));
char addr_str[INET_ADDRSTRLEN];
if (connect_or_error.is_error()) {
warnln("connection to {}:{} has failed due to {}", inet_ntop(dst_addr.sin_family, &dst_addr.sin_addr, addr_str, sizeof(addr_str)), ntohs(dst_addr.sin_port), strerror(connect_or_error.error().code()));
return 1;
}
warnln("connection to {}:{} has succeeded", inet_ntop(dst_addr.sin_family, &dst_addr.sin_addr, addr_str, sizeof(addr_str)), ntohs(dst_addr.sin_port));
return 0;
}

TRY(Core::System::connect(fd, (struct sockaddr*)&dst_addr, sizeof(dst_addr)));
if (verbose)
warnln("connected!");
Expand Down

0 comments on commit 972f758

Please sign in to comment.