aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--FILES11
-rw-r--r--Makefile178
-rw-r--r--README.ipv623
-rw-r--r--TARGETS26
-rw-r--r--axfr-get.c9
-rw-r--r--axfrdns.c23
-rw-r--r--clientloc.c46
-rw-r--r--clientloc.h6
-rw-r--r--conf-cc2
-rw-r--r--conf-ld2
-rw-r--r--dns.h15
-rw-r--r--dns_ip6.c103
-rw-r--r--dns_ipq6.c72
-rw-r--r--dns_name.c22
-rw-r--r--dns_nd6.c35
-rw-r--r--dns_rcip.c25
-rw-r--r--dns_resolve.c5
-rw-r--r--dns_sortip6.c20
-rw-r--r--dns_transmit.c25
-rw-r--r--dnscache.c64
-rw-r--r--dnsfilter.c5
-rw-r--r--dnsip6.c40
-rw-r--r--dnsip6q.c43
-rw-r--r--dnsname.c15
-rw-r--r--dnsq.c13
-rw-r--r--dnstrace.c50
-rw-r--r--error.h2
-rw-r--r--fmt_xlong.c22
-rw-r--r--haveip6.h11
-rw-r--r--haveip6.h21
-rw-r--r--haven2i.h11
-rw-r--r--haven2i.h21
-rw-r--r--hier.c2
-rw-r--r--ip6.h28
-rw-r--r--ip6_fmt.c60
-rw-r--r--ip6_scan.c115
-rw-r--r--log.c39
-rw-r--r--okclient.c18
-rw-r--r--pickdns.c6
-rw-r--r--printrecord.c10
-rw-r--r--qlog.c10
-rw-r--r--query.c287
-rw-r--r--query.h8
-rw-r--r--roots.c17
-rw-r--r--scan_xlong.c23
-rw-r--r--server.c100
-rw-r--r--sockaddr_in6.h121
-rw-r--r--sockaddr_in6.h24
-rw-r--r--socket.h18
-rw-r--r--socket_accept6.c43
-rw-r--r--socket_bind.c2
-rw-r--r--socket_bind6.c43
-rw-r--r--socket_connect6.c39
-rw-r--r--socket_getifidx.c13
-rw-r--r--socket_noipv6.c7
-rw-r--r--socket_recv6.c42
-rw-r--r--socket_send6.c39
-rw-r--r--socket_tcp6.c50
-rw-r--r--socket_udp6.c49
-rw-r--r--tdlookup.c53
-rw-r--r--tinydns-conf.c12
-rw-r--r--tinydns-data.c57
-rw-r--r--tinydns-edit.c35
-rw-r--r--tinydns-get.c5
-rw-r--r--tryip6.c8
-rw-r--r--tryn2i.c8
-rw-r--r--trysa6.c8
67 files changed, 1937 insertions, 248 deletions
diff --git a/FILES b/FILES
index 7adf6d4..27a4e26 100644
--- a/FILES
+++ b/FILES
@@ -135,6 +135,7 @@ error_str.c
exit.h
fmt.h
fmt_ulong.c
+fmt_xlong.c
gen_alloc.h
gen_allocdefs.h
getln.c
@@ -151,6 +152,9 @@ iopause.h2
ip4.h
ip4_fmt.c
ip4_scan.c
+ip6.h
+ip6_fmt.c
+ip6_scan.c
ndelay.h
ndelay_off.c
ndelay_on.c
@@ -164,6 +168,7 @@ prot.h
readclose.c
readclose.h
scan.h
+scan_0x.c
scan_ulong.c
seek.h
seek_set.c
@@ -241,3 +246,9 @@ uint64.h2
warn-shsgr
buffer_read.c
buffer_write.c
+dns_nd6.c
+socket_udp6.c
+socket_getifidx.c
+tryn2i.c
+haven2i.h1
+haven2i.h2
diff --git a/Makefile b/Makefile
index 1429643..9ebf4c8 100644
--- a/Makefile
+++ b/Makefile
@@ -52,10 +52,10 @@ iopause.h taia.h tai.h uint64.h taia.h
axfrdns: \
load axfrdns.o iopause.o droproot.o tdlookup.o response.o qlog.o \
-prot.o timeoutread.o timeoutwrite.o dns.a libtai.a alloc.a env.a \
+prot.o timeoutread.o timeoutwrite.o clientloc.o dns.a libtai.a alloc.a env.a \
cdb.a buffer.a unix.a byte.a
./load axfrdns iopause.o droproot.o tdlookup.o response.o \
- qlog.o prot.o timeoutread.o timeoutwrite.o dns.a libtai.a \
+ qlog.o prot.o timeoutread.o timeoutwrite.o clientloc.o dns.a libtai.a \
alloc.a env.a cdb.a buffer.a unix.a byte.a
axfrdns-conf: \
@@ -73,7 +73,7 @@ compile axfrdns.c droproot.h exit.h env.h uint32.h uint16.h ip4.h \
tai.h uint64.h buffer.h timeoutread.h timeoutwrite.h open.h seek.h \
cdb.h uint32.h stralloc.h gen_alloc.h strerr.h str.h byte.h case.h \
dns.h stralloc.h iopause.h taia.h tai.h taia.h scan.h qlog.h uint16.h \
-response.h uint32.h
+response.h uint32.h clientloc.h
./compile axfrdns.c
buffer.a: \
@@ -120,12 +120,14 @@ makelib byte_chr.o byte_copy.o byte_cr.o byte_diff.o byte_zero.o \
case_diffb.o case_diffs.o case_lowerb.o fmt_ulong.o ip4_fmt.o \
ip4_scan.o scan_ulong.o str_chr.o str_diff.o str_len.o str_rchr.o \
str_start.o uint16_pack.o uint16_unpack.o uint32_pack.o \
-uint32_unpack.o
+uint32_unpack.o ip6_fmt.o ip6_scan.o fmt_xlong.o \
+scan_xlong.o
./makelib byte.a byte_chr.o byte_copy.o byte_cr.o \
byte_diff.o byte_zero.o case_diffb.o case_diffs.o \
case_lowerb.o fmt_ulong.o ip4_fmt.o ip4_scan.o scan_ulong.o \
str_chr.o str_diff.o str_len.o str_rchr.o str_start.o \
- uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o
+ uint16_pack.o uint16_unpack.o uint32_pack.o uint32_unpack.o \
+ ip6_fmt.o ip6_scan.o fmt_xlong.o scan_xlong.o
byte_chr.o: \
compile byte_chr.c byte.h
@@ -209,6 +211,10 @@ warn-auto.sh choose.sh conf-home
> choose
chmod 755 choose
+clientloc.o: \
+compile clientloc.c open.h byte.h cdb.h ip6.h
+ ./compile clientloc.c
+
compile: \
warn-auto.sh conf-cc
( cat warn-auto.sh; \
@@ -228,11 +234,13 @@ choose compile trydrent.c direntry.h1 direntry.h2
dns.a: \
makelib 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
+dns_resolve.o dns_sortip.o dns_transmit.o dns_txt.o dns_ip6.o \
+dns_sortip6.o dns_nd6.o dns_ipq6.o
./makelib dns.a 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
+ dns_sortip.o dns_transmit.o dns_txt.o dns_ip6.o dns_sortip6.o \
+ dns_nd6.o dns_ipq6.o
dns_dfd.o: \
compile dns_dfd.c error.h alloc.h byte.h dns.h stralloc.h gen_alloc.h \
@@ -254,11 +262,21 @@ compile dns_ip.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
stralloc.h iopause.h taia.h tai.h uint64.h taia.h
./compile dns_ip.c
+dns_ip6.o: \
+compile dns_ip6.c stralloc.h gen_alloc.h uint16.h byte.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_ip6.c
+
dns_ipq.o: \
compile dns_ipq.c stralloc.h gen_alloc.h case.h byte.h str.h dns.h \
stralloc.h iopause.h taia.h tai.h uint64.h taia.h
./compile dns_ipq.c
+dns_ipq6.o: \
+compile dns_ipq6.c stralloc.h gen_alloc.h case.h byte.h str.h dns.h \
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dns_ipq6.c
+
dns_mx.o: \
compile dns_mx.c stralloc.h gen_alloc.h byte.h uint16.h dns.h \
stralloc.h iopause.h taia.h tai.h uint64.h taia.h
@@ -274,6 +292,11 @@ compile dns_nd.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \
taia.h tai.h uint64.h taia.h
./compile dns_nd.c
+dns_nd6.o: \
+compile dns_nd6.c byte.h fmt.h dns.h stralloc.h gen_alloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_nd6.c
+
dns_packet.o: \
compile dns_packet.c error.h dns.h stralloc.h gen_alloc.h iopause.h \
taia.h tai.h uint64.h taia.h
@@ -306,6 +329,11 @@ compile dns_sortip.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
taia.h tai.h uint64.h taia.h
./compile dns_sortip.c
+dns_sortip6.o: \
+compile dns_sortip6.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
+taia.h tai.h uint64.h taia.h
+ ./compile dns_sortip6.c
+
dns_transmit.o: \
compile dns_transmit.c socket.h uint16.h alloc.h error.h byte.h \
uint16.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h \
@@ -369,6 +397,17 @@ compile dnsip.c buffer.h exit.h strerr.h ip4.h dns.h stralloc.h \
gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
./compile dnsip.c
+dnsip6: \
+load dnsip6.o iopause.o dns.a env.a libtai.a alloc.a buffer.a unix.a \
+byte.a socket.lib
+ ./load dnsip6 iopause.o dns.a env.a libtai.a alloc.a \
+ buffer.a unix.a byte.a `cat socket.lib`
+
+dnsip6.o: \
+compile dnsip6.c buffer.h exit.h strerr.h ip6.h dns.h stralloc.h \
+gen_alloc.h iopause.h taia.h tai.h uint64.h
+ ./compile dnsip6.c
+
dnsipq: \
load dnsipq.o iopause.o dns.a env.a libtai.a alloc.a buffer.a unix.a \
byte.a socket.lib
@@ -380,6 +419,17 @@ compile dnsipq.c buffer.h exit.h strerr.h ip4.h dns.h stralloc.h \
gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
./compile dnsipq.c
+dnsip6q: \
+load dnsip6q.o iopause.o dns.a env.a libtai.a alloc.a buffer.a unix.a \
+byte.a socket.lib
+ ./load dnsip6q iopause.o dns.a env.a libtai.a alloc.a \
+ buffer.a unix.a byte.a `cat socket.lib`
+
+dnsip6q.o: \
+compile dnsip6q.c buffer.h exit.h strerr.h ip4.h dns.h stralloc.h \
+gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
+ ./compile dnsip6q.c
+
dnsmx: \
load dnsmx.o iopause.o dns.a env.a libtai.a alloc.a buffer.a unix.a \
byte.a socket.lib
@@ -399,7 +449,7 @@ byte.a socket.lib
dnsname.o: \
compile dnsname.c buffer.h exit.h strerr.h ip4.h dns.h stralloc.h \
-gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
+gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h ip6.h
./compile dnsname.c
dnsq: \
@@ -484,6 +534,10 @@ fmt_ulong.o: \
compile fmt_ulong.c fmt.h
./compile fmt_ulong.c
+fmt_xlong.o: \
+compile fmt_xlong.c scan.h
+ ./compile fmt_xlong.c
+
generic-conf.o: \
compile generic-conf.c strerr.h buffer.h open.h generic-conf.h \
buffer.h
@@ -546,10 +600,18 @@ ip4_fmt.o: \
compile ip4_fmt.c fmt.h ip4.h
./compile ip4_fmt.c
+ip6_fmt.o: \
+compile ip6_fmt.c fmt.h ip6.h
+ ./compile ip6_fmt.c
+
ip4_scan.o: \
compile ip4_scan.c scan.h ip4.h
./compile ip4_scan.c
+ip6_scan.o: \
+compile ip6_scan.c scan.h ip6.h
+ ./compile ip6_scan.c
+
it: \
prog install instcheck
@@ -626,9 +688,9 @@ iopause.h taia.h tai.h uint64.h taia.h uint16.h parsetype.h
./compile parsetype.c
pickdns: \
-load pickdns.o server.o response.o droproot.o qlog.o prot.o dns.a \
+load pickdns.o server.o iopause.o response.o droproot.o qlog.o prot.o dns.a \
env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
- ./load pickdns server.o response.o droproot.o qlog.o \
+ ./load pickdns server.o iopause.o response.o droproot.o qlog.o \
prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
byte.a `cat socket.lib`
@@ -677,7 +739,7 @@ dnscache-conf dnscache walldns-conf walldns rbldns-conf rbldns \
rbldns-data pickdns-conf pickdns pickdns-data tinydns-conf tinydns \
tinydns-data tinydns-get tinydns-edit axfr-get axfrdns-conf axfrdns \
dnsip dnsipq dnsname dnstxt dnsmx dnsfilter random-ip dnsqr dnsq \
-dnstrace dnstracesort cachetest utime rts
+dnstrace dnstracesort cachetest utime rts dnsip6 dnsip6q
prot.o: \
compile prot.c hasshsgr.h prot.h
@@ -704,9 +766,9 @@ gen_alloc.h iopause.h taia.h tai.h uint64.h taia.h
./compile random-ip.c
rbldns: \
-load rbldns.o server.o response.o dd.o droproot.o qlog.o prot.o dns.a \
+load rbldns.o server.o iopause.o response.o dd.o droproot.o qlog.o prot.o dns.a \
env.a libtai.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
- ./load rbldns server.o response.o dd.o droproot.o qlog.o \
+ ./load rbldns server.o iopause.o response.o dd.o droproot.o qlog.o \
prot.o dns.a env.a libtai.a cdb.a alloc.a buffer.a unix.a \
byte.a `cat socket.lib`
@@ -762,6 +824,10 @@ scan_ulong.o: \
compile scan_ulong.c scan.h
./compile scan_ulong.c
+scan_xlong.o: \
+compile scan_xlong.c scan.h
+ ./compile scan_xlong.c
+
seek_set.o: \
compile seek_set.c seek.h
./compile seek_set.c
@@ -774,7 +840,7 @@ server.o: \
compile server.c byte.h case.h env.h buffer.h strerr.h ip4.h uint16.h \
ndelay.h socket.h uint16.h droproot.h qlog.h uint16.h response.h \
uint32.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h uint64.h \
-taia.h
+taia.h iopause.h alloc.h str.h
./compile server.c
setup: \
@@ -796,14 +862,26 @@ socket_accept.o: \
compile socket_accept.c byte.h socket.h uint16.h
./compile socket_accept.c
+socket_accept6.o: \
+compile socket_accept6.c byte.h socket.h uint16.h
+ ./compile socket_accept6.c
+
socket_bind.o: \
compile socket_bind.c byte.h socket.h uint16.h
./compile socket_bind.c
+socket_bind6.o: \
+compile socket_bind6.c sockaddr_in6.h haveip6.h byte.h socket.h uint16.h uint32.h ip6.h error.h
+ ./compile socket_bind6.c
+
socket_conn.o: \
compile socket_conn.c byte.h socket.h uint16.h
./compile socket_conn.c
+socket_connect6.o: \
+compile socket_connect6.c byte.h socket.h uint16.h uint32.h
+ ./compile socket_connect6.c
+
socket_listen.o: \
compile socket_listen.c socket.h uint16.h
./compile socket_listen.c
@@ -812,18 +890,47 @@ socket_recv.o: \
compile socket_recv.c byte.h socket.h uint16.h
./compile socket_recv.c
+socket_recv6.o: \
+compile socket_recv6.c sockaddr_in6.h haveip6.h byte.h socket.h uint16.h uint32.h ip6.h error.h
+ ./compile socket_recv6.c
+
socket_send.o: \
compile socket_send.c byte.h socket.h uint16.h
./compile socket_send.c
+socket_send6.o: \
+compile socket_send6.c byte.h socket.h uint16.h uint32.h ip6.h haveip6.h error.h
+ ./compile socket_send6.c
+
socket_tcp.o: \
compile socket_tcp.c ndelay.h socket.h uint16.h
./compile socket_tcp.c
+socket_tcp6.o: \
+compile socket_tcp6.c ndelay.h socket.h uint16.h uint32.h haveip6.h
+ ./compile socket_tcp6.c
+
socket_udp.o: \
compile socket_udp.c ndelay.h socket.h uint16.h
./compile socket_udp.c
+socket_udp6.o: \
+compile socket_udp6.c ndelay.h socket.h uint16.h uint32.h haveip6.h
+ ./compile socket_udp6.c
+
+socket_noipv6.o: \
+compile socket_noipv6.c haveip6.h
+ ./compile socket_noipv6.c
+
+socket_getifidx.o: \
+compile socket_getifidx.c socket.h uint16.h uint32.h haven2i.h
+ ./compile socket_getifidx.c
+
+haven2i.h: \
+tryn2i.c choose compile load socket.lib haven2i.h1 haven2i.h2
+ cp /dev/null haven2i.h
+ ./choose cL tryn2i haven2i.h1 haven2i.h2 socket > haven2i.h
+
str_chr.o: \
compile str_chr.c str.h
./compile str_chr.c
@@ -965,7 +1072,7 @@ compile taia_uint.c taia.h tai.h uint64.h
tdlookup.o: \
compile tdlookup.c uint16.h open.h tai.h uint64.h cdb.h uint32.h \
byte.h case.h dns.h stralloc.h gen_alloc.h iopause.h taia.h tai.h \
-taia.h seek.h response.h uint32.h
+taia.h seek.h response.h uint32.h ip6.h clientloc.h
./compile tdlookup.c
timeoutread.o: \
@@ -979,11 +1086,11 @@ timeoutwrite.h
./compile timeoutwrite.c
tinydns: \
-load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \
-prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
+load tinydns.o server.o iopause.o droproot.o tdlookup.o response.o qlog.o \
+prot.o clientloc.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a byte.a \
socket.lib
- ./load tinydns server.o droproot.o tdlookup.o response.o \
- qlog.o prot.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
+ ./load tinydns server.o iopause.o droproot.o tdlookup.o response.o \
+ qlog.o prot.o clientloc.o dns.a libtai.a env.a cdb.a alloc.a buffer.a \
unix.a byte.a `cat socket.lib`
tinydns-conf: \
@@ -1005,7 +1112,7 @@ tinydns-data.o: \
compile tinydns-data.c uint16.h uint32.h str.h byte.h fmt.h ip4.h \
exit.h case.h scan.h buffer.h strerr.h getln.h buffer.h stralloc.h \
gen_alloc.h cdb_make.h buffer.h uint32.h stralloc.h open.h dns.h \
-stralloc.h iopause.h taia.h tai.h uint64.h taia.h
+stralloc.h iopause.h taia.h tai.h uint64.h taia.h ip6.h
./compile tinydns-data.c
tinydns-edit: \
@@ -1020,9 +1127,9 @@ dns.h stralloc.h iopause.h taia.h tai.h uint64.h taia.h
tinydns-get: \
load tinydns-get.o tdlookup.o response.o printpacket.o printrecord.o \
-parsetype.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
+parsetype.o clientloc.o dns.a libtai.a cdb.a buffer.a alloc.a unix.a byte.a
./load tinydns-get tdlookup.o response.o printpacket.o \
- printrecord.o parsetype.o dns.a libtai.a cdb.a buffer.a \
+ printrecord.o parsetype.o clientloc.o dns.a libtai.a cdb.a buffer.a \
alloc.a unix.a byte.a
tinydns-get.o: \
@@ -1068,12 +1175,18 @@ unix.a: \
makelib buffer_read.o buffer_write.o error.o error_str.o ndelay_off.o \
ndelay_on.o open_read.o open_trunc.o openreadclose.o readclose.o \
seek_set.o socket_accept.o socket_bind.o socket_conn.o \
-socket_listen.o socket_recv.o socket_send.o socket_tcp.o socket_udp.o
+socket_listen.o socket_recv.o socket_send.o socket_tcp.o socket_udp.o \
+socket_udp6.o socket_getifidx.o socket_recv6.o socket_send6.o \
+socket_bind6.o socket_noipv6.o socket_tcp6.o socket_connect6.o \
+socket_accept6.o
./makelib unix.a buffer_read.o buffer_write.o error.o \
error_str.o ndelay_off.o ndelay_on.o open_read.o \
open_trunc.o openreadclose.o readclose.o seek_set.o \
socket_accept.o socket_bind.o socket_conn.o socket_listen.o \
- socket_recv.o socket_send.o socket_tcp.o socket_udp.o
+ socket_recv.o socket_send.o socket_tcp.o socket_udp.o \
+ socket_udp6.o socket_getifidx.o socket_recv6.o socket_send6.o \
+ socket_bind6.o socket_noipv6.o socket_tcp6.o socket_connect6.o \
+ socket_accept6.o
utime: \
load utime.o byte.a
@@ -1084,10 +1197,10 @@ compile utime.c scan.h exit.h
./compile utime.c
walldns: \
-load walldns.o server.o response.o droproot.o qlog.o prot.o dd.o \
+load walldns.o server.o iopause.o response.o droproot.o qlog.o prot.o dd.o \
dns.a env.a cdb.a alloc.a buffer.a unix.a byte.a socket.lib
- ./load walldns server.o response.o droproot.o qlog.o \
- prot.o dd.o dns.a env.a cdb.a alloc.a buffer.a unix.a \
+ ./load walldns server.o iopause.o response.o droproot.o qlog.o \
+ prot.o dd.o dns.a libtai.a env.a cdb.a alloc.a buffer.a unix.a \
byte.a `cat socket.lib`
walldns-conf: \
@@ -1104,3 +1217,14 @@ walldns.o: \
compile walldns.c byte.h dns.h stralloc.h gen_alloc.h iopause.h \
taia.h tai.h uint64.h taia.h dd.h response.h uint32.h
./compile walldns.c
+
+haveip6.h: \
+tryip6.c choose compile haveip6.h1 haveip6.h2
+ ./choose c tryip6 haveip6.h1 haveip6.h2 > haveip6.h
+
+sockaddr_in6.h: \
+trysa6.c choose compile sockaddr_in6.h1 sockaddr_in6.h2 haveip6.h
+ ./choose c trysa6 sockaddr_in6.h1 sockaddr_in6.h2 > sockaddr_in6.h
+
+clean:
+ rm -f `cat TARGETS`
diff --git a/README.ipv6 b/README.ipv6
new file mode 100644
index 0000000..9be5a10
--- /dev/null
+++ b/README.ipv6
@@ -0,0 +1,23 @@
+The patch adds ipv6 transport support for djbdns. It would work for
+tinydns and dnscache. It requires IPv4 mapped addresses support enabled
+in the operating system (which is true for Linux and can be enabled for
+the BSDs except OpenBSD).
+
+The log format changes to log the full IPv6 addresses in a non-standard,
+"flat" form, for example 00000000000000000000ffffc7fe1f01 (this is
+analogous to ::ffff:199.254.31.1).
+
+The localization format of dnscache-data was amended to support IPv6.
+Instead of
+
+ %in:192.168
+
+you need to use the above flat form with a prepended s for IPv6. The
+IPv4 form should still work unchanged. Note that the "data.cdb" file
+format changes for this and is not compatible. If you run an unpatched
+tinydns on it, it will not recognize any of the localization data.
+
+dnscache will only try to lookup AAAA records for finding nameservers if
+the A record lookup failed. So IPv4 is default and stays like that, to
+not slow down DNS lookups by looking up all name servers as IPv6 and
+failing for all of them.
diff --git a/TARGETS b/TARGETS
index 2490b1a..8e8e457 100644
--- a/TARGETS
+++ b/TARGETS
@@ -20,6 +20,7 @@ strerr_sys.o
buffer.a
buffer_read.o
buffer_write.o
+clientloc.o
error.o
error_str.o
ndelay_off.o
@@ -102,6 +103,7 @@ dns_domain.o
dns_dtda.o
dns_ip.o
dns_ipq.o
+dns_ipq6.o
dns_mx.o
dns_name.o
dns_nd.o
@@ -180,6 +182,8 @@ dnsip.o
dnsip
dnsipq.o
dnsipq
+dnsip6q.o
+dnsip6q
dnsname.o
dnsname
dnstxt.o
@@ -214,3 +218,25 @@ instcheck
it
setup
check
+scan_0x.o
+fmt_xlong.o
+ip6_scan.o
+ip6_fmt.o
+dnsip6.o
+dns_ip6.o
+dns_sortip6.o
+dnsip6
+dns_nd6.o
+socket_udp6.o
+socket_getifidx.o
+socket_bind6.o
+socket_noipv6.o
+socket_recv6.o
+socket_send6.o
+haveip6.h
+haven2i.h
+sockaddr_in6.h
+scan_xlong.o
+socket_accept6.o
+socket_connect6.o
+socket_tcp6.o
diff --git a/axfr-get.c b/axfr-get.c
index 75db627..f6bf5bd 100644
--- a/axfr-get.c
+++ b/axfr-get.c
@@ -13,6 +13,7 @@
#include "byte.h"
#include "str.h"
#include "ip4.h"
+#include "ip6.h"
#include "timeoutread.h"
#include "timeoutwrite.h"
#include "dns.h"
@@ -217,6 +218,14 @@ unsigned int doit(char *buf,unsigned int len,unsigned int pos)
x_copy(buf,len,pos,data,4);
if (!stralloc_catb(&line,ipstr,ip4_fmt(ipstr,data))) return 0;
}
+ else if (byte_equal(data,2,DNS_T_AAAA)) {
+ char ipstr[IP6_FMT];
+ if (!stralloc_copys(&line,"3")) return 0;
+ if (!dns_domain_todot_cat(&line,d1)) return 0;
+ if (!stralloc_cats(&line,":")) return 0;
+ x_copy(buf,len,pos,data,16);
+ if (!stralloc_catb(&line,ipstr,ip6_fmt_flat(ipstr,data))) return 0;
+ }
else {
unsigned char ch;
unsigned char ch2;
diff --git a/axfrdns.c b/axfrdns.c
index 7079850..85723c9 100644
--- a/axfrdns.c
+++ b/axfrdns.c
@@ -21,6 +21,8 @@
#include "scan.h"
#include "qlog.h"
#include "response.h"
+#include "ip6.h"
+#include "clientloc.h"
extern int respond(char *,char *,char *);
@@ -123,7 +125,7 @@ void get(char *buf,unsigned int len)
}
}
-char ip[4];
+char ip[16];
unsigned long port;
char clientloc[2];
@@ -231,22 +233,11 @@ void doaxfr(char id[2])
axfrcheck(zone);
+ find_client_loc(clientloc, ip);
+
tai_now(&now);
cdb_init(&c,fdcdb);
- byte_zero(clientloc,2);
- key[0] = 0;
- key[1] = '%';
- byte_copy(key + 2,4,ip);
- r = cdb_find(&c,key,6);
- if (!r) r = cdb_find(&c,key,5);
- if (!r) r = cdb_find(&c,key,4);
- if (!r) r = cdb_find(&c,key,3);
- if (!r) r = cdb_find(&c,key,2);
- if (r == -1) die_cdbread();
- if (r && (cdb_datalen(&c) == 2))
- if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) die_cdbread();
-
cdb_findstart(&c);
for (;;) {
r = cdb_findnext(&c,zone,zonelen);
@@ -328,10 +319,10 @@ int main()
axfr = env_get("AXFR");
x = env_get("TCPREMOTEIP");
- if (x && ip4_scan(x,ip))
+ if (x && ip6_scan(x,ip))
;
else
- byte_zero(ip,4);
+ byte_zero(ip,16);
x = env_get("TCPREMOTEPORT");
if (!x) x = "0";
diff --git a/clientloc.c b/clientloc.c
new file mode 100644
index 0000000..99fc04d
--- /dev/null
+++ b/clientloc.c
@@ -0,0 +1,46 @@
+#include "open.h"
+#include "byte.h"
+#include "cdb.h"
+#include "ip6.h"
+
+int find_client_loc(char loc[2],const char ip[16])
+{
+ int r, fd;
+ char key[32+3];
+ static struct cdb c;
+
+ fd = open_read("data.cdb");
+ if (fd == -1) return 0;
+ cdb_init(&c,fd);
+
+ byte_zero(loc,2);
+ key[0] = 0;
+ key[1] = '%';
+ if (byte_equal(ip,12,V4mappedprefix)) {
+ key[2] = 'f';
+ byte_copy(key + 3,4,ip+12);
+ r = cdb_find(&c,key,7);
+ if (!r) r = cdb_find(&c,key,6);
+ if (!r) r = cdb_find(&c,key,5);
+ if (!r) r = cdb_find(&c,key,4);
+ if (!r) r = cdb_find(&c,key,3);
+ if (r == -1) return 0;
+ if (r && (cdb_datalen(&c) == 2))
+ if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0;
+ } else {
+ unsigned int n;
+ key[2] = 's';
+ ip6_fmt_flat(key+3,ip);
+ for (n=19; n>3; --n) {
+ r = cdb_find(&c,key,n);
+ if (r) break;
+ }
+ if (r == -1) return 0;
+ if (r && (cdb_datalen(&c) == 2))
+ if (cdb_read(&c,loc,2,cdb_datapos(&c)) == -1) return 0;
+ }
+
+ cdb_free(&c);
+ close(fd);
+ return r;
+}
diff --git a/clientloc.h b/clientloc.h
new file mode 100644
index 0000000..e522fce
--- /dev/null
+++ b/clientloc.h
@@ -0,0 +1,6 @@
+#ifndef CLIENTLOC_H
+#define CLIENTLOC_H
+
+extern int find_client_loc(char loc[2],const char ip[16]);
+
+#endif
diff --git a/conf-cc b/conf-cc
index b315ecb..ea5b66d 100644
--- a/conf-cc
+++ b/conf-cc
@@ -1,3 +1,3 @@
-gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
+diet -Os gcc -O2 -Wimplicit -Wunused -Wcomment -Wchar-subscripts -Wuninitialized -Wshadow -Wcast-qual -Wcast-align -Wwrite-strings
This will be used to compile .c files.
diff --git a/conf-ld b/conf-ld
index 59a0de7..97917c3 100644
--- a/conf-ld
+++ b/conf-ld
@@ -1,3 +1,3 @@
-gcc -s
+diet -Os gcc -s
This will be used to link .o files into an executable.
diff --git a/dns.h b/dns.h
index 2f899ef..5398e2b 100644
--- a/dns.h
+++ b/dns.h
@@ -35,7 +35,8 @@ struct dns_transmit {
struct taia deadline;
unsigned int pos;
const char *servers;
- char localip[4];
+ char localip[16];
+ unsigned int scope_id;
char qtype[2];
} ;
@@ -43,6 +44,7 @@ extern void dns_random_init(const char *);
extern unsigned int dns_random(unsigned int);
extern void dns_sortip(char *,unsigned int);
+extern void dns_sortip6(char *,unsigned int);
extern void dns_domain_free(char **);
extern int dns_domain_copy(char **,const char *);
@@ -68,10 +70,13 @@ extern struct dns_transmit dns_resolve_tx;
extern int dns_ip4_packet(stralloc *,const char *,unsigned int);
extern int dns_ip4(stralloc *,const stralloc *);
+extern int dns_ip6_packet(stralloc *,char *,unsigned int);
+extern int dns_ip6(stralloc *,stralloc *);
extern int dns_name_packet(stralloc *,const char *,unsigned int);
extern void dns_name4_domain(char *,const char *);
#define DNS_NAME4_DOMAIN 31
extern int dns_name4(stralloc *,const char *);
+extern int dns_name6(stralloc *,const char *);
extern int dns_txt_packet(stralloc *,const char *,unsigned int);
extern int dns_txt(stralloc *,const stralloc *);
extern int dns_mx_packet(stralloc *,const char *,unsigned int);
@@ -80,5 +85,13 @@ extern int dns_mx(stralloc *,const stralloc *);
extern int dns_resolvconfrewrite(stralloc *);
extern int dns_ip4_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *);
extern int dns_ip4_qualify(stralloc *,stralloc *,const stralloc *);
+extern int dns_ip6_qualify_rules(stralloc *,stralloc *,const stralloc *,const stralloc *);
+extern int dns_ip6_qualify(stralloc *,stralloc *,const stralloc *);
+
+#define DNS_IP6_INT 0
+#define DNS_IP6_ARPA 1
+
+extern int dns_name6_domain(char *,const char *,int);
+#define DNS_NAME6_DOMAIN (4*16+11)
#endif
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;
+}
diff --git a/dns_ipq6.c b/dns_ipq6.c
new file mode 100644
index 0000000..d5cea12
--- /dev/null
+++ b/dns_ipq6.c
@@ -0,0 +1,72 @@
+#include "stralloc.h"
+#include "case.h"
+#include "byte.h"
+#include "str.h"
+#include "dns.h"
+
+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(rule,':');
+ if (!rule[colon]) return 1;
+
+ if (work->len < colon) return 1;
+ prefixlen = work->len - colon;
+ if ((ch == '=') && prefixlen) return 1;
+ if (case_diffb(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;
+ if (byte_chr(work->s,prefixlen,']') < prefixlen) return 1;
+ }
+
+ work->len = prefixlen;
+ if (ch == '-') work->len = 0;
+ return stralloc_cats(work,rule + colon + 1);
+}
+
+int dns_ip6_qualify_rules(stralloc *out,stralloc *fqdn,const stralloc *in,const stralloc *rules)
+{
+ unsigned int i;
+ unsigned int j;
+ unsigned int plus;
+ unsigned int fqdnlen;
+
+ if (!stralloc_copy(fqdn,in)) return -1;
+
+ for (j = i = 0;j < rules->len;++j)
+ if (!rules->s[j]) {
+ if (!doit(fqdn,rules->s + i)) return -1;
+ i = j + 1;
+ }
+
+ fqdnlen = fqdn->len;
+ plus = byte_chr(fqdn->s,fqdnlen,'+');
+ if (plus >= fqdnlen)
+ return dns_ip6(out,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 (dns_ip6(out,fqdn) == -1) return -1;
+ if (out->len) return 0;
+ i += j;
+ if (i >= fqdnlen) return 0;
+ ++i;
+ }
+}
+
+int dns_ip6_qualify(stralloc *out,stralloc *fqdn,const stralloc *in)
+{
+ static stralloc rules;
+ if (dns_resolvconfrewrite(&rules) == -1) return -1;
+ return dns_ip6_qualify_rules(out,fqdn,in,&rules);
+}
diff --git a/dns_name.c b/dns_name.c
index 6f7cdc3..518a0c0 100644
--- a/dns_name.c
+++ b/dns_name.c
@@ -2,6 +2,7 @@
#include "uint16.h"
#include "byte.h"
#include "dns.h"
+#include "ip6.h"
static char *q = 0;
@@ -46,3 +47,24 @@ int dns_name4(stralloc *out,const char ip[4])
dns_domain_free(&q);
return 0;
}
+
+int dns_name6_inner(stralloc *out,const char ip[16],int t)
+{
+ char name[DNS_NAME6_DOMAIN];
+
+ dns_name6_domain(name,ip,t);
+ if (dns_resolve(name,DNS_T_PTR) == -1) return -1;
+ if (dns_name_packet(out,dns_resolve_tx.packet,dns_resolve_tx.packetlen) == -1) return -1;
+ dns_transmit_free(&dns_resolve_tx);
+ dns_domain_free(&q);
+ return 0;
+}
+
+int dns_name6(stralloc *out,const char ip[16])
+{
+ if (ip6_isv4mapped(ip))
+ return dns_name4(out,ip+12);
+ if (dns_name6_inner(out,ip,DNS_IP6_ARPA)) return -1;
+ if (!out->len) return dns_name6_inner(out,ip,DNS_IP6_INT);
+ return 0;
+}
diff --git a/dns_nd6.c b/dns_nd6.c
new file mode 100644
index 0000000..6dbeb89
--- /dev/null
+++ b/dns_nd6.c
@@ -0,0 +1,35 @@
+#include "byte.h"
+#include "fmt.h"
+#include "dns.h"
+
+/* RFC1886:
+ * 4321:0:1:2:3:4:567:89ab
+ * ->
+ * b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.INT.
+ * b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.ARPA.
+ */
+
+extern char tohex(char num);
+
+unsigned int mkint(unsigned char a,unsigned char b) {
+ return ((unsigned int)a << 8) + (unsigned int)b;
+}
+
+int dns_name6_domain(char name[DNS_NAME6_DOMAIN],const char ip[16],int t)
+{
+ 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);
+ }
+ if (t==DNS_IP6_INT)
+ byte_copy(name + 4*16,9,"\3ip6\3int\0");
+ else if (t==DNS_IP6_ARPA)
+ byte_copy(name + 4*16,10,"\3ip6\4arpa\0");
+ else return 0;
+ return 4*16+9+t;
+}
+
diff --git a/dns_rcip.c b/dns_rcip.c
index 97bd8f5..efd1b21 100644
--- a/dns_rcip.c
+++ b/dns_rcip.c
@@ -2,12 +2,13 @@
#include "openreadclose.h"
#include "byte.h"
#include "ip4.h"
+#include "ip6.h"
#include "env.h"
#include "dns.h"
static stralloc data = {0};
-static int init(char ip[64])
+static int init(char ip[256])
{
int i;
int j;
@@ -20,10 +21,10 @@ static int init(char ip[64])
if (*x == '.')
++x;
else {
- i = ip4_scan(x,ip + iplen);
+ i = ip6_scan(x,ip + iplen);
if (!i) break;
x += i;
- iplen += 4;
+ iplen += 16;
}
}
@@ -40,10 +41,8 @@ static int init(char ip[64])
while ((data.s[i] == ' ') || (data.s[i] == '\t'))
++i;
if (iplen <= 60)
- if (ip4_scan(data.s + i,ip + iplen)) {
- if (byte_equal(ip + iplen,4,"\0\0\0\0"))
- byte_copy(ip + iplen,4,"\177\0\0\1");
- iplen += 4;
+ if (ip6_scan(data.s + i,ip + iplen)) {
+ iplen += 16;
}
}
i = j + 1;
@@ -52,19 +51,19 @@ static int init(char ip[64])
}
if (!iplen) {
- byte_copy(ip,4,"\177\0\0\1");
- iplen = 4;
+ 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,64 - iplen);
+ byte_zero(ip + iplen,256 - iplen);
return 0;
}
static int ok = 0;
static unsigned int uses;
static struct taia deadline;
-static char ip[64]; /* defined if ok */
+static char ip[256]; /* defined if ok */
-int dns_resolvconfip(char s[64])
+int dns_resolvconfip(char s[256])
{
struct taia now;
@@ -81,6 +80,6 @@ int dns_resolvconfip(char s[64])
}
--uses;
- byte_copy(s,64,ip);
+ byte_copy(s,256,ip);
return 0;
}
diff --git a/dns_resolve.c b/dns_resolve.c
index 8bdea0d..82b5bbb 100644
--- a/dns_resolve.c
+++ b/dns_resolve.c
@@ -2,6 +2,7 @@
#include "taia.h"
#include "byte.h"
#include "dns.h"
+#include "ip6.h"
struct dns_transmit dns_resolve_tx = {0};
@@ -9,12 +10,12 @@ int dns_resolve(const char *q,const char qtype[2])
{
struct taia stamp;
struct taia deadline;
- char servers[64];
+ char servers[256];
iopause_fd x[1];
int r;
if (dns_resolvconfip(servers) == -1) return -1;
- if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,"\0\0\0\0") == -1) return -1;
+ if (dns_transmit_start(&dns_resolve_tx,servers,1,q,qtype,V6any) == -1) return -1;
for (;;) {
taia_now(&stamp);
diff --git a/dns_sortip6.c b/dns_sortip6.c
new file mode 100644
index 0000000..7e752e9
--- /dev/null
+++ b/dns_sortip6.c
@@ -0,0 +1,20 @@
+#include "byte.h"
+#include "dns.h"
+
+/* XXX: sort servers by configurable notion of closeness? */
+/* XXX: pay attention to competence of each server? */
+
+void dns_sortip6(char *s,unsigned int n)
+{
+ unsigned int i;
+ char tmp[16];
+
+ n >>= 4;
+ 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/dns_transmit.c b/dns_transmit.c
index 4d6e39f..cba1fd2 100644
--- a/dns_transmit.c
+++ b/dns_transmit.c
@@ -7,6 +7,7 @@
#include "byte.h"
#include "uint16.h"
#include "dns.h"
+#include "ip6.h"
static int serverwantstcp(const char *buf,unsigned int len)
{
@@ -85,9 +86,9 @@ static int randombind(struct dns_transmit *d)
int j;
for (j = 0;j < 10;++j)
- if (socket_bind4(d->s1 - 1,d->localip,1025 + dns_random(64510)) == 0)
+ if (socket_bind6(d->s1 - 1,d->localip,1025 + dns_random(64510),d->scope_id) == 0)
return 0;
- if (socket_bind4(d->s1 - 1,d->localip,0) == 0)
+ if (socket_bind6(d->s1 - 1,d->localip,0,d->scope_id) == 0)
return 0;
return -1;
}
@@ -102,16 +103,16 @@ static int thisudp(struct dns_transmit *d)
while (d->udploop < 4) {
for (;d->curserver < 16;++d->curserver) {
- ip = d->servers + 4 * d->curserver;
- if (byte_diff(ip,4,"\0\0\0\0")) {
+ ip = d->servers + 16 * d->curserver;
+ if (byte_diff(ip,16,V6any)) {
d->query[2] = dns_random(256);
d->query[3] = dns_random(256);
- d->s1 = 1 + socket_udp();
+ d->s1 = 1 + socket_udp6();
if (!d->s1) { dns_transmit_free(d); return -1; }
if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
- if (socket_connect4(d->s1 - 1,ip,53) == 0)
+ if (socket_connect6(d->s1 - 1,ip,53,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);
@@ -153,19 +154,19 @@ static int thistcp(struct dns_transmit *d)
packetfree(d);
for (;d->curserver < 16;++d->curserver) {
- ip = d->servers + 4 * d->curserver;
- if (byte_diff(ip,4,"\0\0\0\0")) {
+ ip = d->servers + 16 * d->curserver;
+ if (byte_diff(ip,16,V6any)) {
d->query[2] = dns_random(256);
d->query[3] = dns_random(256);
- d->s1 = 1 + socket_tcp();
+ d->s1 = 1 + socket_tcp6();
if (!d->s1) { dns_transmit_free(d); return -1; }
if (randombind(d) == -1) { dns_transmit_free(d); return -1; }
taia_now(&now);
taia_uint(&d->deadline,10);
taia_add(&d->deadline,&d->deadline,&now);
- if (socket_connect4(d->s1 - 1,ip,53) == 0) {
+ if (socket_connect6(d->s1 - 1,ip,53,d->scope_id) == 0) {
d->tcpstate = 2;
return 0;
}
@@ -193,7 +194,7 @@ static int nexttcp(struct dns_transmit *d)
return thistcp(d);
}
-int dns_transmit_start(struct dns_transmit *d,const char servers[64],int flagrecursive,const char *q,const char qtype[2],const char localip[4])
+int dns_transmit_start(struct dns_transmit *d,const char servers[256],int flagrecursive,const char *q,const char qtype[2],const char localip[16])
{
unsigned int len;
@@ -213,7 +214,7 @@ int dns_transmit_start(struct dns_transmit *d,const char servers[64],int flagrec
byte_copy(d->qtype,2,qtype);
d->servers = servers;
- byte_copy(d->localip,4,localip);
+ byte_copy(d->localip,16,localip);
d->udploop = flagrecursive ? 1 : 0;
diff --git a/dnscache.c b/dnscache.c
index 8c899a3..abcba69 100644
--- a/dnscache.c
+++ b/dnscache.c
@@ -5,6 +5,7 @@
#include "strerr.h"
#include "error.h"
#include "ip4.h"
+#include "ip6.h"
#include "uint16.h"
#include "uint64.h"
#include "socket.h"
@@ -23,6 +24,10 @@
#include "okclient.h"
#include "droproot.h"
+long interface;
+
+stralloc ignoreip = {0};
+
static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qclass[2],char id[2])
{
unsigned int pos;
@@ -46,8 +51,8 @@ static int packetquery(char *buf,unsigned int len,char **q,char qtype[2],char qc
}
-static char myipoutgoing[4];
-static char myipincoming[4];
+static char myipoutgoing[16];
+static char myipincoming[16];
static char buf[1024];
uint64 numqueries = 0;
@@ -60,9 +65,10 @@ static struct udpclient {
struct taia start;
uint64 active; /* query number, if active; otherwise 0 */
iopause_fd *io;
- char ip[4];
+ char ip[16];
uint16 port;
char id[2];
+ uint32 scope_id;
} u[MAXUDP];
int uactive = 0;
@@ -78,7 +84,7 @@ void u_respond(int j)
if (!u[j].active) return;
response_id(u[j].id);
if (response_len > 512) response_tc();
- socket_send4(udp53,response,response_len,u[j].ip,u[j].port);
+ socket_send6(udp53,response,response_len,u[j].ip,u[j].port,u[j].scope_id);
log_querydone(&u[j].active,response_len);
u[j].active = 0; --uactive;
}
@@ -109,7 +115,7 @@ void u_new(void)
x = u + j;
taia_now(&x->start);
- len = socket_recv4(udp53,buf,sizeof buf,x->ip,&x->port);
+ len = socket_recv6(udp53,buf,sizeof buf,x->ip,&x->port,&x->scope_id);
if (len == -1) return;
if (len >= sizeof buf) return;
if (x->port < 1024) if (x->port != 53) return;
@@ -119,7 +125,7 @@ void u_new(void)
x->active = ++numqueries; ++uactive;
log_query(&x->active,x->ip,x->port,x->id,q,qtype);
- switch(query_start(&x->q,q,qtype,qclass,myipoutgoing)) {
+ switch(query_start(&x->q,q,qtype,qclass,myipoutgoing,interface)) {
case -1:
u_drop(j);
return;
@@ -128,7 +134,6 @@ void u_new(void)
}
}
-
static int tcp53;
#define MAXTCP 20
@@ -138,7 +143,7 @@ struct tcpclient {
struct taia timeout;
uint64 active; /* query number or 1, if active; otherwise 0 */
iopause_fd *io;
- char ip[4]; /* send response to this address */
+ char ip[16]; /* send response to this address */
uint16 port; /* send response to this port */
char id[2];
int tcp; /* open TCP socket, if active */
@@ -146,6 +151,7 @@ struct tcpclient {
char *buf; /* 0, or dynamically allocated of length len */
unsigned int len;
unsigned int pos;
+ uint32 scope_id;
} t[MAXTCP];
int tactive = 0;
@@ -254,7 +260,7 @@ void t_rw(int j)
x->active = ++numqueries;
log_query(&x->active,x->ip,x->port,x->id,q,qtype);
- switch(query_start(&x->q,q,qtype,qclass,myipoutgoing)) {
+ switch(query_start(&x->q,q,qtype,qclass,myipoutgoing,interface)) {
case -1:
t_drop(j);
return;
@@ -291,7 +297,7 @@ void t_new(void)
x = t + j;
taia_now(&x->start);
- x->tcp = socket_accept4(tcp53,x->ip,&x->port);
+ x->tcp = socket_accept6(tcp53,x->ip,&x->port,&x->scope_id);
if (x->tcp == -1) return;
if (x->port < 1024) if (x->port != 53) { close(x->tcp); return; }
if (!okclient(x->ip)) { close(x->tcp); return; }
@@ -389,24 +395,36 @@ char seed[128];
int main()
{
char *x;
+ unsigned int i, j, k;
unsigned long cachesize;
+ static stralloc sa = {0};
+
+ x = env_get("INTERFACE");
+ if (x) scan_ulong(x,&interface);
x = env_get("IP");
if (!x)
strerr_die2x(111,FATAL,"$IP not set");
- if (!ip4_scan(x,myipincoming))
+ if (!ip6_scan(x,myipincoming))
strerr_die3x(111,FATAL,"unable to parse IP address ",x);
- udp53 = socket_udp();
+#if 0
+ /* if if IP is a mapped-IPv4 address, disable IPv6 functionality */
+ /* this is actually a bad idea */
+ if (ip6_isv4mapped(myipincoming))
+ noipv6 = 1;
+#endif
+
+ udp53 = socket_udp6();
if (udp53 == -1)
strerr_die2sys(111,FATAL,"unable to create UDP socket: ");
- if (socket_bind4_reuse(udp53,myipincoming,53) == -1)
+ if (socket_bind6_reuse(udp53,myipincoming,53,interface) == -1)
strerr_die2sys(111,FATAL,"unable to bind UDP socket: ");
- tcp53 = socket_tcp();
+ tcp53 = socket_tcp6();
if (tcp53 == -1)
strerr_die2sys(111,FATAL,"unable to create TCP socket: ");
- if (socket_bind4_reuse(tcp53,myipincoming,53) == -1)
+ if (socket_bind6_reuse(tcp53,myipincoming,53,interface) == -1)
strerr_die2sys(111,FATAL,"unable to bind TCP socket: ");
droproot(FATAL);
@@ -421,7 +439,7 @@ int main()
x = env_get("IPSEND");
if (!x)
strerr_die2x(111,FATAL,"$IPSEND not set");
- if (!ip4_scan(x,myipoutgoing))
+ if (!ip6_scan(x,myipoutgoing))
strerr_die3x(111,FATAL,"unable to parse IP address ",x);
x = env_get("CACHESIZE");
@@ -431,6 +449,20 @@ int main()
if (!cache_init(cachesize))
strerr_die3x(111,FATAL,"not enough memory for cache of size ",x);
+ if (openreadclose("ignoreip",&sa,64) < 0)
+ strerr_die2x(111,FATAL,"trouble reading ignoreip");
+ for(j = k = i = 0; i < sa.len; i++)
+ if (sa.s[i] == '\n') {
+ sa.s[i] = '\0';
+ if (!stralloc_readyplus(&ignoreip,16))
+ strerr_die2x(111,FATAL,"out of memory parsing ignoreip");
+ if (!ip6_scan(sa.s+k,ignoreip.s+j))
+ strerr_die3x(111,FATAL,"unable to parse address in ignoreip ",ignoreip.s+k);
+ j += 16;
+ k = i + 1;
+ }
+ ignoreip.len = j;
+
if (env_get("HIDETTL"))
response_hidettl();
if (env_get("FORWARDONLY"))
diff --git a/dnsfilter.c b/dnsfilter.c
index 9e6863a..822ff1e 100644
--- a/dnsfilter.c
+++ b/dnsfilter.c
@@ -12,6 +12,7 @@
#include "iopause.h"
#include "error.h"
#include "exit.h"
+#include "ip6.h"
#define FATAL "dnsfilter: fatal: "
@@ -44,7 +45,7 @@ int flag0 = 1;
iopause_fd *io;
int iolen;
-char servers[64];
+char servers[256];
char ip[4];
char name[DNS_NAME4_DOMAIN];
@@ -191,7 +192,7 @@ int main(int argc,char **argv)
dns_name4_domain(name,ip);
if (dns_resolvconfip(servers) == -1)
strerr_die2sys(111,FATAL,"unable to read /etc/resolv.conf: ");
- if (dns_transmit_start(&x[xnum].dt,servers,1,name,DNS_T_PTR,"\0\0\0\0") == -1)
+ if (dns_transmit_start(&x[xnum].dt,servers,1,name,DNS_T_PTR,V6any) == -1)
errout(xnum);
else {
x[xnum].flagactive = 1;
diff --git a/dnsip6.c b/dnsip6.c
new file mode 100644
index 0000000..5b65823
--- /dev/null
+++ b/dnsip6.c
@@ -0,0 +1,40 @@
+#include "buffer.h"
+#include "exit.h"
+#include "strerr.h"
+#include "ip6.h"
+#include "dns.h"
+
+#define FATAL "dnsip: fatal: "
+
+static char seed[128];
+
+static stralloc fqdn;
+static stralloc out;
+char str[IP6_FMT];
+
+main(int argc,char **argv)
+{
+ int i;
+
+ dns_random_init(seed);
+
+ if (*argv) ++argv;
+
+ while (*argv) {
+ if (!stralloc_copys(&fqdn,*argv))
+ strerr_die2x(111,FATAL,"out of memory");
+ if (dns_ip6(&out,&fqdn) == -1)
+ strerr_die4sys(111,FATAL,"unable to find IPv6 address for ",*argv,": ");
+
+ for (i = 0;i + 16 <= out.len;i += 16) {
+ buffer_put(buffer_1,str,ip6_fmt(str,out.s + i));
+ buffer_puts(buffer_1," ");
+ }
+ buffer_puts(buffer_1,"\n");
+
+ ++argv;
+ }
+
+ buffer_flush(buffer_1);
+ _exit(0);
+}
diff --git a/dnsip6q.c b/dnsip6q.c
new file mode 100644
index 0000000..82ab04e
--- /dev/null
+++ b/dnsip6q.c
@@ -0,0 +1,43 @@
+#include "buffer.h"
+#include "exit.h"
+#include "strerr.h"
+#include "ip6.h"
+#include "dns.h"
+
+#define FATAL "dnsipq: fatal: "
+
+static char seed[128];
+
+static stralloc in;
+static stralloc fqdn;
+static stralloc out;
+char str[IP6_FMT];
+
+int main(int argc,char **argv)
+{
+ int i;
+
+ dns_random_init(seed);
+
+ if (*argv) ++argv;
+
+ while (*argv) {
+ if (!stralloc_copys(&in,*argv))
+ strerr_die2x(111,FATAL,"out of memory");
+ if (dns_ip6_qualify(&out,&fqdn,&in) == -1)
+ strerr_die4sys(111,FATAL,"unable to find IP6 address for ",*argv,": ");
+
+ buffer_put(buffer_1,fqdn.s,fqdn.len);
+ buffer_puts(buffer_1," ");
+ for (i = 0;i + 16 <= out.len;i += 16) {
+ buffer_put(buffer_1,str,ip6_fmt(str,out.s + i));
+ buffer_puts(buffer_1," ");
+ }
+ buffer_puts(buffer_1,"\n");
+
+ ++argv;
+ }
+
+ buffer_flush(buffer_1);
+ _exit(0);
+}
diff --git a/dnsname.c b/dnsname.c
index 0e5eb26..ff9166d 100644
--- a/dnsname.c
+++ b/dnsname.c
@@ -2,6 +2,7 @@
#include "exit.h"
#include "strerr.h"
#include "ip4.h"
+#include "ip6.h"
#include "dns.h"
#define FATAL "dnsname: fatal: "
@@ -9,6 +10,7 @@
static char seed[128];
char ip[4];
+char ip6[16];
static stralloc out;
int main(int argc,char **argv)
@@ -18,10 +20,15 @@ int main(int argc,char **argv)
if (*argv) ++argv;
while (*argv) {
- if (!ip4_scan(*argv,ip))
- strerr_die3x(111,FATAL,"unable to parse IP address ",*argv);
- if (dns_name4(&out,ip) == -1)
- strerr_die4sys(111,FATAL,"unable to find host name for ",*argv,": ");
+ if (ip6_scan(*argv,ip6)) {
+ if (dns_name6(&out,ip6) == -1)
+ strerr_die4sys(111,FATAL,"unable to find host name for ",*argv,": ");
+ } else {
+ if (!ip4_scan(*argv,ip))
+ strerr_die3x(111,FATAL,"unable to parse IP address ",*argv);
+ if (dns_name4(&out,ip) == -1)
+ strerr_die4sys(111,FATAL,"unable to find host name for ",*argv,": ");
+ }
buffer_put(buffer_1,out.s,out.len);
buffer_puts(buffer_1,"\n");
diff --git a/dnsq.c b/dnsq.c
index 533e6af..9e89efe 100644
--- a/dnsq.c
+++ b/dnsq.c
@@ -10,6 +10,7 @@
#include "printpacket.h"
#include "parsetype.h"
#include "dns.h"
+#include "ip6.h"
#define FATAL "dnsq: fatal: "
@@ -24,14 +25,14 @@ void oops(void)
static struct dns_transmit tx;
-int resolve(char *q,char qtype[2],char servers[64])
+int resolve(char *q,char qtype[2],char servers[256])
{
struct taia stamp;
struct taia deadline;
iopause_fd x[1];
int r;
- if (dns_transmit_start(&tx,servers,0,q,qtype,"\0\0\0\0") == -1) return -1;
+ if (dns_transmit_start(&tx,servers,0,q,qtype,V6any) == -1) return -1;
for (;;) {
taia_now(&stamp);
@@ -47,7 +48,7 @@ int resolve(char *q,char qtype[2],char servers[64])
return 0;
}
-char servers[64];
+char servers[256];
static stralloc ip;
static stralloc fqdn;
@@ -73,9 +74,9 @@ int main(int argc,char **argv)
if (!*++argv) usage();
if (!stralloc_copys(&out,*argv)) oops();
- if (dns_ip4_qualify(&ip,&fqdn,&out) == -1) oops();
- if (ip.len >= 64) ip.len = 64;
- byte_zero(servers,64);
+ if (dns_ip6_qualify(&ip,&fqdn,&out) == -1) oops();
+ if (ip.len >= 256) ip.len = 256;
+ byte_zero(servers,256);
byte_copy(servers,ip.len,ip.s);
if (!stralloc_copys(&out,"")) oops();
diff --git a/dnstrace.c b/dnstrace.c
index 3f2159b..1d331bd 100644
--- a/dnstrace.c
+++ b/dnstrace.c
@@ -4,6 +4,7 @@
#include "str.h"
#include "byte.h"
#include "ip4.h"
+#include "ip6.h"
#include "gen_alloc.h"
#include "gen_allocdefs.h"
#include "exit.h"
@@ -30,7 +31,7 @@ void usage(void)
}
static stralloc querystr;
-char ipstr[IP4_FMT];
+char ipstr[IP6_FMT];
static stralloc tmp;
void printdomain(const char *d)
@@ -42,19 +43,19 @@ void printdomain(const char *d)
static struct dns_transmit tx;
-int resolve(char *q,char qtype[2],char ip[4])
+int resolve(char *q,char qtype[2],char ip[16])
{
struct taia start;
struct taia stamp;
struct taia deadline;
- char servers[64];
+ char servers[256];
iopause_fd x[1];
int r;
taia_now(&start);
- byte_zero(servers,64);
- byte_copy(servers,4,ip);
+ byte_zero(servers,256);
+ byte_copy(servers,16,ip);
if (dns_transmit_start(&tx,servers,0,q,qtype,"\0\0\0\0") == -1) return -1;
@@ -82,7 +83,7 @@ int resolve(char *q,char qtype[2],char ip[4])
struct address {
char *owner;
- char ip[4];
+ char ip[16];
} ;
GEN_ALLOC_typedef(address_alloc,struct address,s,len,a)
@@ -117,7 +118,7 @@ struct qt {
char *owner;
char type[2];
char *control;
- char ip[4];
+ char ip[16];
} ;
GEN_ALLOC_typedef(qt_alloc,struct qt,s,len,a)
@@ -126,7 +127,7 @@ GEN_ALLOC_append(qt_alloc,struct qt,s,len,a,i,n,x,30,qt_alloc_readyplus,qt_alloc
static qt_alloc qt;
-void qt_add(const char *q,const char type[2],const char *control,const char ip[4])
+void qt_add(const char *q,const char type[2],const char *control,const char ip[16])
{
struct qt x;
int i;
@@ -137,14 +138,14 @@ void qt_add(const char *q,const char type[2],const char *control,const char ip[4
if (dns_domain_equal(qt.s[i].owner,q))
if (dns_domain_equal(qt.s[i].control,control))
if (byte_equal(qt.s[i].type,2,type))
- if (byte_equal(qt.s[i].ip,4,ip))
+ if (byte_equal(qt.s[i].ip,16,ip))
return;
byte_zero(&x,sizeof x);
if (!dns_domain_copy(&x.owner,q)) nomem();
if (!dns_domain_copy(&x.control,control)) nomem();
byte_copy(x.type,2,type);
- byte_copy(x.ip,4,ip);
+ byte_copy(x.ip,16,ip);
if (!qt_alloc_append(&qt,&x)) nomem();
}
@@ -203,7 +204,7 @@ void ns_add(const char *owner,const char *server)
qt_add(query.s[i].owner,query.s[i].type,owner,address.s[j].ip);
}
-void address_add(const char *owner,const char ip[4])
+void address_add(const char *owner,const char ip[16])
{
struct address x;
int i;
@@ -213,17 +214,20 @@ void address_add(const char *owner,const char ip[4])
buffer_puts(buffer_1,"A:");
printdomain(owner);
buffer_puts(buffer_1,":");
- buffer_put(buffer_1,ipstr,ip4_fmt(ipstr,ip));
+ if (ip6_isv4mapped(ip))
+ buffer_put(buffer_1,ipstr,ip4_fmt(ipstr,ip+12));
+ else
+ buffer_put(buffer_1,ipstr,ip6_fmt(ipstr,ip));
buffer_puts(buffer_1,"\n");
for (i = 0;i < address.len;++i)
if (dns_domain_equal(address.s[i].owner,owner))
- if (byte_equal(address.s[i].ip,4,ip))
+ if (byte_equal(address.s[i].ip,16,ip))
return;
byte_zero(&x,sizeof x);
if (!dns_domain_copy(&x.owner,owner)) nomem();
- byte_copy(x.ip,4,ip);
+ byte_copy(x.ip,16,ip);
if (!address_alloc_append(&address,&x)) nomem();
for (i = 0;i < ns.len;++i)
@@ -331,7 +335,12 @@ void parsepacket(const char *buf,unsigned int len,const char *d,const char dtype
ns_add(t1,t2);
}
else if (typematch(header,DNS_T_A) && datalen == 4) {
- if (!dns_packet_copy(buf,len,pos,misc,4)) goto DIE;
+ if (!dns_packet_copy(buf,len,pos,misc+12,4)) goto DIE;
+ byte_copy(misc,12,V4mappedprefix);
+ address_add(t1,misc);
+ }
+ else if (typematch(header,DNS_T_AAAA) && datalen == 16) {
+ if (!dns_packet_copy(buf,len,pos,misc,16)) goto DIE;
address_add(t1,misc);
}
}
@@ -419,8 +428,8 @@ int main(int argc,char **argv)
while (*++argv) {
if (!stralloc_copys(&udn,*argv)) nomem();
- if (dns_ip4_qualify(&out,&fqdn,&udn) == -1) nomem(); /* XXX */
- for (i = 0;i + 4 <= out.len;i += 4)
+ if (dns_ip6_qualify(&out,&fqdn,&udn) == -1) nomem(); /* XXX */
+ for (i = 0;i + 16 <= out.len;i += 16)
address_add("",out.s + i);
}
@@ -429,7 +438,7 @@ int main(int argc,char **argv)
control = qt.s[i].control;
if (!dns_domain_suffix(q,control)) continue;
byte_copy(type,2,qt.s[i].type);
- byte_copy(ip,4,qt.s[i].ip);
+ byte_copy(ip,16,qt.s[i].ip);
if (!stralloc_copys(&querystr,"")) nomem();
uint16_unpack_big(type,&u16);
@@ -439,7 +448,10 @@ int main(int argc,char **argv)
if (!stralloc_cats(&querystr,":")) nomem();
if (!dns_domain_todot_cat(&querystr,control)) nomem();
if (!stralloc_cats(&querystr,":")) nomem();
- if (!stralloc_catb(&querystr,ipstr,ip4_fmt(ipstr,ip))) nomem();
+ if (ip6_isv4mapped(ip)) {
+ if (!stralloc_catb(&querystr,ipstr,ip4_fmt(ipstr,ip+12))) nomem();
+ } else
+ if (!stralloc_catb(&querystr,ipstr,ip6_fmt(ipstr,ip))) nomem();
if (!stralloc_cats(&querystr,":")) nomem();
buffer_put(buffer_1,querystr.s,querystr.len);
diff --git a/error.h b/error.h
index 35c976e..9cdd527 100644
--- a/error.h
+++ b/error.h
@@ -1,7 +1,7 @@
#ifndef ERROR_H
#define ERROR_H
-extern int errno;
+#include <errno.h>
extern int error_intr;
extern int error_nomem;
diff --git a/fmt_xlong.c b/fmt_xlong.c
new file mode 100644
index 0000000..332fc9a
--- /dev/null
+++ b/fmt_xlong.c
@@ -0,0 +1,22 @@
+#include "fmt.h"
+
+char tohex(char num) {
+ if (num<10)
+ return num+'0';
+ else if (num<16)
+ return num-10+'a';
+ else
+ return -1;
+}
+
+unsigned int fmt_xlong(register char *s,register unsigned long u)
+{
+ register unsigned int len; register unsigned long q;
+ len = 1; q = u;
+ while (q > 15) { ++len; q /= 16; }
+ if (s) {
+ s += len;
+ do { *--s = tohex(u % 16); u /= 16; } while(u); /* handles u == 0 */
+ }
+ return len;
+}
diff --git a/haveip6.h1 b/haveip6.h1
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/haveip6.h1
@@ -0,0 +1 @@
+
diff --git a/haveip6.h2 b/haveip6.h2
new file mode 100644
index 0000000..5564de9
--- /dev/null
+++ b/haveip6.h2
@@ -0,0 +1 @@
+#define LIBC_HAS_IP6 1
diff --git a/haven2i.h1 b/haven2i.h1
new file mode 100644
index 0000000..732c485
--- /dev/null
+++ b/haven2i.h1
@@ -0,0 +1 @@
+#undef HAVE_N2I
diff --git a/haven2i.h2 b/haven2i.h2
new file mode 100644
index 0000000..fd50644
--- /dev/null
+++ b/haven2i.h2
@@ -0,0 +1 @@
+#define HAVE_N2I
diff --git a/hier.c b/hier.c
index 4aef75b..f154ccf 100644
--- a/hier.c
+++ b/hier.c
@@ -29,7 +29,9 @@ void hier()
c(auto_home,"bin","axfr-get",-1,-1,0755);
c(auto_home,"bin","dnsip",-1,-1,0755);
+ c(auto_home,"bin","dnsip6",-1,-1,0755);
c(auto_home,"bin","dnsipq",-1,-1,0755);
+ c(auto_home,"bin","dnsip6q",-1,-1,0755);
c(auto_home,"bin","dnsname",-1,-1,0755);
c(auto_home,"bin","dnstxt",-1,-1,0755);
c(auto_home,"bin","dnsmx",-1,-1,0755);
diff --git a/ip6.h b/ip6.h
new file mode 100644
index 0000000..f8576cf
--- /dev/null
+++ b/ip6.h
@@ -0,0 +1,28 @@
+#ifndef IP6_H
+#define IP6_H
+
+extern unsigned int ip6_scan(const char *,char *);
+extern unsigned int ip6_fmt(char *,const char *);
+
+extern unsigned int ip6_scan_flat(const char *,char *);
+extern unsigned int ip6_fmt_flat(char *,const char *);
+
+/*
+ ip6 address syntax: (h = hex digit), no leading '0' required
+ 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh
+ 2. any number of 0000 may be abbreviated as "::", but only once
+ flat ip6 address syntax:
+ hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh
+ */
+
+#define IP6_FMT 40
+
+const static unsigned char V4mappedprefix[12]={0,0,0,0,0,0,0,0,0,0,0xff,0xff};
+const static unsigned char V6loopback[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1};
+const static unsigned char V6any[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+#define ip6_isv4mapped(ip) (byte_equal(ip,12,V4mappedprefix))
+
+const static char ip4loopback[4] = {127,0,0,1};
+
+#endif
diff --git a/ip6_fmt.c b/ip6_fmt.c
new file mode 100644
index 0000000..ce2115a
--- /dev/null
+++ b/ip6_fmt.c
@@ -0,0 +1,60 @@
+#include "fmt.h"
+#include "byte.h"
+#include "ip4.h"
+#include "ip6.h"
+#include <stdio.h>
+
+extern char tohex(char num);
+
+unsigned int ip6_fmt(char *s,const char ip[16])
+{
+ unsigned int len;
+ unsigned int i;
+ unsigned int temp;
+ unsigned int compressing;
+ unsigned int compressed;
+ int j;
+
+ len = 0; compressing = 0; compressed = 0;
+ for (j=0; j<16; j+=2) {
+ if (j==12 && ip6_isv4mapped(ip)) {
+ temp=ip4_fmt(s,ip+12);
+ len+=temp;
+ break;
+ }
+ temp = ((unsigned long) (unsigned char) ip[j] << 8) +
+ (unsigned long) (unsigned char) ip[j+1];
+ if (temp == 0 && !compressed) {
+ if (!compressing) {
+ compressing=1;
+ if (j==0) {
+ if (s) *s++=':'; ++len;
+ }
+ }
+ } else {
+ if (compressing) {
+ compressing=0; ++compressed;
+ if (s) *s++=':'; ++len;
+ }
+ i = fmt_xlong(s,temp); len += i; if (s) s += i;
+ if (j<14) {
+ if (s) *s++ = ':';
+ ++len;
+ }
+ }
+ }
+ if (compressing) { *s++=':'; ++len; }
+
+/* if (s) *s=0; */
+ return len;
+}
+
+unsigned int ip6_fmt_flat(char *s,const char ip[16])
+{
+ int i;
+ for (i=0; i<16; i++) {
+ *s++=tohex((unsigned char)ip[i] >> 4);
+ *s++=tohex((unsigned char)ip[i] & 15);
+ }
+ return 32;
+}
diff --git a/ip6_scan.c b/ip6_scan.c
new file mode 100644
index 0000000..f355d46
--- /dev/null
+++ b/ip6_scan.c
@@ -0,0 +1,115 @@
+#include "scan.h"
+#include "ip4.h"
+#include "ip6.h"
+#include "byte.h"
+
+/*
+ * IPv6 addresses are really ugly to parse.
+ * Syntax: (h = hex digit)
+ * 1. hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh:hhhh
+ * 2. any number of 0000 may be abbreviated as "::", but only once
+ * 3. The last two words may be written as IPv4 address
+ */
+
+unsigned int ip6_scan(const char *s,char ip[16])
+{
+ unsigned int i;
+ unsigned int len=0;
+ unsigned long u;
+
+ char suffix[16];
+ int prefixlen=0;
+ int suffixlen=0;
+
+ if ((i=ip4_scan(s,ip+12))) {
+ const char *c=V4mappedprefix;
+ if (byte_equal(ip+12,4,V6any)) c=V6any;
+ for (len=0; len<12; ++len) ip[len]=c[len];
+ return i;
+ }
+ for (i=0; i<16; i++) ip[i]=0;
+ for (;;) {
+ if (*s == ':') {
+ len++;
+ if (s[1] == ':') { /* Found "::", skip to part 2 */
+ s+=2;
+ len++;
+ break;
+ }
+ s++;
+ }
+ i = scan_xlong(s,&u);
+ if (!i) return 0;
+ if (prefixlen==12 && s[i]=='.') {
+ /* the last 4 bytes may be written as IPv4 address */
+ i=ip4_scan(s,ip+12);
+ if (i)
+ return i+len;
+ else
+ return 0;
+ }
+ ip[prefixlen++] = (u >> 8);
+ ip[prefixlen++] = (u & 255);
+ s += i; len += i;
+ if (prefixlen==16)
+ return len;
+ }
+
+/* part 2, after "::" */
+ for (;;) {
+ if (*s == ':') {
+ if (suffixlen==0)
+ break;
+ s++;
+ len++;
+ } else if (suffixlen!=0)
+ break;
+ i = scan_xlong(s,&u);
+ if (!i) {
+ len--;
+ break;
+ }
+ if (suffixlen+prefixlen<=12 && s[i]=='.') {
+ int j=ip4_scan(s,suffix+suffixlen);
+ if (j) {
+ suffixlen+=4;
+ len+=j;
+ break;
+ } else
+ prefixlen=12-suffixlen; /* make end-of-loop test true */
+ }
+ suffix[suffixlen++] = (u >> 8);
+ suffix[suffixlen++] = (u & 255);
+ s += i; len += i;
+ if (prefixlen+suffixlen==16)
+ break;
+ }
+ for (i=0; i<suffixlen; i++)
+ ip[16-suffixlen+i] = suffix[i];
+ return len;
+}
+
+static long int fromhex(unsigned char c) {
+ if (c>='0' && c<='9')
+ return c-'0';
+ else if (c>='A' && c<='F')
+ return c-'A'+10;
+ else if (c>='a' && c<='f')
+ return c-'a'+10;
+ return -1;
+}
+
+unsigned int ip6_scan_flat(const char *s,char ip[16])
+{
+ int i;
+ for (i=0; i<16; i++) {
+ int tmp;
+ tmp=fromhex(*s++);
+ if (tmp<0) return 0;
+ ip[i]=tmp << 4;
+ tmp=fromhex(*s++);
+ if (tmp<0) return 0;
+ ip[i]+=tmp;
+ }
+ return 32;
+}
diff --git a/log.c b/log.c
index c43e8b0..df465e2 100644
--- a/log.c
+++ b/log.c
@@ -3,6 +3,7 @@
#include "uint16.h"
#include "error.h"
#include "byte.h"
+#include "ip6.h"
#include "log.h"
/* work around gcc 2.95.2 bug */
@@ -45,12 +46,10 @@ static void space(void)
string(" ");
}
-static void ip(const char i[4])
+static void ip(const char i[16])
{
- hex(i[0]);
- hex(i[1]);
- hex(i[2]);
- hex(i[3]);
+ int j;
+ for (j=0; j<16; ++j) hex(i[j]);
}
static void logid(const char id[2])
@@ -94,7 +93,7 @@ void log_startup(void)
line();
}
-void log_query(uint64 *qnum,const char client[4],unsigned int port,const char id[2],const char *q,const char qtype[2])
+void log_query(uint64 *qnum,const char client[16],unsigned int port,const char id[2],const char *q,const char qtype[2])
{
string("query "); number(*qnum); space();
ip(client); string(":"); hex(port >> 8); hex(port & 255);
@@ -119,14 +118,14 @@ void log_querydrop(uint64 *qnum)
line();
}
-void log_tcpopen(const char client[4],unsigned int port)
+void log_tcpopen(const char client[16],unsigned int port)
{
string("tcpopen ");
ip(client); string(":"); hex(port >> 8); hex(port & 255);
line();
}
-void log_tcpclose(const char client[4],unsigned int port)
+void log_tcpclose(const char client[16],unsigned int port)
{
const char *x = error_str(errno);
string("tcpclose ");
@@ -135,15 +134,15 @@ void log_tcpclose(const char client[4],unsigned int port)
line();
}
-void log_tx(const char *q,const char qtype[2],const char *control,const char servers[64],unsigned int gluelessness)
+void log_tx(const char *q,const char qtype[2],const char *control,const char servers[256],unsigned int gluelessness)
{
int i;
string("tx "); number(gluelessness); space();
logtype(qtype); space(); name(q); space();
name(control);
- for (i = 0;i < 64;i += 4)
- if (byte_diff(servers + i,4,"\0\0\0\0")) {
+ for (i = 0;i < 256;i += 16)
+ if (byte_diff(servers + i,16,V6any)) {
space();
ip(servers + i);
}
@@ -175,21 +174,21 @@ void log_cachednxdomain(const char *dn)
line();
}
-void log_nxdomain(const char server[4],const char *q,unsigned int ttl)
+void log_nxdomain(const char server[16],const char *q,unsigned int ttl)
{
string("nxdomain "); ip(server); space(); number(ttl); space();
name(q);
line();
}
-void log_nodata(const char server[4],const char *q,const char qtype[2],unsigned int ttl)
+void log_nodata(const char server[16],const char *q,const char qtype[2],unsigned int ttl)
{
string("nodata "); ip(server); space(); number(ttl); space();
logtype(qtype); space(); name(q);
line();
}
-void log_lame(const char server[4],const char *control,const char *referral)
+void log_lame(const char server[16],const char *control,const char *referral)
{
string("lame "); ip(server); space();
name(control); space(); name(referral);
@@ -205,7 +204,7 @@ void log_servfail(const char *dn)
line();
}
-void log_rr(const char server[4],const char *q,const char type[2],const char *buf,unsigned int len,unsigned int ttl)
+void log_rr(const char server[16],const char *q,const char type[2],const char *buf,unsigned int len,unsigned int ttl)
{
int i;
@@ -222,7 +221,7 @@ void log_rr(const char server[4],const char *q,const char type[2],const char *bu
line();
}
-void log_rrns(const char server[4],const char *q,const char *data,unsigned int ttl)
+void log_rrns(const char server[16],const char *q,const char *data,unsigned int ttl)
{
string("rr "); ip(server); space(); number(ttl);
string(" ns "); name(q); space();
@@ -230,7 +229,7 @@ void log_rrns(const char server[4],const char *q,const char *data,unsigned int t
line();
}
-void log_rrcname(const char server[4],const char *q,const char *data,unsigned int ttl)
+void log_rrcname(const char server[16],const char *q,const char *data,unsigned int ttl)
{
string("rr "); ip(server); space(); number(ttl);
string(" cname "); name(q); space();
@@ -238,7 +237,7 @@ void log_rrcname(const char server[4],const char *q,const char *data,unsigned in
line();
}
-void log_rrptr(const char server[4],const char *q,const char *data,unsigned int ttl)
+void log_rrptr(const char server[16],const char *q,const char *data,unsigned int ttl)
{
string("rr "); ip(server); space(); number(ttl);
string(" ptr "); name(q); space();
@@ -246,7 +245,7 @@ void log_rrptr(const char server[4],const char *q,const char *data,unsigned int
line();
}
-void log_rrmx(const char server[4],const char *q,const char *mx,const char pref[2],unsigned int ttl)
+void log_rrmx(const char server[16],const char *q,const char *mx,const char pref[2],unsigned int ttl)
{
uint16 u;
@@ -257,7 +256,7 @@ void log_rrmx(const char server[4],const char *q,const char *mx,const char pref[
line();
}
-void log_rrsoa(const char server[4],const char *q,const char *n1,const char *n2,const char misc[20],unsigned int ttl)
+void log_rrsoa(const char server[16],const char *q,const char *n1,const char *n2,const char misc[20],unsigned int ttl)
{
uint32 u;
int i;
diff --git a/okclient.c b/okclient.c
index a648c02..9a0d3c6 100644
--- a/okclient.c
+++ b/okclient.c
@@ -2,24 +2,34 @@
#include <sys/stat.h>
#include "str.h"
#include "ip4.h"
+#include "ip6.h"
+#include "byte.h"
#include "okclient.h"
-static char fn[3 + IP4_FMT];
+static char fn[3 + IP6_FMT];
-int okclient(char ip[4])
+int okclient(char ip[16])
{
struct stat st;
int i;
+ char sep;
fn[0] = 'i';
fn[1] = 'p';
fn[2] = '/';
- fn[3 + ip4_fmt(fn + 3,ip)] = 0;
+ if (byte_equal(ip,12,V4mappedprefix)) {
+ fn[3 + ip4_fmt(fn + 3,ip+12)] = 0;
+ sep='.';
+ } else {
+ fn[3 + ip6_fmt(fn + 3,ip)] = 0;
+ sep=':';
+ }
for (;;) {
+ if (!fn[3]) return 0;
if (stat(fn,&st) == 0) return 1;
/* treat temporary error as rejection */
- i = str_rchr(fn,'.');
+ i = str_rchr(fn,sep);
if (!fn[i]) return 0;
fn[i] = 0;
}
diff --git a/pickdns.c b/pickdns.c
index 28c4ba5..aa74dd8 100644
--- a/pickdns.c
+++ b/pickdns.c
@@ -20,7 +20,7 @@ static struct cdb c;
static char key[258];
static char data[512];
-static int doit(char *q,char qtype[2],char ip[4])
+static int doit(char *q,char qtype[2],char ip[16])
{
int r;
uint32 dlen;
@@ -37,7 +37,7 @@ static int doit(char *q,char qtype[2],char ip[4])
if (!flaga && !flagmx) goto REFUSE;
key[0] = '%';
- byte_copy(key + 1,4,ip);
+ byte_copy(key + 1,4,ip+12);
r = cdb_find(&c,key,5);
if (!r) r = cdb_find(&c,key,4);
@@ -86,7 +86,7 @@ static int doit(char *q,char qtype[2],char ip[4])
return 1;
}
-int respond(char *q,char qtype[2],char ip[4])
+int respond(char *q,char qtype[2],char ip[16])
{
int fd;
int result;
diff --git a/printrecord.c b/printrecord.c
index ed0b42d..4bc7c3e 100644
--- a/printrecord.c
+++ b/printrecord.c
@@ -4,6 +4,7 @@
#include "byte.h"
#include "dns.h"
#include "printrecord.h"
+#include "ip6.h"
static char *d;
@@ -82,6 +83,15 @@ unsigned int printrecord_cat(stralloc *out,const char *buf,unsigned int len,unsi
if (!stralloc_catulong0(out,ch,0)) return 0;
}
}
+ else if (byte_equal(misc,2,DNS_T_AAAA)) {
+ char ip6str[IP6_FMT];
+ int stringlen;
+ if (datalen != 16) { errno = error_proto; return 0; }
+ if (!stralloc_cats(out," AAAA ")) return 0;
+ pos = dns_packet_copy(buf,len,pos,misc,16); if (!pos) return 0;
+ stringlen=ip6_fmt(ip6str,misc);
+ if (!stralloc_catb(out,ip6str,stringlen)) return 0;
+ }
else {
if (!stralloc_cats(out," ")) return 0;
uint16_unpack_big(misc,&u16);
diff --git a/qlog.c b/qlog.c
index 5c5c7ba..60816df 100644
--- a/qlog.c
+++ b/qlog.c
@@ -20,15 +20,15 @@ static void octal(unsigned char c)
put('0' + (c & 7));
}
-void qlog(const char ip[4],uint16 port,const char id[2],const char *q,const char qtype[2],const char *result)
+void qlog(const char ip[16],uint16 port,const char id[2],const char *q,const char qtype[2],const char *result)
{
char ch;
char ch2;
- hex(ip[0]);
- hex(ip[1]);
- hex(ip[2]);
- hex(ip[3]);
+ {
+ int i;
+ for (i=0; i<16; ++i) hex(ip[i]);
+ }
put(':');
hex(port >> 8);
hex(port & 255);
diff --git a/query.c b/query.c
index 46cdc00..d61b20c 100644
--- a/query.c
+++ b/query.c
@@ -12,6 +12,9 @@
#include "alloc.h"
#include "response.h"
#include "query.h"
+#include "ip6.h"
+
+extern stralloc ignoreip;
static int flagforwardonly = 0;
@@ -110,7 +113,7 @@ static int rqa(struct query *z)
return 1;
}
-static int globalip(char *d,char ip[4])
+static int globalip(char *d,char ip[16])
{
if (dns_domain_equal(d,"\011localhost\0")) {
byte_copy(ip,4,"\177\0\0\1");
@@ -165,7 +168,7 @@ static int doit(struct query *z,int state)
char *buf;
unsigned int len;
const char *whichserver;
- char header[12];
+ char header[24];
char misc[20];
unsigned int rcode;
unsigned int posanswers;
@@ -193,6 +196,7 @@ static int doit(struct query *z,int state)
int k;
int p;
int q;
+ unsigned int ii;
errno = error_io;
if (state == 1) goto HAVEPACKET;
@@ -205,14 +209,15 @@ static int doit(struct query *z,int state)
NEWNAME:
if (++z->loop == 100) goto DIE;
d = z->name[z->level];
- dtype = z->level ? DNS_T_A : z->type;
+ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
dlen = dns_domain_length(d);
if (globalip(d,misc)) {
if (z->level) {
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- byte_copy(z->servers[z->level - 1] + k,4,misc);
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ byte_copy(z->servers[z->level - 1] + k + 12,4,misc);
break;
}
goto LOWERLEVEL;
@@ -227,6 +232,158 @@ static int doit(struct query *z,int state)
return 1;
}
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\016ipv6-localhost\0")) goto DIE;
+ if (!response_addname("\015ipv6-loopback\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\001e\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-localnet\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\020ipv6-mcastprefix\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-allnodes\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0012\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\017ipv6-allrouters\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\0011\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0010\0012\0010\001f\001f\003ip6\003int\0")) {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_PTR,dtype)) {
+ if (!response_rstart(d,DNS_T_PTR,655360)) goto DIE;
+ if (!response_addname("\015ipv6-allhosts\0")) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\016ipv6-localhost\0") ||
+ dns_domain_equal(d,"\015ipv6-loopback\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\001",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\015ipv6-localnet\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\376\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\020ipv6-mcastprefix\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\15ipv6-allnodes\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\001",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\17ipv6-allrouters\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\002",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
+ if (dns_domain_equal(d,"\15ipv6-allhosts\0"))
+ {
+ if (z->level) goto LOWERLEVEL;
+ if (!rqa(z)) goto DIE;
+ if (typematch(DNS_T_AAAA,dtype)) {
+ if (!response_rstart(d,DNS_T_AAAA,655360)) goto DIE;
+ if (!response_addbytes("\377\002\000\000\000\000\000\000\000\000\000\000\000\000\000\003",16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ }
+ cleanup(z);
+ return 1;
+ }
+
if (dns_domain_equal(d,"\0011\0010\0010\003127\7in-addr\4arpa\0")) {
if (z->level) goto LOWERLEVEL;
if (!rqa(z)) goto DIE;
@@ -322,13 +479,18 @@ static int doit(struct query *z,int state)
if (typematch(DNS_T_A,dtype)) {
byte_copy(key,2,DNS_T_A);
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+ if (cached && !cachedlen && z->level) { /* if we were looking the A record up to find an NS, try IPv6 too */
+ z->ipv6[z->level]=1;
+ goto NEWNAME;
+ }
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
if (z->level) {
log_cachedanswer(d,DNS_T_A);
while (cachedlen >= 4) {
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- byte_copy(z->servers[z->level - 1] + k,4,cached);
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ byte_copy(z->servers[z->level - 1] + k + 12,4,cached);
break;
}
cached += 4;
@@ -351,7 +513,39 @@ static int doit(struct query *z,int state)
}
}
- if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype)) {
+ if (typematch(DNS_T_AAAA,dtype)) {
+ byte_copy(key,2,DNS_T_AAAA);
+ cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
+ if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
+ if (z->level) {
+ log_cachedanswer(d,DNS_T_AAAA);
+ while (cachedlen >= 16) {
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,16,cached);
+ break;
+ }
+ cached += 16;
+ cachedlen -= 16;
+ }
+ goto LOWERLEVEL;
+ }
+
+ log_cachedanswer(d,DNS_T_AAAA);
+ if (!rqa(z)) goto DIE;
+ while (cachedlen >= 16) {
+ if (!response_rstart(d,DNS_T_AAAA,ttl)) goto DIE;
+ if (!response_addbytes(cached,16)) goto DIE;
+ response_rfinish(RESPONSE_ANSWER);
+ cached += 16;
+ cachedlen -= 16;
+ }
+ cleanup(z);
+ return 1;
+ }
+ }
+
+ if (!typematch(DNS_T_ANY,dtype) && !typematch(DNS_T_AXFR,dtype) && !typematch(DNS_T_CNAME,dtype) && !typematch(DNS_T_NS,dtype) && !typematch(DNS_T_PTR,dtype) && !typematch(DNS_T_A,dtype) && !typematch(DNS_T_MX,dtype) && !typematch(DNS_T_AAAA,dtype)) {
byte_copy(key,2,dtype);
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
if (cached && (cachedlen || byte_diff(dtype,2,DNS_T_ANY))) {
@@ -390,7 +584,7 @@ static int doit(struct query *z,int state)
cached = cache_get(key,dlen + 2,&cachedlen,&ttl);
if (cached && cachedlen) {
z->control[z->level] = d;
- byte_zero(z->servers[z->level],64);
+ byte_zero(z->servers[z->level],256);
for (j = 0;j < QUERY_MAXNS;++j)
dns_domain_free(&z->ns[z->level][j]);
pos = 0;
@@ -418,20 +612,22 @@ static int doit(struct query *z,int state)
if (!dns_domain_copy(&z->name[z->level + 1],z->ns[z->level][j])) goto DIE;
dns_domain_free(&z->ns[z->level][j]);
++z->level;
+ z->ipv6[z->level]=0;
goto NEWNAME;
}
dns_domain_free(&z->ns[z->level][j]);
}
- for (j = 0;j < 64;j += 4)
- if (byte_diff(z->servers[z->level] + j,4,"\0\0\0\0"))
+ for (j = 0;j < 256;j += 16)
+ if (byte_diff(z->servers[z->level] + j,16,V6any))
break;
- if (j == 64) goto SERVFAIL;
+ if (j == 256) goto SERVFAIL;
- dns_sortip(z->servers[z->level],64);
+ dns_sortip6(z->servers[z->level],256);
if (z->level) {
- log_tx(z->name[z->level],DNS_T_A,z->control[z->level],z->servers[z->level],z->level);
- if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],DNS_T_A,z->localip) == -1) goto DIE;
+ dtype = z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A;
+ log_tx(z->name[z->level],dtype,z->control[z->level],z->servers[z->level],z->level);
+ if (dns_transmit_start(&z->dt,z->servers[z->level],flagforwardonly,z->name[z->level],dtype,z->localip) == -1) goto DIE;
}
else {
log_tx(z->name[0],z->type,z->control[0],z->servers[0],0);
@@ -453,10 +649,11 @@ static int doit(struct query *z,int state)
buf = z->dt.packet;
len = z->dt.packetlen;
- whichserver = z->dt.servers + 4 * z->dt.curserver;
+ whichserver = z->dt.servers + 16 * z->dt.curserver;
control = z->control[z->level];
d = z->name[z->level];
- dtype = z->level ? DNS_T_A : z->type;
+/* dtype = z->level ? DNS_T_A : z->type; */
+ dtype = z->level ? (z->ipv6[z->level] ? DNS_T_AAAA : DNS_T_A) : z->type;
pos = dns_packet_copy(buf,len,0,header,12); if (!pos) goto DIE;
pos = dns_packet_skipname(buf,len,pos); if (!pos) goto DIE;
@@ -519,7 +716,7 @@ static int doit(struct query *z,int state)
if (!flagcname && !rcode && !flagout && flagreferral && !flagsoa)
if (dns_domain_equal(referral,control) || !dns_domain_suffix(referral,control)) {
log_lame(whichserver,control,referral);
- byte_zero(whichserver,4);
+ byte_zero(whichserver,16);
goto HAVENS;
}
@@ -643,6 +840,11 @@ static int doit(struct query *z,int state)
pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
if (byte_equal(header + 8,2,"\0\4")) {
pos = dns_packet_copy(buf,len,pos,header,4); if (!pos) goto DIE;
+ if (ignoreip.len)
+ for(ii = 0; ii < ignoreip.len; ii+= 16) {
+ if (byte_equal(ignoreip.s+ii,12,V4mappedprefix) &&
+ byte_equal(header,4,ignoreip.s+ii+12)) goto NXDOMAIN;
+ }
save_data(header,4);
log_rr(whichserver,t1,DNS_T_A,header,4,ttl);
}
@@ -650,6 +852,23 @@ static int doit(struct query *z,int state)
}
save_finish(DNS_T_A,t1,ttl);
}
+ else if (byte_equal(type,2,DNS_T_AAAA)) {
+ save_start();
+ while (i < j) {
+ pos = dns_packet_skipname(buf,len,records[i]); if (!pos) goto DIE;
+ pos = dns_packet_copy(buf,len,pos,header,10); if (!pos) goto DIE;
+ if (byte_equal(header + 8,2,"\0\20")) {
+ pos = dns_packet_copy(buf,len,pos,header,16); if (!pos) goto DIE;
+ if (ignoreip.len)
+ for(ii = 0; ii < ignoreip.len; ii+= 16)
+ if (byte_equal(header,16,ignoreip.s+ii)) goto NXDOMAIN;
+ save_data(header,16);
+ log_rr(whichserver,t1,DNS_T_AAAA,header,16,ttl);
+ }
+ ++i;
+ }
+ save_finish(DNS_T_AAAA,t1,ttl);
+ }
else {
save_start();
while (i < j) {
@@ -707,6 +926,11 @@ static int doit(struct query *z,int state)
save_start();
save_finish(dtype,d,soattl);
log_nodata(whichserver,d,dtype,soattl);
+ if (z->level && !byte_diff(DNS_T_A,2,dtype)) {
+ d = z->name[z->level];
+ z->ipv6[z->level] = 1;
+ goto NEWNAME; /* retry, will ask for AAAA next */
+ }
}
log_stats();
@@ -723,9 +947,18 @@ static int doit(struct query *z,int state)
if (typematch(header,DNS_T_A))
if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
if (datalen == 4)
- for (k = 0;k < 64;k += 4)
- if (byte_equal(z->servers[z->level - 1] + k,4,"\0\0\0\0")) {
- if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k,4)) goto DIE;
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ byte_copy(z->servers[z->level - 1] + k,12,V4mappedprefix);
+ if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k + 12,4)) goto DIE;
+ break;
+ }
+ if (typematch(header,DNS_T_AAAA))
+ if (byte_equal(header + 2,2,DNS_C_IN)) /* should always be true */
+ if (datalen == 16)
+ for (k = 0;k < 256;k += 16)
+ if (byte_equal(z->servers[z->level - 1] + k,16,V6any)) {
+ if (!dns_packet_copy(buf,len,pos,z->servers[z->level - 1] + k,16)) goto DIE;
break;
}
pos += datalen;
@@ -783,7 +1016,7 @@ static int doit(struct query *z,int state)
if (!dns_domain_suffix(d,referral)) goto DIE;
control = d + dns_domain_suffixpos(d,referral);
z->control[z->level] = control;
- byte_zero(z->servers[z->level],64);
+ byte_zero(z->servers[z->level],256);
for (j = 0;j < QUERY_MAXNS;++j)
dns_domain_free(&z->ns[z->level][j]);
k = 0;
@@ -818,7 +1051,7 @@ static int doit(struct query *z,int state)
return -1;
}
-int query_start(struct query *z,char *dn,char type[2],char class[2],char localip[4])
+int query_start(struct query *z,char *dn,char type[2],char class[2],char localip[16],unsigned int scope_id)
{
if (byte_equal(type,2,DNS_T_AXFR)) { errno = error_perm; return -1; }
@@ -829,7 +1062,9 @@ int query_start(struct query *z,char *dn,char type[2],char class[2],char localip
if (!dns_domain_copy(&z->name[0],dn)) return -1;
byte_copy(z->type,2,type);
byte_copy(z->class,2,class);
- byte_copy(z->localip,4,localip);
+ byte_copy(z->localip,16,localip);
+ z->scope_id=scope_id;
+ z->ipv6[0]=0;
return doit(z,0);
}
diff --git a/query.h b/query.h
index eff68b2..61812aa 100644
--- a/query.h
+++ b/query.h
@@ -14,16 +14,18 @@ struct query {
char *name[QUERY_MAXLEVEL];
char *control[QUERY_MAXLEVEL]; /* pointing inside name */
char *ns[QUERY_MAXLEVEL][QUERY_MAXNS];
- char servers[QUERY_MAXLEVEL][64];
+ char servers[QUERY_MAXLEVEL][256];
char *alias[QUERY_MAXALIAS];
uint32 aliasttl[QUERY_MAXALIAS];
- char localip[4];
+ char ipv6[QUERY_MAXLEVEL];
+ char localip[16];
+ uint32 scope_id;
char type[2];
char class[2];
struct dns_transmit dt;
} ;
-extern int query_start(struct query *,char *,char *,char *,char *);
+extern int query_start(struct query *,char *,char *,char *,char *,unsigned int);
extern void query_io(struct query *,iopause_fd *,struct taia *);
extern int query_get(struct query *,iopause_fd *,struct taia *);
diff --git a/roots.c b/roots.c
index 3cfe959..4162ec5 100644
--- a/roots.c
+++ b/roots.c
@@ -6,6 +6,7 @@
#include "error.h"
#include "direntry.h"
#include "ip4.h"
+#include "ip6.h"
#include "dns.h"
#include "openreadclose.h"
#include "roots.h"
@@ -22,7 +23,7 @@ static int roots_find(char *q)
j = dns_domain_length(data.s + i);
if (dns_domain_equal(data.s + i,q)) return i + j;
i += j;
- i += 64;
+ i += 256;
}
return -1;
}
@@ -40,12 +41,12 @@ static int roots_search(char *q)
}
}
-int roots(char servers[64],char *q)
+int roots(char servers[256],char *q)
{
int r;
r = roots_find(q);
if (r == -1) return 0;
- byte_copy(servers,64,data.s + r);
+ byte_copy(servers,256,data.s + r);
return 1;
}
@@ -60,7 +61,7 @@ static int init2(DIR *dir)
const char *fqdn;
static char *q;
static stralloc text;
- char servers[64];
+ char servers[256];
int serverslen;
int i;
int j;
@@ -86,14 +87,14 @@ static int init2(DIR *dir)
for (i = 0;i < text.len;++i)
if (text.s[i] == '\n') {
if (serverslen <= 60)
- if (ip4_scan(text.s + j,servers + serverslen))
- serverslen += 4;
+ if (ip6_scan(text.s + j,servers + serverslen))
+ serverslen += 16;
j = i + 1;
}
- byte_zero(servers + serverslen,64 - serverslen);
+ byte_zero(servers + serverslen,256 - serverslen);
if (!stralloc_catb(&data,q,dns_domain_length(q))) return 0;
- if (!stralloc_catb(&data,servers,64)) return 0;
+ if (!stralloc_catb(&data,servers,256)) return 0;
}
}
}
diff --git a/scan_xlong.c b/scan_xlong.c
new file mode 100644
index 0000000..1113433
--- /dev/null
+++ b/scan_xlong.c
@@ -0,0 +1,23 @@
+#include "scan.h"
+
+static inline int fromhex(unsigned char c) {
+ if (c>='0' && c<='9')
+ return c-'0';
+ else if (c>='A' && c<='F')
+ return c-'A'+10;
+ else if (c>='a' && c<='f')
+ return c-'a'+10;
+ return -1;
+}
+
+unsigned int scan_xlong(const char *src,unsigned long *dest) {
+ register const char *tmp=src;
+ register int l=0;
+ register unsigned char c;
+ while ((c=fromhex(*tmp))<16) {
+ l=(l<<4)+c;
+ ++tmp;
+ }
+ *dest=l;
+ return tmp-src;
+}
diff --git a/server.c b/server.c
index e486fe1..d52ce87 100644
--- a/server.c
+++ b/server.c
@@ -4,6 +4,7 @@
#include "buffer.h"
#include "strerr.h"
#include "ip4.h"
+#include "ip6.h"
#include "uint16.h"
#include "ndelay.h"
#include "socket.h"
@@ -11,13 +12,16 @@
#include "qlog.h"
#include "response.h"
#include "dns.h"
+#include "alloc.h"
+#include "iopause.h"
+#include "str.h"
extern char *fatal;
extern char *starting;
extern int respond(char *,char *,char *);
extern void initialize(void);
-static char ip[4];
+static char ip[16];
static uint16 port;
static char buf[513];
@@ -25,6 +29,11 @@ static int len;
static char *q;
+void nomem()
+{
+ strerr_die2x(111,fatal,"out of memory");
+}
+
static int doit(void)
{
unsigned int pos;
@@ -82,35 +91,86 @@ static int doit(void)
int main()
{
char *x;
- int udp53;
+ int *udp53;
+ unsigned int off;
+ unsigned int cnt;
+ iopause_fd *iop;
x = env_get("IP");
if (!x)
strerr_die2x(111,fatal,"$IP not set");
- if (!ip4_scan(x,ip))
- strerr_die3x(111,fatal,"unable to parse IP address ",x);
-
- udp53 = socket_udp();
- if (udp53 == -1)
- strerr_die2sys(111,fatal,"unable to create UDP socket: ");
- if (socket_bind4_reuse(udp53,ip,53) == -1)
- strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
-
+ off=cnt=0;
+ while (x[off]) {
+ unsigned int l;
+ char dummy[16];
+ l=ip6_scan(x+off,dummy);
+ if (!l)
+ strerr_die3x(111,fatal,"unable to parse IP address ",x+off);
+ cnt++;
+ if (!x[off+l]) break;
+ if (x[off+l]=='%')
+ while (x[off+l] && x[off+l]!=',') ++l;
+ if (x[off+l]!=',')
+ strerr_die3x(111,fatal,"unable to parse IP address ",x+off);
+ off+=l+1;
+ }
+ udp53=(int *) alloc(sizeof(int) *cnt);
+ if (!udp53) nomem();
+ iop=(iopause_fd *) alloc(sizeof(*iop) * cnt);
+ if (!iop) nomem();
+
+ off=cnt=0;
+ while (x[off]) {
+ unsigned int l;
+ uint32 ifid=0;
+ l=ip6_scan(x+off,ip);
+ udp53[cnt] = socket_udp6();
+ if (udp53[cnt] == -1)
+ strerr_die2sys(111,fatal,"unable to create UDP socket: ");
+ if (x[off+l]=='%') {
+ char* interface=x+off+l+1;
+ int Len=str_chr(interface,',');
+ if (interface[Len]) {
+ interface[Len]=0;
+ ifid=socket_getifidx(interface);
+ interface[Len]=',';
+ } else
+ ifid=socket_getifidx(interface);
+ l+=Len;
+ }
+ if (socket_bind6_reuse(udp53[cnt],ip,53,ifid) == -1)
+ strerr_die2sys(111,fatal,"unable to bind UDP socket: ");
+ ndelay_off(udp53[cnt]);
+ socket_tryreservein(udp53[cnt],65536);
+ iop[cnt].fd=udp53[cnt];
+ iop[cnt].events=IOPAUSE_READ;
+ cnt++;
+ if (!x[off+l]) break;
+ off+=l+1;
+ }
droproot(fatal);
initialize();
-
- ndelay_off(udp53);
- socket_tryreservein(udp53,65536);
buffer_putsflush(buffer_2,starting);
for (;;) {
- len = socket_recv4(udp53,buf,sizeof buf,ip,&port);
- if (len < 0) continue;
- if (!doit()) continue;
- if (response_len > 512) response_tc();
- socket_send4(udp53,response,response_len,ip,port);
- /* may block for buffer space; if it fails, too bad */
+ struct taia stamp;
+ struct taia deadline;
+ unsigned int i;
+ uint32 ifid;
+ taia_now(&stamp);
+ taia_uint(&deadline,300);
+ taia_add(&deadline,&deadline,&stamp);
+ iopause(iop,cnt,&deadline,&stamp);
+ for (i=0;i<cnt;i++)
+ if (iop[i].revents) {
+ len = socket_recv6(udp53[i],buf,sizeof buf,ip,&port,&ifid);
+ if (len < 0) continue;
+ if (!doit()) continue;
+ if (response_len > 512) response_tc();
+ socket_send6(udp53[i],response,response_len,ip,port,ifid);
+ /* may block for buffer space; if it fails, too bad */
+ }
}
}
diff --git a/sockaddr_in6.h1 b/sockaddr_in6.h1
new file mode 100644
index 0000000..b1f8f5e
--- /dev/null
+++ b/sockaddr_in6.h1
@@ -0,0 +1,21 @@
+#include "haveip6.h"
+#ifdef LIBC_HAS_IP6
+#include <sys/types.h>
+#include <sys/socket.h>
+#define sockaddr_in6 blub
+#include <netinet/in.h>
+#undef sockaddr_in6
+
+struct sockaddr_in6 {
+ sa_family_t sin6_family; /* AF_INET6 */
+ unsigned short sin6_port; /* transport layer port # */
+ uint32_t sin6_flowinfo; /* IPv6 traffic class & flow info */
+ struct in6_addr sin6_addr; /* IPv6 address */
+ uint32_t sin6_scope_id; /* set of interfaces for a scope */
+};
+
+#else
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#endif
diff --git a/sockaddr_in6.h2 b/sockaddr_in6.h2
new file mode 100644
index 0000000..d484041
--- /dev/null
+++ b/sockaddr_in6.h2
@@ -0,0 +1,4 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
diff --git a/socket.h b/socket.h
index 95e2a7c..bbb0f82 100644
--- a/socket.h
+++ b/socket.h
@@ -2,21 +2,37 @@
#define SOCKET_H
#include "uint16.h"
+#include "uint32.h"
extern int socket_tcp(void);
extern int socket_udp(void);
+extern int socket_tcp6(void);
+extern int socket_udp6(void);
extern int socket_connect4(int,const char *,uint16);
+extern int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id);
extern int socket_connected(int);
-extern int socket_bind4(int,char *,uint16);
+extern int socket_bind4(int,const char *,uint16);
extern int socket_bind4_reuse(int,char *,uint16);
+extern int socket_bind6(int s,const char *ip,uint16 port,uint32 scope_id);
+extern int socket_bind6_reuse(int s,const char *ip,uint16 port,uint32 scope_id);
extern int socket_listen(int,int);
extern int socket_accept4(int,char *,uint16 *);
+extern int socket_accept6(int s,char *ip,uint16 *port,uint32 *scope_id);
extern int socket_recv4(int,char *,int,char *,uint16 *);
extern int socket_send4(int,const char *,int,const char *,uint16);
+extern int socket_recv6(int s,char *buf,unsigned int len,char *ip,uint16 *port,uint32 *scope_id);
+extern int socket_send6(int s,const char *buf,unsigned int len,const char *ip,uint16 port,uint32 scope_id);
extern int socket_local4(int,char *,uint16 *);
extern int socket_remote4(int,char *,uint16 *);
+extern int socket_local6(int s,char *ip,uint16 *port,uint32 *scope_id);
+extern int socket_remote6(int s,char *ip,uint16 *port,uint32 *scope_id);
extern void socket_tryreservein(int,int);
+extern const char* socket_getifname(uint32 interface);
+extern uint32 socket_getifidx(const char *ifname);
+
+extern int noipv6;
+
#endif
diff --git a/socket_accept6.c b/socket_accept6.c
new file mode 100644
index 0000000..48a0b6d
--- /dev/null
+++ b/socket_accept6.c
@@ -0,0 +1,43 @@
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+#include "ip6.h"
+#include "haveip6.h"
+#include "error.h"
+
+int socket_accept6(int s,char ip[16],uint16 *port,uint32 *scope_id)
+{
+#ifdef LIBC_HAS_IP6
+ struct sockaddr_in6 sa;
+#else
+ struct sockaddr_in sa;
+#endif
+ unsigned int dummy = sizeof sa;
+ int fd;
+
+ fd = accept(s,(struct sockaddr *) &sa,&dummy);
+ if (fd == -1) return -1;
+
+#ifdef LIBC_HAS_IP6
+ if (sa.sin6_family==AF_INET) {
+ struct sockaddr_in *sa4=(struct sockaddr_in*)&sa;
+ byte_copy(ip,12,V4mappedprefix);
+ byte_copy(ip+12,4,(char *) &sa4->sin_addr);
+ uint16_unpack_big((char *) &sa4->sin_port,port);
+ return fd;
+ }
+ byte_copy(ip,16,(char *) &sa.sin6_addr);
+ uint16_unpack_big((char *) &sa.sin6_port,port);
+ if (scope_id) *scope_id=sa.sin6_scope_id;
+
+ return fd;
+#else
+ byte_copy(ip,12,V4mappedprefix);
+ byte_copy(ip+12,4,(char *) &sa.sin_addr);
+ uint16_unpack_big((char *) &sa.sin_port,port);
+ if (scope_id) *scope_id=0;
+ return fd;
+#endif
+}
diff --git a/socket_bind.c b/socket_bind.c
index 20830a4..a33efca 100644
--- a/socket_bind.c
+++ b/socket_bind.c
@@ -5,7 +5,7 @@
#include "byte.h"
#include "socket.h"
-int socket_bind4(int s,char ip[4],uint16 port)
+int socket_bind4(int s,const char ip[4],uint16 port)
{
struct sockaddr_in sa;
diff --git a/socket_bind6.c b/socket_bind6.c
new file mode 100644
index 0000000..20b22b8
--- /dev/null
+++ b/socket_bind6.c
@@ -0,0 +1,43 @@
+#include <sys/param.h>
+#include "sockaddr_in6.h"
+#include "byte.h"
+#include "socket.h"
+#include "ip6.h"
+#include "haveip6.h"
+#include "error.h"
+
+int socket_bind6(int s,const char ip[16],uint16 port,uint32 scope_id)
+{
+#ifdef LIBC_HAS_IP6
+ struct sockaddr_in6 sa;
+
+ if (noipv6) {
+#endif
+ int i;
+ for (i=0; i<16; i++)
+ if (ip[i]!=0) break;
+ if (i==16 || ip6_isv4mapped(ip))
+ return socket_bind4(s,ip+12,port);
+#ifdef LIBC_HAS_IP6
+ }
+ byte_zero(&sa,sizeof sa);
+ sa.sin6_family = AF_INET6;
+ uint16_pack_big((char *) &sa.sin6_port,port);
+/* implicit: sa.sin6_flowinfo = 0; */
+ byte_copy((char *) &sa.sin6_addr,16,ip);
+ sa.sin6_scope_id=scope_id;
+
+ return bind(s,(struct sockaddr *) &sa,sizeof sa);
+#else
+ errno=error_proto;
+ return -1;
+#endif
+}
+
+int socket_bind6_reuse(int s,const char ip[16],uint16 port,uint32 scope_id)
+{
+ int opt = 1;
+ setsockopt(s,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof opt);
+ return socket_bind6(s,ip,port,scope_id);
+}
+
diff --git a/socket_connect6.c b/socket_connect6.c
new file mode 100644
index 0000000..d2df4a2
--- /dev/null
+++ b/socket_connect6.c
@@ -0,0 +1,39 @@
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include "byte.h"
+#include "socket.h"
+#include "ip6.h"
+#include "haveip6.h"
+#include "error.h"
+#include "uint32.h"
+#include "ip4.h"
+
+int socket_connect6(int s,const char ip[16],uint16 port,uint32 scope_id)
+{
+#ifdef LIBC_HAS_IP6
+ struct sockaddr_in6 sa;
+
+ if (noipv6) {
+#endif
+ if (ip6_isv4mapped(ip))
+ return socket_connect4(s,ip+12,port);
+ if (byte_equal(ip,16,V6loopback))
+ return socket_connect4(s,ip4loopback,port);
+#ifdef LIBC_HAS_IP6
+ }
+ byte_zero(&sa,sizeof sa);
+ sa.sin6_family = PF_INET6;
+ uint16_pack_big((char *) &sa.sin6_port,port);
+ sa.sin6_flowinfo = 0;
+ sa.sin6_scope_id = scope_id;
+ byte_copy((char *) &sa.sin6_addr,16,ip);
+
+ return connect(s,(struct sockaddr *) &sa,sizeof sa);
+#else
+ errno=error_proto;
+ return -1;
+#endif
+}
diff --git a/socket_getifidx.c b/socket_getifidx.c
new file mode 100644
index 0000000..c71fc48
--- /dev/null
+++ b/socket_getifidx.c
@@ -0,0 +1,13 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include "socket.h"
+#include "haven2i.h"
+
+uint32 socket_getifidx(const char* ifname) {
+#ifdef HAVE_N2I
+ return if_nametoindex(ifname);
+#else
+ return 0;
+#endif
+}
diff --git a/socket_noipv6.c b/socket_noipv6.c
new file mode 100644
index 0000000..289d699
--- /dev/null
+++ b/socket_noipv6.c
@@ -0,0 +1,7 @@
+#include "haveip6.h"
+
+#ifdef LIBC_HAS_IP6
+int noipv6=0;
+#else
+int noipv6=1;
+#endif
diff --git a/socket_recv6.c b/socket_recv6.c
new file mode 100644
index 0000000..dfbd781
--- /dev/null
+++ b/socket_recv6.c
@@ -0,0 +1,42 @@
+#include <sys/param.h>
+#include "sockaddr_in6.h"
+#include "byte.h"
+#include "socket.h"
+#include "ip6.h"
+#include "haveip6.h"
+#include "error.h"
+
+int socket_recv6(int s,char *buf,unsigned int len,char ip[16],uint16 *port,uint32 *scope_id)
+{
+#ifdef LIBC_HAS_IP6
+ struct sockaddr_in6 sa;
+#else
+ struct sockaddr_in sa;
+#endif
+ unsigned int dummy = sizeof sa;
+ int r;
+
+ byte_zero(&sa,dummy);
+ r = recvfrom(s,buf,len,0,(struct sockaddr *) &sa,&dummy);
+ if (r == -1) return -1;
+
+#ifdef LIBC_HAS_IP6
+ if (noipv6 || sa.sin6_family==AF_INET || sa.sin6_family==PF_INET) {
+ struct sockaddr_in *sa4=(struct sockaddr_in *)&sa;
+ byte_copy(ip,12,V4mappedprefix);
+ byte_copy(ip+12,4,(char *) &sa4->sin_addr);
+ uint16_unpack_big((char *) &sa4->sin_port,port);
+ return r;
+ }
+ byte_copy(ip,16,(char *) &sa.sin6_addr);
+ uint16_unpack_big((char *) &sa.sin6_port,port);
+ if (scope_id) *scope_id=sa.sin6_scope_id;
+#else
+ byte_copy(ip,12,(char *)V4mappedprefix);
+ byte_copy(ip+12,4,(char *) &sa.sin_addr);
+ uint16_unpack_big((char *) &sa.sin_port,port);
+ if (scope_id) *scope_id=0;
+#endif
+
+ return r;
+}
diff --git a/socket_send6.c b/socket_send6.c
new file mode 100644
index 0000000..ded6793
--- /dev/null
+++ b/socket_send6.c
@@ -0,0 +1,39 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include "byte.h"
+#include "socket.h"
+#include "ip6.h"
+#include "haveip6.h"
+#include "error.h"
+
+int socket_send6(int s,const char *buf,unsigned int len,const char ip[16],uint16 port,uint32 scope_id)
+{
+#ifdef LIBC_HAS_IP6
+ struct sockaddr_in6 sa;
+#else
+ struct sockaddr_in sa;
+#endif
+
+ byte_zero(&sa,sizeof sa);
+#ifdef LIBC_HAS_IP6
+ if (noipv6) {
+#endif
+ if (ip6_isv4mapped(ip))
+ return socket_send4(s,buf,len,ip+12,port);
+ if (byte_equal(ip,16,V6loopback))
+ return socket_send4(s,buf,len,ip4loopback,port);
+#ifdef LIBC_HAS_IP6
+ errno=error_proto;
+ return -1;
+ }
+ sa.sin6_family = AF_INET6;
+ uint16_pack_big((char *) &sa.sin6_port,port);
+ byte_copy((char *) &sa.sin6_addr,16,ip);
+ return sendto(s,buf,len,0,(struct sockaddr *) &sa,sizeof sa);
+#else
+ errno=error_proto;
+ return -1;
+#endif
+}
diff --git a/socket_tcp6.c b/socket_tcp6.c
new file mode 100644
index 0000000..bfc78f5
--- /dev/null
+++ b/socket_tcp6.c
@@ -0,0 +1,50 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <unistd.h>
+#include "ndelay.h"
+#include "socket.h"
+#include "haveip6.h"
+#include "error.h"
+
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT EINVAL
+#endif
+#ifndef EPFNOSUPPORT
+#define EPFNOSUPPORT EAFNOSUPPORT
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT EAFNOSUPPORT
+#endif
+
+int socket_tcp6(void)
+{
+#ifdef LIBC_HAS_IP6
+ int s;
+
+ if (noipv6) goto compat;
+ s = socket(PF_INET6,SOCK_STREAM,0);
+ if (s == -1) {
+ if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPROTONOSUPPORT || errno == EPFNOSUPPORT) {
+compat:
+ s=socket(AF_INET,SOCK_STREAM,0);
+ noipv6=1;
+ if (s==-1) return -1;
+ } else
+ return -1;
+ }
+ if (ndelay_on(s) == -1) { close(s); return -1; }
+#ifdef IPV6_V6ONLY
+ {
+ int zero=0;
+ setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero));
+ }
+#endif
+ return s;
+#else
+ return socket_tcp();
+#endif
+}
+
diff --git a/socket_udp6.c b/socket_udp6.c
new file mode 100644
index 0000000..b58b55c
--- /dev/null
+++ b/socket_udp6.c
@@ -0,0 +1,49 @@
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <errno.h>
+#include <unistd.h>
+#include "ndelay.h"
+#include "socket.h"
+#include "haveip6.h"
+#include "error.h"
+
+#ifndef EAFNOSUPPORT
+#define EAFNOSUPPORT EINVAL
+#endif
+#ifndef EPFNOSUPPORT
+#define EPFNOSUPPORT EAFNOSUPPORT
+#endif
+#ifndef EPROTONOSUPPORT
+#define EPROTONOSUPPORT EAFNOSUPPORT
+#endif
+
+int socket_udp6(void)
+{
+#ifdef LIBC_HAS_IP6
+ int s;
+
+ if (noipv6) goto compat;
+ s = socket(PF_INET6,SOCK_DGRAM,0);
+ if (s == -1) {
+ if (errno == EINVAL || errno == EAFNOSUPPORT || errno == EPFNOSUPPORT || errno == EPROTONOSUPPORT) {
+compat:
+ s=socket(AF_INET,SOCK_DGRAM,0);
+ noipv6=1;
+ if (s==-1) return -1;
+ } else
+ return -1;
+ }
+ if (ndelay_on(s) == -1) { close(s); return -1; }
+#ifdef IPV6_V6ONLY
+ {
+ int zero=0;
+ setsockopt(s,IPPROTO_IPV6,IPV6_V6ONLY,(void*)&zero,sizeof(zero));
+ }
+#endif
+ return s;
+#else
+ return socket_udp();
+#endif
+}
diff --git a/tdlookup.c b/tdlookup.c
index da7420d..b760340 100644
--- a/tdlookup.c
+++ b/tdlookup.c
@@ -8,6 +8,8 @@
#include "dns.h"
#include "seek.h"
#include "response.h"
+#include "ip6.h"
+#include "clientloc.h"
static int want(const char *owner,const char type[2])
{
@@ -61,7 +63,7 @@ static int find(char *d,int flagwild)
if (cdb_read(&c,data,dlen,cdb_datapos(&c)) == -1) return -1;
dpos = dns_packet_copy(data,dlen,0,type,2); if (!dpos) return -1;
dpos = dns_packet_copy(data,dlen,dpos,&ch,1); if (!dpos) return -1;
- if ((ch == '=' + 1) || (ch == '*' + 1)) {
+ if ((ch == '=' + 1) || (ch == '*' + 1) || (ch == '6' + 1)) {
--ch;
dpos = dns_packet_copy(data,dlen,dpos,recordloc,2); if (!dpos) return -1;
if (byte_diff(recordloc,2,clientloc)) continue;
@@ -119,8 +121,9 @@ static int doit(char *q,char qtype[2])
char x[20];
uint16 u16;
char addr[8][4];
- int addrnum;
- uint32 addrttl;
+ char addr6[8][16];
+ int addrnum,addr6num;
+ uint32 addrttl,addr6ttl;
int i;
anpos = response_len;
@@ -152,8 +155,8 @@ static int doit(char *q,char qtype[2])
wild = q;
for (;;) {
- addrnum = 0;
- addrttl = 0;
+ addrnum = addr6num = 0;
+ addrttl = addr6ttl = 0;
cdb_findstart(&c);
while (r = find(wild,wild != q)) {
if (r == -1) return 0;
@@ -171,6 +174,17 @@ static int doit(char *q,char qtype[2])
if (addrnum < 1000000) ++addrnum;
continue;
}
+ if (byte_equal(type,2,DNS_T_AAAA) && (dlen - dpos == 16)) {
+ addr6ttl = ttl;
+ i = dns_random(addr6num + 1);
+ if (i < 8) {
+ if ((i < addr6num) && (addr6num < 8))
+ byte_copy(addr6[addr6num],16,addr6[i]);
+ byte_copy(addr6[i],16,data + dpos);
+ }
+ if (addr6num < 1000000) ++addr6num;
+ continue;
+ }
if (!response_rstart(q,type,ttl)) return 0;
if (byte_equal(type,2,DNS_T_NS) || byte_equal(type,2,DNS_T_CNAME) || byte_equal(type,2,DNS_T_PTR)) {
if (!doname()) return 0;
@@ -195,6 +209,12 @@ static int doit(char *q,char qtype[2])
if (!response_addbytes(addr[i],4)) return 0;
response_rfinish(RESPONSE_ANSWER);
}
+ for (i = 0;i < addr6num;++i)
+ if (i < 8) {
+ if (!response_rstart(q,DNS_T_AAAA,addr6ttl)) return 0;
+ if (!response_addbytes(addr6[i],16)) return 0;
+ response_rfinish(RESPONSE_ANSWER);
+ }
if (flagfound) break;
if (wild == control) break;
@@ -259,6 +279,11 @@ static int doit(char *q,char qtype[2])
if (!dobytes(4)) return 0;
response_rfinish(RESPONSE_ADDITIONAL);
}
+ else if (byte_equal(type,2,DNS_T_AAAA)) {
+ if (!response_rstart(d1,DNS_T_AAAA,ttl)) return 0;
+ if (!dobytes(16)) return 0;
+ response_rfinish(RESPONSE_ADDITIONAL);
+ }
}
}
}
@@ -278,30 +303,18 @@ static int doit(char *q,char qtype[2])
return 1;
}
-int respond(char *q,char qtype[2],char ip[4])
+int respond(char *q,char qtype[2],char ip[16])
{
int fd;
int r;
- char key[6];
+
+ find_client_loc(clientloc, ip);
tai_now(&now);
fd = open_read("data.cdb");
if (fd == -1) return 0;
cdb_init(&c,fd);
- byte_zero(clientloc,2);
- key[0] = 0;
- key[1] = '%';
- byte_copy(key + 2,4,ip);
- r = cdb_find(&c,key,6);
- if (!r) r = cdb_find(&c,key,5);
- if (!r) r = cdb_find(&c,key,4);
- if (!r) r = cdb_find(&c,key,3);
- if (!r) r = cdb_find(&c,key,2);
- if (r == -1) return 0;
- if (r && (cdb_datalen(&c) == 2))
- if (cdb_read(&c,clientloc,2,cdb_datapos(&c)) == -1) return 0;
-
r = doit(q,qtype);
cdb_free(&c);
diff --git a/tinydns-conf.c b/tinydns-conf.c
index d3a4ce5..db83f11 100644
--- a/tinydns-conf.c
+++ b/tinydns-conf.c
@@ -82,6 +82,18 @@ int main(int argc,char **argv)
finish();
perm(0755);
+ start("root/add-host6");
+ outs("#!/bin/sh\nexec ");
+ outs(auto_home); outs("/bin/tinydns-edit data data.new add host6 ${1+\"$@\"}\n");
+ finish();
+ perm(0755);
+
+ start("root/add-alias6");
+ outs("#!/bin/sh\nexec ");
+ outs(auto_home); outs("/bin/tinydns-edit data data.new add alias6 ${1+\"$@\"}\n");
+ finish();
+ perm(0755);
+
start("root/add-mx");
outs("#!/bin/sh\nexec ");
outs(auto_home); outs("/bin/tinydns-edit data data.new add mx ${1+\"$@\"}\n");
diff --git a/tinydns-data.c b/tinydns-data.c
index ba82f84..4d66865 100644
--- a/tinydns-data.c
+++ b/tinydns-data.c
@@ -8,6 +8,7 @@
#include "byte.h"
#include "fmt.h"
#include "ip4.h"
+#include "ip6.h"
#include "exit.h"
#include "case.h"
#include "scan.h"
@@ -65,16 +66,23 @@ void ipprefix_cat(stralloc *out,char *s)
char ch;
unsigned int j;
- for (;;)
- if (*s == '.')
- ++s;
- else {
- j = scan_ulong(s,&u);
- if (!j) return;
- s += j;
- ch = u;
- if (!stralloc_catb(out,&ch,1)) nomem();
- }
+ if (*s=='s') {
+ ++s;
+ if (!stralloc_catb(out,"s",1) || !stralloc_cats(out,s)) nomem();
+ } else {
+ if (*s=='f') ++s;
+ if (!stralloc_catb(out,"f",1)) nomem();
+ for (;;)
+ if (*s == '.')
+ ++s;
+ else {
+ j = scan_ulong(s,&u);
+ if (!j) return;
+ s += j;
+ ch = u;
+ if (!stralloc_catb(out,&ch,1)) nomem();
+ }
+ }
}
void txtparse(stralloc *sa)
@@ -172,6 +180,7 @@ static stralloc f[NUMFIELDS];
static char *d1;
static char *d2;
char dptr[DNS_NAME4_DOMAIN];
+char d6ptr[DNS_NAME6_DOMAIN];
char strnum[FMT_ULONG];
@@ -193,6 +202,7 @@ int main()
char loc[2];
unsigned long u;
char ip[4];
+ char ip6[16];
char type[2];
char soa[20];
char buf[4];
@@ -339,6 +349,33 @@ int main()
}
break;
+ case '6': case '3':
+ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+ if (!stralloc_0(&f[2])) nomem();
+ if (!scan_ulong(f[2].s,&ttl)) ttl = TTL_POSITIVE;
+ ttdparse(&f[3],ttd);
+ locparse(&f[4],loc);
+
+ if (!stralloc_0(&f[1])) nomem();
+ if (ip6_scan_flat(f[1].s,ip6)) {
+ rr_start(DNS_T_AAAA,ttl,ttd,loc);
+ rr_add(ip6,16);
+ rr_finish(d1);
+
+ if (line.s[0] == '6') { /* emit both .ip6.arpa and .ip6.int */
+ dns_name6_domain(d6ptr,ip6,DNS_IP6_ARPA);
+ rr_start(DNS_T_PTR,ttl,ttd,loc);
+ rr_addname(d1);
+ rr_finish(d6ptr);
+
+ dns_name6_domain(d6ptr,ip6,DNS_IP6_INT);
+ rr_start(DNS_T_PTR,ttl,ttd,loc);
+ rr_addname(d1);
+ rr_finish(d6ptr);
+ }
+ }
+ break;
+
case '@':
if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
if (!stralloc_0(&f[4])) nomem();
diff --git a/tinydns-edit.c b/tinydns-edit.c
index 126a7e0..8633220 100644
--- a/tinydns-edit.c
+++ b/tinydns-edit.c
@@ -13,6 +13,7 @@
#include "str.h"
#include "fmt.h"
#include "ip4.h"
+#include "ip6.h"
#include "dns.h"
#define FATAL "tinydns-edit: fatal: "
@@ -25,7 +26,8 @@ char *fnnew;
void die_usage()
{
- strerr_die1x(100,"tinydns-edit: usage: tinydns-edit data data.new add [ns|childns|host|alias|mx] domain a.b.c.d");
+ strerr_die1x(100,"tinydns-edit: usage: tinydns-edit data data.new add [ns|childns|host|alias|mx] domain a.b.c.d\n"
+ "tinydns-edit: usage: tinydns-edit data data.new add [host6|alias6] domain a:b:c:d:e:f:g:h");
}
void nomem()
{
@@ -43,6 +45,7 @@ void die_write()
char mode;
static char *target;
char targetip[4];
+char targetip6[16];
int fd;
buffer b;
@@ -61,7 +64,9 @@ static stralloc f[NUMFIELDS];
static char *d1;
static char *d2;
char ip[4];
+char ip6[16];
char ipstr[IP4_FMT];
+char ip6str[IP6_FMT];
char strnum[FMT_ULONG];
static char *names[26];
@@ -96,7 +101,9 @@ int main(int argc,char **argv)
if (str_equal(*argv,"ns")) mode = '.';
else if (str_equal(*argv,"childns")) mode = '&';
else if (str_equal(*argv,"host")) mode = '=';
+ else if (str_equal(*argv,"host6")) mode = '6';
else if (str_equal(*argv,"alias")) mode = '+';
+ else if (str_equal(*argv,"alias6")) mode = '3';
else if (str_equal(*argv,"mx")) mode = '@';
else die_usage();
@@ -104,7 +111,11 @@ int main(int argc,char **argv)
if (!dns_domain_fromdot(&target,*argv,str_len(*argv))) nomem();
if (!*++argv) die_usage();
- if (!ip4_scan(*argv,targetip)) die_usage();
+ if (mode == '6' || mode == '3') {
+ if (!ip6_scan(*argv,targetip6)) die_usage();
+ } else {
+ if (!ip4_scan(*argv,targetip)) die_usage();
+ }
umask(077);
@@ -129,7 +140,7 @@ int main(int argc,char **argv)
if (!dns_domain_fromdot(&names[i],f[0].s,f[0].len)) nomem();
}
break;
- case '+': case '=':
+ case '+': case '=': case '6': case '3':
ttl = TTL_POSITIVE;
break;
case '@':
@@ -203,6 +214,18 @@ int main(int argc,char **argv)
}
break;
+ case '6':
+ if (line.s[0] == '6') {
+ if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
+ if (dns_domain_equal(d1,target))
+ strerr_die2x(100,FATAL,"host name already used");
+ if (!stralloc_0(&f[1])) nomem();
+ if (ip6_scan(f[1].s,ip6))
+ if (byte_equal(ip,16,targetip6))
+ strerr_die2x(100,FATAL,"IPv6 address already used");
+ }
+ break;
+
case '@':
if (line.s[0] == '@') {
if (!dns_domain_fromdot(&d1,f[0].s,f[0].len)) nomem();
@@ -228,7 +251,11 @@ int main(int argc,char **argv)
if (!stralloc_copyb(&f[0],&mode,1)) nomem();
if (!dns_domain_todot_cat(&f[0],target)) nomem();
if (!stralloc_cats(&f[0],":")) nomem();
- if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem();
+ if (mode == '6' || mode == '3') {
+ if (!stralloc_catb(&f[0],ip6str,ip6_fmt_flat(ip6str,targetip6))) nomem();
+ } else {
+ if (!stralloc_catb(&f[0],ipstr,ip4_fmt(ipstr,targetip))) nomem();
+ }
switch(mode) {
case '.': case '&': case '@':
for (i = 0;i < 26;++i)
diff --git a/tinydns-get.c b/tinydns-get.c
index f7fd67f..56edb13 100644
--- a/tinydns-get.c
+++ b/tinydns-get.c
@@ -11,6 +11,7 @@
#include "printpacket.h"
#include "parsetype.h"
#include "ip4.h"
+#include "ip6.h"
#include "dns.h"
extern int respond(char *,char *,char *);
@@ -26,7 +27,7 @@ void oops(void)
strerr_die2sys(111,FATAL,"unable to parse: ");
}
-static char ip[4];
+static char ip[16];
static char type[2];
static char *q;
@@ -45,7 +46,7 @@ int main(int argc,char **argv)
if (!dns_domain_fromdot(&q,*argv,str_len(*argv))) oops();
if (*++argv) {
- if (!ip4_scan(*argv,ip)) usage();
+ if (!ip6_scan(*argv,ip)) usage();
}
if (!stralloc_copys(&out,"")) oops();
diff --git a/tryip6.c b/tryip6.c
new file mode 100644
index 0000000..e0d7cfb
--- /dev/null
+++ b/tryip6.c
@@ -0,0 +1,8 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+main() {
+ struct sockaddr_in6 sa;
+ sa.sin6_family = PF_INET6;
+}
diff --git a/tryn2i.c b/tryn2i.c
new file mode 100644
index 0000000..84c3a08
--- /dev/null
+++ b/tryn2i.c
@@ -0,0 +1,8 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+
+int main() {
+ static char ifname[IFNAMSIZ];
+ char *tmp=if_indextoname(0,ifname);
+}
diff --git a/trysa6.c b/trysa6.c
new file mode 100644
index 0000000..0fd180c
--- /dev/null
+++ b/trysa6.c
@@ -0,0 +1,8 @@
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+main() {
+ struct sockaddr_in6 sa;
+ sa.sin6_scope_id = 1;
+}