Merge HTTP request / response parsing code

This change also fixes a bug so that DNS lookups work correctly when the
first answer is a CNAME record.
This commit is contained in:
Justine Tunney 2021-06-27 17:03:06 -07:00
parent 5a6c0f27c3
commit a68cc690ff
20 changed files with 561 additions and 616 deletions

View file

@ -1,13 +1,19 @@
#ifndef COSMOPOLITAN_LIBC_DNS_CONSTS_H_
#define COSMOPOLITAN_LIBC_DNS_CONSTS_H_
#include "libc/sock/sock.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define DNS_TYPE_A 0x01
#define DNS_TYPE_PTR 0x0c
#define DNS_TYPE_A 1
#define DNS_TYPE_NS 2
#define DNS_TYPE_CNAME 5
#define DNS_TYPE_SOA 6
#define DNS_TYPE_PTR 12
#define DNS_TYPE_MX 15
#define DNS_TYPE_TXT 16
#define DNS_CLASS_IN 1
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define kMinSockaddr4Size \
(offsetof(struct sockaddr_in, sin_addr) + sizeof(struct in_addr))

View file

@ -27,6 +27,7 @@
#include "libc/rand/rand.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"
@ -49,12 +50,14 @@
*/
int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
struct sockaddr *addr, uint32_t addrsize) {
int32_t ttl;
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;
if (addrsize < kMinSockaddr4Size) return einval();
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!resolvconf->nameservers.i) return 0;
memset(&h, 0, sizeof(h));
@ -75,38 +78,31 @@ int ResolveDns(const struct ResolvConf *resolvconf, int af, const char *name,
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--;
p = msg + 12;
pe = msg + n;
while (p < pe && h2.qdcount--) {
p += strnlen((char *)p, pe - p) + 1 + 4;
}
while (p < pe && h2.ancount--) {
if ((p[0] & 0xc0) == 0xc0) { /* 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)) {
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();
}
}
}
if (p + 10 <= pe) {
rtype = READ16BE(p);
rclass = READ16BE(p + 2);
ttl = READ32BE(p + 4);
rdlength = READ16BE(p + 8);
if (p + 10 + rdlength <= pe && rdlength == 4 &&
rclass == DNS_CLASS_IN && rtype == DNS_TYPE_A) {
rc = 1;
a4 = (struct sockaddr_in *)addr;
a4->sin_family = AF_INET;
memcpy(&a4->sin_addr.s_addr, p + 10, 4);
break;
}
p += 10 + rdlength;
}
}
}

View file

@ -125,11 +125,11 @@ static int PrintBacktraceUsingAddr2line(int fd, const struct StackFrame *bp) {
}
static int PrintBacktrace(int fd, const struct StackFrame *bp) {
if (!IsTiny()) {
if (PrintBacktraceUsingAddr2line(fd, bp) != -1) {
return 0;
}
/* if (!IsTiny()) { */
if (PrintBacktraceUsingAddr2line(fd, bp) != -1) {
return 0;
}
/* } */
return PrintBacktraceUsingSymbols(fd, bp, GetSymbolTable());
}