Add libresolv from Musl Libc

Locally modified to get nameservers from Windows Registry when
`\etc\resolv.conf` isn't defined.
This commit is contained in:
Justine Tunney 2023-12-08 20:03:03 -08:00
parent 8874a37abc
commit 1a96de6eda
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
36 changed files with 2313 additions and 73 deletions

View file

@ -208,20 +208,20 @@ include libc/log/BUILD.mk # │
include third_party/getopt/BUILD.mk # │
include third_party/bzip2/BUILD.mk # │
include dsp/core/BUILD.mk # │
include third_party/musl/BUILD.mk # │
include libc/x/BUILD.mk # │
include third_party/stb/BUILD.mk # │
include dsp/scale/BUILD.mk # │
include dsp/mpeg/BUILD.mk # │
include dsp/BUILD.mk # │
include third_party/zlib/gz/BUILD.mk # │
include third_party/intel/BUILD.mk # │
include third_party/aarch64/BUILD.mk # │
include libc/BUILD.mk #─┘
include libc/sock/BUILD.mk #─┐
include dsp/tty/BUILD.mk # ├──ONLINE RUNTIME
include libc/dns/BUILD.mk # │ You can communicate with the network
include net/http/BUILD.mk # │
include libc/dns/BUILD.mk # ├──ONLINE RUNTIME
include net/http/BUILD.mk # │ You can communicate with the network
include third_party/musl/BUILD.mk # │
include libc/x/BUILD.mk # │
include dsp/scale/BUILD.mk # │
include dsp/mpeg/BUILD.mk # │
include dsp/tty/BUILD.mk # │
include dsp/BUILD.mk # │
include third_party/stb/BUILD.mk # │
include third_party/mbedtls/BUILD.mk # │
include third_party/libcxx/BUILD.mk # │
include third_party/ggml/BUILD.mk # │

View file

@ -14,6 +14,7 @@ libc/isystem/arm_bf16.h \
libc/isystem/arm_fp16.h \
libc/isystem/arm_neon.h \
libc/isystem/arpa/inet.h \
libc/isystem/arpa/nameser.h \
libc/isystem/array \
libc/isystem/assert.h \
libc/isystem/atomic \
@ -98,6 +99,7 @@ libc/isystem/langinfo.h \
libc/isystem/libgen.h \
libc/isystem/limits \
libc/isystem/limits.h \
libc/isystem/link.h \
libc/isystem/linux/futex.h \
libc/isystem/linux/limits.h \
libc/isystem/linux/param.h \
@ -154,6 +156,7 @@ libc/isystem/random \
libc/isystem/ratio \
libc/isystem/regex \
libc/isystem/regex.h \
libc/isystem/resolv.h \
libc/isystem/sched.h \
libc/isystem/scoped_allocator \
libc/isystem/search.h \

View file

@ -16,9 +16,11 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dns/dns.h"
#include "libc/dns/ent.h"
/**
* Error number global for gethostbyname*(), gethostbyaddr*(), etc.
*/
int h_errno;
// error number global for gethostbyname*(), gethostbyaddr*(), etc.
static _Thread_local int __h_errno;
errno_t *__h_errno_location(void) {
return &__h_errno;
}

View file

@ -15,14 +15,12 @@ char *dlerror(void);
void *dlopen(const char *, int);
void *dlsym(void *, const char *);
int dlclose(void *);
int dl_iterate_phdr(int (*)(void *, size_t, void *), void *);
#ifdef _COSMO_SOURCE
char *cosmo_dlerror(void);
void *cosmo_dlopen(const char *, int);
void *cosmo_dlsym(void *, const char *);
int cosmo_dlclose(void *);
int cosmo_dl_iterate_phdr(int (*)(void *, size_t, void *), void *);
#endif
COSMOPOLITAN_C_END_

View file

@ -39,7 +39,9 @@ struct servent {
char *s_proto; /* protocol to use */
};
extern int h_errno;
#define h_errno (*__h_errno_location())
errno_t *__h_errno_location(void) dontthrow pureconst;
void herror(const char *);
const char *hstrerror(int);

View file

@ -5,7 +5,7 @@
#define SYSDEBUG 0
#endif
#define _NTTRACE 0 /* not configurable w/ flag yet */
#define _NTTRACE 1 /* not configurable w/ flag yet */
#define _POLLTRACE 0 /* not configurable w/ flag yet */
#define _DATATRACE 1 /* not configurable w/ flag yet */
#define _LOCKTRACE 0 /* not configurable w/ flag yet */

View file

@ -46,7 +46,7 @@ textwindows int WSARecv(
// be NULL only if the lpOverlapped parameter is not NULL.
unassert(!opt_out_lpNumberOfBytesRecvd);
}
#if defined(SYSDEBUG) && _NTTRACE
#if SYSDEBUG && _NTTRACE
uint32_t NumberOfBytesRecvd;
if (opt_out_lpNumberOfBytesRecvd) {
NumberOfBytesRecvd = *opt_out_lpNumberOfBytesRecvd;

View file

@ -22,6 +22,7 @@
#include "libc/intrin/kprintf.h"
#include "libc/intrin/likely.h"
#include "libc/intrin/strace.internal.h"
#include "libc/nt/runtime.h"
#include "libc/nt/thunk/msabi.h"
#include "libc/nt/winsock.h"
#include "libc/runtime/runtime.h"
@ -39,7 +40,7 @@ textwindows int WSARecvFrom(
struct NtOverlapped *opt_inout_lpOverlapped,
const NtWsaOverlappedCompletionRoutine opt_lpCompletionRoutine) {
int rc;
#if defined(SYSDEBUG) && _NTTRACE
#if SYSDEBUG && _NTTRACE
uint32_t NumberOfBytesRecvd;
if (opt_out_lpNumberOfBytesRecvd) {
NumberOfBytesRecvd = *opt_out_lpNumberOfBytesRecvd;
@ -55,10 +56,10 @@ textwindows int WSARecvFrom(
kprintf(STRACE_PROLOGUE "WSARecvFrom(%lu, [", s);
DescribeIovNt(inout_lpBuffers, dwBufferCount,
rc != -1 ? NumberOfBytesRecvd : 0);
kprintf("], %u, [%'u], %p, %p, %p, %s, %p) → %d% lm\n", dwBufferCount,
kprintf("], %u, [%'u], %p, %p, %p, %s, %p) → %d %d\n", dwBufferCount,
NumberOfBytesRecvd, opt_out_fromsockaddr, opt_inout_fromsockaddrlen,
inout_lpFlags, DescribeNtOverlapped(opt_inout_lpOverlapped),
opt_lpCompletionRoutine, rc);
opt_lpCompletionRoutine, rc, GetLastError());
}
#else
rc = __imp_WSARecvFrom(s, inout_lpBuffers, dwBufferCount,

View file

@ -0,0 +1,4 @@
#ifndef _ARPA_NAMESER_H
#define _ARPA_NAMESER_H
#include "third_party/musl/nameser.h"
#endif /* _ARPA_NAMESER_H */

View file

@ -1,6 +1,7 @@
#ifndef COSMOPOLITAN_LIBC_ISYSTEM_NETINET_IN_H_
#define COSMOPOLITAN_LIBC_ISYSTEM_NETINET_IN_H_
#include "libc/calls/weirdtypes.h"
#include "libc/sock/in.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/in6_pktinfo.h"
#include "libc/sock/struct/in_pktinfo.h"
@ -17,46 +18,4 @@
#include "libc/sysv/consts/mcast.h"
#include "libc/sysv/consts/pf.h"
#include "libc/sysv/consts/sock.h"
# define IN6_ARE_ADDR_EQUAL(a,b) \
((((const uint32_t *) (a))[0] == ((const uint32_t *) (b))[0]) \
&& (((const uint32_t *) (a))[1] == ((const uint32_t *) (b))[1]) \
&& (((const uint32_t *) (a))[2] == ((const uint32_t *) (b))[2]) \
&& (((const uint32_t *) (a))[3] == ((const uint32_t *) (b))[3]))
# define IN6_IS_ADDR_UNSPECIFIED(a) \
(((const uint32_t *) (a))[0] == 0 \
&& ((const uint32_t *) (a))[1] == 0 \
&& ((const uint32_t *) (a))[2] == 0 \
&& ((const uint32_t *) (a))[3] == 0)
# define IN6_IS_ADDR_LOOPBACK(a) \
(((const uint32_t *) (a))[0] == 0 \
&& ((const uint32_t *) (a))[1] == 0 \
&& ((const uint32_t *) (a))[2] == 0 \
&& ((const uint32_t *) (a))[3] == htonl (1))
# define IN6_IS_ADDR_LINKLOCAL(a) \
((((const uint32_t *) (a))[0] & htonl (0xffc00000)) \
== htonl (0xfe800000))
# define IN6_IS_ADDR_SITELOCAL(a) \
((((const uint32_t *) (a))[0] & htonl (0xffc00000)) \
== htonl (0xfec00000))
# define IN6_IS_ADDR_V4MAPPED(a) \
((((const uint32_t *) (a))[0] == 0) \
&& (((const uint32_t *) (a))[1] == 0) \
&& (((const uint32_t *) (a))[2] == htonl (0xffff)))
# define IN6_IS_ADDR_V4COMPAT(a) \
((((const uint32_t *) (a))[0] == 0) \
&& (((const uint32_t *) (a))[1] == 0) \
&& (((const uint32_t *) (a))[2] == 0) \
&& (ntohl (((const uint32_t *) (a))[3]) > 1))
#define IN6_IS_ADDR_MULTICAST(a) (((const uint8_t *) (a))[0] == 0xff)
#endif /* COSMOPOLITAN_LIBC_ISYSTEM_NETINET_IN_H_ */

5
libc/isystem/resolv.h Normal file
View file

@ -0,0 +1,5 @@
#ifndef _RESOLV_H
#define _RESOLV_H
#include "third_party/musl/nameser.h"
#include "third_party/musl/resolv.h"
#endif /* _RESOLV_H */

71
libc/sock/in.h Normal file
View file

@ -0,0 +1,71 @@
#ifndef COSMOPOLITAN_LIBC_SOCK_IN_H_
#define COSMOPOLITAN_LIBC_SOCK_IN_H_
#include "libc/sock/sock.h"
#define IN_CLASSA(a) ((((in_addr_t)(a)) & 0x80000000) == 0)
#define IN_CLASSA_NET 0xff000000
#define IN_CLASSA_NSHIFT 24
#define IN_CLASSA_HOST (0xffffffff & ~IN_CLASSA_NET)
#define IN_CLASSA_MAX 128
#define IN_CLASSB(a) ((((in_addr_t)(a)) & 0xc0000000) == 0x80000000)
#define IN_CLASSB_NET 0xffff0000
#define IN_CLASSB_NSHIFT 16
#define IN_CLASSB_HOST (0xffffffff & ~IN_CLASSB_NET)
#define IN_CLASSB_MAX 65536
#define IN_CLASSC(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xc0000000)
#define IN_CLASSC_NET 0xffffff00
#define IN_CLASSC_NSHIFT 8
#define IN_CLASSC_HOST (0xffffffff & ~IN_CLASSC_NET)
#define IN_CLASSD(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xe0000000)
#define IN_MULTICAST(a) IN_CLASSD(a)
#define IN_EXPERIMENTAL(a) ((((in_addr_t)(a)) & 0xe0000000) == 0xe0000000)
#define IN_BADCLASS(a) ((((in_addr_t)(a)) & 0xf0000000) == 0xf0000000)
#define IN6_IS_ADDR_UNSPECIFIED(a) \
(((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
((uint32_t *)(a))[2] == 0 && ((uint32_t *)(a))[3] == 0)
#define IN6_IS_ADDR_LOOPBACK(a) \
(((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
((uint32_t *)(a))[2] == 0 && ((uint8_t *)(a))[12] == 0 && \
((uint8_t *)(a))[13] == 0 && ((uint8_t *)(a))[14] == 0 && \
((uint8_t *)(a))[15] == 1)
#define IN6_IS_ADDR_MULTICAST(a) (((uint8_t *)(a))[0] == 0xff)
#define IN6_IS_ADDR_LINKLOCAL(a) \
((((uint8_t *)(a))[0]) == 0xfe && (((uint8_t *)(a))[1] & 0xc0) == 0x80)
#define IN6_IS_ADDR_SITELOCAL(a) \
((((uint8_t *)(a))[0]) == 0xfe && (((uint8_t *)(a))[1] & 0xc0) == 0xc0)
#define IN6_IS_ADDR_V4MAPPED(a) \
(((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
((uint8_t *)(a))[8] == 0 && ((uint8_t *)(a))[9] == 0 && \
((uint8_t *)(a))[10] == 0xff && ((uint8_t *)(a))[11] == 0xff)
#define IN6_IS_ADDR_V4COMPAT(a) \
(((uint32_t *)(a))[0] == 0 && ((uint32_t *)(a))[1] == 0 && \
((uint32_t *)(a))[2] == 0 && ((uint8_t *)(a))[15] > 1)
#define IN6_IS_ADDR_MC_NODELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *)(a))[1] & 0xf) == 0x1))
#define IN6_IS_ADDR_MC_LINKLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *)(a))[1] & 0xf) == 0x2))
#define IN6_IS_ADDR_MC_SITELOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *)(a))[1] & 0xf) == 0x5))
#define IN6_IS_ADDR_MC_ORGLOCAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *)(a))[1] & 0xf) == 0x8))
#define IN6_IS_ADDR_MC_GLOBAL(a) \
(IN6_IS_ADDR_MULTICAST(a) && ((((uint8_t *)(a))[1] & 0xf) == 0xe))
#define __ARE_4_EQUAL(a, b) \
(!((0 [a] - 0 [b]) | (1 [a] - 1 [b]) | (2 [a] - 2 [b]) | (3 [a] - 3 [b])))
#define IN6_ARE_ADDR_EQUAL(a, b) \
__ARE_4_EQUAL((const uint32_t *)(a), (const uint32_t *)(b))
#endif /* COSMOPOLITAN_LIBC_SOCK_IN_H_ */

View file

@ -23,6 +23,7 @@
#include "libc/nt/struct/iovec.h"
#include "libc/nt/winsock.h"
#include "libc/sock/internal.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/sock/syscall_fd.internal.h"
#include "libc/sysv/consts/msg.h"
#include "libc/sysv/consts/o.h"

View file

@ -23,6 +23,10 @@
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/iovec.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/sock/struct/msghdr.h"
#include "libc/sock/struct/msghdr.internal.h"
@ -99,12 +103,12 @@ ssize_t recvmsg(int fd, struct msghdr *msg, int flags) {
}
END_CANCELATION_POINT;
#if defined(SYSDEBUG) && _DATATRACE
#if SYSDEBUG && _DATATRACE
if (__strace > 0 && strace_enabled(0) > 0) {
if (!msg || (rc == -1 && errno == EFAULT)) {
DATATRACE("recvmsg(%d, %p, %#x) → %'ld% m", fd, msg, flags, rc);
} else {
kprintf(STRACE_PROLOGUE "recvmsg(%d, [{");
kprintf(STRACE_PROLOGUE "recvmsg(%d, [{", fd);
if (msg->msg_namelen)
kprintf(".name=%#.*hhs, ", msg->msg_namelen, msg->msg_name);
if (msg->msg_controllen)

View file

@ -87,10 +87,10 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags) {
}
END_CANCELATION_POINT;
#if defined(SYSDEBUG) && _DATATRACE
#if SYSDEBUG && _DATATRACE
// TODO(jart): Write a DescribeMsg() function.
if (strace_enabled(0) > 0) {
kprintf(STRACE_PROLOGUE "sendmsg(");
kprintf(STRACE_PROLOGUE "sendmsg(%d, ", fd);
if ((!IsAsan() && kisdangerous(msg)) ||
(IsAsan() && !__asan_is_valid(msg, sizeof(*msg)))) {
kprintf("%p", msg);

View file

@ -16,16 +16,18 @@ struct ifreq {
struct sockaddr ifru_netmask; /* SIOCGIFNETMASK */
struct sockaddr ifru_broadaddr; /* SIOCGIFBRDADDR */
short ifru_flags; /* SIOCGIFFLAGS */
int ifru_ivalue; /* todo(jart) */
char ifru_pad[24]; /* ifru_map is the largest, just pad */
} ifr_ifru;
};
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_netmask ifr_ifru.ifru_netmask /* netmask */
#define ifr_name ifr_ifrn.ifrn_name /* interface name */
#define ifr_addr ifr_ifru.ifru_addr /* address */
#define ifr_netmask ifr_ifru.ifru_netmask /* netmask */
#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* destination address */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* destination address */
#define ifr_flags ifr_ifru.ifru_flags /* flags */
#define ifr_ifindex ifr_ifru.ifru_ivalue
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_LIBC_SOCK_STRUCT_IFREQ_H_ */

View file

@ -22,8 +22,10 @@ THIRD_PARTY_MUSL_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_MEM \
LIBC_NEXGEN32E \
LIBC_NT_ADVAPI32 \
LIBC_PROC \
LIBC_RUNTIME \
LIBC_SOCK \
LIBC_STDIO \
LIBC_STR \
LIBC_SYSV \

139
third_party/musl/dn_comp.c vendored Normal file
View file

@ -0,0 +1,139 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/musl/resolv.h"
#include "libc/str/str.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
/* RFC 1035 message compression */
/* label start offsets of a compressed domain name s */
static int getoffs(short *offs, const unsigned char *base, const unsigned char *s)
{
int i=0;
for (;;) {
while (*s & 0xc0) {
if ((*s & 0xc0) != 0xc0) return 0;
s = base + ((s[0]&0x3f)<<8 | s[1]);
}
if (!*s) return i;
if (s-base >= 0x4000) return 0;
offs[i++] = s-base;
s += *s + 1;
}
}
/* label lengths of an ascii domain name s */
static int getlens(unsigned char *lens, const char *s, int l)
{
int i=0,j=0,k=0;
for (;;) {
for (; j<l && s[j]!='.'; j++);
if (j-k-1u > 62) return 0;
lens[i++] = j-k;
if (j==l) return i;
k = ++j;
}
}
/* longest suffix match of an ascii domain with a compressed domain name dn */
static int match(int *offset, const unsigned char *base, const unsigned char *dn,
const char *end, const unsigned char *lens, int nlen)
{
int l, o, m=0;
short offs[128];
int noff = getoffs(offs, base, dn);
if (!noff) return 0;
for (;;) {
l = lens[--nlen];
o = offs[--noff];
end -= l;
if (l != base[o] || memcmp(base+o+1, end, l))
return m;
*offset = o;
m += l;
if (nlen) m++;
if (!nlen || !noff) return m;
end--;
}
}
int dn_comp(const char *src, unsigned char *dst, int space, unsigned char **dnptrs, unsigned char **lastdnptr)
{
int i, j, n, m=0, offset, bestlen=0, bestoff;
unsigned char lens[127];
unsigned char **p;
const char *end;
size_t l = strnlen(src, 255);
if (l && src[l-1] == '.') l--;
if (l>253 || space<=0) return -1;
if (!l) {
*dst = 0;
return 1;
}
end = src+l;
n = getlens(lens, src, l);
if (!n) return -1;
p = dnptrs;
if (p && *p) for (p++; *p; p++) {
m = match(&offset, *dnptrs, *p, end, lens, n);
if (m > bestlen) {
bestlen = m;
bestoff = offset;
if (m == l)
break;
}
}
/* encode unmatched part */
if (space < l-bestlen+2+(bestlen-1 < l-1)) return -1;
memcpy(dst+1, src, l-bestlen);
for (i=j=0; i<l-bestlen; i+=lens[j++]+1)
dst[i] = lens[j];
/* add tail */
if (bestlen) {
dst[i++] = 0xc0 | bestoff>>8;
dst[i++] = bestoff;
} else
dst[i++] = 0;
/* save dst pointer */
if (i>2 && lastdnptr && dnptrs && *dnptrs) {
while (*p) p++;
if (p+1 < lastdnptr) {
*p++ = dst;
*p=0;
}
}
return i;
}

65
third_party/musl/dn_expand.c vendored Normal file
View file

@ -0,0 +1,65 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/musl/resolv.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int __dn_expand(const unsigned char *base, const unsigned char *end, const unsigned char *src, char *dest, int space)
{
const unsigned char *p = src;
char *dend, *dbegin = dest;
int len = -1, i, j;
if (p==end || space <= 0) return -1;
dend = dest + (space > 254 ? 254 : space);
/* detect reference loop using an iteration counter */
for (i=0; i < end-base; i+=2) {
/* loop invariants: p<end, dest<dend */
if (*p & 0xc0) {
if (p+1==end) return -1;
j = ((p[0] & 0x3f) << 8) | p[1];
if (len < 0) len = p+2-src;
if (j >= end-base) return -1;
p = base+j;
} else if (*p) {
if (dest != dbegin) *dest++ = '.';
j = *p++;
if (j >= end-p || j >= dend-dest) return -1;
while (j--) *dest++ = *p++;
} else {
*dest = 0;
if (len < 0) len = p+1-src;
return len;
}
}
return -1;
}
__weak_reference(__dn_expand, dn_expand);

47
third_party/musl/dn_skipname.c vendored Normal file
View file

@ -0,0 +1,47 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "third_party/musl/resolv.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int dn_skipname(const unsigned char *s, const unsigned char *end)
{
const unsigned char *p = s;
while (p < end)
if (!*p) return p-s+1;
else if (*p>=192)
if (p+1<end) return p-s+2;
else break;
else
if (end-p<*p+1) break;
else p += *p + 1;
return -1;
}

52
third_party/musl/lookup.internal.h vendored Normal file
View file

@ -0,0 +1,52 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_LOOKUP_INTERNAL_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_LOOKUP_INTERNAL_H_
#include "libc/sock/struct/sockaddr6.h"
#include "libc/sock/struct/sockaddr.h"
#include "libc/dns/dns.h"
COSMOPOLITAN_C_START_
struct aibuf {
struct addrinfo ai;
union sa {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa;
volatile int lock[1];
short slot, ref;
};
struct address {
int family;
unsigned scopeid;
uint8_t addr[16];
int sortkey;
};
struct service {
uint16_t port;
unsigned char proto, socktype;
};
#define MAXNS 3
struct resolvconf {
struct address ns[MAXNS];
unsigned nns, attempts, ndots;
unsigned timeout;
};
/* The limit of 48 results is a non-sharp bound on the number of addresses
* that can fit in one 512-byte DNS packet full of v4 results and a second
* packet full of v6 results. Due to headers, the actual limit is lower. */
#define MAXADDRS 48
#define MAXSERVS 2
int __lookup_serv(struct service buf[static MAXSERVS], const char *name, int proto, int socktype, int flags);
int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags);
int __lookup_ipliteral(struct address buf[static 1], const char *name, int family);
int __get_resolv_conf(struct resolvconf *, char *, size_t);
int __res_msend_rc(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int, const struct resolvconf *);
int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *, int), void *);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_LOOKUP_INTERNAL_H_ */

90
third_party/musl/lookup_ipliteral.c vendored Normal file
View file

@ -0,0 +1,90 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/sock/struct/sockaddr.h"
#include "libc/sysv/consts/af.h"
#include "libc/str/str.h"
#include "libc/fmt/conv.h"
#include "libc/limits.h"
#include "third_party/musl/lookup.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int __lookup_ipliteral(struct address buf[static 1], const char *name, int family)
{
struct in_addr a4;
struct in6_addr a6;
if (inet_aton(name, &a4) > 0) {
if (family == AF_INET6) /* wrong family */
return EAI_NODATA;
memcpy(&buf[0].addr, &a4, sizeof a4);
buf[0].family = AF_INET;
buf[0].scopeid = 0;
return 1;
}
char tmp[64];
char *p = strchr(name, '%'), *z;
unsigned long long scopeid = 0;
if (p && p-name < 64) {
memcpy(tmp, name, p-name);
tmp[p-name] = 0;
name = tmp;
}
if (inet_pton(AF_INET6, name, &a6) <= 0)
return 0;
if (family == AF_INET) /* wrong family */
return EAI_NODATA;
memcpy(&buf[0].addr, &a6, sizeof a6);
buf[0].family = AF_INET6;
if (p) {
if (isdigit(*++p)) scopeid = strtoull(p, &z, 10);
else z = p-1;
if (*z) {
#if 1
// todo(jart): do something
return EAI_NONAME;
#else
if (!IN6_IS_ADDR_LINKLOCAL(&a6) &&
!IN6_IS_ADDR_MC_LINKLOCAL(&a6))
return EAI_NONAME;
scopeid = if_nametoindex(p);
if (!scopeid)
return EAI_NONAME;
#endif
}
if (scopeid > UINT_MAX)
return EAI_NONAME;
}
buf[0].scopeid = scopeid;
return 1;
}

446
third_party/musl/nameser.h vendored Normal file
View file

@ -0,0 +1,446 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_NAMESER_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_NAMESER_H_
COSMOPOLITAN_C_START_
#define __NAMESER 19991006
#define NS_PACKETSZ 512
#define NS_MAXDNAME 1025
#define NS_MAXMSG 65535
#define NS_MAXCDNAME 255
#define NS_MAXLABEL 63
#define NS_HFIXEDSZ 12
#define NS_QFIXEDSZ 4
#define NS_RRFIXEDSZ 10
#define NS_INT32SZ 4
#define NS_INT16SZ 2
#define NS_INT8SZ 1
#define NS_INADDRSZ 4
#define NS_IN6ADDRSZ 16
#define NS_CMPRSFLGS 0xc0
#define NS_DEFAULTPORT 53
typedef enum __ns_sect {
ns_s_qd = 0,
ns_s_zn = 0,
ns_s_an = 1,
ns_s_pr = 1,
ns_s_ns = 2,
ns_s_ud = 2,
ns_s_ar = 3,
ns_s_max = 4
} ns_sect;
typedef struct __ns_msg {
const unsigned char *_msg, *_eom;
uint16_t _id, _flags, _counts[ns_s_max];
const unsigned char *_sections[ns_s_max];
ns_sect _sect;
int _rrnum;
const unsigned char *_msg_ptr;
} ns_msg;
struct _ns_flagdata { int mask, shift; };
extern const struct _ns_flagdata _ns_flagdata[];
#define ns_msg_id(handle) ((handle)._id + 0)
#define ns_msg_base(handle) ((handle)._msg + 0)
#define ns_msg_end(handle) ((handle)._eom + 0)
#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
#define ns_msg_getflag(handle, flag) \
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
typedef struct __ns_rr {
char name[NS_MAXDNAME];
uint16_t type;
uint16_t rr_class;
uint32_t ttl;
uint16_t rdlength;
const unsigned char *rdata;
} ns_rr;
#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".")
#define ns_rr_type(rr) ((ns_type)((rr).type + 0))
#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0))
#define ns_rr_ttl(rr) ((rr).ttl + 0)
#define ns_rr_rdlen(rr) ((rr).rdlength + 0)
#define ns_rr_rdata(rr) ((rr).rdata + 0)
typedef enum __ns_flag {
ns_f_qr,
ns_f_opcode,
ns_f_aa,
ns_f_tc,
ns_f_rd,
ns_f_ra,
ns_f_z,
ns_f_ad,
ns_f_cd,
ns_f_rcode,
ns_f_max
} ns_flag;
typedef enum __ns_opcode {
ns_o_query = 0,
ns_o_iquery = 1,
ns_o_status = 2,
ns_o_notify = 4,
ns_o_update = 5,
ns_o_max = 6
} ns_opcode;
typedef enum __ns_rcode {
ns_r_noerror = 0,
ns_r_formerr = 1,
ns_r_servfail = 2,
ns_r_nxdomain = 3,
ns_r_notimpl = 4,
ns_r_refused = 5,
ns_r_yxdomain = 6,
ns_r_yxrrset = 7,
ns_r_nxrrset = 8,
ns_r_notauth = 9,
ns_r_notzone = 10,
ns_r_max = 11,
ns_r_badvers = 16,
ns_r_badsig = 16,
ns_r_badkey = 17,
ns_r_badtime = 18
} ns_rcode;
typedef enum __ns_update_operation {
ns_uop_delete = 0,
ns_uop_add = 1,
ns_uop_max = 2
} ns_update_operation;
struct ns_tsig_key {
char name[NS_MAXDNAME], alg[NS_MAXDNAME];
unsigned char *data;
int len;
};
typedef struct ns_tsig_key ns_tsig_key;
struct ns_tcp_tsig_state {
int counter;
struct dst_key *key;
void *ctx;
unsigned char sig[NS_PACKETSZ];
int siglen;
};
typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
#define NS_TSIG_FUDGE 300
#define NS_TSIG_TCP_COUNT 100
#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
#define NS_TSIG_ERROR_NO_TSIG -10
#define NS_TSIG_ERROR_NO_SPACE -11
#define NS_TSIG_ERROR_FORMERR -12
typedef enum __ns_type {
ns_t_invalid = 0,
ns_t_a = 1,
ns_t_ns = 2,
ns_t_md = 3,
ns_t_mf = 4,
ns_t_cname = 5,
ns_t_soa = 6,
ns_t_mb = 7,
ns_t_mg = 8,
ns_t_mr = 9,
ns_t_null = 10,
ns_t_wks = 11,
ns_t_ptr = 12,
ns_t_hinfo = 13,
ns_t_minfo = 14,
ns_t_mx = 15,
ns_t_txt = 16,
ns_t_rp = 17,
ns_t_afsdb = 18,
ns_t_x25 = 19,
ns_t_isdn = 20,
ns_t_rt = 21,
ns_t_nsap = 22,
ns_t_nsap_ptr = 23,
ns_t_sig = 24,
ns_t_key = 25,
ns_t_px = 26,
ns_t_gpos = 27,
ns_t_aaaa = 28,
ns_t_loc = 29,
ns_t_nxt = 30,
ns_t_eid = 31,
ns_t_nimloc = 32,
ns_t_srv = 33,
ns_t_atma = 34,
ns_t_naptr = 35,
ns_t_kx = 36,
ns_t_cert = 37,
ns_t_a6 = 38,
ns_t_dname = 39,
ns_t_sink = 40,
ns_t_opt = 41,
ns_t_apl = 42,
ns_t_tkey = 249,
ns_t_tsig = 250,
ns_t_ixfr = 251,
ns_t_axfr = 252,
ns_t_mailb = 253,
ns_t_maila = 254,
ns_t_any = 255,
ns_t_zxfr = 256,
ns_t_max = 65536
} ns_type;
#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
(t) == ns_t_mailb || (t) == ns_t_maila)
#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
(t) == ns_t_zxfr)
typedef enum __ns_class {
ns_c_invalid = 0,
ns_c_in = 1,
ns_c_2 = 2,
ns_c_chaos = 3,
ns_c_hs = 4,
ns_c_none = 254,
ns_c_any = 255,
ns_c_max = 65536
} ns_class;
typedef enum __ns_key_types {
ns_kt_rsa = 1,
ns_kt_dh = 2,
ns_kt_dsa = 3,
ns_kt_private = 254
} ns_key_types;
typedef enum __ns_cert_types {
cert_t_pkix = 1,
cert_t_spki = 2,
cert_t_pgp = 3,
cert_t_url = 253,
cert_t_oid = 254
} ns_cert_types;
#define NS_KEY_TYPEMASK 0xC000
#define NS_KEY_TYPE_AUTH_CONF 0x0000
#define NS_KEY_TYPE_CONF_ONLY 0x8000
#define NS_KEY_TYPE_AUTH_ONLY 0x4000
#define NS_KEY_TYPE_NO_KEY 0xC000
#define NS_KEY_NO_AUTH 0x8000
#define NS_KEY_NO_CONF 0x4000
#define NS_KEY_RESERVED2 0x2000
#define NS_KEY_EXTENDED_FLAGS 0x1000
#define NS_KEY_RESERVED4 0x0800
#define NS_KEY_RESERVED5 0x0400
#define NS_KEY_NAME_TYPE 0x0300
#define NS_KEY_NAME_USER 0x0000
#define NS_KEY_NAME_ENTITY 0x0200
#define NS_KEY_NAME_ZONE 0x0100
#define NS_KEY_NAME_RESERVED 0x0300
#define NS_KEY_RESERVED8 0x0080
#define NS_KEY_RESERVED9 0x0040
#define NS_KEY_RESERVED10 0x0020
#define NS_KEY_RESERVED11 0x0010
#define NS_KEY_SIGNATORYMASK 0x000F
#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
NS_KEY_RESERVED4 | \
NS_KEY_RESERVED5 | \
NS_KEY_RESERVED8 | \
NS_KEY_RESERVED9 | \
NS_KEY_RESERVED10 | \
NS_KEY_RESERVED11 )
#define NS_KEY_RESERVED_BITMASK2 0xFFFF
#define NS_ALG_MD5RSA 1
#define NS_ALG_DH 2
#define NS_ALG_DSA 3
#define NS_ALG_DSS NS_ALG_DSA
#define NS_ALG_EXPIRE_ONLY 253
#define NS_ALG_PRIVATE_OID 254
#define NS_KEY_PROT_TLS 1
#define NS_KEY_PROT_EMAIL 2
#define NS_KEY_PROT_DNSSEC 3
#define NS_KEY_PROT_IPSEC 4
#define NS_KEY_PROT_ANY 255
#define NS_MD5RSA_MIN_BITS 512
#define NS_MD5RSA_MAX_BITS 4096
#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8)
#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8)
#define NS_DSA_SIG_SIZE 41
#define NS_DSA_MIN_SIZE 213
#define NS_DSA_MAX_BYTES 405
#define NS_SIG_TYPE 0
#define NS_SIG_ALG 2
#define NS_SIG_LABELS 3
#define NS_SIG_OTTL 4
#define NS_SIG_EXPIR 8
#define NS_SIG_SIGNED 12
#define NS_SIG_FOOT 16
#define NS_SIG_SIGNER 18
#define NS_NXT_BITS 8
#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
#define NS_NXT_MAX 127
#define NS_OPT_DNSSEC_OK 0x8000U
#define NS_OPT_NSID 3
#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2))
#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4))
#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2)
#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4)
unsigned ns_get16(const unsigned char *);
unsigned long ns_get32(const unsigned char *);
void ns_put16(unsigned, unsigned char *);
void ns_put32(unsigned long, unsigned char *);
int ns_initparse(const unsigned char *, int, ns_msg *);
int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int);
int ns_name_uncompress(const unsigned char *, const unsigned char *, const unsigned char *, char *, size_t);
#define __BIND 19950621
typedef struct {
unsigned id :16;
#if __BYTE_ORDER == __BIG_ENDIAN
unsigned qr: 1;
unsigned opcode: 4;
unsigned aa: 1;
unsigned tc: 1;
unsigned rd: 1;
unsigned ra: 1;
unsigned unused :1;
unsigned ad: 1;
unsigned cd: 1;
unsigned rcode :4;
#else
unsigned rd :1;
unsigned tc :1;
unsigned aa :1;
unsigned opcode :4;
unsigned qr :1;
unsigned rcode :4;
unsigned cd: 1;
unsigned ad: 1;
unsigned unused :1;
unsigned ra :1;
#endif
unsigned qdcount :16;
unsigned ancount :16;
unsigned nscount :16;
unsigned arcount :16;
} HEADER;
#define PACKETSZ NS_PACKETSZ
#define MAXDNAME NS_MAXDNAME
#define MAXCDNAME NS_MAXCDNAME
#define MAXLABEL NS_MAXLABEL
#define HFIXEDSZ NS_HFIXEDSZ
#define QFIXEDSZ NS_QFIXEDSZ
#define RRFIXEDSZ NS_RRFIXEDSZ
#define INT32SZ NS_INT32SZ
#define INT16SZ NS_INT16SZ
#define INT8SZ NS_INT8SZ
#define INADDRSZ NS_INADDRSZ
#define IN6ADDRSZ NS_IN6ADDRSZ
#define INDIR_MASK NS_CMPRSFLGS
#define NAMESERVER_PORT NS_DEFAULTPORT
#define S_ZONE ns_s_zn
#define S_PREREQ ns_s_pr
#define S_UPDATE ns_s_ud
#define S_ADDT ns_s_ar
#define QUERY ns_o_query
#define IQUERY ns_o_iquery
#define STATUS ns_o_status
#define NS_NOTIFY_OP ns_o_notify
#define NS_UPDATE_OP ns_o_update
#define NOERROR ns_r_noerror
#define FORMERR ns_r_formerr
#define SERVFAIL ns_r_servfail
#define NXDOMAIN ns_r_nxdomain
#define NOTIMP ns_r_notimpl
#define REFUSED ns_r_refused
#define YXDOMAIN ns_r_yxdomain
#define YXRRSET ns_r_yxrrset
#define NXRRSET ns_r_nxrrset
#define NOTAUTH ns_r_notauth
#define NOTZONE ns_r_notzone
#define DELETE ns_uop_delete
#define ADD ns_uop_add
#define T_A ns_t_a
#define T_NS ns_t_ns
#define T_MD ns_t_md
#define T_MF ns_t_mf
#define T_CNAME ns_t_cname
#define T_SOA ns_t_soa
#define T_MB ns_t_mb
#define T_MG ns_t_mg
#define T_MR ns_t_mr
#define T_NULL ns_t_null
#define T_WKS ns_t_wks
#define T_PTR ns_t_ptr
#define T_HINFO ns_t_hinfo
#define T_MINFO ns_t_minfo
#define T_MX ns_t_mx
#define T_TXT ns_t_txt
#define T_RP ns_t_rp
#define T_AFSDB ns_t_afsdb
#define T_X25 ns_t_x25
#define T_ISDN ns_t_isdn
#define T_RT ns_t_rt
#define T_NSAP ns_t_nsap
#define T_NSAP_PTR ns_t_nsap_ptr
#define T_SIG ns_t_sig
#define T_KEY ns_t_key
#define T_PX ns_t_px
#define T_GPOS ns_t_gpos
#define T_AAAA ns_t_aaaa
#define T_LOC ns_t_loc
#define T_NXT ns_t_nxt
#define T_EID ns_t_eid
#define T_NIMLOC ns_t_nimloc
#define T_SRV ns_t_srv
#define T_ATMA ns_t_atma
#define T_NAPTR ns_t_naptr
#define T_A6 ns_t_a6
#define T_DNAME ns_t_dname
#define T_TSIG ns_t_tsig
#define T_IXFR ns_t_ixfr
#define T_AXFR ns_t_axfr
#define T_MAILB ns_t_mailb
#define T_MAILA ns_t_maila
#define T_ANY ns_t_any
#define C_IN ns_c_in
#define C_CHAOS ns_c_chaos
#define C_HS ns_c_hs
#define C_NONE ns_c_none
#define C_ANY ns_c_any
#define GETSHORT NS_GET16
#define GETLONG NS_GET32
#define PUTSHORT NS_PUT16
#define PUTLONG NS_PUT32
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_NAMESER_H_ */

201
third_party/musl/ns_parse.c vendored Normal file
View file

@ -0,0 +1,201 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/errno.h"
#include "third_party/musl/resolv.h"
#include "third_party/musl/nameser.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
const struct _ns_flagdata _ns_flagdata[16] = {
{ 0x8000, 15 },
{ 0x7800, 11 },
{ 0x0400, 10 },
{ 0x0200, 9 },
{ 0x0100, 8 },
{ 0x0080, 7 },
{ 0x0040, 6 },
{ 0x0020, 5 },
{ 0x0010, 4 },
{ 0x000f, 0 },
{ 0x0000, 0 },
{ 0x0000, 0 },
{ 0x0000, 0 },
{ 0x0000, 0 },
{ 0x0000, 0 },
{ 0x0000, 0 },
};
unsigned ns_get16(const unsigned char *cp)
{
return cp[0]<<8 | cp[1];
}
unsigned long ns_get32(const unsigned char *cp)
{
return (unsigned)cp[0]<<24 | cp[1]<<16 | cp[2]<<8 | cp[3];
}
void ns_put16(unsigned s, unsigned char *cp)
{
*cp++ = s>>8;
*cp++ = s;
}
void ns_put32(unsigned long l, unsigned char *cp)
{
*cp++ = l>>24;
*cp++ = l>>16;
*cp++ = l>>8;
*cp++ = l;
}
int ns_initparse(const unsigned char *msg, int msglen, ns_msg *handle)
{
int i, r;
handle->_msg = msg;
handle->_eom = msg + msglen;
if (msglen < (2 + ns_s_max) * NS_INT16SZ) goto bad;
NS_GET16(handle->_id, msg);
NS_GET16(handle->_flags, msg);
for (i = 0; i < ns_s_max; i++) NS_GET16(handle->_counts[i], msg);
for (i = 0; i < ns_s_max; i++) {
if (handle->_counts[i]) {
handle->_sections[i] = msg;
r = ns_skiprr(msg, handle->_eom, i, handle->_counts[i]);
if (r < 0) return -1;
msg += r;
} else {
handle->_sections[i] = NULL;
}
}
if (msg != handle->_eom) goto bad;
handle->_sect = ns_s_max;
handle->_rrnum = -1;
handle->_msg_ptr = NULL;
return 0;
bad:
errno = EMSGSIZE;
return -1;
}
int ns_skiprr(const unsigned char *ptr, const unsigned char *eom, ns_sect section, int count)
{
const unsigned char *p = ptr;
int r;
while (count--) {
r = dn_skipname(p, eom);
if (r < 0) goto bad;
if (r + 2 * NS_INT16SZ > eom - p) goto bad;
p += r + 2 * NS_INT16SZ;
if (section != ns_s_qd) {
if (NS_INT32SZ + NS_INT16SZ > eom - p) goto bad;
p += NS_INT32SZ;
NS_GET16(r, p);
if (r > eom - p) goto bad;
p += r;
}
}
return p - ptr;
bad:
errno = EMSGSIZE;
return -1;
}
int ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr)
{
int r;
if (section < 0 || section >= ns_s_max) goto bad;
if (section != handle->_sect) {
handle->_sect = section;
handle->_rrnum = 0;
handle->_msg_ptr = handle->_sections[section];
}
if (rrnum == -1) rrnum = handle->_rrnum;
if (rrnum < 0 || rrnum >= handle->_counts[section]) goto bad;
if (rrnum < handle->_rrnum) {
handle->_rrnum = 0;
handle->_msg_ptr = handle->_sections[section];
}
if (rrnum > handle->_rrnum) {
r = ns_skiprr(handle->_msg_ptr, handle->_eom, section, rrnum - handle->_rrnum);
if (r < 0) return -1;
handle->_msg_ptr += r;
handle->_rrnum = rrnum;
}
r = ns_name_uncompress(handle->_msg, handle->_eom, handle->_msg_ptr, rr->name, NS_MAXDNAME);
if (r < 0) return -1;
handle->_msg_ptr += r;
if (2 * NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
NS_GET16(rr->type, handle->_msg_ptr);
NS_GET16(rr->rr_class, handle->_msg_ptr);
if (section != ns_s_qd) {
if (NS_INT32SZ + NS_INT16SZ > handle->_eom - handle->_msg_ptr) goto size;
NS_GET32(rr->ttl, handle->_msg_ptr);
NS_GET16(rr->rdlength, handle->_msg_ptr);
if (rr->rdlength > handle->_eom - handle->_msg_ptr) goto size;
rr->rdata = handle->_msg_ptr;
handle->_msg_ptr += rr->rdlength;
} else {
rr->ttl = 0;
rr->rdlength = 0;
rr->rdata = NULL;
}
handle->_rrnum++;
if (handle->_rrnum > handle->_counts[section]) {
handle->_sect = section + 1;
if (handle->_sect == ns_s_max) {
handle->_rrnum = -1;
handle->_msg_ptr = NULL;
} else {
handle->_rrnum = 0;
}
}
return 0;
bad:
errno = ENODEV;
return -1;
size:
errno = EMSGSIZE;
return -1;
}
int ns_name_uncompress(const unsigned char *msg, const unsigned char *eom,
const unsigned char *src, char *dst, size_t dstsiz)
{
int r;
r = dn_expand(msg, eom, src, dst, dstsiz);
if (r < 0) errno = EMSGSIZE;
return r;
}

6
third_party/musl/res_init.c vendored Normal file
View file

@ -0,0 +1,6 @@
#include "third_party/musl/resolv.h"
int res_init()
{
return 0;
}

78
third_party/musl/res_mkquery.c vendored Normal file
View file

@ -0,0 +1,78 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/calls/struct/timespec.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/clock.h"
#include "third_party/musl/resolv.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int __res_mkquery(int op, const char *dname, int class, int type,
const unsigned char *data, int datalen,
const unsigned char *newrr, unsigned char *buf, int buflen)
{
int id, i, j;
unsigned char q[280];
struct timespec ts;
size_t l = strnlen(dname, 255);
int n;
if (l && dname[l-1]=='.') l--;
if (l && dname[l-1]=='.') return -1;
n = 17+l+!!l;
if (l>253 || buflen<n || op>15u || class>255u || type>255u)
return -1;
/* Construct query template - ID will be filled later */
memset(q, 0, n);
q[2] = op*8 + 1;
q[3] = 32; /* AD */
q[5] = 1;
memcpy((char *)q+13, dname, l);
for (i=13; q[i]; i=j+1) {
for (j=i; q[j] && q[j] != '.'; j++);
if (j-i-1u > 62u) return -1;
q[i-1] = j-i;
}
q[i+1] = type;
q[i+3] = class;
/* Make a reasonably unpredictable id */
clock_gettime(CLOCK_REALTIME, &ts);
id = (ts.tv_nsec + ts.tv_nsec/65536UL) & 0xffff;
q[0] = id/256;
q[1] = id;
memcpy(buf, q, n);
return n;
}
__weak_reference(__res_mkquery, res_mkquery);

363
third_party/musl/res_msend.c vendored Normal file
View file

@ -0,0 +1,363 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/sock/struct/pollfd.h"
#include "libc/calls/struct/timespec.h"
#include "libc/sysv/consts/clock.h"
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/sock/struct/msghdr.h"
#include "libc/sysv/consts/poll.h"
#include "libc/sysv/consts/tcp.h"
#include "libc/sysv/consts/msg.h"
#include "libc/sysv/consts/af.h"
#include "libc/thread/thread.h"
#include "libc/str/str.h"
#include "libc/calls/weirdtypes.h"
#include "libc/sysv/consts/sock.h"
#include "libc/sysv/consts/ipproto.h"
#include "libc/sysv/consts/ipv6.h"
#include "lookup.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
static void cleanup(void *p)
{
struct pollfd *pfd = p;
for (int i=0; pfd[i].fd >= -1; i++)
if (pfd[i].fd >= 0)
close(pfd[i].fd);
}
static unsigned long mtime()
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0 && errno == ENOSYS)
clock_gettime(CLOCK_REALTIME, &ts);
return (unsigned long)ts.tv_sec * 1000
+ ts.tv_nsec / 1000000;
}
static int start_tcp(struct pollfd *pfd, int family, const void *sa, socklen_t sl, const unsigned char *q, int ql)
{
struct msghdr mh = {
.msg_name = (void *)sa,
.msg_namelen = sl,
.msg_iovlen = 2,
.msg_iov = (struct iovec [2]){
{ .iov_base = (uint8_t[]){ ql>>8, ql }, .iov_len = 2 },
{ .iov_base = (void *)q, .iov_len = ql } }
};
int r;
int fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
pfd->fd = fd;
pfd->events = POLLOUT;
if (!setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
&(int){1}, sizeof(int))) {
r = sendmsg(fd, &mh, MSG_FASTOPEN|MSG_NOSIGNAL);
if (r == ql+2) pfd->events = POLLIN;
if (r >= 0) return r;
if (errno == EINPROGRESS) return 0;
}
r = connect(fd, sa, sl);
if (!r || errno == EINPROGRESS) return 0;
close(fd);
pfd->fd = -1;
return -1;
}
static void step_mh(struct msghdr *mh, size_t n)
{
/* Adjust iovec in msghdr to skip first n bytes. */
while (mh->msg_iovlen && n >= mh->msg_iov->iov_len) {
n -= mh->msg_iov->iov_len;
mh->msg_iov++;
mh->msg_iovlen--;
}
if (!mh->msg_iovlen) return;
mh->msg_iov->iov_base = (char *)mh->msg_iov->iov_base + n;
mh->msg_iov->iov_len -= n;
}
/* Internal contract for __res_msend[_rc]: asize must be >=512, nqueries
* must be sufficiently small to be safe as VLA size. In practice it's
* either 1 or 2, anyway. */
int __res_msend_rc(int nqueries, const unsigned char *const *queries,
const int *qlens, unsigned char *const *answers, int *alens, int asize,
const struct resolvconf *conf)
{
int fd;
int timeout, attempts, retry_interval, servfail_retry = 0;
union {
struct sockaddr_in sin;
struct sockaddr_in6 sin6;
} sa = {0}, ns[MAXNS] = {0};
socklen_t sl = sizeof sa.sin;
int nns = 0;
int family = AF_INET;
int rlen;
int next;
int i, j;
int cs;
struct pollfd pfd[nqueries+2];
int qpos[nqueries], apos[nqueries];
unsigned char alen_buf[nqueries][2];
int r;
unsigned long t0, t1, t2;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
timeout = 1000*conf->timeout;
attempts = conf->attempts;
for (nns=0; nns<conf->nns; nns++) {
const struct address *iplit = &conf->ns[nns];
if (iplit->family == AF_INET) {
memcpy(&ns[nns].sin.sin_addr, iplit->addr, 4);
ns[nns].sin.sin_port = htons(53);
ns[nns].sin.sin_family = AF_INET;
} else {
sl = sizeof sa.sin6;
memcpy(&ns[nns].sin6.sin6_addr, iplit->addr, 16);
ns[nns].sin6.sin6_port = htons(53);
ns[nns].sin6.sin6_scope_id = iplit->scopeid;
ns[nns].sin6.sin6_family = family = AF_INET6;
}
}
/* Get local address and open/bind a socket */
fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
/* Handle case where system lacks IPv6 support */
if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
for (i=0; i<nns && conf->ns[nns].family == AF_INET6; i++);
if (i==nns) {
pthread_setcancelstate(cs, 0);
return -1;
}
fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
family = AF_INET;
sl = sizeof sa.sin;
}
/* Convert any IPv4 addresses in a mixed environment to v4-mapped */
if (fd >= 0 && family == AF_INET6) {
setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
for (i=0; i<nns; i++) {
if (ns[i].sin.sin_family != AF_INET) continue;
memcpy(ns[i].sin6.sin6_addr.s6_addr+12,
&ns[i].sin.sin_addr, 4);
memcpy(ns[i].sin6.sin6_addr.s6_addr,
"\0\0\0\0\0\0\0\0\0\0\xff\xff", 12);
ns[i].sin6.sin6_family = AF_INET6;
ns[i].sin6.sin6_flowinfo = 0;
ns[i].sin6.sin6_scope_id = 0;
}
}
sa.sin.sin_family = family;
if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
if (fd >= 0) close(fd);
pthread_setcancelstate(cs, 0);
return -1;
}
/* Past this point, there are no errors. Each individual query will
* yield either no reply (indicated by zero length) or an answer
* packet which is up to the caller to interpret. */
for (i=0; i<nqueries; i++) pfd[i].fd = -1;
pfd[nqueries].fd = fd;
pfd[nqueries].events = POLLIN;
pfd[nqueries+1].fd = -2;
pthread_cleanup_push(cleanup, pfd);
pthread_setcancelstate(cs, 0);
memset(alens, 0, sizeof *alens * nqueries);
retry_interval = timeout / attempts;
next = 0;
t0 = t2 = mtime();
t1 = t2 - retry_interval;
for (; t2-t0 < timeout; t2=mtime()) {
/* This is the loop exit condition: that all queries
* have an accepted answer. */
for (i=0; i<nqueries && alens[i]>0; i++);
if (i==nqueries) break;
if (t2-t1 >= retry_interval) {
/* Query all configured namservers in parallel */
for (i=0; i<nqueries; i++)
if (!alens[i])
for (j=0; j<nns; j++)
sendto(fd, queries[i],
qlens[i], MSG_NOSIGNAL,
(void *)&ns[j], sl);
t1 = t2;
servfail_retry = 2 * nqueries;
}
/* Wait for a response, or until time to retry */
if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue;
while (next < nqueries) {
struct msghdr mh = {
.msg_name = (void *)&sa,
.msg_namelen = sl,
.msg_iovlen = 1,
.msg_iov = (struct iovec []){
{ .iov_base = (void *)answers[next],
.iov_len = asize }
}
};
rlen = recvmsg(fd, &mh, 0);
if (rlen < 0) break;
/* Ignore non-identifiable packets */
if (rlen < 4) continue;
/* Ignore replies from addresses we didn't send to */
for (j=0; j<nns && memcmp(ns+j, &sa, sl); j++);
if (j==nns) continue;
/* Find which query this answer goes with, if any */
for (i=next; i<nqueries && (
answers[next][0] != queries[i][0] ||
answers[next][1] != queries[i][1] ); i++);
if (i==nqueries) continue;
if (alens[i]) continue;
/* Only accept positive or negative responses;
* retry immediately on server failure, and ignore
* all other codes such as refusal. */
switch (answers[next][3] & 15) {
case 0:
case 3:
break;
case 2:
if (servfail_retry && servfail_retry--)
sendto(fd, queries[i],
qlens[i], MSG_NOSIGNAL,
(void *)&ns[j], sl);
default:
continue;
}
/* Store answer in the right slot, or update next
* available temp slot if it's already in place. */
alens[i] = rlen;
if (i == next)
for (; next<nqueries && alens[next]; next++);
else
memcpy(answers[i], answers[next], rlen);
/* Ignore further UDP if all slots full or TCP-mode */
if (next == nqueries) pfd[nqueries].events = 0;
/* If answer is truncated (TC bit), fallback to TCP */
if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) {
alens[i] = -1;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]);
pthread_setcancelstate(cs, 0);
if (r >= 0) {
qpos[i] = r;
apos[i] = 0;
}
continue;
}
}
for (i=0; i<nqueries; i++) {
if (pfd[i].revents & POLLOUT) {
struct msghdr mh = {
.msg_iovlen = 2,
.msg_iov = (struct iovec [2]){
{ .iov_base = (uint8_t[]){ qlens[i]>>8, qlens[i] }, .iov_len = 2 },
{ .iov_base = (void *)queries[i], .iov_len = qlens[i] } }
};
step_mh(&mh, qpos[i]);
r = sendmsg(pfd[i].fd, &mh, MSG_NOSIGNAL);
if (r < 0) goto out;
qpos[i] += r;
if (qpos[i] == qlens[i]+2)
pfd[i].events = POLLIN;
}
}
for (i=0; i<nqueries; i++) {
if (pfd[i].revents & POLLIN) {
struct msghdr mh = {
.msg_iovlen = 2,
.msg_iov = (struct iovec [2]){
{ .iov_base = alen_buf[i], .iov_len = 2 },
{ .iov_base = answers[i], .iov_len = asize } }
};
step_mh(&mh, apos[i]);
r = recvmsg(pfd[i].fd, &mh, 0);
if (r <= 0) goto out;
apos[i] += r;
if (apos[i] < 2) continue;
int alen = alen_buf[i][0]*256 + alen_buf[i][1];
if (alen < 13) goto out;
if (apos[i] < alen+2 && apos[i] < asize+2)
continue;
int rcode = answers[i][3] & 15;
if (rcode != 0 && rcode != 3)
goto out;
/* Storing the length here commits the accepted answer.
* Immediately close TCP socket so as not to consume
* resources we no longer need. */
alens[i] = alen;
close(pfd[i].fd);
pfd[i].fd = -1;
}
}
}
out:
pthread_cleanup_pop(1);
/* Disregard any incomplete TCP results */
for (i=0; i<nqueries; i++) if (alens[i]<0) alens[i] = 0;
return 0;
}
int __res_msend(int nqueries, const unsigned char *const *queries,
const int *qlens, unsigned char *const *answers, int *alens, int asize)
{
struct resolvconf conf;
if (__get_resolv_conf(&conf, 0, 0) < 0) return -1;
return __res_msend_rc(nqueries, queries, qlens, answers, alens, asize, &conf);
}

58
third_party/musl/res_query.c vendored Normal file
View file

@ -0,0 +1,58 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/dns/ent.h"
#include "third_party/musl/resolv.h"
#include "third_party/musl/resolv.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int res_query(const char *name, int class, int type, unsigned char *dest, int len)
{
unsigned char q[280];
int ql = __res_mkquery(0, name, class, type, 0, 0, 0, q, sizeof q);
if (ql < 0) return ql;
int r = __res_send(q, ql, dest, len);
if (r<12) {
h_errno = TRY_AGAIN;
return -1;
}
if ((dest[3] & 15) == 3) {
h_errno = HOST_NOT_FOUND;
return -1;
}
if ((dest[3] & 15) == 0 && !dest[6] && !dest[7]) {
h_errno = NO_DATA;
return -1;
}
return r;
}
__weak_reference(res_query, res_search);

46
third_party/musl/res_querydomain.c vendored Normal file
View file

@ -0,0 +1,46 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/str/str.h"
#include "third_party/musl/resolv.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int res_querydomain(const char *name, const char *domain, int class, int type, unsigned char *dest, int len)
{
char tmp[255];
size_t nl = strnlen(name, 255);
size_t dl = strnlen(domain, 255);
if (nl+dl+1 > 254) return -1;
memcpy(tmp, name, nl);
tmp[nl] = '.';
memcpy(tmp+nl+1, domain, dl+1);
return res_query(tmp, class, type, dest, len);
}

49
third_party/musl/res_send.c vendored Normal file
View file

@ -0,0 +1,49 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/str/str.h"
#include "third_party/musl/resolv.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
{
int r;
if (anslen < 512) {
unsigned char buf[512];
r = __res_send(msg, msglen, buf, sizeof buf);
if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen);
return r;
}
r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
return r<0 || !anslen ? -1 : anslen;
}
__weak_reference(__res_send, res_send);

9
third_party/musl/res_state.c vendored Normal file
View file

@ -0,0 +1,9 @@
#include "third_party/musl/resolv.h"
/* This is completely unused, and exists purely to satisfy broken apps. */
struct __res_state *__res_state()
{
static struct __res_state res;
return &res;
}

134
third_party/musl/resolv.h vendored Normal file
View file

@ -0,0 +1,134 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_H_
#include "libc/sock/struct/sockaddr6.h"
#include "libc/sock/struct/sockaddr.h"
COSMOPOLITAN_C_START_
#define MAXNS 3
#define MAXDFLSRCH 3
#define MAXDNSRCH 6
#define LOCALDOMAINPARTS 2
#define RES_TIMEOUT 5
#define MAXRESOLVSORT 10
#define RES_MAXNDOTS 15
#define RES_MAXRETRANS 30
#define RES_MAXRETRY 5
#define RES_DFLRETRY 2
#define RES_MAXTIME 65535
/* unused; purely for broken apps */
typedef struct __res_state {
int retrans;
int retry;
unsigned long options;
int nscount;
struct sockaddr_in nsaddr_list[MAXNS];
# define nsaddr nsaddr_list[0]
unsigned short id;
char *dnsrch[MAXDNSRCH+1];
char defdname[256];
unsigned long pfcode;
unsigned ndots:4;
unsigned nsort:4;
unsigned ipv6_unavail:1;
unsigned unused:23;
struct {
struct in_addr addr;
uint32_t mask;
} sort_list[MAXRESOLVSORT];
void *qhook;
void *rhook;
int res_h_errno;
int _vcsock;
unsigned _flags;
union {
char pad[52];
struct {
uint16_t nscount;
uint16_t nsmap[MAXNS];
int nssocks[MAXNS];
uint16_t nscount6;
uint16_t nsinit;
struct sockaddr_in6 *nsaddrs[MAXNS];
unsigned int _initstamp[2];
} _ext;
} _u;
} *res_state;
#define __RES 19960801
#ifndef _PATH_RESCONF
#define _PATH_RESCONF "/etc/resolv.conf"
#endif
struct res_sym {
int number;
char *name;
char *humanname;
};
#define RES_F_VC 0x00000001
#define RES_F_CONN 0x00000002
#define RES_F_EDNS0ERR 0x00000004
#define RES_EXHAUSTIVE 0x00000001
#define RES_INIT 0x00000001
#define RES_DEBUG 0x00000002
#define RES_AAONLY 0x00000004
#define RES_USEVC 0x00000008
#define RES_PRIMARY 0x00000010
#define RES_IGNTC 0x00000020
#define RES_RECURSE 0x00000040
#define RES_DEFNAMES 0x00000080
#define RES_STAYOPEN 0x00000100
#define RES_DNSRCH 0x00000200
#define RES_INSECURE1 0x00000400
#define RES_INSECURE2 0x00000800
#define RES_NOALIASES 0x00001000
#define RES_USE_INET6 0x00002000
#define RES_ROTATE 0x00004000
#define RES_NOCHECKNAME 0x00008000
#define RES_KEEPTSIG 0x00010000
#define RES_BLAST 0x00020000
#define RES_USEBSTRING 0x00040000
#define RES_NOIP6DOTINT 0x00080000
#define RES_USE_EDNS0 0x00100000
#define RES_SNGLKUP 0x00200000
#define RES_SNGLKUPREOP 0x00400000
#define RES_USE_DNSSEC 0x00800000
#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
#define RES_PRF_STATS 0x00000001
#define RES_PRF_UPDATE 0x00000002
#define RES_PRF_CLASS 0x00000004
#define RES_PRF_CMD 0x00000008
#define RES_PRF_QUES 0x00000010
#define RES_PRF_ANS 0x00000020
#define RES_PRF_AUTH 0x00000040
#define RES_PRF_ADD 0x00000080
#define RES_PRF_HEAD1 0x00000100
#define RES_PRF_HEAD2 0x00000200
#define RES_PRF_TTLID 0x00000400
#define RES_PRF_HEADX 0x00000800
#define RES_PRF_QUERY 0x00001000
#define RES_PRF_REPLY 0x00002000
#define RES_PRF_INIT 0x00004000
struct __res_state *__res_state(void);
#define _res (*__res_state())
int res_init(void);
int res_query(const char *, int, int, unsigned char *, int);
int res_querydomain(const char *, const char *, int, int, unsigned char *, int);
int res_search(const char *, int, int, unsigned char *, int);
int res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int);
int res_send(const unsigned char *, int, unsigned char *, int);
int dn_comp(const char *, unsigned char *, int, unsigned char **, unsigned char **);
int dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int);
int dn_skipname(const unsigned char *, const unsigned char *);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_H_ */

11
third_party/musl/resolv.internal.h vendored Normal file
View file

@ -0,0 +1,11 @@
#ifndef COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_INTERNAL_H_
#define COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_INTERNAL_H_
COSMOPOLITAN_C_START_
int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int);
int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int);
int __res_send(const unsigned char *, int, unsigned char *, int);
int __res_msend(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int);
COSMOPOLITAN_C_END_
#endif /* COSMOPOLITAN_THIRD_PARTY_MUSL_RESOLV_INTERNAL_H_ */

196
third_party/musl/resolvconf.c vendored Normal file
View file

@ -0,0 +1,196 @@
/*-*- mode:c;indent-tabs-mode:t;c-basic-offset:8;tab-width:8;coding:utf-8 -*-│
vi: set noet ft=c ts=8 tw=8 fenc=utf-8 :vi
Musl Libc
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "libc/calls/syscall_support-nt.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/fmt/conv.h"
#include "libc/nt/enum/keyaccess.h"
#include "libc/nt/enum/reggetvalueflags.h"
#include "libc/nt/registry.h"
#include "libc/nt/runtime.h"
#include "libc/stdio/internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "third_party/musl/lookup.internal.h"
asm(".ident\t\"\\n\\n\
Musl libc (MIT License)\\n\
Copyright 2005-2014 Rich Felker, et. al.\"");
asm(".include \"libc/disclaimer.inc\"");
// TODO(jart): ipv6 nameservers on windows
// TODO(jart): can we polyfill `search` on windows
static dontinline textwindows int __get_resolv_conf_nt(struct resolvconf *conf)
{
int64_t hkInterfaces;
uint32_t i, keycount;
if (RegOpenKeyEx(
kNtHkeyLocalMachine,
u"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces",
0, kNtKeyRead, &hkInterfaces)) {
return __winerr();
}
if (RegQueryInfoKey(hkInterfaces, 0, 0, 0, &keycount, 0, 0, 0, 0, 0, 0, 0)) {
RegCloseKey(hkInterfaces);
return __winerr();
}
for (i = 0; i < keycount; ++i) {
char value8[128];
uint32_t valuebytes, uuidlen;
char16_t value[128], uuid[64];
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, uuid, u"IpAddress",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t))) &&
((!RegGetValue(hkInterfaces, uuid, u"DhcpNameServer",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)) ||
(!RegGetValue(hkInterfaces, uuid, u"NameServer",
kNtRrfRtRegSz | kNtRrfRtRegMultiSz, NULL, value,
((valuebytes = sizeof(value)), &valuebytes)) &&
valuebytes > 2 * sizeof(char16_t)))) {
char *state, *addr, *tmp;
tprecode16to8(value8, sizeof(value8), value);
tmp = value8;
while ((addr = strtok_r(tmp, ", ", &state))) {
uint32_t ip;
if (inet_pton(AF_INET, addr, &ip) == 1) {
if (conf->nns < MAXNS) {
conf->ns[conf->nns].family = AF_INET;
conf->ns[conf->nns].scopeid = 0;
memcpy(conf->ns[conf->nns].addr, &ip, 4);
++conf->nns;
}
}
tmp = NULL;
}
}
}
RegCloseKey(hkInterfaces);
return 0;
}
int __get_resolv_conf(struct resolvconf *conf, char *search, size_t search_sz)
{
FILE *f;
int nns = 0;
char line[256];
conf->ndots = 1;
conf->timeout = 5;
conf->attempts = 2;
if (search) *search = 0;
f = fopen("/etc/resolv.conf", "rb");
if (!f) {
if (errno == ENOENT ||
errno == ENOTDIR ||
errno == EACCES) {
if (IsWindows())
return __get_resolv_conf_nt(conf);
goto no_resolv_conf;
} else {
return -1;
}
}
while (fgets(line, sizeof line, f)) {
char *p, *z;
if (!strchr(line, '\n') && !feof(f)) {
/* Ignore lines that get truncated rather than
* potentially misinterpreting them. */
int c;
do c = getc(f);
while (c != '\n' && c != EOF);
continue;
}
if (!strncmp(line, "options", 7) && isspace(line[7])) {
p = strstr(line, "ndots:");
if (p && isdigit(p[6])) {
p += 6;
unsigned long x = strtoul(p, &z, 10);
if (z != p) conf->ndots = x > 15 ? 15 : x;
}
p = strstr(line, "attempts:");
if (p && isdigit(p[9])) {
p += 9;
unsigned long x = strtoul(p, &z, 10);
if (z != p) conf->attempts = x > 10 ? 10 : x;
}
p = strstr(line, "timeout:");
if (p && (isdigit(p[8]) || p[8]=='.')) {
p += 8;
unsigned long x = strtoul(p, &z, 10);
if (z != p) conf->timeout = x > 60 ? 60 : x;
}
continue;
}
if (!strncmp(line, "nameserver", 10) && isspace(line[10])) {
if (nns >= MAXNS) continue;
for (p=line+11; isspace(*p); p++);
for (z=p; *z && !isspace(*z); z++);
*z=0;
if (__lookup_ipliteral(conf->ns+nns, p, AF_UNSPEC) > 0)
nns++;
continue;
}
if (!search) continue;
if ((strncmp(line, "domain", 6) && strncmp(line, "search", 6))
|| !isspace(line[6]))
continue;
for (p=line+7; isspace(*p); p++);
size_t l = strlen(p);
/* This can never happen anyway with chosen buffer sizes. */
if (l >= search_sz) continue;
memcpy(search, p, l+1);
}
fclose(f);
no_resolv_conf:
if (!nns) {
__lookup_ipliteral(conf->ns, "127.0.0.1", AF_UNSPEC);
nns = 1;
}
conf->nns = nns;
return 0;
}

View file

@ -21,6 +21,7 @@ TOOL_NET_COMS = \
o/$(MODE)/tool/net/redbean.com \
o/$(MODE)/tool/net/redbean-demo.com \
o/$(MODE)/tool/net/redbean-static.com \
o/$(MODE)/tool/net/libresolv_query.com \
o/$(MODE)/tool/net/redbean-unsecure.com \
o/$(MODE)/tool/net/redbean-original.com
@ -62,6 +63,7 @@ TOOL_NET_DIRECTDEPS = \
THIRD_PARTY_LUA \
THIRD_PARTY_LUA_UNIX \
THIRD_PARTY_MAXMIND \
THIRD_PARTY_MUSL \
THIRD_PARTY_MBEDTLS \
THIRD_PARTY_REGEX \
THIRD_PARTY_SQLITE3 \

194
tool/net/libresolv_query.c Normal file
View file

@ -0,0 +1,194 @@
/*
* Copyright (c) 2013 by Wil Tan <wil@cloudregistry.net>
*
* Based on dump_dns.c from the dnscap <https://www.dns-oarc.net/tools/dnscap>
* originally written by Paul Vixie.
*
* Copyright (c) 2007 by Internet Systems Consortium, Inc. ("ISC")
*
* 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 ISC DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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/calls/typedef/u.h"
#include "libc/errno.h"
#include "libc/runtime/runtime.h"
#include "libc/sock/sock.h"
#include "libc/stdio/internal.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/af.h"
#include "third_party/musl/nameser.h"
#include "third_party/musl/resolv.h"
const char *_res_opcodes[] = {
"QUERY", //
"IQUERY", //
"CQUERYM", //
"CQUERYU", //
"NOTIFY", //
"UPDATE", //
"6", //
"7", //
"8", //
"9", //
"10", //
"11", //
"12", //
"13", //
"ZONEINIT", //
"ZONEREF", //
};
#define MY_GET16(s, cp) \
do { \
register const u_char *t_cp = (const u_char *)(cp); \
(s) = ((u_int16_t)t_cp[0] << 8) | ((u_int16_t)t_cp[1]); \
(cp) += NS_INT16SZ; \
} while (0)
#define MY_GET32(l, cp) \
do { \
register const u_char *t_cp = (const u_char *)(cp); \
(l) = ((u_int32_t)t_cp[0] << 24) | ((u_int32_t)t_cp[1] << 16) | \
((u_int32_t)t_cp[2] << 8) | ((u_int32_t)t_cp[3]); \
(cp) += NS_INT32SZ; \
} while (0)
static void dump_dns_rr(ns_msg *msg, ns_rr *rr, ns_sect sect, FILE *trace) {
char buf[NS_MAXDNAME];
u_int class, type;
const u_char *rd;
u_int32_t soa[5];
u_int16_t mx;
int n;
class = ns_rr_class(*rr);
type = ns_rr_type(*rr);
fprintf(trace, "%s,%d,%d", ns_rr_name(*rr), class, type);
if (sect == ns_s_qd) return;
fprintf(trace, ",%lu", (u_long)ns_rr_ttl(*rr));
rd = ns_rr_rdata(*rr);
switch (type) {
case ns_t_soa:
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
sizeof buf);
if (n < 0) goto error;
putc(',', trace);
fputs(buf, trace);
rd += n;
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
sizeof buf);
if (n < 0) goto error;
putc(',', trace);
fputs(buf, trace);
rd += n;
if (ns_msg_end(*msg) - rd < 5 * NS_INT32SZ) goto error;
for (n = 0; n < 5; n++) MY_GET32(soa[n], rd);
sprintf(buf, "%u,%u,%u,%u,%u", soa[0], soa[1], soa[2], soa[3], soa[4]);
break;
case ns_t_a:
inet_ntop(AF_INET, rd, buf, sizeof buf);
break;
case ns_t_aaaa:
inet_ntop(AF_INET6, rd, buf, sizeof buf);
break;
case ns_t_mx:
MY_GET16(mx, rd);
fprintf(trace, ",%u", mx);
/* FALLTHROUGH */
case ns_t_ns:
case ns_t_ptr:
case ns_t_cname:
n = ns_name_uncompress(ns_msg_base(*msg), ns_msg_end(*msg), rd, buf,
sizeof buf);
if (n < 0) goto error;
break;
case ns_t_txt:
snprintf(buf, (size_t)rd[0] + 1, "%s", rd + 1);
break;
default:
error:
sprintf(buf, "[%u]", ns_rr_rdlen(*rr));
}
if (buf[0] != '\0') {
putc(',', trace);
fputs(buf, trace);
}
}
static void dump_dns_sect(ns_msg *msg, ns_sect sect, FILE *trace,
const char *endline) {
int rrnum, rrmax;
const char *sep;
ns_rr rr;
rrmax = ns_msg_count(*msg, sect);
if (rrmax == 0) {
fputs(" 0", trace);
return;
}
fprintf(trace, " %s%d", endline, rrmax);
sep = "";
for (rrnum = 0; rrnum < rrmax; rrnum++) {
if (ns_parserr(msg, sect, rrnum, &rr)) {
fputs(strerror(errno), trace);
return;
}
fprintf(trace, " %s", sep);
dump_dns_rr(msg, &rr, sect, trace);
sep = endline;
}
}
void dump_dns(const u_char *payload, size_t paylen, FILE *trace,
const char *endline) {
u_int opcode, rcode, id;
const char *sep;
ns_msg msg;
fprintf(trace, " %sdns ", endline);
if (ns_initparse(payload, paylen, &msg) < 0) {
fputs(strerror(errno), trace);
return;
}
opcode = ns_msg_getflag(msg, ns_f_opcode);
rcode = ns_msg_getflag(msg, ns_f_rcode);
id = ns_msg_id(msg);
fprintf(trace, "%s,%d,%u", _res_opcodes[opcode], rcode, id);
sep = ",";
#define FLAG(t, f) \
if (ns_msg_getflag(msg, f)) { \
fprintf(trace, "%s%s", sep, t); \
sep = "|"; \
}
FLAG("qr", ns_f_qr);
FLAG("aa", ns_f_aa);
FLAG("tc", ns_f_tc);
FLAG("rd", ns_f_rd);
FLAG("ra", ns_f_ra);
FLAG("z", ns_f_z);
FLAG("ad", ns_f_ad);
FLAG("cd", ns_f_cd);
#undef FLAG
dump_dns_sect(&msg, ns_s_an, trace, endline);
}
int main() {
ShowCrashReports();
u_char answer[1024] = "";
res_init();
int rv = res_query("google.com", ns_c_in, ns_t_txt, answer, sizeof(answer));
// printf("rv=%d\n", rv);
dump_dns(answer, rv, stdout, "\n");
printf("\n");
}