diff options
Diffstat (limited to 'dnsstub')
-rw-r--r-- | dnsstub/Makefile | 23 | ||||
-rw-r--r-- | dnsstub/README.md | 171 | ||||
-rw-r--r-- | dnsstub/TARGETS | 18 | ||||
-rw-r--r-- | dnsstub/dns_cname.c | 59 | ||||
-rw-r--r-- | dnsstub/dns_dfd.c | 76 | ||||
-rw-r--r-- | dnsstub/dns_domain.c | 80 | ||||
-rw-r--r-- | dnsstub/dns_dtda.c | 43 | ||||
-rw-r--r-- | dnsstub/dns_ip.c | 198 | ||||
-rw-r--r-- | dnsstub/dns_ipq.c | 236 | ||||
-rw-r--r-- | dnsstub/dns_mx.c | 63 | ||||
-rw-r--r-- | dnsstub/dns_name.c | 80 | ||||
-rw-r--r-- | dnsstub/dns_nd.c | 48 | ||||
-rw-r--r-- | dnsstub/dns_packet.c | 85 | ||||
-rw-r--r-- | dnsstub/dns_random.c | 70 | ||||
-rw-r--r-- | dnsstub/dns_rcip.c | 114 | ||||
-rw-r--r-- | dnsstub/dns_rcrw.c | 141 | ||||
-rw-r--r-- | dnsstub/dns_resolve.c | 39 | ||||
-rw-r--r-- | dnsstub/dns_sortip.c | 45 | ||||
-rw-r--r-- | dnsstub/dns_transmit.c | 436 | ||||
-rw-r--r-- | dnsstub/dns_txt.c | 64 |
20 files changed, 0 insertions, 2089 deletions
diff --git a/dnsstub/Makefile b/dnsstub/Makefile deleted file mode 100644 index 6c3bab3..0000000 --- a/dnsstub/Makefile +++ /dev/null @@ -1,23 +0,0 @@ - -COMPILE=../compile -MAKELIB=../makelib -CCFLAGS=-I../include - -default: clean check dnsresolv.a - -check: - @[ -f $(COMPILE) ] && [ -f $(MAKELIB) ] || ( cd .. ; ./configure ; ) - -clean: - rm -f `cat TARGETS` - -dnsresolv.a: \ -dns_domain.c dns_dtda.c dns_ip.c dns_ipq.c dns_name.c \ -dns_nd.c dns_packet.c dns_random.c dns_rcip.c dns_rcrw.c dns_resolve.c \ -dns_sortip.c dns_transmit.c dns_txt.c - $(COMPILE) $(CCFLAGS) dns_domain.c dns_dfd.c dns_dtda.c dns_ip.c dns_ipq.c \ - dns_mx.c dns_name.c dns_nd.c dns_packet.c dns_random.c dns_rcip.c \ - dns_rcrw.c dns_resolve.c dns_sortip.c dns_transmit.c dns_txt.c dns_cname.c - $(MAKELIB) dnsresolv.a dns_domain.o dns_dfd.o dns_dtda.o dns_ip.o dns_ipq.o \ - dns_mx.o dns_name.o dns_nd.o dns_packet.o dns_random.o dns_rcip.o \ - dns_rcrw.o dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o dns_cname.o diff --git a/dnsstub/README.md b/dnsstub/README.md deleted file mode 100644 index 95cd11c..0000000 --- a/dnsstub/README.md +++ /dev/null @@ -1,171 +0,0 @@ -/*! \mainpage - -Stub Resolver -============= - -Simple DJBDNS stub-resolver based on 'djbdns-1.05(IPv6)' allowing for each -calling application individually to include up to 16 DNSCACHEIP(s) -as DNS forwarding/resolving servers to be tried sequentially. - -IP Addresses ------------- - -Here, - - global IPv6, - - IPv6 ULA, and - - IPv6 LLU addresses with a given Interface-Id -can be specified. The IPv4 format could be either a - - legacy dotted-decimal or a - - IPv4-mapped IPv6 address. - -In any case, compactified IPv6 addresses are understood. -IPv4/IPv6 addresses in brackets are understood by dns_ip. - -Resolver Call -------------- - -If $DNSCACHEIP is not provided as environment variable, the stub-resolver -will use the system-wide - - /etc/resolv.conf -file; however now without the capability for IPv6 LLU addresses. -While IPv4-mapped IPv6 addresses are supported here by default as well, -care has to taken not to jeopardize other client's usage. - -Name Qualification ------------------- - -If provided, the stub-resolver uses either a system-wide configuration file - - /etc/dnsrewritefile or assumes this file to available as given in - - $DNSREWRITEFILE -in order to define persistent mapping-rules of local domain names to public -ones (for lookup) or IP addresses (for direct matching). - -Well-known domain names 'localhost', 'ip4-loopback' and 'ip6-loopback' -are handled locally, thus no DNS query is used (RFC 6761). -'localhost' is advertised as '::1' and '::ff:127.0.0.1' in it's native -IPv6 format. It is up to the caller to convert the IPv6-mapped IPv4 -address to the IPv4 format. - -Local domain names can be alternatively specified (per application) using -the environment variable - - $LOCALDOMAIN -to be appended to unqualified hostnames dynamically. This is roughly equivalent -with the 'search' string in /etc/resolv. Several domains names may be -specified within $LOCALDOMAIN separated by blanks. - -See: https://cr.yp.to/djbdns/qualify.html - - -Specific DNS Record type lookup -------------------------------- - -* dns_ip (A, AAAAA) -* dns_name (PTR) -* dns_cname (CNAME) -* dns_txt (TXT) -- now considering several 'labels' -* dns_mx (MX) - - -Internals ---------- - -* UDP message size: -Unlike other implementations, this DNS stub-resolver supports UDP packet -sizes up to 1028 byte without the need for (E)DNS0 packet enhancements. - -* DNS UDP query retrials: -In case the NS is not able to initally reply to the query, -it is retried again at the intervalls {1, 2, 4, 8, 16} secs. - -* DNS name qualification (dns_ip_qualify): -Well-known domain names are qualified locally without invoking a DNS query -while handling IPv4 and IPv6 addresses separately. - -* NS qualification/sorting for NS replies: -NS qualification is not supported (yet), thus we use a randomly sorted -list of NS IP addresses. - -* Query/Reply to/from DNS Cache servers/forwarders: -Neither message (CurveDNS) nor transport layer (TLS) encryption is provided; -the sub-resolver 'trusts' it's upstream caches/forwarders. We recommend to -setup communication on private IPv4/IPv6 addresses; if applicable. - -* DNS TXT Records: -The label substructure is now recognized in the RDATA section; -each label may have the size of 255 byte. -The length information is excluded from the output. -Only printable characters are recognized in the output. - -* Return Codes: -Different from DJB's initial routines, the DNS front-end routines - dns_cname*, dns_ip*, dns_mx*, dns_name*, dns dns_txt* -return now the number of replies received (not bytes!). -Thus, three cases need to be considered: - - - rc < 0: Problem occured (SOFTFAIL, HARDFAIL) - - rc = 0: No answer obtained (but query was successful) = NXDOMAIN - - rc > 0: rc answers received; positive reply - -For return codes < 0, the following conventions have been applied: - - include/dnsresolv.h - -\#define DNS_NXD 0 -\#define DNS_MEM -1 -\#define DNS_ERR -2 /* parsing errors and others */ -\#define DNS_COM -3 /* (socket) communication errors */ -\#define DNS_INT -4 /* internal errors */ -\#define DNS_SOFT -5 /* either -2 or -3 */ -\#define DNS_HARD -6 /* CNAME loop problem */ - -The modification of the return code is typically not problematic, -since mostly just rc = -1 is checked. - -In the future, these return codes are subject of change. -Thus, instead of - - if (dns_XX(...) == -1) - -one shoud use the more general syntax - - if (dns_XX(...) < 0) - -to check for 'negative' results, allowing further actions -and refinements given the calling sequence. - - - -Environment Variables Read --------------------------- - -$DNSCACHEPIP The upstream resolver's IP[v4|v6] addresses (up to 32). - IPv6 LLU addresses may be suffixed with the interface name. -$DNSREWRITEFILE Alternate location for the system-wide - /etc/dnsrewrite -file -$LOCALDOMAIN Additional local domain name appended to unqualified - hostnames dynamically. - -Sample for the file /etc/dnsrewrite: - -\#annything.local -> me -\-.example.com:me -\# me -> 127.0.0.1 -\=me:127.0.0.1 -\# any.name.a -> any.name.af.mil -\*.a:.af.mil -\# any-name-without-dots -> any-name-without-dots.heaven.af.mil -\?:.heaven.af.mil -\# remove trailing dot -\*.: - -and DJB's explanations are given here: - -Instructions are followed in order, each at most once. There are four types of instructions: - -\=post:new means that the host name post is replaced by new. -\*post:new means that any name of the form prepost is replaced by prenew. -\?post:new means that any name of the form prepost, where pre does not contain dots or brackets, is replaced by prenew. -\-post:new means that any name of the form prepost is replaced by new. - -Erwin Hoffmann, June 2023. diff --git a/dnsstub/TARGETS b/dnsstub/TARGETS deleted file mode 100644 index 62f40be..0000000 --- a/dnsstub/TARGETS +++ /dev/null @@ -1,18 +0,0 @@ -dns_cname.o -dns_dfd.o -dns_domain.o -dns_dtda.o -dns_ip.o -dns_ipq.o -dns_mx.o -dns_name.o -dns_nd.o -dns_packet.o -dns_random.o -dns_rcip.o -dns_rcrw.o -dns_resolve.o -dns_sortip.o -dns_transmit.o -dns_txt.o -dnsresolv.a diff --git a/dnsstub/dns_cname.c b/dnsstub/dns_cname.c deleted file mode 100644 index 408949a..0000000 --- a/dnsstub/dns_cname.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "case.h" -#include "dnsresolv.h" - -/** - @file dns_cname.c - @author feh - @brief DNS cname lookup -*/ - -static char *q = 0; - -int dns_cname_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_CNAME)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - } - pos += datalen; - ++ranswers; - } - - return ranswers; -} - -int dns_cname(stralloc *out,stralloc *fqdn) -{ - int rc; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_CNAME) < 0) return DNS_ERR; - if ((rc = dns_cname_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - if (case_equals(out->s,fqdn->s)) rc = -6; // loop DNS_HARD - - return rc; -} diff --git a/dnsstub/dns_dfd.c b/dnsstub/dns_dfd.c deleted file mode 100644 index 756a1f8..0000000 --- a/dnsstub/dns_dfd.c +++ /dev/null @@ -1,76 +0,0 @@ -#include "error.h" -#include "alloc.h" -#include "byte.h" -#include "dnsresolv.h" - -/** - @file dns_dfd.c - @author djb - @source ucspi-tcp - @brief domain name qualification (domain from dot) -*/ - -int dns_domain_fromdot(char **out,const char *buf,unsigned int n) -{ - char label[63]; - unsigned int labellen = 0; /* <= sizeof label */ - char name[255]; - unsigned int namelen = 0; /* <= sizeof name */ - char ch; - char *x; - - errno = EPROTO; - - for (;;) { - if (!n) break; - ch = *buf++; --n; - if (ch == '.') { - if (labellen) { - if (namelen + labellen + 1 > sizeof(name)) return 0; - name[namelen++] = labellen; - byte_copy(name + namelen,labellen,label); - namelen += labellen; - labellen = 0; - } - continue; - } - if (ch == '\\') { // octal -> decimal - if (!n) break; - ch = *buf++; --n; - if ((ch >= '0') && (ch <= '7')) { - ch -= '0'; - if (n && (*buf >= '0') && (*buf <= '7')) { - ch <<= 3; - ch += *buf - '0'; - ++buf; --n; - if (n && (*buf >= '0') && (*buf <= '7')) { - ch <<= 3; - ch += *buf - '0'; - ++buf; --n; - } - } - } - } - if (labellen >= sizeof(label)) return 0; - label[labellen++] = ch; - } - - if (labellen) { - if (namelen + labellen + 1 > sizeof(name)) return 0; - name[namelen++] = labellen; - byte_copy(name + namelen,labellen,label); - namelen += labellen; - labellen = 0; - } - - if (namelen + 1 > sizeof(name)) return 0; - name[namelen++] = 0; - - x = alloc(namelen); - if (!x) return DNS_MEM; - byte_copy(x,namelen,name); - - if (*out) alloc_free(*out); - *out = x; - return 1; -} diff --git a/dnsstub/dns_domain.c b/dnsstub/dns_domain.c deleted file mode 100644 index 654a827..0000000 --- a/dnsstub/dns_domain.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "alloc.h" -#include "case.h" -#include "byte.h" -#include "dnsresolv.h" - -/** - @file dns_domain.c - @author djb - @source ucspi-tcp - @brief domain qualification -*/ - -unsigned int dns_domain_length(const char *dn) -{ - const char *x; - unsigned char c; - - x = dn; - while ((c = *x++)) - x += (unsigned int) c; - return x - dn; -} - -void dns_domain_free(char **out) -{ - if (*out) { - alloc_free(*out); - *out = 0; - } -} - -int dns_domain_copy(char **out,const char *in) -{ - unsigned int len; - char *x; - - len = dns_domain_length(in); - x = alloc(len); - if (!x) return 0; - byte_copy(x,len,in); - if (*out) alloc_free(*out); - *out = x; - return 1; -} - -int dns_domain_equal(const char *dn1,const char *dn2) -{ - unsigned int len; - - len = dns_domain_length(dn1); - if (len != dns_domain_length(dn2)) return 0; - - if (case_diffb((char *)dn1,len,(char *)dn2)) return 0; /* safe since 63 < 'A' */ - return 1; -} - -int dns_domain_suffix(const char *big,const char *little) -{ - unsigned char c; - - for (;;) { - if (dns_domain_equal(big,little)) return 1; - c = *big++; - if (!c) return 0; - big += c; - } -} - -unsigned int dns_domain_suffixpos(const char *big,const char *little) -{ - const char *orig = big; - unsigned char c; - - for (;;) { - if (dns_domain_equal(big,little)) return big - orig; - c = *big++; - if (!c) return 0; - big += c; - } -} diff --git a/dnsstub/dns_dtda.c b/dnsstub/dns_dtda.c deleted file mode 100644 index 38358a2..0000000 --- a/dnsstub/dns_dtda.c +++ /dev/null @@ -1,43 +0,0 @@ -#include "stralloc.h" -#include "dnsresolv.h" - -/** - @file dns_dtda.c - @author djb - @source ucspi-tcp - @brief domain to dot append -*/ - -int dns_domain_todot_cat(stralloc *out,const char *d) -{ - char ch; - char ch2; - unsigned char ch3; - char buf[4]; - - if (!*d) - return stralloc_append(out,"."); - - for (;;) { - ch = *d++; - while (ch--) { - ch2 = *d++; - if ((ch2 >= 'A') && (ch2 <= 'Z')) ch2 += 32; // FQDN -> lowercase - if (((ch2 >= 'a') && (ch2 <= 'z')) || - ((ch2 >= '0') && (ch2 <= '9')) || - (ch2 == '-') || (ch2 == '_')) { - if (!stralloc_append(out,&ch2)) return DNS_MEM; - } - else { // decimal -> octal - ch3 = ch2; - buf[3] = '0' + (ch3 & 7); ch3 >>= 3; - buf[2] = '0' + (ch3 & 7); ch3 >>= 3; - buf[1] = '0' + (ch3 & 7); - buf[0] = '\\'; - if (!stralloc_catb(out,buf,4)) return DNS_MEM; - } - } - if (!*d) return 1; - if (!stralloc_append(out,".")) return DNS_MEM; - } -} diff --git a/dnsstub/dns_ip.c b/dnsstub/dns_ip.c deleted file mode 100644 index f89728c..0000000 --- a/dnsstub/dns_ip.c +++ /dev/null @@ -1,198 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_ip.c - @author djb, fefe, feh - @source ucspi-tcp6 - @brief DNS IP query -*/ - -static char *q = 0; - -int dns_ip4_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_A)) - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 4) { - if (!dns_packet_copy(buf,len,pos,header,4)) return DNS_ERR; - if (!stralloc_catb(out,header,4)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - dns_sortip4(out->s,out->len); - return ranswers; -} - -int dns_ip4(stralloc *out,stralloc *fqdn) -{ - unsigned int i; - char code = 0; - int dot = 0; - char ch; - char ip[4]; - int r; - int rc = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; - - fqdn->s[fqdn->len] = 0; /* test FQDN string */ - for (i = 1; i < fqdn->len; i++) { - if (fqdn->s[i] >= '_') { code = 127; break; } - if (fqdn->s[i] == '.') dot++; - } - - if (code != 127 && dot == 3) /* if FQDN is just IPv4 */ - if (ip4_scan(fqdn->s,ip) || ip4_scanbracket(fqdn->s,ip)) { - if (!stralloc_copyb(out,ip,4)) return DNS_MEM; - return 1; - } - - code = 0; - for (i = 0; i <= fqdn->len; ++i) { - if (i < fqdn->len) - ch = fqdn->s[i]; - else - ch = '.'; - - if ((ch == '[') || (ch == ']')) continue; - if (ch == '.') { - if (!stralloc_append(out,&code)) return DNS_MEM; - code = 0; - continue; - } - if ((ch >= '0') && (ch <= '9')) { - code *= 10; - code += ch - '0'; - continue; - } - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fdqn -> A query -> response - if (dns_resolve(q,DNS_T_A) >= 0) { - if ((r = dns_ip4_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - rc += r; - } - - return rc; - } - - out->len &= ~3; - return 0; -} - -int dns_ip6_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[16]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_AAAA)) { - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 16) { - if (!dns_packet_copy(buf,len,pos,header,16)) return DNS_ERR; - if (!stralloc_catb(out,header,16)) return DNS_MEM; - } - } else if (byte_equal(header,2,DNS_T_A)) - if (byte_equal(header + 2,2,DNS_C_IN)) - if (datalen == 4) { - byte_copy(header,12,V4mappedprefix); - if (!dns_packet_copy(buf,len,pos,header + 12,4)) return DNS_ERR; - if (!stralloc_catb(out,header,16)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - dns_sortip6(out->s,out->len); - return ranswers; -} - -int dns_ip6(stralloc *out,stralloc *fqdn) -{ - unsigned int i; - char code; - char ch; - char ip[16]; - int r; - int rc = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - if (!stralloc_readyplus(fqdn,1)) return DNS_MEM; - - fqdn->s[fqdn->len] = 0; /* if FQDN is just IPv6 */ - if (ip6_scan(fqdn->s,ip) || ip6_scanbracket(fqdn->s,ip)) { - if (!stralloc_copyb(out,ip,16)) return DNS_MEM; - return 1; - } - - code = 0; - for (i = 0; i <= fqdn->len; ++i) { - if (i < fqdn->len) - ch = fqdn->s[i]; - else - ch = '.'; - - if ((ch == '[') || (ch == ']')) continue; - if (ch == '.') { - if (!stralloc_append(out,&code)) return DNS_MEM; - code = 0; - continue; - } - if ((ch >= '0') && (ch <= '9')) { - code *= 10; - code += ch - '0'; - continue; - } - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; // fqdn -> AAAA query -> response - if (dns_resolve(q,DNS_T_AAAA) >= 0) { - if ((r = dns_ip6_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - rc += r; - } - - return rc; - } - - out->len &= ~3; - return 0; -} diff --git a/dnsstub/dns_ipq.c b/dnsstub/dns_ipq.c deleted file mode 100644 index 26c3818..0000000 --- a/dnsstub/dns_ipq.c +++ /dev/null @@ -1,236 +0,0 @@ -#include "case.h" -#include "byte.h" -#include "str.h" -#include "stralloc.h" -#include "dnsresolv.h" -#include "socket_if.h" -#include "ip.h" - -/** - @file dns_ipq.c - @author djb, feh - @source ucspi-tcp - @brief DNS hostname qualification for ipv4 and ipv6 -*/ - -/** - @fn int doit -> @return number of added chars to name -*/ -static int doit(stralloc *work,const char *rule) -{ - char ch; - unsigned int colon; - unsigned int prefixlen; - - ch = *rule++; - if ((ch != '?') && (ch != '=') && (ch != '*') && (ch != '-')) return 1; - colon = str_chr((char *)rule,':'); - if (!rule[colon]) return 1; - - if (work->len < colon) return 1; - prefixlen = work->len - colon; - if ((ch == '=') && prefixlen) return 1; - if (case_diffb((char *)rule,colon,work->s + prefixlen)) return 1; - if (ch == '?') { - if (byte_chr(work->s,prefixlen,'.') < prefixlen) return 1; - if (byte_chr(work->s,prefixlen,'[') < prefixlen) return 1; - if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1; - } - - work->len = prefixlen; - if (ch == '-') work->len = 0; - return stralloc_cats(work,rule + colon + 1); -} - -/** @fn int dns_ip4_qualify_rules -> @return number of IPv4 addresss with rules */ - -int dns_ip4_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int plus; - unsigned int fqdnlen; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) - return dns_ip4(ipout,fqdn); - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if (rc += dns_ip4(ipout,fqdn) < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip4_qualify -> @return number of IPv4 addresss qualified */ - -int dns_ip4_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip4_qualify_rules(ipout,fqdn,in,&rules); -} - -/** @fn int dns_ip4_qualify_rules -> @return number of IPv6 addresss with rules */ - -int dns_ip6_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int plus; - unsigned int fqdnlen; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) - return dns_ip6(ipout,fqdn); - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if ((rc += dns_ip6(ipout,fqdn)) < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip6_qualify -> @return number of IPv6 addresss qualified */ - -int dns_ip6_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip6_qualify_rules(ipout,fqdn,in,&rules); -} - -/** @fn int dns_ip_qualify_rules -> @return number of IPv6+IPv4 addresss with rules */ - -int dns_ip_qualify_rules(stralloc *ipout,stralloc *fqdn,const stralloc *in,const stralloc *rules) -{ - unsigned int i; - unsigned int j; - unsigned int k; - unsigned int plus; - unsigned int fqdnlen; - stralloc tmp = {0}; - int rc = 0; - - if (!stralloc_copy(fqdn,(stralloc *)in)) return DNS_MEM; - if (!stralloc_copys(ipout,"")) return DNS_MEM; - - for (j = i = 0; j < rules->len; ++j) - if (!rules->s[j]) { - if (!doit(fqdn,rules->s + i)) return DNS_INT; - i = j + 1; - } - - fqdnlen = fqdn->len; - plus = byte_chr(fqdn->s,fqdnlen,'+'); - if (plus >= fqdnlen) { - rc = dns_ip6(ipout,fqdn); - if (dns_ip4(&tmp,fqdn) > 0) { - for (k = 0; k < tmp.len; k += 4) { - if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; - if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; - rc++; - } - } - return rc; - } - - i = plus + 1; - for (;;) { - j = byte_chr(fqdn->s + i,fqdnlen - i,'+'); - byte_copy(fqdn->s + plus,j,fqdn->s + i); - fqdn->len = plus + j; - if (!stralloc_copys(ipout,"")) return DNS_MEM; - rc = dns_ip6(&tmp,fqdn); - if (rc) if (!stralloc_cat(ipout,&tmp)) return DNS_MEM; - if (dns_ip4(&tmp,fqdn) > 0) { - for (k = 0; k < tmp.len; k += 4) { - if (!stralloc_catb(ipout,(const char *) V4mappedprefix,12)) return DNS_MEM; - if (!stralloc_catb(ipout,tmp.s + k,4)) return DNS_MEM; - rc++; - } - } - - if (rc < 0) return DNS_ERR; - i += j; - if (i >= fqdnlen) return rc; - ++i; - } - return 0; -} - -/** @fn int dns_ip_qualify_localhost -> @return number of IP addresss */ - -int dns_ip_qualify_localhost(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - if (!stralloc_copys(ipout,"")) return DNS_MEM; - if (!stralloc_copys(fqdn,"")) return DNS_MEM; - ipout->len = 0; - - if (byte_equal(in->s,9,LOCALHOST)) { - if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; - if (!stralloc_catb(ipout,(const char *) V46loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"localhost.localhost.")) return DNS_MEM; - } - if (byte_equal(in->s,13,IP4_LOOPBACK)) { - if (!stralloc_copyb(ipout,(const char *) V46loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"ip4-loopback.localhost.")) return DNS_MEM; - } - if (byte_equal(in->s,13,IP6_LOOPBACK)) { - if (!stralloc_copyb(ipout,(const char *) V6loopback,16)) return DNS_MEM; - if (!stralloc_copys(fqdn,"ip6-loopback.localhost.")) return DNS_MEM; - } -// if (!stralloc_0(fqdn)) return DNS_MEM; // don't do it - - return ipout->len ? ipout->len % 15 : 0; -} - -/** @fn int dns_ip_qualify -> @return number of IP addresss */ - -int dns_ip_qualify(stralloc *ipout,stralloc *fqdn,const stralloc *in) -{ - int r; - static stralloc rules; - - if ((r = dns_ip_qualify_localhost(ipout,fqdn,in)) > 0 ) return r; - if (dns_resolvconfrewrite(&rules) < 0) return DNS_INT; - return dns_ip_qualify_rules(ipout,fqdn,in,&rules); -} diff --git a/dnsstub/dns_mx.c b/dnsstub/dns_mx.c deleted file mode 100644 index c0845ef..0000000 --- a/dnsstub/dns_mx.c +++ /dev/null @@ -1,63 +0,0 @@ -#include "stralloc.h" -#include "byte.h" -#include "uint_t.h" -#include "dnsresolv.h" - -/** - @file dns_mx.c - @author djb - @source qmail - @brief dns MX query - @param (on output) stralloc out -*/ - -static char *q = 0; - -int dns_mx_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - char pref[2]; - uint16 numanswers; - uint16 datalen; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_MX)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_copy(buf,len,pos,pref,2)) return DNS_ERR; - if (!dns_packet_getname(buf,len,pos + 2,&q)) return DNS_ERR; - if (!stralloc_catb(out,pref,2)) return DNS_MEM; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - if (!stralloc_0(out)) return DNS_MEM; - } - pos += datalen; - ++ranswers; - } - - return ranswers; -} - -int dns_mx(stralloc *out,const stralloc *fqdn) -{ - int rc = 0; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_MX) >= 0) { - if ((rc = dns_mx_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - } - - return rc; -} diff --git a/dnsstub/dns_name.c b/dnsstub/dns_name.c deleted file mode 100644 index 0723a8f..0000000 --- a/dnsstub/dns_name.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_name.c - @author djb, fefe, feh - @source ucspi-tcp - @brief DNS name query (ptr) -*/ - -static char *q = 0; - -int dns_name_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_PTR)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (!dns_packet_getname(buf,len,pos,&q)) return DNS_ERR; - if (dns_domain_todot_cat(out,q) <= 0) return DNS_ERR; - return 1; - } - pos += datalen; - } - - return 0; -} - -int dns_name4(stralloc *out,const char ip[4]) -{ - int rc; - char name[DNS_NAME4_DOMAIN]; - - dns_name4_domain(name,ip); - if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; - if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} - -int dns_name6(stralloc *out,const char ip[16]) -{ - int rc; - char name[DNS_NAME6_DOMAIN]; - - dns_name6_domain(name,ip); - if (dns_resolve(name,DNS_T_PTR) < 0) return DNS_ERR; - if ((rc = dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} - -int dns_name(stralloc *out,const char ip[16]) -{ - if (ip6_isv4mapped(ip)) - return dns_name4(out,ip+12); - else - return dns_name6(out,ip); -} diff --git a/dnsstub/dns_nd.c b/dnsstub/dns_nd.c deleted file mode 100644 index 6ce8ed9..0000000 --- a/dnsstub/dns_nd.c +++ /dev/null @@ -1,48 +0,0 @@ -#include "byte.h" -#include "fmt.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_nd.c - @autor djb, fefe - @source ucspi-tcp - @brief DNS domain name for ip (wire format) -*/ - -int dns_name4_domain(char name[DNS_NAME4_DOMAIN],const char ip[4]) -{ - unsigned int namelen; - unsigned int i; - - namelen = 0; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[3]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[2]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[1]); - name[namelen++] = i; - namelen += i; - i = fmt_ulong(name + namelen + 1,(unsigned long) (unsigned char) ip[0]); - name[namelen++] = i; - namelen += i; - byte_copy(name + namelen,14,"\7in-addr\4arpa\0"); - return namelen+14; -} - -int dns_name6_domain(char name[DNS_NAME6_DOMAIN],const char ip[16]) -{ - unsigned int j; - - for (j = 0; j < 16; j++) { - name[j * 4] = 1; - name[j * 4 + 1] = tohex(ip[15 - j] & 15); - name[j * 4 + 2] = 1; - name[j * 4 + 3] = tohex((unsigned char)ip[15 - j] >> 4); - } - byte_copy(name + 4 * 16,10,"\3ip6\4arpa\0"); - return 4 * 16 + 10; -} - diff --git a/dnsstub/dns_packet.c b/dnsstub/dns_packet.c deleted file mode 100644 index ce322ea..0000000 --- a/dnsstub/dns_packet.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "error.h" -#include "dnsresolv.h" - -/** - @file dns_packet.c - @author djb - @source ucspi-tcp - @brief DNS low level packet routine - @brief DNS should have used LZ77 instead of its own sophomoric compression algorithm. -*/ - -unsigned int dns_packet_copy(const char *buf,unsigned int len,unsigned int pos,char *out,unsigned int outlen) -{ - while (outlen) { - if (pos >= len) { errno = EPROTO; return 0; } - *out = buf[pos++]; - ++out; --outlen; - } - return pos; -} - -unsigned int dns_packet_skipname(const char *buf,unsigned int len,unsigned int pos) -{ - unsigned char ch; - - for (;;) { - if (pos >= len) break; - ch = buf[pos++]; - if (ch >= 192) return pos + 1; - if (ch >= 64) break; - if (!ch) return pos; - pos += ch; - } - - errno = EPROTO; - return 0; -} - -unsigned int dns_packet_getname(const char *buf,unsigned int len,unsigned int pos,char **d) -{ - unsigned int loop = 0; - unsigned int state = 0; - unsigned int firstcompress = 0; - unsigned int where; - unsigned char ch; - char name[255]; - unsigned int namelen = 0; - - for (;;) { - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (++loop >= 1000) goto PROTO; - - if (state) { - if (namelen + 1 > sizeof(name)) goto PROTO; - name[namelen++] = ch; - --state; - } else { - while (ch >= 192) { - where = ch; where -= 192; where <<= 8; - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (!firstcompress) firstcompress = pos; - pos = where + ch; - if (pos >= len) goto PROTO; - ch = buf[pos++]; - if (++loop >= 1000) goto PROTO; - } - if (ch >= 64) goto PROTO; - if (namelen + 1 > sizeof(name)) goto PROTO; - name[namelen++] = ch; - if (!ch) break; - state = ch; - } - } - - if (!dns_domain_copy(d,name)) return 0; - - if (firstcompress) return firstcompress; - return pos; - - PROTO: - errno = EPROTO; - return 0; -} diff --git a/dnsstub/dns_random.c b/dnsstub/dns_random.c deleted file mode 100644 index 200cd6c..0000000 --- a/dnsstub/dns_random.c +++ /dev/null @@ -1,70 +0,0 @@ -#include <unistd.h> -#include "taia.h" -#include "uint_t.h" -#include "dnsresolv.h" - -/** - @file dns_random.c - @author djb - @source ucspi-tcp - @brief random use of DNS resolvers given their IP -*/ - -static uint32 seed[32]; -static uint32 in[12]; -static uint32 out[8]; -static int outleft = 0; - -#define ROTATE(x,b) (((x) << (b)) | ((x) >> (32 - (b)))) -#define MUSH(i,b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROTATE(x,b)); - -static void surf(void) -{ - uint32 t[12]; uint32 x; uint32 sum = 0; - int r; int i; int loop; - - for (i = 0; i < 12; ++i) t[i] = in[i] ^ seed[12 + i]; - for (i = 0; i < 8; ++i) out[i] = seed[24 + i]; - x = t[11]; - for (loop = 0; loop < 2; ++loop) { - for (r = 0; r < 16; ++r) { - sum += 0x9e3779b9; - MUSH(0,5) MUSH(1,7) MUSH(2,9) MUSH(3,13) - MUSH(4,5) MUSH(5,7) MUSH(6,9) MUSH(7,13) - MUSH(8,5) MUSH(9,7) MUSH(10,9) MUSH(11,13) - } - for (i = 0; i < 8; ++i) out[i] ^= t[i + 4]; - } -} - -void dns_random_init(const char data[128]) -{ - int i; - struct taia t; - char tpack[16]; - - for (i = 0; i < 32; ++i) - uint32_unpack((char *)data + 4 * i,seed + i); - - taia_now(&t); - taia_pack(tpack,&t); - for (i = 0; i < 4; ++i) - uint32_unpack(tpack + 4 * i,in + 4 + i); - - in[8] = getpid(); - in[9] = getppid(); - /* more space in 10 and 11, but this is probably enough */ -} - -unsigned int dns_random(unsigned int n) -{ - if (!n) return 0; - - if (!outleft) { - if (!++in[0]) if (!++in[1]) if (!++in[2]) ++in[3]; - surf(); - outleft = 8; - } - - return out[--outleft] % n; -} diff --git a/dnsstub/dns_rcip.c b/dnsstub/dns_rcip.c deleted file mode 100644 index 93b0daa..0000000 --- a/dnsstub/dns_rcip.c +++ /dev/null @@ -1,114 +0,0 @@ -#include "taia.h" -#include "readclose.h" -#include "byte.h" -#include "ip.h" -#include "env.h" -#include "dnsresolv.h" -#include "socket_if.h" - -/** - @file dns_rcip.c - @author djb, fefe, feh - @source ucspi-tcp - @brief DNS receive for query -*/ - -static stralloc data = {0}; -static stralloc ifname = {0}; - -static int init(char ip[QUERY_MAXIPLEN],uint32 sid[QUERY_MAXNS]) -{ - int i; - int j; - int k = 0; - int iplen = 0; - char *x; - char ip4[4]; - -/* Read (compactified) IPv4|v6 addresses of resolvers - Store them in array IP with fixed length : - ip(64) -> 16 IPv4 addresses (not used anymore) - ip(512) -> 16*2 IPv6 addresses (we use IPv4 mapped IPv6 addresses) - sid(32) -> the scope for the respective IPv6 or 0 -*/ - for (i = 0; i < QUERY_MAXNS; ++i) sid[i] = 0; - - x = env_get("DNSCACHEIP"); - if (x) - while (iplen <= 240 && *x != '\0') { - if (*x == ' ') - ++x; - else - if ((i = ip6_ifscan(x,ip + iplen,&ifname))) { - if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); - iplen += 16; k++; - if (*(x += i) == '\0') break; - } - } - - if (!iplen) { - i = openreadclose("/etc/resolv.conf",&data,64); - if (i == -1) return DNS_INT; - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (byte_equal("nameserver ",11,data.s + i) || byte_equal("nameserver\t",11,data.s + i)) { - i += 10; - while ((data.s[i] == ' ') || (data.s[i] == '\t')) - i++; - if (iplen <= 240) { - data.s[j] = '\0'; /* ip6_ifscan needs terminated string on input */ - if (ip4_scan(data.s + i,ip4)) { - if (byte_equal(ip4,4,"\0\0\0\0")) - byte_copy(ip4,4,"\177\0\0\1"); - byte_copy(ip + iplen,12,V4mappedprefix); - byte_copy(ip + iplen + 12,4,ip4); - sid[k] = 0; iplen += 16; k++; - } else if (ip6_ifscan(data.s + i,ip + iplen,&ifname)) { - if (ifname.len > 2) sid[k] = socket_getifidx(ifname.s); - iplen += 16; k++; - } - } - } - i = j + 1; - } - } - } - - if (!iplen) { - byte_copy(ip,16,"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1"); - iplen = 16; - } - byte_zero(ip + iplen,QUERY_MAXIPLEN - iplen); - return 0; -} - -static int ok = 0; -static unsigned int uses; -static struct taia deadline; -static char ip[QUERY_MAXIPLEN]; /* defined if ok */ -static uint32 scopes[QUERY_MAXNS]; - -int dns_resolvconfip(char s[QUERY_MAXIPLEN],uint32 scope[QUERY_MAXNS]) -{ - struct taia now; - - taia_now(&now); - if (taia_less(&deadline,&now)) ok = 0; - if (!uses) ok = 0; - - if (!ok) { - if (init(ip,scopes) < 0) return DNS_INT; - taia_uint(&deadline,600); - taia_add(&deadline,&now,&deadline); - uses = 10000; - ok = 1; - } - - --uses; - byte_copy(s,QUERY_MAXIPLEN,ip); - byte_copy(scope,128,scopes); - return 0; -} diff --git a/dnsstub/dns_rcrw.c b/dnsstub/dns_rcrw.c deleted file mode 100644 index 4633fed..0000000 --- a/dnsstub/dns_rcrw.c +++ /dev/null @@ -1,141 +0,0 @@ -#include <unistd.h> -#include "taia.h" -#include "env.h" -#include "byte.h" -#include "str.h" -#include "readclose.h" -#include "dnsresolv.h" - -/** - @file dns_rcrw.c - @author djb - @source ucspi-tcp - @brief DNS receive rewrite -*/ - -static stralloc data = {0}; - -static int init(stralloc *rules) -{ - char host[256]; - const char *x; - int i; - int j; - int k; - - if (!stralloc_copys(rules,"")) return DNS_MEM; - - x = env_get("DNSREWRITEFILE"); - if (!x) x = "/etc/dnsrewrite"; - - i = openreadclose(x,&data,64); - if (i == -1) return DNS_INT; - - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; - while (rules->len) { - if (rules->s[rules->len - 1] != ' ') - if (rules->s[rules->len - 1] != '\t') - if (rules->s[rules->len - 1] != '\r') - break; - --rules->len; - } - if (!stralloc_0(rules)) return DNS_MEM; - i = j + 1; - } - return 0; - } - - x = env_get("LOCALDOMAIN"); - if (x) { - if (!stralloc_copys(&data,x)) return DNS_MEM; - if (!stralloc_append(&data," ")) return DNS_MEM; - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == ' ') { - if (!stralloc_cats(rules,"+.")) return DNS_MEM; - if (!stralloc_catb(rules,data.s + i,j - i)) return DNS_MEM; - i = j + 1; - } - if (!stralloc_0(rules)) return DNS_MEM; - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - return 0; - } - - i = openreadclose("/etc/resolv.conf",&data,64); - if (i == -1) return DNS_INT; - - if (i) { - if (!stralloc_append(&data,"\n")) return DNS_MEM; - i = 0; - for (j = 0; j < data.len; ++j) - if (data.s[j] == '\n') { - if (byte_equal("search ",7,data.s + i) || - byte_equal("search\t",7,data.s + i) || - byte_equal("domain ",7,data.s + i) || - byte_equal("domain\t",7,data.s + i)) { - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - i += 7; - while (i < j) { - k = byte_chr(data.s + i,j - i,' '); - k = byte_chr(data.s + i,k,'\t'); - if (!k) { ++i; continue; } - if (!stralloc_cats(rules,"+.")) return DNS_MEM; - if (!stralloc_catb(rules,data.s + i,k)) return DNS_MEM; - i += k; - } - if (!stralloc_0(rules)) return DNS_MEM; - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - return 0; - } - i = j + 1; - } - } - - host[0] = 0; - if (gethostname(host,sizeof(host)) == -1) return DNS_ERR; - host[(sizeof(host)) - 1] = 0; - i = str_chr(host,'.'); - if (host[i]) { - if (!stralloc_copys(rules,"?:")) return DNS_MEM; - if (!stralloc_cats(rules,host + i)) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - } - if (!stralloc_cats(rules,"*.:")) return DNS_MEM; - if (!stralloc_0(rules)) return DNS_MEM; - - return 0; -} - -static int ok = 0; -static unsigned int uses; -static struct taia deadline; -static stralloc rules = {0}; /* defined if ok */ - -int dns_resolvconfrewrite(stralloc *out) -{ - struct taia now; - - taia_now(&now); - if (taia_less(&deadline,&now)) ok = 0; - if (!uses) ok = 0; - - if (!ok) { - if (init(&rules) < 0) return DNS_INT; - taia_uint(&deadline,600); - taia_add(&deadline,&now,&deadline); - uses = 10000; - ok = 1; - } - - --uses; - if (!stralloc_copy(out,&rules)) return DNS_MEM; - return 0; -} diff --git a/dnsstub/dns_resolve.c b/dnsstub/dns_resolve.c deleted file mode 100644 index bcc4308..0000000 --- a/dnsstub/dns_resolve.c +++ /dev/null @@ -1,39 +0,0 @@ -#include "iopause.h" -#include "taia.h" -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_resolve.c - @author djb, fefe, feh - @source ucspi-tcp - @brief high-level DNS resolve function -*/ - -struct dns_transmit dns_resolve_tx = {0}; - -int dns_resolve(const char *q,const char qtype[2]) -{ - struct taia stamp; - struct taia deadline; - char servers[QUERY_MAXIPLEN]; - uint32 scopes[QUERY_MAXNS]; - iopause_fd x[1]; - int r; - - if (dns_resolvconfip(servers,scopes) < 0) return DNS_INT; - - if (dns_transmit_start6(&dns_resolve_tx,servers,1,q,qtype,(const char *)V6localnet,scopes) < 0) return DNS_COM; - - for (;;) { - taia_now(&stamp); - taia_uint(&deadline,120); - taia_add(&deadline,&deadline,&stamp); - dns_transmit_io(&dns_resolve_tx,x,&deadline); - iopause(x,1,&deadline,&stamp); - r = dns_transmit_get(&dns_resolve_tx,x,&stamp); - if (r < 0) return DNS_COM; - if (r == 1) return 0; - } -} diff --git a/dnsstub/dns_sortip.c b/dnsstub/dns_sortip.c deleted file mode 100644 index 56742e0..0000000 --- a/dnsstub/dns_sortip.c +++ /dev/null @@ -1,45 +0,0 @@ -#include "byte.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_sortip.c - @authors djb, fefe, feh - @source ucspi-tcp6 - @brief random sort of DNS servers per IP -*/ - -/* XXX: sort servers by configurable notion of closeness? */ -/* XXX: pay attention to competence of each server? */ -/* XXX: pay attention to qualification (DNSSec, DNSCurve) of each server? */ -/* YYY: we use a randomly sorted list of NS; not depending on answer */ - -void dns_sortip4(char *s,unsigned int n) -{ - unsigned int i; - char tmp[4]; - - n >>= 2; /* 4 byte per IPv4 address */ - while (n > 1) { - i = dns_random(n); - --n; - byte_copy(tmp,4,s + (i << 2)); - byte_copy(s + (i << 2),4,s + (n << 2)); - byte_copy(s + (n << 2),4,tmp); - } -} - -void dns_sortip6(char *s,unsigned int n) -{ - unsigned int i; - char tmp[16]; - - n >>= 4; /* 16 byte per IPv4 address */ - while (n > 1) { - i = dns_random(n); - --n; - byte_copy(tmp,16,s + (i << 4)); - byte_copy(s + (i << 4),16,s + (n << 4)); - byte_copy(s + (n << 4),16,tmp); - } -} diff --git a/dnsstub/dns_transmit.c b/dnsstub/dns_transmit.c deleted file mode 100644 index 2513565..0000000 --- a/dnsstub/dns_transmit.c +++ /dev/null @@ -1,436 +0,0 @@ -#include <sys/types.h> -#include <sys/socket.h> -#include <unistd.h> -#include "socket_if.h" -#include "alloc.h" -#include "error.h" -#include "byte.h" -#include "uint_t.h" -#include "ip.h" -#include "dnsresolv.h" - -/** - @file dns_transmit.c - @authors djb, fefe, feh - @source qlibs - @brief DNS query function - @brief scope_ids[32] -> 32 LLU root servers supported -*/ - -#define DNSPORT 53 - -uint32 scope_ids[QUERY_MAXNS]; - -static const int timeouts[5] = { 1, 2, 4, 8, 16 }; /* quadratic, not exponentially */ - -int getscopeid(const struct dns_transmit *d,const char *ip) -{ - int i; - - if (byte_diff(ip,2,V6linklocal)) return 0; - for (i = 0; i < QUERY_MAXNS; ++i) - if (byte_equal(d->servers + 16 * i,16,ip)) - return scope_ids[i]; - - return 0; -} - -int serverwantstcp(const char *buf,unsigned int len) -{ - char out[12]; - - if (!dns_packet_copy(buf,len,0,out,12)) return 1; - if (out[2] & 2) return 1; - - return 0; -} - -int serverfailed(const char *buf,unsigned int len) -{ - char out[12]; - unsigned int rcode; - - if (!dns_packet_copy(buf,len,0,out,12)) return 1; - rcode = out[3]; - rcode &= 15; - if (rcode && (rcode != 3)) { errno = EAGAIN; return 1; } - - return 0; -} - -int irrelevant(const struct dns_transmit *d,const char *buf,unsigned int len) -{ - char out[12]; - char *dn; - unsigned int pos; - - pos = dns_packet_copy(buf,len,0,out,12); if (!pos) return 1; - if (byte_diff(out,2,d->query + 2)) return 1; - if (out[4] != 0) return 1; - if (out[5] != 1) return 1; - - dn = 0; - pos = dns_packet_getname(buf,len,pos,&dn); if (!pos) return 1; - if (!dns_domain_equal(dn,d->query + 14)) { alloc_free(dn); return 1; } - alloc_free(dn); - - pos = dns_packet_copy(buf,len,pos,out,4); if (!pos) return 1; - if (byte_diff(out,2,d->qtype)) return 1; - if (byte_diff(out + 2,2,DNS_C_IN)) return 1; - - return 0; -} - -void packetfree(struct dns_transmit *d) -{ - if (!d->packet) return; - alloc_free(d->packet); - d->packet = 0; -} - -void queryfree(struct dns_transmit *d) -{ - if (!d->query) return; - alloc_free(d->query); - d->query = 0; -} - -void socketfree(struct dns_transmit *d) -{ - if (!d->s1) return; - close(d->s1 - 1); - d->s1 = 0; -} - -void dns_transmit_free(struct dns_transmit *d) -{ - queryfree(d); - socketfree(d); - packetfree(d); -} - -int randombind6(struct dns_transmit *d) -{ - int j; - - for (j = 0; j < 10; ++j) { - if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0) - return 0; - } - if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0) - return 0; - - return DNS_COM; -} - -int randombind4(struct dns_transmit *d) -{ - int j; - - for (j = 0; j < 10; ++j) { - if (socket_bind4(d->s1 - 1,d->localip + 12,1025 + dns_random(64510)) == 0) - return 0; - } - if (socket_bind4(d->s1 - 1,d->localip + 12,0) == 0) - return 0; - - return DNS_COM; -} - -int thisudp(struct dns_transmit *d) -{ - const char *ip; - - socketfree(d); - - while (d->udploop < 5) { - for (; d->curserver < QUERY_MAXNS; ++d->curserver) { - ip = d->servers + 16 * d->curserver; - if (byte_diff(ip,16,V6localnet)) { - d->query[2] = dns_random(256); - d->query[3] = dns_random(256); - - if (ip6_isv4mapped(ip)) { - d->s1 = 1 + socket_udp4(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } else { - d->s1 = 1 + socket_udp6(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } - - if (byte_equal(ip,2,V6linklocal) && !d->scope_id) - d->scope_id = getscopeid(d,ip); - if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) - if (send(d->s1 - 1,d->query + 2,d->querylen - 2,0) == d->querylen - 2) { - struct taia now; - taia_now(&now); - taia_uint(&d->deadline,timeouts[d->udploop]); - taia_add(&d->deadline,&d->deadline,&now); - d->tcpstate = 0; - return 0; - } - socketfree(d); - } - } - ++d->udploop; - d->curserver = 0; - } - - dns_transmit_free(d); return DNS_COM; -} - -int firstudp(struct dns_transmit *d) -{ - d->curserver = 0; - return thisudp(d); -} - -int nextudp(struct dns_transmit *d) -{ - ++d->curserver; - return thisudp(d); -} - -int thistcp(struct dns_transmit *d) -{ - struct taia now; - const char *ip; - - socketfree(d); - packetfree(d); - - for (; d->curserver < QUERY_MAXNS; ++d->curserver) { - ip = d->servers + 16 * d->curserver; - if (byte_diff(ip,16,V6localnet)) { - d->query[2] = dns_random(256); - d->query[3] = dns_random(256); - - if (ip6_isv4mapped(ip)) { - d->s1 = 1 + socket_tcp4(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind4(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } else { - d->s1 = 1 + socket_tcp6(); - if (!d->s1) { dns_transmit_free(d); return DNS_COM; } - if (randombind6(d) < 0) { dns_transmit_free(d); return DNS_COM; } - } - - taia_now(&now); - taia_uint(&d->deadline,10); - taia_add(&d->deadline,&d->deadline,&now); - - if (byte_equal(ip,2,V6linklocal) && !d->scope_id) - d->scope_id = getscopeid(d,ip); - if (socket_connect(d->s1 - 1,ip,DNSPORT,d->scope_id) == 0) { - d->tcpstate = 2; - return 0; - } - if ((errno == EINPROGRESS) || (errno == EWOULDBLOCK)) { - d->tcpstate = 1; - return 0; - } - - socketfree(d); - } - } - - dns_transmit_free(d); - return DNS_COM; -} - -int firsttcp(struct dns_transmit *d) -{ - d->curserver = 0; - return thistcp(d); -} - -int nexttcp(struct dns_transmit *d) -{ - ++d->curserver; - return thistcp(d); -} - -int dns_transmit_start(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ - int flagrecursive,const char *q,const char qtype[2],const char localip[16]) -{ - unsigned int len; - - dns_transmit_free(d); - errno = EIO; - - len = dns_domain_length(q); - d->querylen = len + 18; - d->query = alloc(d->querylen); - if (!d->query) return DNS_COM; - - uint16_pack_big(d->query,len + 16); - byte_copy(d->query + 2,12,flagrecursive ? "\0\0\1\0\0\1\0\0\0\0\0\0" : \ - "\0\0\0\0\0\1\0\0\0\0\0\0gcc-bug-workaround"); - byte_copy(d->query + 14,len,q); - byte_copy(d->query + 14 + len,2,qtype); - byte_copy(d->query + 16 + len,2,DNS_C_IN); - - byte_copy(d->qtype,2,(char *) qtype); - d->servers = servers; - byte_copy(d->localip,16,(char *) localip); - - d->udploop = flagrecursive ? 1 : 0; - - if (len + 16 > MSGSIZE) return firsttcp(d); - return firstudp(d); -} - -int dns_transmit_start6(struct dns_transmit *d,const char servers[QUERY_MAXIPLEN], \ - int flagrecursive,const char *q,const char qtype[2], \ - const char localip[16],const uint32 scopes[QUERY_MAXNS]) -{ - byte_copy(scope_ids,128,(char *) scopes); - - return dns_transmit_start(d,servers,flagrecursive,q,qtype,localip); -} - -void dns_transmit_io(struct dns_transmit *d,iopause_fd *x,struct taia *deadline) -{ - x->fd = d->s1 - 1; - - switch (d->tcpstate) { - case 0: case 3: case 4: case 5: - x->events = IOPAUSE_READ; - break; - case 1: case 2: - x->events = IOPAUSE_WRITE; - break; - } - - if (taia_less(&d->deadline,deadline)) - *deadline = d->deadline; -} - -int dns_transmit_get(struct dns_transmit *d,const iopause_fd *x,const struct taia *when) -{ - char udpbuf[MSGSIZE + 1]; - unsigned char ch; - int r; - int fd; - - errno = EIO; - fd = d->s1 - 1; - - if (!x->revents) { - if (taia_less((struct taia *)when,&d->deadline)) return 0; - errno = ETIMEDOUT; - if (d->tcpstate == 0) return nextudp(d); - return nexttcp(d); - } - -/* -have attempted to send UDP query to each server udploop times -have sent query to curserver on UDP socket s -*/ - if (d->tcpstate == 0) { - r = recv(fd,udpbuf,sizeof(udpbuf),0); - if (r <= 0) { - if (errno == ECONNREFUSED) if (d->udploop == 2) return 0; - return nextudp(d); - } - if (r + 1 > sizeof(udpbuf)) return 0; - - if (irrelevant(d,udpbuf,r)) return 0; - if (serverwantstcp(udpbuf,r)) return firsttcp(d); - if (serverfailed(udpbuf,r)) { - if (d->udploop == 2) return 0; - return nextudp(d); - } - socketfree(d); - - d->packetlen = r; - d->packet = alloc(d->packetlen); - if (!d->packet) { dns_transmit_free(d); return DNS_COM; } - byte_copy(d->packet,d->packetlen,udpbuf); - queryfree(d); - return 1; - } - -/* -have sent connection attempt to curserver on TCP socket s -pos not defined -*/ - if (d->tcpstate == 1) { - if (!socket_connected(fd)) return nexttcp(d); - d->pos = 0; - d->tcpstate = 2; - return 0; - } - -/* -have connection to curserver on TCP socket s -have sent pos bytes of query -*/ - if (d->tcpstate == 2) { - r = write(fd,d->query + d->pos,d->querylen - d->pos); - if (r <= 0) return nexttcp(d); - d->pos += r; - if (d->pos == d->querylen) { - struct taia now; - taia_now(&now); - taia_uint(&d->deadline,10); - taia_add(&d->deadline,&d->deadline,&now); - d->tcpstate = 3; - } - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -pos not defined -*/ - if (d->tcpstate == 3) { - r = read(fd,&ch,1); - if (r <= 0) return nexttcp(d); - d->packetlen = ch; - d->tcpstate = 4; - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -pos not defined -have received one byte of packet length into packetlen -*/ - if (d->tcpstate == 4) { - r = read(fd,&ch,1); - if (r <= 0) return nexttcp(d); - d->packetlen <<= 8; - d->packetlen += ch; - d->tcpstate = 5; - d->pos = 0; - d->packet = alloc(d->packetlen); - if (!d->packet) { dns_transmit_free(d); return DNS_COM; } - return 0; - } - -/* -have sent entire query to curserver on TCP socket s -have received entire packet length into packetlen -packet is allocated -have received pos bytes of packet -*/ - if (d->tcpstate == 5) { - r = read(fd,d->packet + d->pos,d->packetlen - d->pos); - if (r <= 0) return nexttcp(d); - d->pos += r; - if (d->pos < d->packetlen) return 0; - - socketfree(d); - if (irrelevant(d,d->packet,d->packetlen)) return nexttcp(d); - if (serverwantstcp(d->packet,d->packetlen)) return nexttcp(d); - if (serverfailed(d->packet,d->packetlen)) return nexttcp(d); - - queryfree(d); - return 1; - } - - return 0; -} diff --git a/dnsstub/dns_txt.c b/dnsstub/dns_txt.c deleted file mode 100644 index 9a1b56a..0000000 --- a/dnsstub/dns_txt.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "stralloc.h" -#include "uint_t.h" -#include "byte.h" -#include "dnsresolv.h" - -int dns_txt_packet(stralloc *out,const char *buf,unsigned int len) -{ - unsigned int pos; - char header[12]; - uint16 numanswers; - uint16 datalen; - char ch; - unsigned int txtlen; - int i; - int ranswers = 0; - - if (!stralloc_copys(out,"")) return DNS_MEM; - - pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 6,&numanswers); - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos += 4; - - while (numanswers--) { - pos = dns_packet_skipname(buf,len,pos); if (!pos) return DNS_ERR; - pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return DNS_ERR; - uint16_unpack_big(header + 8,&datalen); - if (byte_equal(header,2,DNS_T_TXT)) - if (byte_equal(header + 2,2,DNS_C_IN)) { - if (pos + datalen > len) return DNS_ERR; - txtlen = (unsigned char) buf[pos]; - for (i = 1; i < datalen; ++i) { - ch = buf[pos + i]; - if (i == txtlen + 1) // next label - txtlen += (unsigned char) ch + 1; - else { - if (ch < 32) ch = '?'; - if (ch > 126) ch = '?'; - if (!stralloc_append(out,&ch)) return DNS_MEM; - } - } - } - pos += datalen; - ++ranswers; - if (numanswers) if (!stralloc_append(out,"\n")) return DNS_MEM; - } - - return ranswers; -} - -static char *q = 0; - -int dns_txt(stralloc *out,const stralloc *fqdn) -{ - int rc; - - if (dns_domain_fromdot(&q,fqdn->s,fqdn->len) <= 0) return DNS_ERR; - if (dns_resolve(q,DNS_T_TXT) < 0) return DNS_ERR; - if ((rc = dns_txt_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen)) < 0) return DNS_ERR; - dns_transmit_free(&dns_resolve_tx); - dns_domain_free(&q); - - return rc; -} |