mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 03:27:39 +00:00
1a96de6eda
Locally modified to get nameservers from Windows Registry when `\etc\resolv.conf` isn't defined.
194 lines
5.7 KiB
C
194 lines
5.7 KiB
C
/*
|
|
* Copyright (c) 2013 by Wil Tan <wil@cloudregistry.net>
|
|
*
|
|
* Based on dump_dns.c from the dnscap <https://www.dns-oarc.net/tools/dnscap>
|
|
* originally written by Paul Vixie.
|
|
*
|
|
* Copyright (c) 2007 by Internet Systems Consortium, Inc. ("ISC")
|
|
*
|
|
* Permission to use, copy, modify, and/or distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
|
|
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include "libc/calls/typedef/u.h"
|
|
#include "libc/errno.h"
|
|
#include "libc/runtime/runtime.h"
|
|
#include "libc/sock/sock.h"
|
|
#include "libc/stdio/internal.h"
|
|
#include "libc/str/str.h"
|
|
#include "libc/sysv/consts/af.h"
|
|
#include "third_party/musl/nameser.h"
|
|
#include "third_party/musl/resolv.h"
|
|
|
|
const char *_res_opcodes[] = {
|
|
"QUERY", //
|
|
"IQUERY", //
|
|
"CQUERYM", //
|
|
"CQUERYU", //
|
|
"NOTIFY", //
|
|
"UPDATE", //
|
|
"6", //
|
|
"7", //
|
|
"8", //
|
|
"9", //
|
|
"10", //
|
|
"11", //
|
|
"12", //
|
|
"13", //
|
|
"ZONEINIT", //
|
|
"ZONEREF", //
|
|
};
|
|
|
|
#define MY_GET16(s, cp) \
|
|
do { \
|
|
register const u_char *t_cp = (const u_char *)(cp); \
|
|
(s) = ((u_int16_t)t_cp[0] << 8) | ((u_int16_t)t_cp[1]); \
|
|
(cp) += NS_INT16SZ; \
|
|
} while (0)
|
|
|
|
#define MY_GET32(l, cp) \
|
|
do { \
|
|
register const u_char *t_cp = (const u_char *)(cp); \
|
|
(l) = ((u_int32_t)t_cp[0] << 24) | ((u_int32_t)t_cp[1] << 16) | \
|
|
((u_int32_t)t_cp[2] << 8) | ((u_int32_t)t_cp[3]); \
|
|
(cp) += NS_INT32SZ; \
|
|
} while (0)
|
|
|
|
static void dump_dns_rr(ns_msg *msg, ns_rr *rr, ns_sect sect, FILE *trace) {
|
|
char buf[NS_MAXDNAME];
|
|
u_int class, type;
|
|
const u_char *rd;
|
|
u_int32_t soa[5];
|
|
u_int16_t mx;
|
|
int n;
|
|
|
|
class = ns_rr_class(*rr);
|
|
type = ns_rr_type(*rr);
|
|
fprintf(trace, "%s,%d,%d", ns_rr_name(*rr), class, type);
|
|
if (sect == ns_s_qd) return;
|
|
fprintf(trace, ",%lu", (u_long)ns_rr_ttl(*rr));
|
|
rd = ns_rr_rdata(*rr);
|
|
switch (type) {
|
|
case ns_t_soa:
|
|
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
|
|
sizeof buf);
|
|
if (n < 0) goto error;
|
|
putc(',', trace);
|
|
fputs(buf, trace);
|
|
rd += n;
|
|
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
|
|
sizeof buf);
|
|
if (n < 0) goto error;
|
|
putc(',', trace);
|
|
fputs(buf, trace);
|
|
rd += n;
|
|
if (ns_msg_end(*msg) - rd < 5 * NS_INT32SZ) goto error;
|
|
for (n = 0; n < 5; n++) MY_GET32(soa[n], rd);
|
|
sprintf(buf, "%u,%u,%u,%u,%u", soa[0], soa[1], soa[2], soa[3], soa[4]);
|
|
break;
|
|
case ns_t_a:
|
|
inet_ntop(AF_INET, rd, buf, sizeof buf);
|
|
break;
|
|
case ns_t_aaaa:
|
|
inet_ntop(AF_INET6, rd, buf, sizeof buf);
|
|
break;
|
|
case ns_t_mx:
|
|
MY_GET16(mx, rd);
|
|
fprintf(trace, ",%u", mx);
|
|
/* FALLTHROUGH */
|
|
case ns_t_ns:
|
|
case ns_t_ptr:
|
|
case ns_t_cname:
|
|
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
|
|
sizeof buf);
|
|
if (n < 0) goto error;
|
|
break;
|
|
case ns_t_txt:
|
|
snprintf(buf, (size_t)rd[0] + 1, "%s", rd + 1);
|
|
break;
|
|
default:
|
|
error:
|
|
sprintf(buf, "[%u]", ns_rr_rdlen(*rr));
|
|
}
|
|
if (buf[0] != '\0') {
|
|
putc(',', trace);
|
|
fputs(buf, trace);
|
|
}
|
|
}
|
|
|
|
static void dump_dns_sect(ns_msg *msg, ns_sect sect, FILE *trace,
|
|
const char *endline) {
|
|
int rrnum, rrmax;
|
|
const char *sep;
|
|
ns_rr rr;
|
|
|
|
rrmax = ns_msg_count(*msg, sect);
|
|
if (rrmax == 0) {
|
|
fputs(" 0", trace);
|
|
return;
|
|
}
|
|
fprintf(trace, " %s%d", endline, rrmax);
|
|
sep = "";
|
|
for (rrnum = 0; rrnum < rrmax; rrnum++) {
|
|
if (ns_parserr(msg, sect, rrnum, &rr)) {
|
|
fputs(strerror(errno), trace);
|
|
return;
|
|
}
|
|
fprintf(trace, " %s", sep);
|
|
dump_dns_rr(msg, &rr, sect, trace);
|
|
sep = endline;
|
|
}
|
|
}
|
|
|
|
void dump_dns(const u_char *payload, size_t paylen, FILE *trace,
|
|
const char *endline) {
|
|
u_int opcode, rcode, id;
|
|
const char *sep;
|
|
ns_msg msg;
|
|
|
|
fprintf(trace, " %sdns ", endline);
|
|
if (ns_initparse(payload, paylen, &msg) < 0) {
|
|
fputs(strerror(errno), trace);
|
|
return;
|
|
}
|
|
opcode = ns_msg_getflag(msg, ns_f_opcode);
|
|
rcode = ns_msg_getflag(msg, ns_f_rcode);
|
|
id = ns_msg_id(msg);
|
|
fprintf(trace, "%s,%d,%u", _res_opcodes[opcode], rcode, id);
|
|
sep = ",";
|
|
#define FLAG(t, f) \
|
|
if (ns_msg_getflag(msg, f)) { \
|
|
fprintf(trace, "%s%s", sep, t); \
|
|
sep = "|"; \
|
|
}
|
|
FLAG("qr", ns_f_qr);
|
|
FLAG("aa", ns_f_aa);
|
|
FLAG("tc", ns_f_tc);
|
|
FLAG("rd", ns_f_rd);
|
|
FLAG("ra", ns_f_ra);
|
|
FLAG("z", ns_f_z);
|
|
FLAG("ad", ns_f_ad);
|
|
FLAG("cd", ns_f_cd);
|
|
#undef FLAG
|
|
|
|
dump_dns_sect(&msg, ns_s_an, trace, endline);
|
|
}
|
|
|
|
int main() {
|
|
ShowCrashReports();
|
|
u_char answer[1024] = "";
|
|
res_init();
|
|
int rv = res_query("google.com", ns_c_in, ns_t_txt, answer, sizeof(answer));
|
|
// printf("rv=%d\n", rv);
|
|
dump_dns(answer, rv, stdout, "\n");
|
|
printf("\n");
|
|
}
|