Initial import

This commit is contained in:
Justine Tunney 2020-06-15 07:18:57 -07:00
commit c91b3c5006
14915 changed files with 590219 additions and 0 deletions

13
libc/dns/consts.h Normal file
View file

@ -0,0 +1,13 @@
#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 1
#define DNS_CLASS_IN 1
#define kMinSockaddr4Size \
(offsetof(struct sockaddr_in, sin_addr) + sizeof(struct in_addr))
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_CONSTS_H_ */

40
libc/dns/dns.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef COSMOPOLITAN_LIBC_DNS_DNS_H_
#define COSMOPOLITAN_LIBC_DNS_DNS_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define DNS_PORT 53
#define DNS_NAME_MAX 253
#define DNS_LABEL_MAX 63
struct sockaddr;
struct sockaddr_in;
struct ResolvConf;
struct addrinfo {
int32_t ai_flags; /* AI_XXX */
int32_t ai_family; /* AF_INET */
int32_t ai_socktype; /* SOCK_XXX */
int32_t ai_protocol; /* IPPROTO_XXX */
uint32_t ai_addrlen;
union {
struct sockaddr *ai_addr;
struct sockaddr_in *ai_addr4;
};
char *ai_canonname /*[DNS_NAME_MAX + 1]*/;
struct addrinfo *ai_next;
};
int getaddrinfo(const char *, const char *, const struct addrinfo *,
struct addrinfo **) paramsnonnull((4));
int freeaddrinfo(struct addrinfo *);
const char *eai2str(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 *,
uint32_t) paramsnonnull();
struct addrinfo *newaddrinfo(uint16_t);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_DNS_H_ */

61
libc/dns/dns.mk Normal file
View file

@ -0,0 +1,61 @@
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
PKGS += LIBC_DNS
LIBC_DNS_ARTIFACTS += LIBC_DNS_A
LIBC_DNS = $(LIBC_DNS_A_DEPS) $(LIBC_DNS_A)
LIBC_DNS_A = o/$(MODE)/libc/dns/dns.a
LIBC_DNS_A_FILES := $(wildcard libc/dns/*)
LIBC_DNS_A_HDRS = $(filter %.h,$(LIBC_DNS_A_FILES))
LIBC_DNS_A_SRCS_C = $(filter %.c,$(LIBC_DNS_A_FILES))
LIBC_DNS_A_SRCS_S = $(filter %.S,$(LIBC_DNS_A_FILES))
LIBC_DNS_A_SRCS = \
$(LIBC_DNS_A_SRCS_S) \
$(LIBC_DNS_A_SRCS_C)
LIBC_DNS_A_OBJS = \
$(LIBC_DNS_A_SRCS:%=o/$(MODE)/%.zip.o) \
$(LIBC_DNS_A_SRCS_S:%.S=o/$(MODE)/%.o) \
$(LIBC_DNS_A_SRCS_C:%.c=o/$(MODE)/%.o)
LIBC_DNS_A_CHECKS = \
$(LIBC_DNS_A).pkg \
$(LIBC_DNS_A_HDRS:%=o/$(MODE)/%.ok)
LIBC_DNS_A_DIRECTDEPS = \
LIBC_ALG \
LIBC_CALLS \
LIBC_FMT \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_RAND \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STUBS \
LIBC_STR \
LIBC_SYSV \
LIBC_NT_KERNELBASE
LIBC_DNS_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_DNS_A_DIRECTDEPS),$($(x))))
$(LIBC_DNS_A): libc/dns/ \
$(LIBC_DNS_A).pkg \
$(LIBC_DNS_A_OBJS)
$(LIBC_DNS_A).pkg: \
$(LIBC_DNS_A_OBJS) \
$(foreach x,$(LIBC_DNS_A_DIRECTDEPS),$($(x)_A).pkg)
LIBC_DNS_LIBS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)))
LIBC_DNS_SRCS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_SRCS))
LIBC_DNS_HDRS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_HDRS))
LIBC_DNS_CHECKS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_CHECKS))
LIBC_DNS_OBJS = $(foreach x,$(LIBC_DNS_ARTIFACTS),$($(x)_OBJS))
$(LIBC_DNS_OBJS): $(BUILD_FILES) libc/dns/dns.mk
.PHONY: o/$(MODE)/libc/dns
o/$(MODE)/libc/dns: $(LIBC_DNS_CHECKS)

BIN
libc/dns/dns.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 KiB

64
libc/dns/dnsheader.c Normal file
View file

@ -0,0 +1,64 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/dns/dnsheader.h"
#include "libc/sysv/errfuns.h"
/**
* Serializes DNS message header 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;
}
/**
* Serializes DNS message header 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;
}

23
libc/dns/dnsheader.h Normal file
View file

@ -0,0 +1,23 @@
#ifndef COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_
#define COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct DnsHeader {
uint16_t id; /* transaction id */
uint8_t bf1; /* bit field 1 */
uint8_t bf2; /* bit field 2 */
uint16_t qdcount; /* question count */
uint16_t ancount; /* answer count */
uint16_t nscount; /* nameserver count */
uint16_t arcount; /* additional record count */
};
int serializednsheader(uint8_t *buf, size_t size,
const struct DnsHeader header);
int deserializednsheader(struct DnsHeader *header, const uint8_t *buf,
size_t size);
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_DNSHEADER_H_ */

76
libc/dns/dnsnamecmp.c Normal file
View file

@ -0,0 +1,76 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/dns/dns.h"
#include "libc/str/str.h"
forceinline void FindDnsLabel(const char *A, size_t *i, size_t *n) {
while (*i) {
if (A[*i - 1] == '.') {
if (*i == *n) {
--(*n);
} else {
break;
}
}
--(*i);
}
}
/**
* Compares DNS hostnames in reverse lexicographical asciibetical order.
* @return <0, 0, or >0
* @see test/libc/dns/dnsnamecmp_test.c (the code that matters)
*/
int dnsnamecmp(const char *A, const char *B) {
if (A == B) return 0;
size_t n = strlen(A);
size_t m = strlen(B);
if (!n || !m || ((A[n - 1] == '.') ^ (B[m - 1] == '.'))) {
if (n && m && A[n - 1] == '.' && strchr(B, '.')) {
--m;
} else if (n && m && B[m - 1] == '.' && strchr(A, '.')) {
--n;
} else {
return A[n ? n - 1 : 0] - B[m ? m - 1 : 0];
}
}
size_t i = n;
size_t j = m;
bool first = true;
for (;;) {
FindDnsLabel(A, &i, &n);
FindDnsLabel(B, &j, &m);
if (first) {
first = false;
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)))) {
return res;
}
if (!i || !j) {
return i - j;
}
n = i;
m = j;
}
}

32
libc/dns/dnsquestion.h Normal file
View file

@ -0,0 +1,32 @@
#ifndef COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_
#define COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_
#include "libc/dns/dns.h"
#include "libc/sysv/errfuns.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct DnsQuestion {
const char *qname;
uint16_t qtype;
uint16_t qclass;
};
/**
* Serializes DNS question record to wire.
*
* @return number of bytes written
* @see pascalifydnsname()
*/
forceinline int serializednsquestion(uint8_t *buf, size_t size,
struct DnsQuestion dq) {
int wrote;
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;
return wrote + 5;
}
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_DNSQUESTION_H_ */

47
libc/dns/eai2str.c Normal file
View file

@ -0,0 +1,47 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/dns.h"
#include "libc/sysv/consts/eai.h"
/**
* Turns getaddrinfo() return code into string.
*/
const char *eai2str(int code) {
if (code == EAI_ADDRFAMILY) return "ADDRFAMILY";
if (code == EAI_AGAIN) return "AGAIN";
if (code == EAI_ALLDONE) return "ALLDONE";
if (code == EAI_BADFLAGS) return "BADFLAGS";
if (code == EAI_CANCELED) return "CANCELED";
if (code == EAI_FAIL) return "FAIL";
if (code == EAI_FAMILY) return "FAMILY";
if (code == EAI_IDN_ENCODE) return "ENCODE";
if (code == EAI_INPROGRESS) return "INPROGRESS";
if (code == EAI_INTR) return "INTR";
if (code == EAI_MEMORY) return "MEMORY";
if (code == EAI_NODATA) return "NODATA";
if (code == EAI_NONAME) return "NONAME";
if (code == EAI_NOTCANCELED) return "NOTCANCELED";
if (code == EAI_OVERFLOW) return "OVERFLOW";
if (code == EAI_SERVICE) return "SERVICE";
if (code == EAI_SOCKTYPE) return "SOCKTYPE";
if (code == EAI_SUCCESS) return "SUCCESS";
if (code == EAI_SYSTEM) return "SYSTEM";
return "???";
}

35
libc/dns/freeaddrinfo.c Normal file
View file

@ -0,0 +1,35 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/dns.h"
#include "libc/mem/mem.h"
/**
* Frees addresses returned by getaddrinfo().
*/
int freeaddrinfo(struct addrinfo *addrs) {
struct addrinfo *next;
while (addrs) {
/* we assume ai_addr and ai_canonname are shoehorned */
next = addrs->ai_next;
free(addrs);
addrs = next;
}
return 0;
}

32
libc/dns/freehoststxt.c Normal file
View file

@ -0,0 +1,32 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/hoststxt.h"
#include "libc/runtime/runtime.h"
/**
* Frees HOSTS.TXT data structure populated by parsehoststxt().
*/
void freehoststxt(struct HostsTxt **ht) {
if (*ht) {
free_s(&(*ht)->entries.p);
free_s(&(*ht)->strings.p);
free_s(ht);
}
}

31
libc/dns/freeresolvconf.c Normal file
View file

@ -0,0 +1,31 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/resolvconf.h"
#include "libc/runtime/runtime.h"
/**
* Frees resolv.conf data structure populated by parseresolvconf().
*/
void freeresolvconf(struct ResolvConf **rvp) {
if (*rvp) {
free_s(&(*rvp)->nameservers.p);
free_s(rvp);
}
}

98
libc/dns/getaddrinfo.c Normal file
View file

@ -0,0 +1,98 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/safemacros.h"
#include "libc/conv/conv.h"
#include "libc/dns/dns.h"
#include "libc/dns/hoststxt.h"
#include "libc/dns/resolvconf.h"
#include "libc/mem/mem.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "libc/calls/calls.h"
#include "libc/sysv/errfuns.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ai.h"
#include "libc/sysv/consts/eai.h"
#include "libc/sysv/consts/inaddr.h"
/**
* Resolves address for internet name.
*
* @param node is either an ip string or a utf-8 hostname
* @param service is the port number as a string
* @param hints may be passed to specialize behavior (optional)
* @param res receives a pointer that must be freed with freeaddrinfo(),
* and won't be modified if -1 is returned
* @return 0 on success or EAI_xxx value
*/
int getaddrinfo(const char *name, const char *service,
const struct addrinfo *hints, struct addrinfo **res) {
int port = 0;
struct addrinfo *ai;
if ((!name && !service) || (service && (port = parseport(service)) == -1)) {
return EAI_NONAME;
}
if (!name && (hints->ai_flags & AI_CANONNAME) == AI_CANONNAME) {
return EAI_BADFLAGS;
}
if (!(ai = newaddrinfo(port))) {
return EAI_MEMORY;
}
if (service) {
ai->ai_addr4->sin_port = htons(port);
}
if (hints) {
ai->ai_socktype = hints->ai_socktype;
ai->ai_protocol = hints->ai_protocol;
}
if (!name) {
ai->ai_addr4->sin_addr.s_addr =
(hints && (hints->ai_flags & AI_PASSIVE) == AI_PASSIVE)
? INADDR_ANY
: INADDR_LOOPBACK;
return 0;
}
const char *canon;
if (inet_pton(AF_INET, name, &ai->ai_addr4->sin_addr.s_addr) == 1) {
*res = ai;
return 0;
} 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,
sizeof(ai->ai_addr4), &canon) > 0) {
memcpy(ai->ai_canonname, canon, min(strlen(canon), DNS_NAME_MAX) + 1);
*res = ai;
return 0;
} else {
int rc = resolvedns(getresolvconf(), AF_INET, name, ai->ai_addr,
sizeof(ai->ai_addr4));
if (rc > 0) {
*res = ai;
return 0;
}
freeaddrinfo(ai);
if (rc == 0) {
return EAI_NONAME;
} else {
return EAI_SYSTEM;
}
}
}

79
libc/dns/gethoststxt.c Normal file
View file

@ -0,0 +1,79 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/bits/pushpop.h"
#include "libc/bits/safemacros.h"
#include "libc/dce.h"
#include "libc/dns/hoststxt.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/nt/systeminfo.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
static struct HostsTxt *g_hoststxt;
static struct HostsTxtInitialStaticMemory {
struct HostsTxt ht;
struct HostsTxtEntry entries[8];
char strings[64];
} g_hoststxt_init;
static textwindows noinline char *getnthoststxtpath(char *pathbuf,
uint32_t size) {
const char *const kWinHostsPath = "\\drivers\\etc\\hosts";
uint32_t len = GetSystemDirectoryA(&pathbuf[0], size);
if (len && len + strlen(kWinHostsPath) + 1 < size) {
if (pathbuf[len] == '\\') pathbuf[len--] = '\0';
memcpy(&pathbuf[len], kWinHostsPath, strlen(kWinHostsPath) + 1);
return &pathbuf[0];
} else {
return NULL;
}
}
/**
* Returns parsed sorted singleton hardcoded hostnameip4 map.
*
* @note yoinking realloc() ensures there's no size limits
*/
const struct HostsTxt *gethoststxt(void) {
struct HostsTxtInitialStaticMemory *init = &g_hoststxt_init;
if (!g_hoststxt) {
g_hoststxt = &init->ht;
init->ht.entries.n = pushpop(ARRAYLEN(init->entries));
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);
char pathbuf[PATH_MAX];
const char *path = "/etc/hosts";
if (IsWindows()) {
path = firstnonnull(getnthoststxtpath(pathbuf, ARRAYLEN(pathbuf)), path);
}
FILE *f;
if (!(f = fopen(path, "r")) || parsehoststxt(g_hoststxt, f) == -1) {
if (!IsTiny()) fprintf(stderr, "%s: %s: %m\n", "warning", path);
}
fclose(f);
sorthoststxt(g_hoststxt);
}
return g_hoststxt;
}

View file

@ -0,0 +1,87 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist.h"
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/dns/dns.h"
#include "libc/dns/resolvconf.h"
#include "libc/nt/registry.h"
#include "libc/nt/runtime.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
/**
* Extracts DNS nameserver IPs from Windows Registry.
*
* @param resolv points to a ResolvConf object, which should be zero
* initialized by the caller; or if it already contains items,
* this function will append
* @return number of nameservers appended, or -1 w/ errno
*/
textwindows int getntnameservers(struct ResolvConf *resolv) {
int rc;
int64_t hkInterfaces = kNtInvalidHandleValue;
uint32_t keycount = 0;
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)) {
struct sockaddr_in nameserver;
nameserver.sin_family = AF_INET;
nameserver.sin_port = htons(DNS_PORT);
rc = 0;
for (uint32_t i = 0; i < keycount; ++i) {
char16_t value[128], ifaceuuid[64];
uint32_t valuebytes, ifaceuuidlen = sizeof(ifaceuuid);
if (!RegEnumKeyEx(hkInterfaces, i, ifaceuuid, &ifaceuuidlen, NULL, NULL,
NULL, NULL) &&
((!RegGetValue(hkInterfaces, ifaceuuid, u"DhcpIpAddress",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)) ||
(!RegGetValue(hkInterfaces, ifaceuuid, u"IpAddress",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t))) &&
((!RegGetValue(hkInterfaces, ifaceuuid, u"DhcpNameServer",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)) ||
(!RegGetValue(hkInterfaces, ifaceuuid, u"NameServer",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)))) {
char value8[128];
tprecode16to8(value8, sizeof(value8), value);
if (inet_pton(AF_INET, value8, &nameserver.sin_addr.s_addr) == 1) {
if (append(&resolv->nameservers, &nameserver) != -1) ++rc;
}
}
}
} else {
rc = winerr();
}
RegCloseKey(hkInterfaces);
return rc;
}

62
libc/dns/getresolvconf.c Normal file
View file

@ -0,0 +1,62 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/pushpop.h"
#include "libc/dce.h"
#include "libc/dns/resolvconf.h"
#include "libc/fmt/fmt.h"
#include "libc/macros.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
static struct ResolvConf *g_resolvconf;
static struct ResolvConfInitialStaticMemory {
struct ResolvConf rv;
struct sockaddr_in nameservers[3];
} g_resolvconf_init;
/**
* Returns singleton with DNS server address.
*/
const struct ResolvConf *getresolvconf(void) {
struct ResolvConfInitialStaticMemory *init = &g_resolvconf_init;
if (!g_resolvconf) {
g_resolvconf = &init->rv;
pushmov(&init->rv.nameservers.n, ARRAYLEN(init->nameservers));
init->rv.nameservers.p = init->nameservers;
__cxa_atexit(freeresolvconf, &g_resolvconf, NULL);
int rc;
if (!IsWindows()) {
FILE *f;
if ((f = fopen("/etc/resolv.conf", "r"))) {
rc = parseresolvconf(g_resolvconf, f);
} else {
rc = -1;
}
fclose(f);
} else {
rc = getntnameservers(g_resolvconf);
}
if (rc == -1 && !IsTiny()) {
fprintf(stderr, "%s: %m\n", "nameserver discovery failed");
}
}
return g_resolvconf;
}

42
libc/dns/hoststxt.h Normal file
View file

@ -0,0 +1,42 @@
#ifndef COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_
#define COSMOPOLITAN_LIBC_DNS_HOSTSTXT_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] */
};
struct HostsTxtEntries {
size_t i;
size_t n;
struct HostsTxtEntry *p;
};
struct HostsTxtStrings {
size_t i;
size_t n;
char *p;
};
struct HostsTxt {
struct HostsTxtEntries entries;
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 *,
struct sockaddr *, uint32_t, const char **)
paramsnonnull((1, 3));
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_HOSTSTXT_H_ */

41
libc/dns/newaddrinfo.c Normal file
View file

@ -0,0 +1,41 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/dns.h"
#include "libc/macros.h"
#include "libc/mem/mem.h"
#include "libc/sock/sock.h"
#include "libc/sysv/consts/af.h"
struct addrinfo *newaddrinfo(uint16_t port) {
void *mem;
struct addrinfo *ai = NULL;
/* shoehorning is ok since this'll never be realloc()'d */
uint32_t size = ROUNDUP(sizeof(struct addrinfo), sizeof(void *));
uint32_t addrlen = sizeof(struct sockaddr_in);
if ((ai = mem = calloc(1, size + addrlen + DNS_NAME_MAX + 1))) {
ai->ai_family = AF_INET;
ai->ai_addrlen = addrlen;
ai->ai_addr4 = (struct sockaddr_in *)((char *)mem + size);
ai->ai_addr4->sin_family = AF_INET;
ai->ai_addr4->sin_port = htons(port);
ai->ai_canonname = (char *)mem + size + addrlen;
}
return ai;
}

69
libc/dns/parsehoststxt.c Normal file
View file

@ -0,0 +1,69 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist.h"
#include "libc/dns/dns.h"
#include "libc/dns/hoststxt.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"
/**
* Parses HOSTS.TXT contents.
*
* Hostnames were invented by Peggy Karp; her format looks like this:
*
* # this is a comment
* # IP CANON [ALT...]
* 203.0.113.1 lol.example. lol
* 203.0.113.2 cat.example. cat
*
* @param htp points to a HostsTxt object, which should be zero
* initialized by the caller; or if it already contains items,
* this function will append
* @param f is the file content; see fopen() and fmemopen()
* @return 0 on success, or -1 w/ errno
* @see hoststxtsort() which is the logical next step
*/
int parsehoststxt(struct HostsTxt *ht, FILE *f) {
int rc = 0;
char stackline[128];
char *line = stackline;
size_t linecap = sizeof(stackline);
while ((getline(&line, &linecap, f)) != -1) {
struct HostsTxtEntry entry;
char *addr, *name, *tok, *comment;
if ((comment = strchr(line, '#'))) *comment = '\0';
if ((addr = strtok_r(line, " \t\r\n\v", &tok)) &&
inet_pton(AF_INET, addr, entry.ip) == 1) {
entry.canon = ht->strings.i;
while ((name = strtok_r(NULL, " \t\r\n\v", &tok))) {
entry.name = ht->strings.i;
if (concat(&ht->strings, name, strnlen(name, DNS_NAME_MAX) + 1) == -1 ||
append(&ht->entries, &entry) == -1) {
rc = -1;
}
}
}
}
free_s(&line);
return rc | ferror(f);
}

View file

@ -0,0 +1,68 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist.h"
#include "libc/dns/dns.h"
#include "libc/dns/resolvconf.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/inaddr.h"
/**
* Parses /etc/resolv.conf file.
*
* The content of the file usually looks like this:
*
* nameserver 8.8.8.8
* nameserver 8.8.4.4
*
* @param resolv points to a ResolvConf object, which should be zero
* initialized by the caller; or if it already contains items,
* this function will append
* @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) {
/* TODO(jart): options ndots:5 */
int rc = 0;
char stackline[32];
char *line = stackline;
size_t linecap = sizeof(stackline);
struct sockaddr_in nameserver;
nameserver.sin_family = AF_INET;
nameserver.sin_port = htons(DNS_PORT);
while (getline(&line, &linecap, f) != -1) {
char *directive, *value, *tok, *comment;
if ((comment = strchr(line, '#'))) *comment = '\0';
if ((directive = strtok_r(line, " \t\r\n\v", &tok)) &&
(value = strtok_r(NULL, " \t\r\n\v", &tok))) {
if ((strcmp(directive, "nameserver") == 0 &&
inet_pton(AF_INET, value, &nameserver.sin_addr.s_addr) == 1) ||
(strcmp(directive, "search") == 0 && strcmp(value, "local") == 0 &&
(nameserver.sin_addr.s_addr = htonl(INADDR_LOOPBACK)))) {
if (append(&resolv->nameservers, &nameserver) != -1) ++rc;
}
}
}
free_s(&line);
return rc | ferror(f);
}

View file

@ -0,0 +1,60 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/dns/dns.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Writes dotted hostname to DNS message wire.
*
* The wire format is basically a sequence of Pascal strings, for each
* label in the name. We only do enough validation to maintain protocol
* invariants.
*
* @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) {
size_t i = 0;
size_t namelen = strlen(name);
if (namelen > DNS_NAME_MAX) return enametoolong();
if (size || namelen) {
if (namelen + 1 > size) return enospc();
buf[0] = '\0';
size_t j = 0;
for (;;) {
size_t k;
for (k = 0; name[j + k] && name[j + k] != '.'; ++k) {
buf[i + k + 1] = name[j + k];
}
if (k) {
if (k > DNS_LABEL_MAX) return enametoolong();
buf[i] = k;
i += k + 1;
}
j += k + 1;
if (!name[j - 1]) {
break;
}
}
buf[i] = '\0';
}
return i;
}

25
libc/dns/resolvconf.h Normal file
View file

@ -0,0 +1,25 @@
#ifndef COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_
#define COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
struct FILE;
struct sockaddr_in;
struct Nameservers {
size_t i, n;
struct sockaddr_in *p;
};
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 *resolv) paramsnonnull();
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_DNS_RESOLVCONF_H_ */

121
libc/dns/resolvedns.c Normal file
View file

@ -0,0 +1,121 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/dns/consts.h"
#include "libc/dns/dns.h"
#include "libc/dns/dnsheader.h"
#include "libc/dns/dnsquestion.h"
#include "libc/dns/resolvconf.h"
#include "libc/mem/mem.h"
#include "libc/rand/rand.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/errfuns.h"
/**
* Queries Domain Name System for address associated with name.
*
* @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
* succeeds, its sin_family and sin_addr fields will be modified
* @param addrsize is the byte size of addr
* @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,
struct sockaddr *addr, uint32_t addrsize) {
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
if (!resolvconf->nameservers.i) return 0;
struct DnsHeader header;
struct DnsQuestion question;
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;
const size_t kMsgMax = 512;
uint8_t *outmsg = NULL;
uint8_t *inmsg = NULL;
size_t msgsize;
int res = -1;
int rc, rc2;
if ((outmsg = malloc(kMsgMax)) && (inmsg = malloc(kMsgMax)) &&
(rc = serializednsheader(outmsg, kMsgMax, header)) != -1 &&
(rc2 = serializednsquestion(outmsg + rc, kMsgMax - rc, question)) != -1) {
msgsize = rc + rc2;
int fd;
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) {
struct DnsHeader response;
if ((rc = recv(fd, inmsg, kMsgMax, 0)) != -1 &&
(rc2 = deserializednsheader(&response, inmsg, rc)) != -1 &&
response.id == header.id) {
res = 0;
if (response.ancount) {
uint8_t *p = inmsg + rc2;
uint8_t *pe = inmsg + rc;
while (p < pe && response.qdcount) {
p += strnlen((char *)p, pe - p) + 1 + 4;
response.qdcount--;
}
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) {
uint16_t rtype, rclass, rdlength;
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) {
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr.s_addr, p, 4);
} else {
res = einval();
}
}
}
}
}
}
}
}
res |= close(fd);
}
free(outmsg);
return res;
}

View file

@ -0,0 +1,69 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/dns/consts.h"
#include "libc/dns/dns.h"
#include "libc/dns/hoststxt.h"
#include "libc/sock/sock.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
#include "libc/sysv/consts/af.h"
static int hoststxtgetcmp(const char *node, const struct HostsTxtEntry *entry,
const char *strings) {
return dnsnamecmp(node, &strings[entry->name]);
}
/**
* Finds address associated with name in HOSTS.TXT table.
*
* This function performs binary search, so sorthoststxt() must be
* called on the table beforehand.
*
* @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
* succeeds, its sin_family and sin_addr fields will be modified
* @param addrsize is the byte size of addr
* @param canon be used to return a pointer to the canonical name
* @return number of matches found, or -1 w/ errno
* @error EAFNOSUPPORT
*/
int resolvehoststxt(const struct HostsTxt *ht, int af, const char *name,
struct sockaddr *addr, uint32_t addrsize,
const char **canon) {
if (af != AF_INET && af != AF_UNSPEC) return eafnosupport();
struct HostsTxtEntry *entry = bsearch_r(
name, ht->entries.p, ht->entries.i, sizeof(struct HostsTxtEntry),
(void *)hoststxtgetcmp, ht->strings.p);
if (entry) {
if (addr) {
if (addrsize < kMinSockaddr4Size) return einval();
struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
addr4->sin_family = AF_INET;
memcpy(&addr4->sin_addr.s_addr, &entry->ip[0], 4);
}
if (canon) *canon = &ht->strings.p[entry->canon];
return 1;
} else {
return 0;
}
}

59
libc/dns/rfc0226.txt Normal file
View file

@ -0,0 +1,59 @@
NETWORK WORKING GROUP PEGGY KARP
REQUEST FOR COMMENTS #226 MITRE
NIC #7625 20 SEPT 71
CATEGORIES: D.3
UPDATES: NONE
OBSOLETES: NONE
STANDARDIZATION OF HOST MNEUMONICS
IN EACH TELNET IMPLEMENTATION, A LIST OF HOST NMEUMONICS IS PROVIDED
FOR THE USER TO INDICATE THE SERVING HOST DESIRED. CURRENTLY, EACH
SITE EMPLOYS THEIR OWN SPECIAL LIST. RATHER THAN REQUIRE THE USER TO
BE COGNIZANT OF THE IDIOSYNCRASIES OF EACH LIST, ESPECIALLY WHEN
CHAINED THROUGH SEVERAL HOSTS VIA TELNET, IT HAS BEEN RECOMMENDED THAT
STANDARD HOST DESIGNATORS BE ADOPTED.
THE FOLLOWING LIST OF SIX CHARACTER DESIGNATORS IS PROPOSED AS THE
STANDARD LIST. REGISTER ANY OBJECTIONS BY 3 OCTOBER TO P. KARP (703)
893-3500 X2391, X2318. AN OFFICIAL POLICY AND IMPLEMENTATION DATE WILL
BE SET ON 8 OCTOBER.
THE LIST:
HOST # DESIGNATOR
1 UCLA
65 UCLA36
2 SRIARC
66 SRIAI
3 UCSB
4 UTAH
6 MULTCS
70 MITDM
7 RAND
8 SDC
9 HARV
10 LNCTX2
74 LNC360
11 STAN
12 ILL
69 BBN
133 BBNB
144 AMES
145 MITRE
158 TIP
[ This RFC was put into machine readable form for entry ]
[ into the online RFC archives by BBN Corp. under the ]
[ direction of Alex McKenzie. 12/96 ]
[Page 1]

222
libc/dns/rfc0247.txt Normal file
View file

@ -0,0 +1,222 @@
Network Working Group Peggy Karp
Request for Comments: #247 MITRE
NIC 7688 12 October 1971
Categories: Policy, Telnet
Related: #226, 236, 239, 233, 237
Obsoletes: #226
Proferred Set of Standard Host Names
In RFC #226, BBN's TENEX list of Host names was set up as a strawman
set of standard Host names. Comments received since then (an RFC
actually generated comments!!!) have influenced me to propose the
following general rules for forming Host names.
The Host names will be 8 characters in length. The general form is
<site> '-' <machine>
<site> will be at most 4 characters, formed as follows:
(a) Use the keyword in the site name, if not more than
four characters, e.g., NASA Ames, Case Western
Reserve. ---- ----
(b) Use the standard acronym, if not more than four
characters, e.g., UCLA, RADC, NBS.
(c) If a standard abbreviation exists, use it, e.g., Ill.
(d) If none of the above apply, use the first four letters
in the site name, e.g., Burr, Mitr, Harv.
(e) If none of the above is acceptable to the site, the
technical liaison should select the site mnemonic.
<machine> will be at most 4 characters of the form <mfg. #>
<designator>.
Examples of mfg. # are:
IBM 360 2 digit model number
IBM 370 3 digit model number
PDP 1 - 2 digit model number
Burroughs 4 digits
CDC 4 digits
etc.
[Page 1]
RFC #247
<designator> will be used when more than one machine of the same
type is located at a site (e.g., 2 PDP-10s at MIT, at SRI, and
at BBN).
Limiting <machine> to 4 characters does not permit distinctions
to be made between machines with 4 digit mfg. #s. I expect
the situation will be handled in an ad hoc manner by the NIC if
it arises.
TIPs are identified as 'TIP' rather than by '316'. If a Host
is not to be permanently addressable, the machine is identified
as 'TEST'.
A list of Host names, formed according to these rules, is
attached. Alternate Host names should be provided, as
suggested by Jon Postel (RFC #236). RFC's 206, 233, and
236 present lists with 4-character alternate names. The
Technical Liaison should select the alternate name for his
site and communicate the selection to the NIC.
The preceding rules and the attached list of Host names are
subject to the approval of the NWG. Hereafter, the list will
be generated and maintained by the NIC in cooperation with
the Technical Liaison at each site, as suggested in RFC #237.
Comments should be addressed to Dick Watson.
[ This RFC was put into machine readable form for entry ]
[ into the online RFC archives by BBN Corp. under the ]
[ direction of Alex McKenzie. 12/96 ]
[Page 2]
RFC #247
Attachment 1
NETWORK ADDRESS STANDARD NAME
--------------- -------------
1 UCLA-7
65 UCLA-91
2 SRI-10NI
66 SRI-10AI
3 UCSB-75
4 UTAH-10
5 BBN-516
69 BBN-10A
133 BBN-10B
6 MIT-645
70 MIT-10DM
134 MIT-10AI
7 RAND-65
71 RAND-10
8 SDC-75
9 HARV-10
73 HARV-1
137 HARV-11
10 LL-67
74 LL-TX2
138 LL-TSP
11 SAIL-10
12 ILL-11
76 ILL-6500
13 CASE-10
14 CMU-10
15 BURR-6500
79 BURR-TEST
16 AMES-67
144 AMES-TIP
145 MITR-TIP
18 RADC-645
146 RADC-TIP
19 NBS-11
147 NBS-TIP
148 ETAC-TIP
21 TINK-418
22 MCCL-418
23 USC-44
151 USC-TIP
152 GWC-TIP
25 NCAR-7600
153 NCAR-TIP
158 BBNX-TEST
[Page 3]
RFC #247
Attachment 2
An Implementation Scheme
If the standard Host names are formed according to the proposed
rules, the following implementation scheme, suggested by Steve
Crocker, can be used.
Map <site> into an 8-bit number, S and
map <machine> into an 8-bit number, M,
where
S + M = Network Address.
S and M can be selected such that specification of <site>
alone could cause a default to the "primary" Host at
the site. Note that this scheme depends on a unique
<site> designator for each IMP.
Some examples:
If the "primary" Host at UCLA is the 91, let
UCLA -> S = X'41'
7 -> M = X'40'
91 -> M = X'00'
then for
UCLA-7, S + M = X'01' = 1 base 10
UCLA-91,S + M = X'41' = 65 base 10
and
UCLA alone = X'41' = 65 base 10
If the primary Host at BBN is TENEX System A, let
BBN -> S = X'45'
516 -> M = X'40'
10A -> M = X'00'
10B -> M = X'C0'
then for
BBN-516, S + M = X'05' = 5 base 10
BBN-10A, S + M = X'45' = 69 base 10
BBN-10B, S + M = X'85' = 133 base 10
and
BBN alone = X'45' = 69 base 10
The primary Host for each IMP would be designated by the
site and such information disseminated by the NIC.
[Page 4]

3077
libc/dns/rfc1035.txt Normal file

File diff suppressed because it is too large Load diff

49
libc/dns/sorthoststxt.c Normal file
View file

@ -0,0 +1,49 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/alg.h"
#include "libc/dns/dns.h"
#include "libc/dns/hoststxt.h"
/**
* Compares hostnames in HOSTS.TXT table.
* @see dnsnamecmp(), 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]);
}
/**
* Sorts entries in HOSTS.TXT table.
*
* 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.
*/
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);
}
}