mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
c995838e5c
- Clean up sigaction() code - Add a port scanner example - Introduce a ParseCidr() API - Clean up our futex abstraction code - Fix a harmless integer overflow in ParseIp() - Use kernel semaphores on NetBSD to make threads much faster
127 lines
3.9 KiB
C
127 lines
3.9 KiB
C
#if 0
|
|
/*─────────────────────────────────────────────────────────────────╗
|
|
│ To the extent possible under law, Justine Tunney has waived │
|
|
│ all copyright and related or neighboring rights to this file, │
|
|
│ as it is written in the following disclaimers: │
|
|
│ • http://unlicense.org/ │
|
|
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
|
|
╚─────────────────────────────────────────────────────────────────*/
|
|
#endif
|
|
#include "libc/assert.h"
|
|
#include "libc/calls/calls.h"
|
|
#include "libc/calls/struct/timeval.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/fmt/conv.h"
|
|
#include "libc/fmt/fmt.h"
|
|
#include "libc/mem/alloca.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/sock/sock.h"
|
|
#include "libc/sock/struct/sockaddr.h"
|
|
#include "libc/stdio/stdio.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/af.h"
|
|
#include "libc/sysv/consts/ipproto.h"
|
|
#include "libc/sysv/consts/so.h"
|
|
#include "libc/sysv/consts/sock.h"
|
|
#include "libc/sysv/consts/sol.h"
|
|
#include "net/http/ip.h"
|
|
|
|
/**
|
|
* @fileoverview fast local network port scanner, e.g.
|
|
*
|
|
* make -j8 o//examples/portscan.com
|
|
* o//examples/portscan.com 10.10.10.0/24 22
|
|
*/
|
|
|
|
const char *FormatIp(char buf[16], uint32_t ip) {
|
|
snprintf(buf, 16, "%hhu.%hhu.%hhu.%hhu", ip >> 24, ip >> 16, ip >> 8, ip);
|
|
return buf;
|
|
}
|
|
|
|
#define FormatIp(x) FormatIp(alloca(16), x)
|
|
|
|
int main(int argc, char *argv[]) {
|
|
int port;
|
|
struct Cidr in;
|
|
uint32_t netmask;
|
|
const char *status;
|
|
struct timeval timeout;
|
|
uint32_t network_address;
|
|
uint32_t last_host_address;
|
|
uint32_t first_host_address;
|
|
|
|
if (argc != 3) {
|
|
PrintUsage:
|
|
fprintf(stderr,
|
|
"usage: %s IP/CIDR PORT\n"
|
|
"example: %s 192.168.0.0/24 22\n",
|
|
argv[0], argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
in = ParseCidr(argv[1], -1);
|
|
if (in.addr == -1) {
|
|
fprintf(stderr, "error: bad ip/cidr\n");
|
|
goto PrintUsage;
|
|
}
|
|
|
|
port = atoi(argv[2]);
|
|
if (!(1 <= port && port <= 65535)) {
|
|
fprintf(stderr, "error: bad port\n");
|
|
goto PrintUsage;
|
|
}
|
|
|
|
if (in.cidr > 30) {
|
|
fprintf(stderr, "error: maximum supported cidr is 30\n");
|
|
goto PrintUsage;
|
|
}
|
|
|
|
if (in.cidr < 22) {
|
|
fprintf(stderr, "error: minimum cidr support right now is 22\n");
|
|
goto PrintUsage;
|
|
}
|
|
|
|
netmask = -1u << (32 - in.cidr);
|
|
network_address = in.addr & netmask;
|
|
first_host_address = network_address + 1;
|
|
last_host_address = (network_address | ~netmask) - 1;
|
|
|
|
assert(last_host_address > first_host_address);
|
|
assert(last_host_address - first_host_address < 1024);
|
|
|
|
fprintf(stderr, "scanning %s through %s\n", FormatIp(first_host_address),
|
|
FormatIp(last_host_address));
|
|
|
|
timeout = timeval_frommillis(100);
|
|
for (int64_t ip = first_host_address; ip <= last_host_address; ++ip) {
|
|
if (!fork()) {
|
|
socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
|
setsockopt(3, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout));
|
|
setsockopt(3, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout));
|
|
if (!connect(3,
|
|
(struct sockaddr *)&(struct sockaddr_in){
|
|
.sin_family = AF_INET,
|
|
.sin_addr.s_addr = htonl(ip),
|
|
.sin_port = htons(port),
|
|
},
|
|
sizeof(struct sockaddr_in))) {
|
|
status = "open";
|
|
} else if (errno == ECONNREFUSED) {
|
|
status = "closed";
|
|
} else if (errno != EINPROGRESS) {
|
|
status = _strerrno(errno);
|
|
} else {
|
|
status = 0;
|
|
}
|
|
if (status) {
|
|
printf("%-15s %s\n", FormatIp(ip), status);
|
|
}
|
|
_Exit(0);
|
|
}
|
|
}
|
|
for (;;) {
|
|
if (wait(0) == -1 && errno == ECHILD) {
|
|
break;
|
|
}
|
|
}
|
|
}
|