aboutsummaryrefslogtreecommitdiff
path: root/dns_ip6.c
diff options
context:
space:
mode:
authorHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:04:14 +0200
committerHenryk Plötz <henryk@ploetzli.ch>2014-10-03 20:04:14 +0200
commitc44d8b51ffb5a413f8bbdbd9991bbc573853e397 (patch)
treee7f2e644de620879f610c909c405cbc4e44d6062 /dns_ip6.c
parent0e5b2871ca6456b01d4bf037a6e68badf1ff1a41 (diff)
downloadtinydnssec-c44d8b51ffb5a413f8bbdbd9991bbc573853e397.tar.gz
tinydnssec-c44d8b51ffb5a413f8bbdbd9991bbc573853e397.tar.bz2
Apply patch djbdns-1.05-test27.diff.bz2
Source was http://www.fefe.de/dns/djbdns-1.05-test27.diff.bz2, SHA1 f0380ec1866f49c0bcf6369a923ac0a4a5095da8
Diffstat (limited to 'dns_ip6.c')
-rw-r--r--dns_ip6.c103
1 files changed, 103 insertions, 0 deletions
diff --git a/dns_ip6.c b/dns_ip6.c
new file mode 100644
index 0000000..30ce699
--- /dev/null
+++ b/dns_ip6.c
@@ -0,0 +1,103 @@
+#include "stralloc.h"
+#include "uint16.h"
+#include "byte.h"
+#include "dns.h"
+#include "ip4.h"
+#include "ip6.h"
+
+static int dns_ip6_packet_add(stralloc *out,char *buf,unsigned int len)
+{
+ unsigned int pos;
+ char header[16];
+ uint16 numanswers;
+ uint16 datalen;
+
+ pos = dns_packet_copy(buf,len,0,header,12); if (!pos) return -1;
+ uint16_unpack_big(header + 6,&numanswers);
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos += 4;
+
+ while (numanswers--) {
+ pos = dns_packet_skipname(buf,len,pos); if (!pos) return -1;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) return -1;
+ 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 -1;
+ if (!stralloc_catb(out,header,16)) return -1;
+ }
+ } 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 -1;
+ if (!stralloc_catb(out,header,16)) return -1;
+ }
+ pos += datalen;
+ }
+
+ dns_sortip6(out->s,out->len);
+ return 0;
+}
+
+int dns_ip6_packet(stralloc *out,char *buf,unsigned int len) {
+ if (!stralloc_copys(out,"")) return -1;
+ return dns_ip6_packet_add(out,buf,len);
+}
+
+static char *q = 0;
+
+int dns_ip6(stralloc *out,stralloc *fqdn)
+{
+ unsigned int i;
+ char code;
+ char ch;
+ char ip[16];
+
+ if (!stralloc_copys(out,"")) return -1;
+ if (!stralloc_readyplus(fqdn,1)) return -1;
+ fqdn->s[fqdn->len]=0;
+ if ((i=ip6_scan(fqdn->s,ip))) {
+ if (fqdn->s[i]) return -1;
+ stralloc_copyb(out,ip,16);
+ return 0;
+ }
+ 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 -1;
+ code = 0;
+ continue;
+ }
+ if ((ch >= '0') && (ch <= '9')) {
+ code *= 10;
+ code += ch - '0';
+ continue;
+ }
+
+ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
+ if (!stralloc_copys(out,"")) return -1;
+ if (dns_resolve(q,DNS_T_AAAA) != -1)
+ if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) {
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ }
+ if (!dns_domain_fromdot(&q,fqdn->s,fqdn->len)) return -1;
+ if (dns_resolve(q,DNS_T_A) != -1)
+ if (dns_ip6_packet_add(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) != -1) {
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ }
+ return out->a>0?0:-1;
+ }
+
+ out->len &= ~3;
+ return 0;
+}