132 lines
3.5 KiB
C
132 lines
3.5 KiB
C
// User application entry points for resolve.
|
|
|
|
#include <stdint.h>
|
|
#include <stddef.h>
|
|
#include <string.h>
|
|
#include <ntlite/syscall.h>
|
|
|
|
// Prints the requested operation.
|
|
static void print(const char* s) {
|
|
if (s) { SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromCstr(s) }; SysWriteConsole(&req); }
|
|
}
|
|
|
|
// Prints char.
|
|
static void print_char(char c) {
|
|
SYS_WRITE_CONSOLE_REQUEST req = { SysSvFromParts(&c, 1) };
|
|
SysWriteConsole(&req);
|
|
}
|
|
|
|
// Prints u64.
|
|
static void print_u64(uint64_t v) {
|
|
char buf[32];
|
|
int n = 0;
|
|
if (v == 0) { print("0"); return; }
|
|
while (v && n < (int)sizeof(buf)) {
|
|
buf[n++] = (char)('0' + (v % 10));
|
|
v /= 10;
|
|
}
|
|
while (n > 0) print_char(buf[--n]);
|
|
}
|
|
|
|
// Implements the next token operation.
|
|
static const char* next_token(const char* s, char* out, size_t outSize) {
|
|
if (!s || !out || outSize == 0) return NULL;
|
|
while (*s == ' ' || *s == '\t') s++;
|
|
if (*s == 0) { out[0] = 0; return NULL; }
|
|
|
|
size_t n = 0;
|
|
while (*s && *s != ' ' && *s != '\t') {
|
|
if (n + 1 < outSize) out[n++] = *s;
|
|
s++;
|
|
}
|
|
out[n] = 0;
|
|
return s;
|
|
}
|
|
|
|
// Prints ipv4.
|
|
static void print_ipv4(const uint8_t ip[4]) {
|
|
print_u64(ip[0]); print("."); print_u64(ip[1]); print(".");
|
|
print_u64(ip[2]); print("."); print_u64(ip[3]);
|
|
}
|
|
|
|
// Prints ipv6.
|
|
static void print_ipv6(const uint8_t ip[16]) {
|
|
static const char hex[] = "0123456789abcdef";
|
|
for (int i = 0; i < 8; ++i) {
|
|
uint16_t word = ((uint16_t)ip[i * 2] << 8) | ip[i * 2 + 1];
|
|
int started = 0;
|
|
for (int shift = 12; shift >= 0; shift -= 4) {
|
|
unsigned nibble = (word >> shift) & 0xfu;
|
|
if (nibble || started || shift == 0) {
|
|
char c = hex[nibble];
|
|
print_char(c);
|
|
started = 1;
|
|
}
|
|
}
|
|
if (i != 7)
|
|
print(":");
|
|
}
|
|
}
|
|
|
|
// Runs the requested operation.
|
|
int main(void) {
|
|
char familyText[16];
|
|
char name[256];
|
|
uint32_t family = 0;
|
|
const char* cmd = SysGetPeb()->CommandLine.Data;
|
|
cmd = next_token(cmd, name, sizeof(name));
|
|
(void)cmd;
|
|
|
|
familyText[0] = 0;
|
|
name[0] = 0;
|
|
if (cmd) {
|
|
const char* rest = next_token(cmd, familyText, sizeof(familyText));
|
|
if (strcmp(familyText, "-4") == 0) {
|
|
family = SYS_AF_INET;
|
|
if (rest)
|
|
(void)next_token(rest, name, sizeof(name));
|
|
} else if (strcmp(familyText, "-6") == 0) {
|
|
family = SYS_AF_INET6;
|
|
if (rest)
|
|
(void)next_token(rest, name, sizeof(name));
|
|
} else {
|
|
strcpy(name, familyText);
|
|
}
|
|
}
|
|
if (!name[0]) {
|
|
print("usage: resolve.exe [-4|-6] hostname\n");
|
|
SysExitProcess(1);
|
|
}
|
|
|
|
SYS_SOCKET_ADDRESS addr;
|
|
size_t addrSize = sizeof(addr);
|
|
SYS_RESOLVE_HOST_REQUEST req;
|
|
memset(&addr, 0, sizeof(addr));
|
|
memset(&req, 0, sizeof(req));
|
|
req.Name = SysSvFromCstr(name);
|
|
req.Family = family ? family : SYS_AF_INET6;
|
|
req.AddressOut = &addr;
|
|
req.AddressSizeInOut = &addrSize;
|
|
|
|
uint32_t st = SysResolveHost(&req);
|
|
if (st != NTLSTATUS_SUCCESS && family == 0) {
|
|
req.Family = SYS_AF_INET;
|
|
addrSize = sizeof(addr);
|
|
st = SysResolveHost(&req);
|
|
}
|
|
if (st != NTLSTATUS_SUCCESS) {
|
|
print("resolve: SysResolveHost failed "); print_u64(st); print("\n");
|
|
SysExitProcess(1);
|
|
}
|
|
|
|
print(name);
|
|
print(" -> ");
|
|
if (addr.Family == SYS_AF_INET6)
|
|
print_ipv6(addr.Address);
|
|
else
|
|
print_ipv4(addr.Address);
|
|
print("\n");
|
|
SysExitProcess(0);
|
|
return 0;
|
|
}
|