wahern / dns Goto Github PK
View Code? Open in Web Editor NEWdns.c: Single file non-blocking DNS C library without callbacks or external dependencies.
Home Page: http://25thandclement.com/~william/projects/dns.c.html
License: MIT License
dns.c: Single file non-blocking DNS C library without callbacks or external dependencies.
Home Page: http://25thandclement.com/~william/projects/dns.c.html
License: MIT License
Why on God's green earth would you guys declare a variable "class" in your C source file. It makes it impossible to include in a C++ source file without a hack like this:
extern "C" {
#define class klass
#include "dns.h"
#undef class
}
Can this be fixed?
Remove the workaround for the buggy compound-literal code emitted by OpenBSD GCC. Rather than figure out if the bug has been fixed (which ideally requires tracking down the culprit code in GCC), just use dynamic memory or a per-resolver static buffer.
Previously dns_ai_nextent worked for numeric addresses even if no resolver object was provided. Now the first thing that dns_ai_nextent calls is dns_ai_nextaf, which immediately tries to dereference a ai->res to reach ai->res->resconf.
Hi,
I want to use dns.c as my raspberry pi dns server, when the raspberry pi is offline , all of dns request will be redirected a IP which I pointed.
now I use dnsmasq to do this function, I set "address=/#/172.1.8.1" on dnsmasq.conf. But I dont like dnsmasq. so how can I use dns.c do same job ?
The current code initializes struct dns_resolv_conf
with a default name server of 0.0.0.0. However, that's only half of the original BIND semantics. 0.0.0.0 should be translated to 127.0.0.1 when finalizing the list, which in our case means when copying the name servers into the hints database. The translation should happen in either dns_hints_insert_resconf
, or dns_hints_insert
. The former is probably safer; the latter has its own appeal, but might be a tad too magical.
This should resolve issues received by the Enlightenment team where broken systems fail to write-out /etc/resolv.conf, yet applications using gethostbyname(3) or getaddrinfo(3) still work when a local DNS proxy is running.
Here's the relevant bits from glibc 2.23:
/*
* Resolver state default settings.
*/
/*
* Set up default settings. If the configuration file exist, the values
* there will have precedence. Otherwise, the server address is set to
* INADDR_ANY and the default domain name comes from the gethostname().
*
* An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
* rather than INADDR_ANY ("0.0.0.0") as the default name server address
* since it was noted that INADDR_ANY actually meant ``the first interface
* you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
* it had to be "up" in order for you to reach your own name server. It
* was later decided that since the recommended practice is to always
* install local static routes through 127.0.0.1 for all your network
* interfaces, that we could solve this problem without a code change.
*
* The configuration file should always be used, since it is the only way
* to specify a default domain. If you are running a server on your local
* machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
* in the configuration file.
*
* Return 0 if completes successfully, -1 on error
*/
and
if (__builtin_expect(statp->nscount == 0, 0)) {
statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1);
statp->nsaddr.sin_family = AF_INET;
statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
statp->nscount = 1;
}
Standardised in https://tools.ietf.org/html/rfc7858
Usage guidelines in https://tools.ietf.org/html/rfc8310
Encountering 6 errors while attempting to compile.
til/dns.c:6528:17: error: array subscript -2 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
so->query->data[-2] = 0xff & (so->query->end >> 8);
util/dns.c:6529:17: error: array subscript -1 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
so->query->data[-1] = 0xff & (so->query->end >> 0);
~~~~~~~~~~~~~~~^~~~
util/dns.c:6531:9: error: array subscript -2 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
qsrc = &so->query->data[-2] + so->qout;
^~~~~~~~~~~~~~~~~~~~
util/dns.c:6557:10: error: array subscript -2 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
asrc = &so->answer->data[-2];
^~~~~~~~~~~~~~~~~~~~~
util/dns.c:6568:18: error: array subscript -2 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
alen = ((0xff & so->answer->data[-2]) << 8)
~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
util/dns.c:6569:42: error: array subscript -1 is below array bounds of 'unsigned char[1]' [-Werror=array-bounds]
| ((0xff & so->answer->data[-1]) << 0);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~
Required for wahern/cqueues#133
inet_pton
for address parsingThe code is filled with traces of Win32 + MinGW. But it's been some time, since the last MinGW compile, I think.
gcc -c dns.c -o dns.o -D_DEFAULT_SOURCE
dns.h:527:16: error: lvalue required as unary ‘&’ operand
527 | dns_rr_i_init(&dns_quietinit((struct dns_rr_i){ 0, __VA_ARGS__ }), (P))
Currently dns_hosts_loadpath, dns_resconf_loadpath, and dns_nssconf_loadpath are not thread-safe. The "e" mode flag to fopen is now widely supported and scheduled for inclusion in the next POSIX standard. Add support conditioned on a compile-time feature macro.
Hi.
I cannot get it to work with IPv6 DNS servers.
Is this supported? I am using current master.
When I set only v6 DNS servers in my resolv.conf, the demo app refused to work:
$ ./dns show-hints
ZONE "."
(1) [2001:4860:4860::8888]:53
$ ./dns send-query -q google.ca
querying 2001:4860:4860::8888 for google.ca IN AAAA
dns: (send_query:9433) dns_so_query: Address family not supported by protocol (97)
It works just fine with IPv4 DNS:
$ ./dns show-hints
ZONE "."
(1) [8.8.8.8]:53
$ ./dns send-query -q google.ca
querying 8.8.8.8 for google.ca IN AAAA
;; [HEADER]
;; qid : 53039
;; qr : RESPONSE(1)
;; opcode : QUERY(0)
;; aa : NON-AUTHORITATIVE(0)
;; tc : NOT-TRUNCATED(0)
;; rd : RECURSION-DESIRED(1)
;; ra : RECURSION-ALLOWED(1)
;; rcode : NOERROR(0)
;; [QUESTION:1]
;google.ca. IN AAAA
;; [ANSWER:1]
google.ca. 294 IN AAAA 2607:f8b0:400b:80e::2003
I also got it working in my application, by adding the DNS server name to hints with dns_hints_insert(),
and using dns_res_submit() and dns_res_check(). It works if I provide IPv4 DNS address,
but always returns 0 addresses when IPv6 DNS server is used.
I can also see that it creates an AF_INET socket in both cases, but only tries to call 'connect' when IPv4 DNS server is used.
Am I missing something?
I was suprised to see dns.c reach out to my dns server to ask about 'localhost'.
rfc6761:
6.3. Domain Name Reservation Considerations for "localhost."
...
- Name resolution APIs and libraries SHOULD recognize localhost
names as special and SHOULD always return the IP loopback address
for address queries and negative responses for all other query
types. Name resolution APIs SHOULD NOT send queries for
localhost names to their configured caching DNS server(s).
I tracked this down to be due to /etc/hosts not containing a 'localhost' entry: dns.c needs to treat localhost specially.
Copy linkage and visibility improvements from dns.c to spf.c. Specifically, qualify API functions with SPF_PUBLIC in spf.h, and move extern objects behind a function interface so visibility can be easily controlled using the simple SPF_PUBLIC macro.
Reported by @oerdnj
Only single occurrence:
Line 155 in 3a1b379
Needs to be ported to cqueues too:
https://github.com/wahern/cqueues/blob/ad256dfd63ae90e663abf599b680f89df128c04e/src/lib/dns.c#L155
If a domain is fully-qualified dns_resconf_search should return it and only it, skipping search domain generation.
Test program:
#include "dns/dns.c"
int main() {
int rc;
struct dns_resolv_conf *dns_conf = dns_resconf_local(&rc);
assert(dns_conf);
struct dns_hosts *dns_hosts = dns_hosts_local(&rc);
assert(dns_hosts);
struct dns_hints *dns_hints = dns_hints_local(dns_conf, &rc);
assert(dns_hints);
struct dns_resolver *resolver = dns_res_open(dns_conf, dns_hosts, dns_hints, NULL, dns_opts(), &rc);
assert(resolver);
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_INET;
struct dns_addrinfo *ai = dns_ai_open("example.org", "80", DNS_T_A, &hints, resolver, &rc);
assert(ai);
struct addrinfo *it = NULL;
while(1) {
rc = dns_ai_nextent(&it, ai);
if(rc == EAGAIN) {
rc = dns_res_poll(resolver, -1);
assert(rc == 0);
continue;
}
if(rc == ENOENT)
break;
}
dns_ai_close(ai);
dns_res_close(resolver);
dns_hints_close(dns_hints);
dns_hosts_close(dns_hosts);
dns_resconf_close(dns_conf);
return 0;
}
Valgrind output:
$ valgrind --leak-check=full ./test
==18871== Memcheck, a memory error detector
==18871== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==18871== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==18871== Command: ./test
==18871==
==18871==
==18871== HEAP SUMMARY:
==18871== in use at exit: 64 bytes in 1 blocks
==18871== total heap usage: 28 allocs, 27 frees, 16,838 bytes allocated
==18871==
==18871== 64 bytes in 1 blocks are definitely lost in loss record 1 of 1
==18871== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==18871== by 0x4130DC: dns_ai_setent (in /home/sustrik/dsock/test)
==18871== by 0x4137A2: dns_ai_nextent (in /home/sustrik/dsock/test)
==18871== by 0x414D6B: main (in /home/sustrik/dsock/test)
==18871==
==18871== LEAK SUMMARY:
==18871== definitely lost: 64 bytes in 1 blocks
==18871== indirectly lost: 0 bytes in 0 blocks
==18871== possibly lost: 0 bytes in 0 blocks
==18871== still reachable: 0 bytes in 0 blocks
==18871== suppressed: 0 bytes in 0 blocks
==18871==
==18871== For counts of detected and suppressed errors, rerun with: -v
==18871== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Hopefully we can implement a simple, user-definable crypto interface provider (e.g. dns_random()) for signing and verification. But first version might just require OpenSSL to get a feel for the contours of the required cryptographic APIs.
This is probably caused by the fact that I am not using the APIs properly,
but I cannot get the cache to work... at all.
I use the resolver generated using dns_res_open(), passing a cache object to it.
Then I use dns_ai_open() and dns_ai_nextent().
Everything works fine, except the cache is getting ignored...
Nothing new is added to it, when I dump it to a file it's empty.
When I manually create a cache, using data generated by 'cache' tool,
it is loaded, but then it is getting ignored and still does the DNS query.
Is there an example how to add cache support to the resolver?
Thanks!
See daurnimator/lua-http#73
Replicated here: https://gist.github.com/daurnimator/6765345776e87a3830ed101d1d983ee1
I've reported it to the linux kernel list: https://marc.info/?l=linux-netdev&m=148903250120465&w=2
A simple workaround seems to be calling connect()
with AF_UNSPEC
between other connect()
calls
Implement something like the Happy Eyeballs protocol for probing IPv6 and IPv4 connectivity.
When dns_so_init in dns_res_open fails, it performs a cleanup.
However, dns_resolver is not fully configured by that point yet.
It calls dns_res_close(), which results in those calls: dns_res_reset(), dns_res_frame_init().
dns_res_frame_init() sets some options on the frame, based on the resconf configuration.
But at that point resconf is not set, and the program crashes.
There should be a check in dns_res_frame_init to make sure that R->resconf even valid.
The code that fails:
static void dns_res_frame_init(struct dns_resolver *R, struct dns_res_frame *frame) {
memset(frame, '\0', sizeof *frame);
if (!R->resconf->options.recurse)
frame->qflags |= DNS_Q_RD;
if (R->resconf->options.edns0)
frame->qflags |= DNS_Q_EDNS0;
} /* dns_res_frame_init() */
I'm not sure why the first flag is SET when the option is NOT set,
but if resconf is not set it probably doesn't really matter...
Clang-5.0.1 on OpenBSD complains when compiling dns.c:
cc -std=gnu99 -Wall -Wextra -O2 -g -fstack-protector -O2 -pipe -DDNS_DEBUG -DDNS_MAIN -o dns dns.c
dns.c:383:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if HAVE___ATOMIC_FETCH_ADD && __GCC_ATOMIC_LONG_LOCK_FREE == 2
^
dns.c:375:34: note: expanded from macro 'HAVE___ATOMIC_FETCH_ADD'
#define HAVE___ATOMIC_FETCH_ADD (defined __ATOMIC_RELAXED)
^
dns.c:392:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if HAVE___ATOMIC_FETCH_SUB && __GCC_ATOMIC_LONG_LOCK_FREE == 2
^
dns.c:379:33: note: expanded from macro 'HAVE___ATOMIC_FETCH_SUB'
#define HAVE___ATOMIC_FETCH_SUB HAVE___ATOMIC_FETCH_ADD
^
dns.c:375:34: note: expanded from macro 'HAVE___ATOMIC_FETCH_ADD'
#define HAVE___ATOMIC_FETCH_ADD (defined __ATOMIC_RELAXED)
^
dns.c:788:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if DNS_HAVE_SOCKADDR_UN
^
dns.c:782:31: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:788:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
dns.c:782:51: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:843:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if DNS_HAVE_SOCKADDR_UN
^
dns.c:782:31: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:843:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
dns.c:782:51: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:849:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if DNS_HAVE_SOCKADDR_UN
^
dns.c:782:31: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:849:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
dns.c:782:51: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:909:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
#if DNS_HAVE_SOCKADDR_UN
^
dns.c:782:31: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:909:5: warning: macro expansion producing 'defined' has undefined behavior
[-Wexpansion-to-defined]
dns.c:782:51: note: expanded from macro 'DNS_HAVE_SOCKADDR_UN'
#define DNS_HAVE_SOCKADDR_UN (defined AF_UNIX && !defined _WIN32)
^
dns.c:6134:5: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
#if HAVE_SOCK_CLOEXEC
^
dns.c:6118:28: note: expanded from macro 'HAVE_SOCK_CLOEXEC'
#define HAVE_SOCK_CLOEXEC (defined SOCK_CLOEXEC)
^
dns.c:6137:5: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
#if HAVE_SOCK_NONBLOCK
^
dns.c:6122:29: note: expanded from macro 'HAVE_SOCK_NONBLOCK'
#define HAVE_SOCK_NONBLOCK (defined SOCK_NONBLOCK)
^
dns.c:6143:25: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
#if defined F_SETFD && !HAVE_SOCK_CLOEXEC
^
dns.c:6118:28: note: expanded from macro 'HAVE_SOCK_CLOEXEC'
#define HAVE_SOCK_CLOEXEC (defined SOCK_CLOEXEC)
^
dns.c:6148:28: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
#if defined O_NONBLOCK && !HAVE_SOCK_NONBLOCK
^
dns.c:6122:29: note: expanded from macro 'HAVE_SOCK_NONBLOCK'
#define HAVE_SOCK_NONBLOCK (defined SOCK_NONBLOCK)
^
dns.c:6206:26: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
#if (defined F_SETFD && !HAVE_SOCK_CLOEXEC) || (defined O_NONBLOCK && !H...
^
dns.c:6118:28: note: expanded from macro 'HAVE_SOCK_CLOEXEC'
#define HAVE_SOCK_CLOEXEC (defined SOCK_CLOEXEC)
^
dns.c:6206:72: warning: macro expansion producing 'defined' has undefined
behavior [-Wexpansion-to-defined]
...F_SETFD && !HAVE_SOCK_CLOEXEC) || (defined O_NONBLOCK && !HAVE_SOCK_NONB...
^
dns.c:6122:29: note: expanded from macro 'HAVE_SOCK_NONBLOCK'
#define HAVE_SOCK_NONBLOCK (defined SOCK_NONBLOCK)
^
16 warnings generated.
Support parallel A/AAAA queries. Likely implementation includes
1.) Do we need to include zone.c, cache.c for cache implementation?
2.) Is there any example, which explains the usage of command line arguments like "-z" (path to zone cache) etc. when using dns.c with cache implementation?
Add support for SOCK_CLOEXEC.
Reimplement Ragel-based policy parser in basic C. The Ragel requirement turns some people off. In this case it should be easy to reimplement. The new implementation should taking into account the remainder of the SPF test suite. We fail some tests because the SPF grammar is ambiguous and the test suite assumes reliance on using naive regular expressions to parse the policy.
Hey all! I have been having trouble getting this to work on the raspberry PI. Can anyone help?
Finish EDNS0 support in the resolver.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.