mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-08 20:28:30 +00:00
Make minor improvements
This commit is contained in:
parent
221817e537
commit
4864565198
41 changed files with 394 additions and 367 deletions
|
@ -16,8 +16,8 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/safemacros.internal.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
forceinline void FindDnsLabel(const char *A, size_t *i, size_t *n) {
|
||||
|
@ -36,12 +36,15 @@ forceinline void FindDnsLabel(const char *A, size_t *i, size_t *n) {
|
|||
/**
|
||||
* Compares DNS hostnames in reverse lexicographical asciibetical order.
|
||||
* @return <0, 0, or >0
|
||||
* @see test/libc/dns/dnsnamecmp_test.c (the code that matters)
|
||||
* @see test/libc/dns/comparednsnames_test.c (the code that matters)
|
||||
*/
|
||||
int dnsnamecmp(const char *A, const char *B) {
|
||||
int CompareDnsNames(const char *A, const char *B) {
|
||||
int res;
|
||||
bool first;
|
||||
size_t n, m, i, j;
|
||||
if (A == B) return 0;
|
||||
size_t n = strlen(A);
|
||||
size_t m = strlen(B);
|
||||
n = strlen(A);
|
||||
m = strlen(B);
|
||||
if (!n || !m || ((A[n - 1] == '.') ^ (B[m - 1] == '.'))) {
|
||||
if (n && m && A[n - 1] == '.' && strchr(B, '.')) {
|
||||
--m;
|
||||
|
@ -51,9 +54,9 @@ int dnsnamecmp(const char *A, const char *B) {
|
|||
return A[n ? n - 1 : 0] - B[m ? m - 1 : 0];
|
||||
}
|
||||
}
|
||||
size_t i = n;
|
||||
size_t j = m;
|
||||
bool first = true;
|
||||
i = n;
|
||||
j = m;
|
||||
first = true;
|
||||
for (;;) {
|
||||
FindDnsLabel(A, &i, &n);
|
||||
FindDnsLabel(B, &j, &m);
|
||||
|
@ -62,8 +65,7 @@ int dnsnamecmp(const char *A, const char *B) {
|
|||
if (!i && j) return 1;
|
||||
if (!j && i) return -1;
|
||||
}
|
||||
int res;
|
||||
if ((res = strncasecmp(&A[i], &B[j], min(n - i + 1, m - j + 1)))) {
|
||||
if ((res = strncasecmp(&A[i], &B[j], MIN(n - i + 1, m - j + 1)))) {
|
||||
return res;
|
||||
}
|
||||
if (!i || !j) {
|
|
@ -57,9 +57,9 @@ int getaddrinfo(const char *, const char *, const struct addrinfo *,
|
|||
struct addrinfo **) paramsnonnull((4));
|
||||
int freeaddrinfo(struct addrinfo *);
|
||||
const char *gai_strerror(int);
|
||||
int dnsnamecmp(const char *, const char *) paramsnonnull();
|
||||
int pascalifydnsname(uint8_t *, size_t, const char *) paramsnonnull();
|
||||
int resolvedns(const struct ResolvConf *, int, const char *, struct sockaddr *,
|
||||
int CompareDnsNames(const char *, const char *) paramsnonnull();
|
||||
int PascalifyDnsName(uint8_t *, size_t, const char *) paramsnonnull();
|
||||
int ResolveDns(const struct ResolvConf *, int, const char *, struct sockaddr *,
|
||||
uint32_t) paramsnonnull();
|
||||
struct addrinfo *newaddrinfo(uint16_t);
|
||||
|
||||
|
|
|
@ -21,43 +21,37 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Serializes DNS message header to wire.
|
||||
* Serializes DNS message h to wire.
|
||||
*
|
||||
* @return number of bytes written (always 12) or -1 w/ errno
|
||||
* @see pascalifydnsname()
|
||||
*/
|
||||
int serializednsheader(uint8_t *buf, size_t size,
|
||||
const struct DnsHeader header) {
|
||||
if (size < 12) return enospc();
|
||||
buf[0x0] = header.id >> 010u;
|
||||
buf[0x1] = header.id >> 000u;
|
||||
buf[0x2] = header.bf1;
|
||||
buf[0x3] = header.bf2;
|
||||
buf[0x4] = header.qdcount >> 010u;
|
||||
buf[0x5] = header.qdcount >> 000u;
|
||||
buf[0x6] = header.ancount >> 010u;
|
||||
buf[0x7] = header.ancount >> 000u;
|
||||
buf[0x8] = header.nscount >> 010u;
|
||||
buf[0x9] = header.nscount >> 000u;
|
||||
buf[0xa] = header.arcount >> 010u;
|
||||
buf[0xb] = header.arcount >> 000u;
|
||||
return 12;
|
||||
void SerializeDnsHeader(uint8_t p[restrict 12], const struct DnsHeader *h) {
|
||||
p[0x0] = h->id >> 8;
|
||||
p[0x1] = h->id;
|
||||
p[0x2] = h->bf1;
|
||||
p[0x3] = h->bf2;
|
||||
p[0x4] = h->qdcount >> 8;
|
||||
p[0x5] = h->qdcount;
|
||||
p[0x6] = h->ancount >> 8;
|
||||
p[0x7] = h->ancount;
|
||||
p[0x8] = h->nscount >> 8;
|
||||
p[0x9] = h->nscount;
|
||||
p[0xa] = h->arcount >> 8;
|
||||
p[0xb] = h->arcount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes DNS message header to wire.
|
||||
* Serializes DNS message h to wire.
|
||||
*
|
||||
* @return number of bytes read (always 12) or -1 w/ errno
|
||||
*/
|
||||
int deserializednsheader(struct DnsHeader *header, const uint8_t *buf,
|
||||
size_t size) {
|
||||
if (size < 12) return ebadmsg();
|
||||
header->id = READ16BE(buf + 0);
|
||||
header->bf1 = buf[2];
|
||||
header->bf2 = buf[3];
|
||||
header->qdcount = READ16BE(buf + 4);
|
||||
header->ancount = READ16BE(buf + 6);
|
||||
header->nscount = READ16BE(buf + 8);
|
||||
header->arcount = READ16BE(buf + 10);
|
||||
return 12;
|
||||
void DeserializeDnsHeader(struct DnsHeader *h, const uint8_t p[restrict 12]) {
|
||||
h->id = READ16BE(p);
|
||||
h->bf1 = p[2];
|
||||
h->bf2 = p[3];
|
||||
h->qdcount = READ16BE(p + 4);
|
||||
h->ancount = READ16BE(p + 6);
|
||||
h->nscount = READ16BE(p + 8);
|
||||
h->arcount = READ16BE(p + 10);
|
||||
}
|
||||
|
|
|
@ -13,8 +13,8 @@ struct DnsHeader {
|
|||
uint16_t arcount; /* additional record count */
|
||||
};
|
||||
|
||||
int serializednsheader(uint8_t *, size_t, const struct DnsHeader);
|
||||
int deserializednsheader(struct DnsHeader *, const uint8_t *, size_t);
|
||||
void SerializeDnsHeader(uint8_t[restrict 12], const struct DnsHeader *);
|
||||
void DeserializeDnsHeader(struct DnsHeader *, const uint8_t[restrict 12]);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -9,7 +9,7 @@ struct DnsQuestion {
|
|||
uint16_t qclass;
|
||||
};
|
||||
|
||||
int serializednsquestion(uint8_t *, size_t, struct DnsQuestion);
|
||||
int SerializeDnsQuestion(uint8_t *, size_t, const struct DnsQuestion *);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -22,13 +22,13 @@
|
|||
/**
|
||||
* Frees addresses returned by getaddrinfo().
|
||||
*/
|
||||
int freeaddrinfo(struct addrinfo *addrs) {
|
||||
int freeaddrinfo(struct addrinfo *ai) {
|
||||
struct addrinfo *next;
|
||||
while (addrs) {
|
||||
while (ai) {
|
||||
/* we assume ai_addr and ai_canonname are shoehorned */
|
||||
next = addrs->ai_next;
|
||||
free(addrs);
|
||||
addrs = next;
|
||||
next = ai->ai_next;
|
||||
free(ai);
|
||||
ai = next;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Frees HOSTS.TXT data structure populated by parsehoststxt().
|
||||
* Frees HOSTS.TXT data structure populated by ParseHostsTxt().
|
||||
*/
|
||||
void freehoststxt(struct HostsTxt **ht) {
|
||||
void FreeHostsTxt(struct HostsTxt **ht) {
|
||||
if (*ht) {
|
||||
free_s(&(*ht)->entries.p);
|
||||
free_s(&(*ht)->strings.p);
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
#include "libc/runtime/runtime.h"
|
||||
|
||||
/**
|
||||
* Frees resolv.conf data structure populated by parseresolvconf().
|
||||
* Frees resolv.conf data structure populated by ParseResolvConf().
|
||||
*/
|
||||
void freeresolvconf(struct ResolvConf **rvp) {
|
||||
void FreeResolvConf(struct ResolvConf **rvp) {
|
||||
if (*rvp) {
|
||||
free_s(&(*rvp)->nameservers.p);
|
||||
free_s(rvp);
|
||||
|
|
|
@ -67,13 +67,13 @@ int getaddrinfo(const char *name, const char *service,
|
|||
} else if (hints && (hints->ai_flags & AI_NUMERICHOST) == AI_NUMERICHOST) {
|
||||
freeaddrinfo(ai);
|
||||
return EAI_NONAME;
|
||||
} else if (resolvehoststxt(gethoststxt(), AF_INET, name, ai->ai_addr,
|
||||
} else if (ResolveHostsTxt(GetHostsTxt(), AF_INET, name, ai->ai_addr,
|
||||
sizeof(ai->ai_addr4), &canon) > 0) {
|
||||
memcpy(ai->ai_canonname, canon, min(strlen(canon), DNS_NAME_MAX) + 1);
|
||||
*res = ai;
|
||||
return 0;
|
||||
} else {
|
||||
rc = resolvedns(getresolvconf(), AF_INET, name, ai->ai_addr,
|
||||
rc = ResolveDns(GetResolvConf(), AF_INET, name, ai->ai_addr,
|
||||
sizeof(ai->ai_addr4));
|
||||
if (rc > 0) {
|
||||
*res = ai;
|
||||
|
|
|
@ -53,7 +53,7 @@ static textwindows noinline char *getnthoststxtpath(char *pathbuf,
|
|||
*
|
||||
* @note yoinking realloc() ensures there's no size limits
|
||||
*/
|
||||
const struct HostsTxt *gethoststxt(void) {
|
||||
const struct HostsTxt *GetHostsTxt(void) {
|
||||
FILE *f;
|
||||
const char *path;
|
||||
char pathbuf[PATH_MAX];
|
||||
|
@ -65,16 +65,16 @@ const struct HostsTxt *gethoststxt(void) {
|
|||
init->ht.entries.p = init->entries;
|
||||
init->ht.strings.n = pushpop(ARRAYLEN(init->strings));
|
||||
init->ht.strings.p = init->strings;
|
||||
__cxa_atexit(freehoststxt, &g_hoststxt, NULL);
|
||||
__cxa_atexit(FreeHostsTxt, &g_hoststxt, NULL);
|
||||
path = "/etc/hosts";
|
||||
if (IsWindows()) {
|
||||
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
|
||||
}
|
||||
if (!(f = fopen(path, "r")) || parsehoststxt(g_hoststxt, f) == -1) {
|
||||
if (!(f = fopen(path, "r")) || ParseHostsTxt(g_hoststxt, f) == -1) {
|
||||
/* TODO(jart): Elevate robustness. */
|
||||
}
|
||||
fclose(f);
|
||||
sorthoststxt(g_hoststxt);
|
||||
SortHostsTxt(g_hoststxt);
|
||||
}
|
||||
return g_hoststxt;
|
||||
}
|
||||
|
|
|
@ -38,41 +38,39 @@
|
|||
* this function will append
|
||||
* @return number of nameservers appended, or -1 w/ errno
|
||||
*/
|
||||
textwindows int getntnameservers(struct ResolvConf *resolv) {
|
||||
textwindows int GetNtNameServers(struct ResolvConf *resolv) {
|
||||
int rc;
|
||||
char value8[128];
|
||||
int64_t hkInterfaces;
|
||||
struct sockaddr_in nameserver;
|
||||
char16_t value[128], ifaceuuid[64];
|
||||
uint32_t i, keycount, valuebytes, ifaceuuidlen;
|
||||
char16_t value[128], uuid[64];
|
||||
uint32_t i, keycount, valuebytes, uuidlen;
|
||||
keycount = 0;
|
||||
hkInterfaces = kNtInvalidHandleValue;
|
||||
if (!RegOpenKeyEx(
|
||||
kNtHkeyLocalMachine,
|
||||
u"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
|
||||
0, kNtKeyRead, &hkInterfaces) &&
|
||||
!RegQueryInfoKey(hkInterfaces, NULL, NULL, NULL, &keycount, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL, NULL)) {
|
||||
!RegQueryInfoKey(hkInterfaces, 0, 0, 0, &keycount, 0, 0, 0, 0, 0, 0, 0)) {
|
||||
nameserver.sin_family = AF_INET;
|
||||
nameserver.sin_port = htons(DNS_PORT);
|
||||
rc = 0;
|
||||
for (i = 0; i < keycount; ++i) {
|
||||
ifaceuuidlen = sizeof(ifaceuuid);
|
||||
if (!RegEnumKeyEx(hkInterfaces, i, ifaceuuid, &ifaceuuidlen, NULL, NULL,
|
||||
NULL, NULL) &&
|
||||
((!RegGetValue(hkInterfaces, ifaceuuid, u"DhcpIpAddress",
|
||||
uuidlen = sizeof(uuid);
|
||||
if (!RegEnumKeyEx(hkInterfaces, i, uuid, &uuidlen, 0, 0, 0, 0) &&
|
||||
((!RegGetValue(hkInterfaces, uuid, u"DhcpIpAddress",
|
||||
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
|
||||
((valuebytes = sizeof(value)), &valuebytes)) &&
|
||||
valuebytes > 2 * sizeof(char16_t)) ||
|
||||
(!RegGetValue(hkInterfaces, ifaceuuid, u"IpAddress",
|
||||
(!RegGetValue(hkInterfaces, uuid, u"IpAddress",
|
||||
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
|
||||
((valuebytes = sizeof(value)), &valuebytes)) &&
|
||||
valuebytes > 2 * sizeof(char16_t))) &&
|
||||
((!RegGetValue(hkInterfaces, ifaceuuid, u"DhcpNameServer",
|
||||
((!RegGetValue(hkInterfaces, uuid, u"DhcpNameServer",
|
||||
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
|
||||
((valuebytes = sizeof(value)), &valuebytes)) &&
|
||||
valuebytes > 2 * sizeof(char16_t)) ||
|
||||
(!RegGetValue(hkInterfaces, ifaceuuid, u"NameServer",
|
||||
(!RegGetValue(hkInterfaces, uuid, u"NameServer",
|
||||
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
|
||||
((valuebytes = sizeof(value)), &valuebytes)) &&
|
||||
valuebytes > 2 * sizeof(char16_t)))) {
|
||||
|
|
|
@ -34,7 +34,7 @@ static struct ResolvConfInitialStaticMemory {
|
|||
/**
|
||||
* Returns singleton with DNS server address.
|
||||
*/
|
||||
const struct ResolvConf *getresolvconf(void) {
|
||||
const struct ResolvConf *GetResolvConf(void) {
|
||||
int rc;
|
||||
FILE *f;
|
||||
struct ResolvConfInitialStaticMemory *init;
|
||||
|
@ -43,16 +43,16 @@ const struct ResolvConf *getresolvconf(void) {
|
|||
g_resolvconf = &init->rv;
|
||||
pushmov(&init->rv.nameservers.n, ARRAYLEN(init->nameservers));
|
||||
init->rv.nameservers.p = init->nameservers;
|
||||
__cxa_atexit(freeresolvconf, &g_resolvconf, NULL);
|
||||
__cxa_atexit(FreeResolvConf, &g_resolvconf, NULL);
|
||||
if (!IsWindows()) {
|
||||
if ((f = fopen("/etc/resolv.conf", "r"))) {
|
||||
rc = parseresolvconf(g_resolvconf, f);
|
||||
rc = ParseResolvConf(g_resolvconf, f);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
fclose(f);
|
||||
} else {
|
||||
rc = getntnameservers(g_resolvconf);
|
||||
rc = GetNtNameServers(g_resolvconf);
|
||||
}
|
||||
if (rc == -1 && !IsTiny()) {
|
||||
/* TODO(jart): Elevate robustness. */
|
||||
|
|
|
@ -1,26 +1,23 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_
|
||||
#define COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct FILE;
|
||||
struct sockaddr;
|
||||
|
||||
struct HostsTxtEntry {
|
||||
unsigned char ip[4]; /* inet_ntop(AF_INET, he->ip, buf, size) */
|
||||
uint32_t name; /* &ht->strings.p[he->name] */
|
||||
uint32_t canon; /* &ht->strings.p[he->canon] */
|
||||
uint8_t ip[4]; /* inet_ntop(AF_INET, he->ip, buf, size) */
|
||||
uint32_t name; /* &ht->strings.p[he->name] */
|
||||
uint32_t canon; /* &ht->strings.p[he->canon] */
|
||||
};
|
||||
|
||||
struct HostsTxtEntries {
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t i, n;
|
||||
struct HostsTxtEntry *p;
|
||||
};
|
||||
|
||||
struct HostsTxtStrings {
|
||||
size_t i;
|
||||
size_t n;
|
||||
size_t i, n;
|
||||
char *p;
|
||||
};
|
||||
|
||||
|
@ -29,11 +26,11 @@ struct HostsTxt {
|
|||
struct HostsTxtStrings strings;
|
||||
};
|
||||
|
||||
const struct HostsTxt *gethoststxt(void) returnsnonnull;
|
||||
void freehoststxt(struct HostsTxt **) paramsnonnull();
|
||||
int parsehoststxt(struct HostsTxt *, struct FILE *) paramsnonnull();
|
||||
void sorthoststxt(struct HostsTxt *) paramsnonnull();
|
||||
int resolvehoststxt(const struct HostsTxt *, int, const char *,
|
||||
const struct HostsTxt *GetHostsTxt(void) returnsnonnull;
|
||||
void FreeHostsTxt(struct HostsTxt **) paramsnonnull();
|
||||
int ParseHostsTxt(struct HostsTxt *, FILE *) paramsnonnull();
|
||||
void SortHostsTxt(struct HostsTxt *) paramsnonnull();
|
||||
int ResolveHostsTxt(const struct HostsTxt *, int, const char *,
|
||||
struct sockaddr *, uint32_t, const char **)
|
||||
paramsnonnull((1, 3));
|
||||
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
* @see hoststxtsort() which is the logical next step
|
||||
*/
|
||||
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
|
||||
int ParseHostsTxt(struct HostsTxt *ht, FILE *f) {
|
||||
char *line;
|
||||
size_t linesize;
|
||||
struct HostsTxtEntry entry;
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
* @param f is an open stream with file content
|
||||
* @return number of nameservers appended, or -1 w/ errno
|
||||
*/
|
||||
int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
||||
int ParseResolvConf(struct ResolvConf *resolv, struct FILE *f) {
|
||||
/* TODO(jart): options ndots:5 */
|
||||
int rc;
|
||||
char *line;
|
||||
|
@ -49,7 +49,7 @@ int parseresolvconf(struct ResolvConf *resolv, struct FILE *f) {
|
|||
struct sockaddr_in nameserver;
|
||||
char *directive, *value, *tok, *comment;
|
||||
rc = 0;
|
||||
line = NULL;
|
||||
line = 0;
|
||||
linesize = 0;
|
||||
nameserver.sin_family = AF_INET;
|
||||
nameserver.sin_port = htons(DNS_PORT);
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
* @param name is a dotted NUL-terminated hostname string
|
||||
* @return bytes written (excluding NUL) or -1 w/ errno
|
||||
*/
|
||||
int pascalifydnsname(uint8_t *buf, size_t size, const char *name) {
|
||||
int PascalifyDnsName(uint8_t *buf, size_t size, const char *name) {
|
||||
size_t i, j, k, namelen;
|
||||
if ((namelen = strlen(name)) > DNS_NAME_MAX) return enametoolong();
|
||||
i = 0;
|
||||
|
|
|
@ -14,10 +14,10 @@ struct ResolvConf {
|
|||
struct Nameservers nameservers;
|
||||
};
|
||||
|
||||
const struct ResolvConf *getresolvconf(void) returnsnonnull;
|
||||
int parseresolvconf(struct ResolvConf *, struct FILE *) paramsnonnull();
|
||||
void freeresolvconf(struct ResolvConf **) paramsnonnull();
|
||||
int getntnameservers(struct ResolvConf *) paramsnonnull();
|
||||
const struct ResolvConf *GetResolvConf(void) returnsnonnull;
|
||||
int ParseResolvConf(struct ResolvConf *, struct FILE *) paramsnonnull();
|
||||
void FreeResolvConf(struct ResolvConf **) paramsnonnull();
|
||||
int GetNtNameServers(struct ResolvConf *) paramsnonnull();
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
/**
|
||||
* Queries Domain Name System for address associated with name.
|
||||
*
|
||||
* @param resolvconf can be getresolvconf()
|
||||
* @param resolvconf can be GetResolvConf()
|
||||
* @param af can be AF_INET, AF_UNSPEC
|
||||
* @param name can be a local or fully-qualified hostname
|
||||
* @param addr should point to a struct sockaddr_in; if this function
|
||||
|
@ -47,65 +47,62 @@
|
|||
* @return number of matches found, or -1 w/ errno
|
||||
* @error EAFNOSUPPORT. ENETDOWN, ENAMETOOLONG, EBADMSG
|
||||
*/
|
||||
int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
|
||||
int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
|
||||
struct sockaddr *addr, uint32_t addrsize) {
|
||||
size_t msgsize;
|
||||
int res, fd, rc, rc2;
|
||||
struct sockaddr_in *addr4;
|
||||
struct DnsQuestion question;
|
||||
int rc, fd, n;
|
||||
struct DnsQuestion q;
|
||||
struct DnsHeader h, h2;
|
||||
struct sockaddr_in *a4;
|
||||
uint8_t *p, *pe, msg[512];
|
||||
uint16_t rtype, rclass, rdlength;
|
||||
uint8_t *p, *pe, *outmsg, *inmsg;
|
||||
struct DnsHeader header, response;
|
||||
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
|
||||
if (!resolvconf->nameservers.i) return 0;
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.id = rand32();
|
||||
header.bf1 = 1; /* recursion desired */
|
||||
header.qdcount = 1;
|
||||
question.qname = name;
|
||||
question.qtype = DNS_TYPE_A;
|
||||
question.qclass = DNS_CLASS_IN;
|
||||
res = -1;
|
||||
if ((outmsg = malloc(kMsgMax)) && (inmsg = malloc(kMsgMax)) &&
|
||||
(rc = serializednsheader(outmsg, kMsgMax, header)) != -1 &&
|
||||
(rc2 = serializednsquestion(outmsg + rc, kMsgMax - rc, question)) != -1) {
|
||||
msgsize = rc + rc2;
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) != -1 &&
|
||||
sendto(fd, outmsg, msgsize, 0, (void *)&resolvconf->nameservers.p[0],
|
||||
sizeof(resolvconf->nameservers.p[0])) == msgsize) {
|
||||
if ((rc = recv(fd, inmsg, kMsgMax, 0)) != -1 &&
|
||||
(rc2 = deserializednsheader(&response, inmsg, rc)) != -1 &&
|
||||
response.id == header.id) {
|
||||
res = 0;
|
||||
if (response.ancount) {
|
||||
p = inmsg + rc2;
|
||||
pe = inmsg + rc;
|
||||
while (p < pe && response.qdcount) {
|
||||
p += strnlen((char *)p, pe - p) + 1 + 4;
|
||||
response.qdcount--;
|
||||
memset(&h, 0, sizeof(h));
|
||||
rc = ebadmsg();
|
||||
h.id = rand32();
|
||||
h.bf1 = 1; /* recursion desired */
|
||||
h.qdcount = 1;
|
||||
q.qname = name;
|
||||
q.qtype = DNS_TYPE_A;
|
||||
q.qclass = DNS_CLASS_IN;
|
||||
memset(msg, 0, sizeof(msg));
|
||||
SerializeDnsHeader(msg, &h);
|
||||
if ((n = SerializeDnsQuestion(msg + 12, 500, &q)) == -1) return -1;
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) return -1;
|
||||
if (sendto(fd, msg, 12 + n, 0, resolvconf->nameservers.p,
|
||||
sizeof(*resolvconf->nameservers.p)) == 12 + n &&
|
||||
(n = read(fd, msg, 512)) >= 12) {
|
||||
DeserializeDnsHeader(&h2, msg);
|
||||
if (h2.id == h.id) {
|
||||
rc = 0;
|
||||
if (h2.ancount) {
|
||||
p = msg + 12;
|
||||
pe = msg + n;
|
||||
while (p < pe && h2.qdcount) {
|
||||
p += strnlen((char *)p, pe - p) + 1 + 4;
|
||||
h2.qdcount--;
|
||||
}
|
||||
if (p + 1 < pe) {
|
||||
if ((p[0] & 0b11000000) == 0b11000000) { /* name pointer */
|
||||
p += 2;
|
||||
} else {
|
||||
p += strnlen((char *)p, pe - p) + 1;
|
||||
}
|
||||
if (p + 1 < pe) {
|
||||
if ((p[0] & 0b11000000) == 0b11000000) { /* name pointer */
|
||||
p += 2;
|
||||
} else {
|
||||
p += strnlen((char *)p, pe - p) + 1;
|
||||
}
|
||||
if (p + 2 + 2 + 4 + 2 < pe) {
|
||||
rtype = READ16BE(p), p += 2;
|
||||
rclass = READ16BE(p), p += 2;
|
||||
/* ttl */ p += 4;
|
||||
rdlength = READ16BE(p), p += 2;
|
||||
if (p + rdlength <= pe && rdlength == 4 &&
|
||||
(rtype == DNS_TYPE_A && rclass == DNS_CLASS_IN)) {
|
||||
res = 1;
|
||||
if (addrsize) {
|
||||
if (addrsize >= kMinSockaddr4Size) {
|
||||
addr4 = (struct sockaddr_in *)addr;
|
||||
addr4->sin_family = AF_INET;
|
||||
memcpy(&addr4->sin_addr.s_addr, p, 4);
|
||||
} else {
|
||||
res = einval();
|
||||
}
|
||||
if (p + 2 + 2 + 4 + 2 < pe) {
|
||||
rtype = READ16BE(p), p += 2;
|
||||
rclass = READ16BE(p), p += 2;
|
||||
/* ttl */ p += 4;
|
||||
rdlength = READ16BE(p), p += 2;
|
||||
if (p + rdlength <= pe && rdlength == 4 &&
|
||||
(rtype == DNS_TYPE_A && rclass == DNS_CLASS_IN)) {
|
||||
rc = 1;
|
||||
if (addrsize) {
|
||||
if (addrsize >= kMinSockaddr4Size) {
|
||||
a4 = (struct sockaddr_in *)addr;
|
||||
a4->sin_family = AF_INET;
|
||||
memcpy(&a4->sin_addr.s_addr, p, 4);
|
||||
} else {
|
||||
rc = einval();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -113,8 +110,7 @@ int resolvedns(const struct ResolvConf *resolvconf, int af, const char *name,
|
|||
}
|
||||
}
|
||||
}
|
||||
res |= close(fd);
|
||||
}
|
||||
free(outmsg);
|
||||
return res;
|
||||
close(fd);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -27,16 +27,16 @@
|
|||
|
||||
static int hoststxtgetcmp(const char *node, const struct HostsTxtEntry *entry,
|
||||
const char *strings) {
|
||||
return dnsnamecmp(node, &strings[entry->name]);
|
||||
return CompareDnsNames(node, &strings[entry->name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds address associated with name in HOSTS.TXT table.
|
||||
*
|
||||
* This function performs binary search, so sorthoststxt() must be
|
||||
* This function performs binary search, so SortHostsTxt() must be
|
||||
* called on the table beforehand.
|
||||
*
|
||||
* @param ht can be gethoststxt()
|
||||
* @param ht can be GetHostsTxt()
|
||||
* @param af can be AF_INET, AF_UNSPEC
|
||||
* @param name can be a local or fully-qualified hostname
|
||||
* @param addr should point to a struct sockaddr_in; if this function
|
||||
|
@ -46,7 +46,7 @@ static int hoststxtgetcmp(const char *node, const struct HostsTxtEntry *entry,
|
|||
* @return number of matches found, or -1 w/ errno
|
||||
* @error EAFNOSUPPORT
|
||||
*/
|
||||
int resolvehoststxt(const struct HostsTxt *ht, int af, const char *name,
|
||||
int ResolveHostsTxt(const struct HostsTxt *ht, int af, const char *name,
|
||||
struct sockaddr *addr, uint32_t addrsize,
|
||||
const char **canon) {
|
||||
struct sockaddr_in *addr4;
|
||||
|
|
|
@ -26,11 +26,14 @@
|
|||
* @return number of bytes written
|
||||
* @see pascalifydnsname()
|
||||
*/
|
||||
int serializednsquestion(uint8_t *buf, size_t size, struct DnsQuestion dq) {
|
||||
int SerializeDnsQuestion(uint8_t *buf, size_t size,
|
||||
const struct DnsQuestion *dq) {
|
||||
int wrote;
|
||||
if ((wrote = pascalifydnsname(buf, size, dq.qname)) == -1) return -1;
|
||||
if ((wrote = PascalifyDnsName(buf, size, dq->qname)) == -1) return -1;
|
||||
if (wrote + 1 + 4 > size) return enospc();
|
||||
buf[wrote + 1] = dq.qtype >> 010, buf[wrote + 2] = dq.qtype >> 000;
|
||||
buf[wrote + 3] = dq.qclass >> 010, buf[wrote + 4] = dq.qclass >> 000;
|
||||
buf[wrote + 1] = dq->qtype >> 8;
|
||||
buf[wrote + 2] = dq->qtype;
|
||||
buf[wrote + 3] = dq->qclass >> 8;
|
||||
buf[wrote + 4] = dq->qclass;
|
||||
return wrote + 5;
|
||||
}
|
||||
|
|
|
@ -22,25 +22,26 @@
|
|||
|
||||
/**
|
||||
* Compares hostnames in HOSTS.TXT table.
|
||||
* @see dnsnamecmp(), parsehoststxt()
|
||||
* @see CompareDnsNames(), ParseHostsTxt()
|
||||
*/
|
||||
static int cmphoststxt(const struct HostsTxtEntry *e1,
|
||||
const struct HostsTxtEntry *e2, const char *strings) {
|
||||
if (e1 == e2) return 0;
|
||||
return dnsnamecmp(&strings[e1->name], &strings[e2->name]);
|
||||
return CompareDnsNames(&strings[e1->name], &strings[e2->name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts entries in HOSTS.TXT table.
|
||||
*
|
||||
* This function enables resolvehoststxt() to be called so hard-coded
|
||||
* This function enables ResolveHostsTxt() to be called so hard-coded
|
||||
* hostname lookups take logarithmic time; you can blackhole all the
|
||||
* spam you want, in your /etc/hosts file.
|
||||
*
|
||||
* The sorted order, defined by dnsnamecmp(), also makes it possible to
|
||||
* efficiently search for subdomains, once the initial sort is done.
|
||||
* The sorted order, defined by CompareDnsNames(), also makes it
|
||||
* possible to efficiently search for subdomains, once the initial sort
|
||||
* is done.
|
||||
*/
|
||||
void sorthoststxt(struct HostsTxt *ht) {
|
||||
void SortHostsTxt(struct HostsTxt *ht) {
|
||||
if (ht->entries.p) {
|
||||
qsort_r(ht->entries.p, ht->entries.i, sizeof(*ht->entries.p),
|
||||
(void *)cmphoststxt, ht->strings.p);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue