mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-02-07 06:53:33 +00:00
Make minor improvements
This commit is contained in:
parent
221817e537
commit
4864565198
41 changed files with 394 additions and 367 deletions
|
@ -8,11 +8,13 @@
|
|||
╚─────────────────────────────────────────────────────────────────*/
|
||||
#endif
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/dns/dns.h"
|
||||
#include "libc/fmt/conv.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
|
@ -28,7 +30,12 @@
|
|||
* Implemented because BusyBox's netcat doesn't detect remote close and
|
||||
* lingers in the CLOSE_WAIT wait possibly due to file descriptor leaks
|
||||
*
|
||||
* Once upon time we called this command "Telnet"
|
||||
* Here's an example usage:
|
||||
*
|
||||
* make -j8 o//examples/nc.com
|
||||
* printf 'GET /\r\n\r\n' | o//examples/nc.com justine.lol 80
|
||||
*
|
||||
* Once upon time we called this command "telnet"
|
||||
*/
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
@ -36,15 +43,26 @@ int main(int argc, char *argv[]) {
|
|||
size_t i, got;
|
||||
char buf[1500];
|
||||
int err, toto, sock;
|
||||
struct addrinfo *ai = NULL;
|
||||
struct linger linger = {true, 1};
|
||||
struct sockaddr_in addr = {AF_INET};
|
||||
struct pollfd fds[2] = {{-1, POLLIN}, {-1, POLLIN}};
|
||||
struct addrinfo hint = {AI_NUMERICSERV, AF_INET, SOCK_STREAM, IPPROTO_TCP};
|
||||
|
||||
if (argc != 3) exit(1);
|
||||
inet_pton(AF_INET, argv[1], &addr.sin_addr);
|
||||
addr.sin_port = htons(atoi(argv[2]));
|
||||
switch ((rc = getaddrinfo(argv[1], argv[2], &hint, &ai))) {
|
||||
case EAI_SUCCESS:
|
||||
break;
|
||||
case EAI_SYSTEM:
|
||||
perror("getaddrinfo");
|
||||
exit(1);
|
||||
default:
|
||||
fputs("EAI_", stderr);
|
||||
fputs(gai_strerror(rc), stderr);
|
||||
fputs("\n", stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||
if ((sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol)) == -1) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -54,7 +72,7 @@ int main(int argc, char *argv[]) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
if (connect(sock, &addr, sizeof(addr)) == -1) {
|
||||
if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
|
||||
perror("connect");
|
||||
exit(1);
|
||||
}
|
||||
|
@ -108,5 +126,6 @@ int main(int argc, char *argv[]) {
|
|||
exit(1);
|
||||
}
|
||||
|
||||
freeaddrinfo(ai);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -17,12 +17,8 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/errno.h"
|
||||
#include "libc/fmt/fmt.h"
|
||||
#include "libc/log/internal.h"
|
||||
#include "libc/log/log.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/stdio/stdio.h"
|
||||
#include "libc/str/str.h"
|
||||
|
||||
/**
|
||||
* Writes error messages to standard error.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -36,6 +37,7 @@
|
|||
int accept4(int fd, void *out_addr, uint32_t *inout_addrsize, int flags) {
|
||||
if (!out_addr) return efault();
|
||||
if (!inout_addrsize) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(out_addr, *inout_addrsize)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_accept4(fd, out_addr, inout_addrsize, flags);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/assert.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -36,12 +37,14 @@
|
|||
*/
|
||||
int bind(int fd, const void *addr, uint32_t addrsize) {
|
||||
if (!addr) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(addr, addrsize)) return efault();
|
||||
if (addrsize == sizeof(struct sockaddr_in)) {
|
||||
if (!IsWindows()) {
|
||||
if (!IsBsd()) {
|
||||
return sys_bind(fd, addr, addrsize);
|
||||
} else {
|
||||
char addr2[sizeof(struct sockaddr_un_bsd)]; /* sockaddr_un_bsd is the largest */
|
||||
char addr2[sizeof(
|
||||
struct sockaddr_un_bsd)]; /* sockaddr_un_bsd is the largest */
|
||||
assert(addrsize <= sizeof(addr2));
|
||||
memcpy(&addr2, addr, addrsize);
|
||||
sockaddr2bsd(&addr2[0]);
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -34,6 +35,7 @@
|
|||
*/
|
||||
int connect(int fd, const void *addr, uint32_t addrsize) {
|
||||
if (!addr) return efault();
|
||||
if (IsAsan() && !__asan_is_valid(addr, addrsize)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_connect(fd, addr, addrsize);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
* @see getsockname()
|
||||
*/
|
||||
int getpeername(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
if (IsAsan() && !__asan_is_valid(out_addr, *out_addrsize)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_getpeername(fd, out_addr, out_addrsize);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -28,6 +29,7 @@
|
|||
* @see getpeername()
|
||||
*/
|
||||
int getsockname(int fd, void *out_addr, uint32_t *out_addrsize) {
|
||||
if (IsAsan() && !__asan_is_valid(out_addr, *out_addrsize)) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_getsockname(fd, out_addr, out_addrsize);
|
||||
} else if (__isfdkind(fd, kFdSocket)) {
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
/**
|
||||
* Waits for something to happen on multiple file descriptors at once.
|
||||
|
@ -34,9 +36,11 @@
|
|||
* @return fds[𝑖].revents flags can have:
|
||||
* (fds[𝑖].events & POLL{IN,OUT,PRI,HUP,ERR,NVAL})
|
||||
* @asyncsignalsafe
|
||||
* @see ppoll()
|
||||
*/
|
||||
int poll(struct pollfd *fds, uint64_t nfds, int32_t timeout_ms) {
|
||||
if (IsAsan() && !__asan_is_valid(fds, nfds * sizeof(struct pollfd))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
return sys_poll(fds, nfds, timeout_ms);
|
||||
} else {
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/nt/winsock.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
|
@ -43,6 +44,12 @@
|
|||
ssize_t recvfrom(int fd, void *buf, size_t size, uint32_t flags,
|
||||
void *opt_out_srcaddr, uint32_t *opt_inout_srcaddrsize) {
|
||||
ssize_t got;
|
||||
if (IsAsan() &&
|
||||
(!__asan_is_valid(buf, size) ||
|
||||
(opt_out_srcaddr &&
|
||||
!__asan_is_valid(opt_out_srcaddr, *opt_inout_srcaddrsize)))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
got = sys_recvfrom(fd, buf, size, flags, opt_out_srcaddr,
|
||||
opt_inout_srcaddrsize);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/str/str.h"
|
||||
|
@ -47,6 +48,10 @@
|
|||
*/
|
||||
ssize_t sendto(int fd, const void *buf, size_t size, uint32_t flags,
|
||||
const void *opt_addr, uint32_t addrsize) {
|
||||
if (IsAsan() && (!__asan_is_valid(buf, size) ||
|
||||
(opt_addr && !__asan_is_valid(opt_addr, addrsize)))) {
|
||||
return efault();
|
||||
}
|
||||
if (!IsWindows()) {
|
||||
if (!IsBsd() || !opt_addr) {
|
||||
return sys_sendto(fd, buf, size, flags, opt_addr, addrsize);
|
||||
|
|
105
test/libc/dns/comparednsnames_test.c
Normal file
105
test/libc/dns/comparednsnames_test.c
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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 THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR 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/dns/dns.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(CompareDnsNames, testEmpty) {
|
||||
char *A = strcpy(malloc(1), "");
|
||||
char *B = strcpy(malloc(1), "");
|
||||
EXPECT_EQ(CompareDnsNames(A, B), 0);
|
||||
EXPECT_EQ(CompareDnsNames(A, A), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testDotless_caseInsensitiveBehavior) {
|
||||
char *A = malloc(2);
|
||||
char *B = malloc(2);
|
||||
EXPECT_EQ(CompareDnsNames(strcpy(A, "a"), strcpy(B, "a")), 0);
|
||||
EXPECT_EQ(CompareDnsNames(A, A), 0);
|
||||
EXPECT_EQ(CompareDnsNames(strcpy(A, "a"), strcpy(B, "A")), 0);
|
||||
EXPECT_EQ(CompareDnsNames(strcpy(A, "A"), strcpy(B, "a")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(A, "a"), strcpy(B, "b")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(A, "a"), strcpy(B, "B")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "d"), strcpy(B, "a")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testMultiLabel_lexiReverse) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_EQ(CompareDnsNames(strcpy(A, "a.example"), strcpy(B, "a.example")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "b.example"), strcpy(B, "a.example")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(A, "b.example"), strcpy(B, "a.examplz")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "a.zxample"), strcpy(B, "a.examplz")), 0);
|
||||
EXPECT_EQ(CompareDnsNames(strcpy(A, "c.a.example"), strcpy(B, "c.a.example")),
|
||||
0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "d.a.example"), strcpy(B, "c.a.example")),
|
||||
0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(A, "cat.example"), strcpy(B, "lol.example")),
|
||||
0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testTldDotQualifier_canBeEqualToDottedNames) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_EQ(
|
||||
CompareDnsNames(strcpy(B, "aaa.example."), strcpy(A, "aaa.example")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testFullyQualified_alwaysComesFirst) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "aaa.example."), strcpy(A, "zzz")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "zzz.example."), strcpy(A, "aaa")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "zzz"), strcpy(B, "aaa.example.")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "aaa"), strcpy(B, "zzz.example.")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testLikelySld_alwaysComesBeforeLocalName) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "z.e"), strcpy(A, "a")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "aaa.example"), strcpy(A, "zzz")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "zzz.example"), strcpy(A, "aaa")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "zzz"), strcpy(B, "aaa.example")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "aaa"), strcpy(B, "zzz.example")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(CompareDnsNames, testLikelySubdomain_alwaysComesAfterSld) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "a.e"), strcpy(A, "z.a.e")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "z.a.e"), strcpy(B, "a.e")), 0);
|
||||
EXPECT_LT(CompareDnsNames(strcpy(B, "b.e"), strcpy(A, "a.b.e")), 0);
|
||||
EXPECT_GT(CompareDnsNames(strcpy(A, "a.b.e"), strcpy(B, "b.e")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
|
@ -25,25 +25,23 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(serializednsheader, test) {
|
||||
TEST(SerializeDnsHeader, test) {
|
||||
uint8_t buf[12];
|
||||
struct DnsHeader header;
|
||||
memset(&header, 0, sizeof(header));
|
||||
header.id = 255;
|
||||
header.bf1 = true;
|
||||
header.qdcount = 1;
|
||||
uint8_t *buf = malloc(12);
|
||||
ASSERT_EQ(12, serializednsheader(buf, 12, header));
|
||||
SerializeDnsHeader(buf, &header);
|
||||
EXPECT_BINEQ(u" λ☺ ☺ ", buf);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(serializednsheader, fuzzSymmetry) {
|
||||
uint8_t *buf;
|
||||
struct DnsHeader *in, *out;
|
||||
buf = gc(malloc(12));
|
||||
in = rngset(gc(malloc(sizeof(struct DnsHeader))), 12, rand64, -1);
|
||||
out = rngset(gc(malloc(sizeof(struct DnsHeader))), 12, rand64, -1);
|
||||
ASSERT_EQ(12, serializednsheader(buf, 12, *in));
|
||||
ASSERT_EQ(12, deserializednsheader(out, buf, 12));
|
||||
ASSERT_EQ(0, memcmp(in, out, 12), "%#.*s\n\t%#.*s", 12, in, 12, buf);
|
||||
TEST(SerializeDnsHeader, fuzzSymmetry) {
|
||||
uint8_t buf[12];
|
||||
struct DnsHeader in, out;
|
||||
rngset(&in, sizeof(in), rand64, -1);
|
||||
rngset(&out, sizeof(out), rand64, -1);
|
||||
SerializeDnsHeader(buf, &in);
|
||||
DeserializeDnsHeader(&out, buf);
|
||||
ASSERT_EQ(0, memcmp(&in, &out, 12), "%#.*s\n\t%#.*s", 12, in, 12, buf);
|
||||
}
|
||||
|
|
|
@ -1,101 +0,0 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ 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 THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR 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/dns/dns.h"
|
||||
#include "libc/mem/mem.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(dnsnamecmp, testEmpty) {
|
||||
char *A = strcpy(malloc(1), "");
|
||||
char *B = strcpy(malloc(1), "");
|
||||
EXPECT_EQ(dnsnamecmp(A, B), 0);
|
||||
EXPECT_EQ(dnsnamecmp(A, A), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testDotless_caseInsensitiveBehavior) {
|
||||
char *A = malloc(2);
|
||||
char *B = malloc(2);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(A, "a"), strcpy(B, "a")), 0);
|
||||
EXPECT_EQ(dnsnamecmp(A, A), 0);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(A, "a"), strcpy(B, "A")), 0);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(A, "A"), strcpy(B, "a")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(A, "a"), strcpy(B, "b")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(A, "a"), strcpy(B, "B")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "d"), strcpy(B, "a")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testMultiLabel_lexiReverse) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(A, "a.example"), strcpy(B, "a.example")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "b.example"), strcpy(B, "a.example")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(A, "b.example"), strcpy(B, "a.examplz")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "a.zxample"), strcpy(B, "a.examplz")), 0);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(A, "c.a.example"), strcpy(B, "c.a.example")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "d.a.example"), strcpy(B, "c.a.example")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(A, "cat.example"), strcpy(B, "lol.example")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testTldDotQualifier_canBeEqualToDottedNames) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_EQ(dnsnamecmp(strcpy(B, "aaa.example."), strcpy(A, "aaa.example")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testFullyQualified_alwaysComesFirst) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "aaa.example."), strcpy(A, "zzz")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "zzz.example."), strcpy(A, "aaa")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "zzz"), strcpy(B, "aaa.example.")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "aaa"), strcpy(B, "zzz.example.")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testLikelySld_alwaysComesBeforeLocalName) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "z.e"), strcpy(A, "a")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "aaa.example"), strcpy(A, "zzz")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "zzz.example"), strcpy(A, "aaa")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "zzz"), strcpy(B, "aaa.example")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "aaa"), strcpy(B, "zzz.example")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
||||
|
||||
TEST(dnsnamecmp, testLikelySubdomain_alwaysComesAfterSld) {
|
||||
char *A = malloc(16);
|
||||
char *B = malloc(16);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "a.e"), strcpy(A, "z.a.e")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "z.a.e"), strcpy(B, "a.e")), 0);
|
||||
EXPECT_LT(dnsnamecmp(strcpy(B, "b.e"), strcpy(A, "a.b.e")), 0);
|
||||
EXPECT_GT(dnsnamecmp(strcpy(A, "a.b.e"), strcpy(B, "b.e")), 0);
|
||||
free(B);
|
||||
free(A);
|
||||
}
|
|
@ -22,29 +22,25 @@
|
|||
#include "libc/mem/mem.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(serializednsquestion, test) {
|
||||
uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1 + 4);
|
||||
char *name = strdup("foo.bar");
|
||||
TEST(SerializeDnsQuestion, test) {
|
||||
struct DnsQuestion dq;
|
||||
char name[] = "foo.bar";
|
||||
uint8_t buf[1 + 3 + 1 + 3 + 1 + 4];
|
||||
dq.qname = name;
|
||||
dq.qtype = 0x0201;
|
||||
dq.qclass = 0x0102;
|
||||
EXPECT_EQ(1 + 3 + 1 + 3 + 1 + 4,
|
||||
serializednsquestion(buf, 1 + 3 + 1 + 3 + 1 + 4, dq));
|
||||
SerializeDnsQuestion(buf, 1 + 3 + 1 + 3 + 1 + 4, &dq));
|
||||
EXPECT_BINEQ(u"♥foo♥bar ☻☺☺☻", buf);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(serializednsquestion, testNoSpace) {
|
||||
uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1 + 3);
|
||||
char *name = strdup("foo.bar");
|
||||
TEST(SerializeDnsQuestion, testNoSpace) {
|
||||
struct DnsQuestion dq;
|
||||
char name[] = "foo.bar";
|
||||
uint8_t buf[1 + 3 + 1 + 3 + 1 + 3];
|
||||
dq.qname = name;
|
||||
dq.qtype = 0x0201;
|
||||
dq.qclass = 0x0102;
|
||||
EXPECT_EQ(-1, serializednsquestion(buf, 1 + 3 + 1 + 3 + 1 + 3, dq));
|
||||
EXPECT_EQ(-1, SerializeDnsQuestion(buf, 1 + 3 + 1 + 3 + 1 + 3, &dq));
|
||||
EXPECT_EQ(ENOSPC, errno);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
|
|
@ -29,16 +29,16 @@ static const char *ParseIp(unsigned char ip[4]) {
|
|||
return inet_ntop(AF_INET, ip, g_ipbuf, sizeof(g_ipbuf));
|
||||
}
|
||||
|
||||
TEST(parsehoststxt, testEmpty) {
|
||||
TEST(ParseHostsTxt, testEmpty) {
|
||||
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
|
||||
FILE *f = fmemopen(NULL, BUFSIZ, "r+");
|
||||
ASSERT_EQ(0, parsehoststxt(ht, f));
|
||||
ASSERT_EQ(0, ParseHostsTxt(ht, f));
|
||||
ASSERT_EQ(0, ht->entries.i);
|
||||
freehoststxt(&ht);
|
||||
FreeHostsTxt(&ht);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
TEST(parsehoststxt, testCorrectlyTokenizesAndSorts) {
|
||||
TEST(ParseHostsTxt, testCorrectlyTokenizesAndSorts) {
|
||||
const char kInput[] = "# this is a comment\n"
|
||||
"# IP HOST1 HOST2\n"
|
||||
"203.0.113.1 lol.example. lol\n"
|
||||
|
@ -47,8 +47,8 @@ TEST(parsehoststxt, testCorrectlyTokenizesAndSorts) {
|
|||
FILE *f = fmemopen(NULL, BUFSIZ, "r+");
|
||||
ASSERT_EQ(1, fwrite(kInput, strlen(kInput), 1, f));
|
||||
rewind(f);
|
||||
ASSERT_EQ(0, parsehoststxt(ht, f));
|
||||
sorthoststxt(ht);
|
||||
ASSERT_EQ(0, ParseHostsTxt(ht, f));
|
||||
SortHostsTxt(ht);
|
||||
ASSERT_EQ(4, ht->entries.i);
|
||||
EXPECT_STREQ("cat.example.", &ht->strings.p[ht->entries.p[0].name]);
|
||||
EXPECT_STREQ("cat.example.", &ht->strings.p[ht->entries.p[0].canon]);
|
||||
|
@ -62,20 +62,20 @@ TEST(parsehoststxt, testCorrectlyTokenizesAndSorts) {
|
|||
EXPECT_STREQ("lol", &ht->strings.p[ht->entries.p[3].name]);
|
||||
EXPECT_STREQ("lol.example.", &ht->strings.p[ht->entries.p[3].canon]);
|
||||
EXPECT_STREQ("203.0.113.1", ParseIp(ht->entries.p[3].ip));
|
||||
freehoststxt(&ht);
|
||||
FreeHostsTxt(&ht);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
TEST(parsehoststxt, testIpv6_isIgnored) {
|
||||
TEST(ParseHostsTxt, testIpv6_isIgnored) {
|
||||
const char kInput[] = "::1 boop\n"
|
||||
"203.0.113.2 cat # ignore me\n";
|
||||
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
|
||||
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
|
||||
ASSERT_EQ(0, parsehoststxt(ht, f));
|
||||
ASSERT_EQ(0, ParseHostsTxt(ht, f));
|
||||
ASSERT_EQ(1, ht->entries.i);
|
||||
EXPECT_STREQ("cat", &ht->strings.p[ht->entries.p[0].name]);
|
||||
EXPECT_STREQ("cat", &ht->strings.p[ht->entries.p[0].canon]);
|
||||
EXPECT_STREQ("203.0.113.2", ParseIp(ht->entries.p[0].ip));
|
||||
freehoststxt(&ht);
|
||||
FreeHostsTxt(&ht);
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -31,22 +31,22 @@ static const char *FormatIp(struct sockaddr_in *ip) {
|
|||
return inet_ntop(ip->sin_family, &ip->sin_addr.s_addr, g_ipbuf, 16);
|
||||
}
|
||||
|
||||
TEST(parseresolvconf, testEmpty) {
|
||||
TEST(ParseResolvConf, testEmpty) {
|
||||
struct ResolvConf *rv = calloc(1, sizeof(struct ResolvConf));
|
||||
FILE *f = fmemopen(NULL, BUFSIZ, "r+");
|
||||
ASSERT_EQ(0, parseresolvconf(rv, f));
|
||||
ASSERT_EQ(0, ParseResolvConf(rv, f));
|
||||
ASSERT_EQ(0, rv->nameservers.i);
|
||||
freeresolvconf(&rv);
|
||||
FreeResolvConf(&rv);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
TEST(parseresolvconf, testCorrectlyTokenizes) {
|
||||
TEST(ParseResolvConf, testCorrectlyTokenizes) {
|
||||
const char kInput[] = "# this is a comment\n"
|
||||
"nameserver 203.0.113.2 \n"
|
||||
" nameserver 203.0.113.1\n";
|
||||
struct ResolvConf *rv = calloc(1, sizeof(struct ResolvConf));
|
||||
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
|
||||
ASSERT_EQ(2, parseresolvconf(rv, f));
|
||||
ASSERT_EQ(2, ParseResolvConf(rv, f));
|
||||
ASSERT_EQ(2, rv->nameservers.i);
|
||||
EXPECT_EQ(AF_INET, rv->nameservers.p[0].sin_family);
|
||||
EXPECT_EQ(DNS_PORT, ntohs(rv->nameservers.p[0].sin_port));
|
||||
|
@ -54,17 +54,17 @@ TEST(parseresolvconf, testCorrectlyTokenizes) {
|
|||
EXPECT_EQ(AF_INET, rv->nameservers.p[1].sin_family);
|
||||
EXPECT_EQ(DNS_PORT, ntohs(rv->nameservers.p[1].sin_port));
|
||||
EXPECT_STREQ("203.0.113.1", FormatIp(&rv->nameservers.p[1]));
|
||||
freeresolvconf(&rv);
|
||||
FreeResolvConf(&rv);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
TEST(parseresolvconf, testMulticastDnsThing_getsIgnored) {
|
||||
TEST(ParseResolvConf, testMulticastDnsThing_getsIgnored) {
|
||||
const char kInput[] = "search local # boop\n";
|
||||
struct ResolvConf *rv = calloc(1, sizeof(struct ResolvConf));
|
||||
FILE *f = fmemopen(NULL, BUFSIZ, "r+");
|
||||
ASSERT_EQ(strlen(kInput), fwrite(kInput, 1, strlen(kInput), f));
|
||||
ASSERT_EQ(0, parseresolvconf(rv, f));
|
||||
ASSERT_EQ(0, ParseResolvConf(rv, f));
|
||||
ASSERT_EQ(0, rv->nameservers.i);
|
||||
freeresolvconf(&rv);
|
||||
FreeResolvConf(&rv);
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -22,57 +22,57 @@
|
|||
#include "libc/str/str.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
TEST(pascalifydnsname, testEmpty) {
|
||||
TEST(PascalifyDnsName, testEmpty) {
|
||||
uint8_t *buf = malloc(1);
|
||||
char *name = strdup("");
|
||||
EXPECT_EQ(0, pascalifydnsname(buf, 1, name));
|
||||
EXPECT_EQ(0, PascalifyDnsName(buf, 1, name));
|
||||
EXPECT_BINEQ(u" ", buf);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(pascalifydnsname, testOneLabel) {
|
||||
TEST(PascalifyDnsName, testOneLabel) {
|
||||
uint8_t *buf = malloc(1 + 3 + 1);
|
||||
char *name = strdup("foo");
|
||||
EXPECT_EQ(1 + 3, pascalifydnsname(buf, 1 + 3 + 1, name));
|
||||
EXPECT_EQ(1 + 3, PascalifyDnsName(buf, 1 + 3 + 1, name));
|
||||
EXPECT_BINEQ(u"♥foo ", buf);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(pascalifydnsname, testTwoLabels) {
|
||||
TEST(PascalifyDnsName, testTwoLabels) {
|
||||
uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1);
|
||||
char *name = strdup("foo.bar");
|
||||
EXPECT_EQ(1 + 3 + 1 + 3, pascalifydnsname(buf, 1 + 3 + 1 + 3 + 1, name));
|
||||
EXPECT_EQ(1 + 3 + 1 + 3, PascalifyDnsName(buf, 1 + 3 + 1 + 3 + 1, name));
|
||||
EXPECT_BINEQ(u"♥foo♥bar ", buf);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(pascalifydnsname, testFqdnDot_isntIncluded) {
|
||||
TEST(PascalifyDnsName, testFqdnDot_isntIncluded) {
|
||||
uint8_t *buf = malloc(1 + 3 + 1 + 3 + 1);
|
||||
char *name = strdup("foo.bar.");
|
||||
EXPECT_EQ(1 + 3 + 1 + 3, pascalifydnsname(buf, 1 + 3 + 1 + 3 + 1, name));
|
||||
EXPECT_EQ(1 + 3 + 1 + 3, PascalifyDnsName(buf, 1 + 3 + 1 + 3 + 1, name));
|
||||
EXPECT_BINEQ(u"♥foo♥bar ", buf);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(pascalifydnsname, testTooLong) {
|
||||
TEST(PascalifyDnsName, testTooLong) {
|
||||
uint8_t *buf = malloc(1);
|
||||
char *name = malloc(1000);
|
||||
memset(name, '.', 999);
|
||||
name[999] = '\0';
|
||||
EXPECT_EQ(-1, pascalifydnsname(buf, 1, name));
|
||||
EXPECT_EQ(-1, PascalifyDnsName(buf, 1, name));
|
||||
EXPECT_EQ(ENAMETOOLONG, errno);
|
||||
free(name);
|
||||
free(buf);
|
||||
}
|
||||
|
||||
TEST(pascalifydnsname, testNoSpace) {
|
||||
TEST(PascalifyDnsName, testNoSpace) {
|
||||
uint8_t *buf = malloc(1);
|
||||
char *name = strdup("foo");
|
||||
EXPECT_EQ(-1, pascalifydnsname(buf, 1, name));
|
||||
EXPECT_EQ(-1, PascalifyDnsName(buf, 1, name));
|
||||
EXPECT_EQ(ENOSPC, errno);
|
||||
free(name);
|
||||
free(buf);
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
static const char *EzIp4Lookup(const struct HostsTxt *ht, const char *name) {
|
||||
struct sockaddr_in addr4;
|
||||
if (resolvehoststxt(ht, AF_INET, name, (void *)&addr4,
|
||||
if (ResolveHostsTxt(ht, AF_INET, name, (void *)&addr4,
|
||||
sizeof(struct sockaddr_in), NULL) > 0) {
|
||||
static char g_ipbuf[16];
|
||||
return inet_ntop(AF_INET, &addr4.sin_addr, g_ipbuf, sizeof(g_ipbuf));
|
||||
|
@ -38,18 +38,18 @@ static const char *EzIp4Lookup(const struct HostsTxt *ht, const char *name) {
|
|||
|
||||
static const char *EzCanonicalize(const struct HostsTxt *ht, const char *name) {
|
||||
const char *res;
|
||||
return resolvehoststxt(ht, AF_INET, name, NULL, 0, &res) > 0 ? res : NULL;
|
||||
return ResolveHostsTxt(ht, AF_INET, name, NULL, 0, &res) > 0 ? res : NULL;
|
||||
}
|
||||
|
||||
static const char kInput[] = "127.0.0.1 localhost\n"
|
||||
"203.0.113.1 lol.example. lol\n"
|
||||
"203.0.113.2 cat.example. cat\n";
|
||||
|
||||
TEST(resolvehoststxt, testBasicLookups) {
|
||||
TEST(ResolveHostsTxt, testBasicLookups) {
|
||||
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
|
||||
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
|
||||
ASSERT_EQ(0, parsehoststxt(ht, f));
|
||||
sorthoststxt(ht);
|
||||
ASSERT_EQ(0, ParseHostsTxt(ht, f));
|
||||
SortHostsTxt(ht);
|
||||
ASSERT_EQ(5, ht->entries.i);
|
||||
EXPECT_STREQ("127.0.0.1", EzIp4Lookup(ht, "localhost"));
|
||||
EXPECT_STREQ("203.0.113.1", EzIp4Lookup(ht, "lol"));
|
||||
|
@ -58,15 +58,15 @@ TEST(resolvehoststxt, testBasicLookups) {
|
|||
EXPECT_STREQ("203.0.113.2", EzIp4Lookup(ht, "cat"));
|
||||
EXPECT_STREQ("203.0.113.2", EzIp4Lookup(ht, "cat.example."));
|
||||
EXPECT_EQ(NULL, EzIp4Lookup(ht, "boop"));
|
||||
freehoststxt(&ht);
|
||||
FreeHostsTxt(&ht);
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
TEST(resolvehoststxt, testCanonicalize) {
|
||||
TEST(ResolveHostsTxt, testCanonicalize) {
|
||||
struct HostsTxt *ht = calloc(1, sizeof(struct HostsTxt));
|
||||
FILE *f = fmemopen(kInput, strlen(kInput), "r+");
|
||||
ASSERT_EQ(0, parsehoststxt(ht, f));
|
||||
sorthoststxt(ht);
|
||||
ASSERT_EQ(0, ParseHostsTxt(ht, f));
|
||||
SortHostsTxt(ht);
|
||||
ASSERT_EQ(5, ht->entries.i);
|
||||
EXPECT_STREQ("localhost", EzCanonicalize(ht, "localhost"));
|
||||
EXPECT_STREQ("lol.example.", EzCanonicalize(ht, "lol"));
|
||||
|
@ -75,6 +75,6 @@ TEST(resolvehoststxt, testCanonicalize) {
|
|||
EXPECT_STREQ("cat.example.", EzCanonicalize(ht, "cat"));
|
||||
EXPECT_STREQ("cat.example.", EzCanonicalize(ht, "cat.example."));
|
||||
EXPECT_EQ(NULL, EzCanonicalize(ht, "boop"));
|
||||
freehoststxt(&ht);
|
||||
FreeHostsTxt(&ht);
|
||||
fclose(f);
|
||||
}
|
||||
|
|
|
@ -31,12 +31,9 @@
|
|||
|
||||
void lookup(const char *name) {
|
||||
int rc;
|
||||
struct addrinfo hints = (struct addrinfo){.ai_family = AF_INET,
|
||||
.ai_socktype = SOCK_STREAM,
|
||||
.ai_protocol = IPPROTO_TCP,
|
||||
.ai_flags = AI_NUMERICSERV};
|
||||
struct addrinfo *addrs = NULL;
|
||||
switch ((rc = getaddrinfo(name, "80", &hints, &addrs))) {
|
||||
struct addrinfo *ai = NULL;
|
||||
struct addrinfo hint = {AI_NUMERICSERV, AF_INET, SOCK_STREAM, IPPROTO_TCP};
|
||||
switch ((rc = getaddrinfo(name, "80", &hint, &ai))) {
|
||||
case EAI_SUCCESS:
|
||||
break;
|
||||
case EAI_SYSTEM:
|
||||
|
@ -47,8 +44,8 @@ void lookup(const char *name) {
|
|||
gai_strerror(rc));
|
||||
exit(1);
|
||||
}
|
||||
if (addrs) {
|
||||
for (struct addrinfo *addr = addrs; addr; addr = addr->ai_next) {
|
||||
if (ai) {
|
||||
for (struct addrinfo *addr = ai; addr; addr = addr->ai_next) {
|
||||
const unsigned char *ip =
|
||||
addr->ai_family == AF_INET
|
||||
? (const unsigned char *)&((struct sockaddr_in *)addr->ai_addr)
|
||||
|
@ -70,7 +67,7 @@ void lookup(const char *name) {
|
|||
ip[3]);
|
||||
printf("%-12s = %s\n", "ai_canonname", addr->ai_canonname);
|
||||
}
|
||||
freeaddrinfo(addrs);
|
||||
freeaddrinfo(ai);
|
||||
} else {
|
||||
fprintf(stderr, "%s: %s\n", name, "no results");
|
||||
}
|
||||
|
|
|
@ -202,7 +202,6 @@ static const struct ContentTypeExtension {
|
|||
{"z", "application/zlib"}, //
|
||||
{"zip", "application/zip"}, //
|
||||
{"zst", "application/zstd"}, //
|
||||
{"zst", "application/zstd"}, //
|
||||
};
|
||||
|
||||
static const char kRegCode[][8] = {
|
||||
|
@ -1941,7 +1940,7 @@ td { padding-right: 3em; }\r\n\
|
|||
}
|
||||
|
||||
static const char *MergeNames(const char *a, const char *b) {
|
||||
return FreeLater(xasprintf("%s.ru_utime", a));
|
||||
return FreeLater(xasprintf("%s.%s", a, b));
|
||||
}
|
||||
|
||||
static void AppendLong1(const char *a, long x) {
|
||||
|
@ -2212,7 +2211,7 @@ static int LuaRoute(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int LuaRespond(lua_State *L, char *respond(unsigned, const char *)) {
|
||||
static int LuaRespond(lua_State *L, char *R(unsigned, const char *)) {
|
||||
char *p;
|
||||
int code;
|
||||
size_t reasonlen;
|
||||
|
@ -2223,11 +2222,11 @@ static int LuaRespond(lua_State *L, char *respond(unsigned, const char *)) {
|
|||
unreachable;
|
||||
}
|
||||
if (lua_isnoneornil(L, 2)) {
|
||||
luaheaderp = respond(code, GetHttpReason(code));
|
||||
luaheaderp = R(code, GetHttpReason(code));
|
||||
} else {
|
||||
reason = lua_tolstring(L, 2, &reasonlen);
|
||||
if (reasonlen < 128 && (p = EncodeHttpHeaderValue(reason, reasonlen, 0))) {
|
||||
luaheaderp = respond(code, p);
|
||||
luaheaderp = R(code, p);
|
||||
free(p);
|
||||
} else {
|
||||
luaL_argerror(L, 2, "invalid");
|
||||
|
@ -2802,7 +2801,7 @@ static int LuaSetHeader(lua_State *L) {
|
|||
}
|
||||
switch (h) {
|
||||
case kHttpConnection:
|
||||
if (evallen != 5 || memcasecmp(eval, "close", 5)) {
|
||||
if (SlicesEqualCase(eval, evallen, "close", 5)) {
|
||||
luaL_argerror(L, 2, "unsupported");
|
||||
unreachable;
|
||||
}
|
||||
|
@ -3017,11 +3016,11 @@ static int LuaHasControlCodes(lua_State *L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int LuaIsValid(lua_State *L, bool IsValid(const char *, size_t)) {
|
||||
static int LuaIsValid(lua_State *L, bool V(const char *, size_t)) {
|
||||
size_t size;
|
||||
const char *data;
|
||||
data = luaL_checklstring(L, 1, &size);
|
||||
lua_pushboolean(L, IsValid(data, size));
|
||||
lua_pushboolean(L, V(data, size));
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue