diff --git a/examples/nc.c b/examples/nc.c index 39b2c099..836c7f23 100644 --- a/examples/nc.c +++ b/examples/nc.c @@ -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; } diff --git a/libc/dns/dnsnamecmp.c b/libc/dns/comparednsnames.c similarity index 89% rename from libc/dns/dnsnamecmp.c rename to libc/dns/comparednsnames.c index 81958aca..6db6fda2 100644 --- a/libc/dns/dnsnamecmp.c +++ b/libc/dns/comparednsnames.c @@ -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) { diff --git a/libc/dns/dns.h b/libc/dns/dns.h index 48bc50b7..431b2c4c 100644 --- a/libc/dns/dns.h +++ b/libc/dns/dns.h @@ -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); diff --git a/libc/dns/dnsheader.c b/libc/dns/dnsheader.c index f26392aa..c66727d6 100644 --- a/libc/dns/dnsheader.c +++ b/libc/dns/dnsheader.c @@ -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); } diff --git a/libc/dns/dnsheader.h b/libc/dns/dnsheader.h index 3d23bfb4..d517ddc0 100644 --- a/libc/dns/dnsheader.h +++ b/libc/dns/dnsheader.h @@ -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) */ diff --git a/libc/dns/dnsquestion.h b/libc/dns/dnsquestion.h index 8463fd6c..920622ab 100644 --- a/libc/dns/dnsquestion.h +++ b/libc/dns/dnsquestion.h @@ -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) */ diff --git a/libc/dns/freeaddrinfo.c b/libc/dns/freeaddrinfo.c index 79b0f733..782b20af 100644 --- a/libc/dns/freeaddrinfo.c +++ b/libc/dns/freeaddrinfo.c @@ -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; } diff --git a/libc/dns/freehoststxt.c b/libc/dns/freehoststxt.c index d43ada01..d586adc1 100644 --- a/libc/dns/freehoststxt.c +++ b/libc/dns/freehoststxt.c @@ -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); diff --git a/libc/dns/freeresolvconf.c b/libc/dns/freeresolvconf.c index f663f572..f11e3e61 100644 --- a/libc/dns/freeresolvconf.c +++ b/libc/dns/freeresolvconf.c @@ -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); diff --git a/libc/dns/getaddrinfo.c b/libc/dns/getaddrinfo.c index 76cb26a3..8da6160b 100644 --- a/libc/dns/getaddrinfo.c +++ b/libc/dns/getaddrinfo.c @@ -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; diff --git a/libc/dns/gethoststxt.c b/libc/dns/gethoststxt.c index f2420328..ab6a5cb0 100644 --- a/libc/dns/gethoststxt.c +++ b/libc/dns/gethoststxt.c @@ -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; } diff --git a/libc/dns/getntnameservers.c b/libc/dns/getntnameservers.c index d7768600..7181cb13 100644 --- a/libc/dns/getntnameservers.c +++ b/libc/dns/getntnameservers.c @@ -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)))) { diff --git a/libc/dns/getresolvconf.c b/libc/dns/getresolvconf.c index a9035af9..3681d9d1 100644 --- a/libc/dns/getresolvconf.c +++ b/libc/dns/getresolvconf.c @@ -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. */ diff --git a/libc/dns/hoststxt.h b/libc/dns/hoststxt.h index 3972684a..d03c4b54 100644 --- a/libc/dns/hoststxt.h +++ b/libc/dns/hoststxt.h @@ -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)); diff --git a/libc/dns/parsehoststxt.c b/libc/dns/parsehoststxt.c index 937ca326..e5a46d1d 100644 --- a/libc/dns/parsehoststxt.c +++ b/libc/dns/parsehoststxt.c @@ -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; diff --git a/libc/dns/parseresolvconf.c b/libc/dns/parseresolvconf.c index 3d51904d..b5159998 100644 --- a/libc/dns/parseresolvconf.c +++ b/libc/dns/parseresolvconf.c @@ -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); diff --git a/libc/dns/pascalifydnsname.c b/libc/dns/pascalifydnsname.c index 86322e3d..f771dc3b 100644 --- a/libc/dns/pascalifydnsname.c +++ b/libc/dns/pascalifydnsname.c @@ -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; diff --git a/libc/dns/resolvconf.h b/libc/dns/resolvconf.h index 222a7fbc..2ce3be2a 100644 --- a/libc/dns/resolvconf.h +++ b/libc/dns/resolvconf.h @@ -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) */ diff --git a/libc/dns/resolvedns.c b/libc/dns/resolvedns.c index 8870e761..79d9fef1 100644 --- a/libc/dns/resolvedns.c +++ b/libc/dns/resolvedns.c @@ -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; } diff --git a/libc/dns/resolvehoststxt.c b/libc/dns/resolvehoststxt.c index 3a0d6d77..f5858b2f 100644 --- a/libc/dns/resolvehoststxt.c +++ b/libc/dns/resolvehoststxt.c @@ -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; diff --git a/libc/dns/serializednsquestion.c b/libc/dns/serializednsquestion.c index 416a566c..13330651 100644 --- a/libc/dns/serializednsquestion.c +++ b/libc/dns/serializednsquestion.c @@ -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; } diff --git a/libc/dns/sorthoststxt.c b/libc/dns/sorthoststxt.c index 957e6d12..e32cc452 100644 --- a/libc/dns/sorthoststxt.c +++ b/libc/dns/sorthoststxt.c @@ -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); diff --git a/libc/log/perror.c b/libc/log/perror.c index e8ea6e21..bb5a9c25 100644 --- a/libc/log/perror.c +++ b/libc/log/perror.c @@ -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. diff --git a/libc/sock/accept4.c b/libc/sock/accept4.c index e92d3331..1d24bb04 100644 --- a/libc/sock/accept4.c +++ b/libc/sock/accept4.c @@ -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)) { diff --git a/libc/sock/bind.c b/libc/sock/bind.c index d9b28a4a..28cb9c68 100644 --- a/libc/sock/bind.c +++ b/libc/sock/bind.c @@ -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]); diff --git a/libc/sock/connect.c b/libc/sock/connect.c index 9cbb2515..10d7beae 100644 --- a/libc/sock/connect.c +++ b/libc/sock/connect.c @@ -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)) { diff --git a/libc/sock/getpeername.c b/libc/sock/getpeername.c index 0da57eb9..444a3e60 100644 --- a/libc/sock/getpeername.c +++ b/libc/sock/getpeername.c @@ -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)) { diff --git a/libc/sock/getsockname.c b/libc/sock/getsockname.c index 70409656..49c7e9db 100644 --- a/libc/sock/getsockname.c +++ b/libc/sock/getsockname.c @@ -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)) { diff --git a/libc/sock/poll.c b/libc/sock/poll.c index ab8c5a07..b1920114 100644 --- a/libc/sock/poll.c +++ b/libc/sock/poll.c @@ -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 { diff --git a/libc/sock/recvfrom.c b/libc/sock/recvfrom.c index f05d9a90..65f2ddc8 100644 --- a/libc/sock/recvfrom.c +++ b/libc/sock/recvfrom.c @@ -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); diff --git a/libc/sock/sendto.c b/libc/sock/sendto.c index cf55bc41..c09333aa 100644 --- a/libc/sock/sendto.c +++ b/libc/sock/sendto.c @@ -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); diff --git a/test/libc/dns/comparednsnames_test.c b/test/libc/dns/comparednsnames_test.c new file mode 100644 index 00000000..2a0d8aad --- /dev/null +++ b/test/libc/dns/comparednsnames_test.c @@ -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); +} diff --git a/test/libc/dns/dnsheader_test.c b/test/libc/dns/dnsheader_test.c index 380a8629..d8617cd8 100644 --- a/test/libc/dns/dnsheader_test.c +++ b/test/libc/dns/dnsheader_test.c @@ -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); } diff --git a/test/libc/dns/dnsnamecmp_test.c b/test/libc/dns/dnsnamecmp_test.c deleted file mode 100644 index 55ba2b48..00000000 --- a/test/libc/dns/dnsnamecmp_test.c +++ /dev/null @@ -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); -} diff --git a/test/libc/dns/dnsquestion_test.c b/test/libc/dns/dnsquestion_test.c index 0fb1078d..b745c9a7 100644 --- a/test/libc/dns/dnsquestion_test.c +++ b/test/libc/dns/dnsquestion_test.c @@ -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); } diff --git a/test/libc/dns/parsehoststxt_test.c b/test/libc/dns/parsehoststxt_test.c index a0649c95..8d8adb9b 100644 --- a/test/libc/dns/parsehoststxt_test.c +++ b/test/libc/dns/parsehoststxt_test.c @@ -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); } diff --git a/test/libc/dns/parseresolvconf_test.c b/test/libc/dns/parseresolvconf_test.c index d4a017bc..b4733360 100644 --- a/test/libc/dns/parseresolvconf_test.c +++ b/test/libc/dns/parseresolvconf_test.c @@ -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); } diff --git a/test/libc/dns/pascalifydnsname_test.c b/test/libc/dns/pascalifydnsname_test.c index 2b372ec4..b57d4064 100644 --- a/test/libc/dns/pascalifydnsname_test.c +++ b/test/libc/dns/pascalifydnsname_test.c @@ -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); diff --git a/test/libc/dns/resolvehoststxt_test.c b/test/libc/dns/resolvehoststxt_test.c index 3f006d09..758ee497 100644 --- a/test/libc/dns/resolvehoststxt_test.c +++ b/test/libc/dns/resolvehoststxt_test.c @@ -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); } diff --git a/tool/net/dig.c b/tool/net/dig.c index 2c734bbf..38575983 100644 --- a/tool/net/dig.c +++ b/tool/net/dig.c @@ -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"); } diff --git a/tool/net/redbean.c b/tool/net/redbean.c index ff459ff9..7f863f34 100644 --- a/tool/net/redbean.c +++ b/tool/net/redbean.c @@ -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; }