From: Michael Orlitzky Date: Thu, 7 Apr 2011 20:49:37 +0000 (-0400) Subject: Second try at ipv6 with my own ipv6 patch. X-Git-Url: https://gitweb.michael.orlitzky.com/?a=commitdiff_plain;h=eb0f9f634415126a1add21bc9b7b12627d4158e7;p=mjo-overlay.git Second try at ipv6 with my own ipv6 patch. --- diff --git a/net-dns/djbdns/Manifest b/net-dns/djbdns/Manifest index cd9ba92..c513310 100644 --- a/net-dns/djbdns/Manifest +++ b/net-dns/djbdns/Manifest @@ -8,12 +8,12 @@ AUX dnscache-setup 6007 RMD160 d5a29943ac29d84a8c83308a497721010ab017bc SHA1 764 AUX dnsroots-r25.patch 356 RMD160 a864738d886d20eb73f657b93bffccd6d4e758a7 SHA1 99381209f126e75d8560ecf4c467ecf123efeee9 SHA256 94e3e8fe9fee39729ec8c8f314ab2adaf7d8e1f48957da888ab990411ba2a3bb AUX dnstracesort.patch 327 RMD160 aaa564aa9cb0dcad4ebb64121c82bf50fda64254 SHA1 cf8b7825d826bfd3f3314c848a8843c2a5a70ae3 SHA256 f1d83e1365f68571fa4e007d5219720f8d65eb3730040a087fceb0ce2d8806bf AUX headtail.patch 1780 RMD160 332af6647e08f3b792bd1b7821974f15041a6b58 SHA1 1b996c6cbe5df1c981f998d004d066ae344bfba8 SHA256 28ebe521132fe35559273b6542505ab4f0bb7b7ccb88585522e4cc2fe8376dd4 +AUX ipv6-mjo.patch 98657 RMD160 dcd108bbc4e7daeedc1fcf3db52ad5bb6b35e457 SHA1 04200398a9d44cfd11765f8a47498427c5297b0f SHA256 880e12f3918553aa5b01a3313e3d2358a693ad66dafdb318ed3ca1a4ba94d9ec AUX query.c-mjo.patch 2600 RMD160 5f6ced3e18e0d010902a3f02b28fcbcff3cf9b1f SHA1 50a18ce5cf16dd75b6706378695fd402be8007d5 SHA256 df40916247fc04b8a8bd0c61b3729278b235495491341beaabcc4c9cee72ddb5 AUX query.h-mjo.patch 807 RMD160 f122f9925cbb9c7b3ef1fc78a754e6c9286e167d SHA1 f8c87f616fb0781b47d3a6c6a70afb246d832bfd SHA256 9b5516ff83eed4927c83d89c587efb778e328baaaa2fc7928f042e91ad7efb34 AUX string_length_255.patch 299 RMD160 df613f1287f6581c963e969eec7fcaec638e2b58 SHA1 bb9e2f7aafed265887ac47d35cc022ef25d7b5f9 SHA256 c9b8d0065cfe6d4a9ad460c31c2a75bcce17bfb8001f4448e3464dea07524401 AUX tinydns-setup 3206 RMD160 16679596e3902c8eda4c9605b0fef6e778cdee63 SHA1 e222c22f924882a3b2d496f7d8fbdf61eb4eb0e8 SHA256 73c0610f15e9bbec1998d10eafe4222277eb8cbaf0c58e802f998e9f7b25bbea -DIST djbdns-1.05-test23.diff.bz2 18480 RMD160 33037f2a41abb49c305f3efec4402c6965c8b8b8 SHA1 34251597d211ff00791cb6546e8ef60d75ce5477 SHA256 e702f47b4a4c77fe5cec474a8219a072cfaaee07282650b7e0dd322ed82e8f33 DIST djbdns-1.05.tar.gz 85648 RMD160 a832cbfd93e4ccec6a565492a4ee0b3c1b4b68ed SHA1 2efdb3a039d0c548f40936aa9cb30829e0ce8c3d SHA256 3ccd826a02f3cde39be088e1fc6aed9fd57756b8f970de5dc99fcd2d92536b48 -EBUILD djbdns-1.05-r26.ebuild 3862 RMD160 44af9095670d98cc8ae48cf309c5b1c8c2a69478 SHA1 2e6b2c08dc8f9953693e881c3e53db9288c915e5 SHA256 a74f3040820af38baebd46451ea0e2db36472eb80329b411d72da52044701187 +EBUILD djbdns-1.05-r26.ebuild 3767 RMD160 6cec9d1bb1e4570b113db1c15e4e176065d747b0 SHA1 18235e2ff48300c354c5832c55d2e55cd1589fcb SHA256 164333dc08e409f5b95c95ad64659bf3502cc6e976e4c19b5fe9fbdbbd5fceda MISC ChangeLog 19007 RMD160 b7c920db6183b8ccfc4682e63b8de6dff63a1516 SHA1 707954ec763701361798825514a098015d83e2a1 SHA256 36df2a604799554de616aa70b1e9a9e730f024b2b3681813836d21bc387d03be MISC metadata.xml 232 RMD160 854b06094287201d0b98f2b21d36054db25d81cd SHA1 cc4f98e9ee0102aea687d71cf3af924cf156edbb SHA256 21382e863647add08888c924279a4b931b2b90ccd0cf5e526ee74a3d5e1fd0df diff --git a/net-dns/djbdns/djbdns-1.05-r26.ebuild b/net-dns/djbdns/djbdns-1.05-r26.ebuild index 718bd12..db04035 100644 --- a/net-dns/djbdns/djbdns-1.05-r26.ebuild +++ b/net-dns/djbdns/djbdns-1.05-r26.ebuild @@ -7,10 +7,8 @@ inherit eutils flag-o-matic toolchain-funcs DESCRIPTION="Excellent high-performance DNS services" HOMEPAGE="http://cr.yp.to/djbdns.html" -IPV6_PATCH="test23" -SRC_URI="http://cr.yp.to/djbdns/${P}.tar.gz - ipv6? ( http://www.fefe.de/dns/${P}-${IPV6_PATCH}.diff.bz2 )" +SRC_URI="http://cr.yp.to/djbdns/${P}.tar.gz" SLOT="0" LICENSE="public-domain" @@ -54,7 +52,7 @@ src_prepare() { "be compiled without IPv6 support." cp -pR "${S}" "${S}-noipv6" # Careful -- >=test21 of the IPv6 patch includes the errno patch - epatch "${DISTDIR}/${P}-${IPV6_PATCH}.diff.bz2" + epatch "${DISTDIR}/ipv6-mjo.patch" # Parts of the ipv6 patch fail due to the CVE2008-4392 fix above. # The following two patches fix those hunks. diff --git a/net-dns/djbdns/files/ipv6-mjo.patch b/net-dns/djbdns/files/ipv6-mjo.patch new file mode 100644 index 0000000..04607f5 --- /dev/null +++ b/net-dns/djbdns/files/ipv6-mjo.patch @@ -0,0 +1,3412 @@ +diff -uNr djbdns-1.05/FILES djbdns-1.05-ipv6/FILES +--- djbdns-1.05/FILES 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/FILES 2005-09-08 21:58:08.166381250 +0200 +@@ -135,6 +135,7 @@ + exit.h + fmt.h + fmt_ulong.c ++fmt_xlong.c + gen_alloc.h + gen_allocdefs.h + getln.c +@@ -151,6 +152,9 @@ + 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 @@ + readclose.c + readclose.h + scan.h ++scan_0x.c + scan_ulong.c + seek.h + seek_set.c +@@ -241,3 +246,9 @@ + warn-shsgr + buffer_read.c + buffer_write.c ++dns_nd6.c ++socket_udp6.c ++socket_getifidx.c ++tryn2i.c ++haven2i.h1 ++haven2i.h2 +diff -uNr djbdns-1.05/Makefile djbdns-1.05-ipv6/Makefile +--- djbdns-1.05/Makefile 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/Makefile 2005-09-08 21:58:08.166381250 +0200 +@@ -120,12 +120,14 @@ + 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 +@@ -228,11 +230,13 @@ + 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 +258,21 @@ + 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 +288,11 @@ + 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 +325,11 @@ + 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 +393,17 @@ + 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 +415,17 @@ + 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 +445,7 @@ + + 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 +530,10 @@ + 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 +596,18 @@ + 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 +684,9 @@ + ./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 +735,7 @@ + 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 +762,9 @@ + ./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 +820,10 @@ + 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 +836,7 @@ + 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 +858,26 @@ + 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 +886,47 @@ + 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 +1068,7 @@ + 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 + ./compile tdlookup.c + + timeoutread.o: \ +@@ -979,10 +1082,10 @@ + ./compile timeoutwrite.c + + tinydns: \ +-load tinydns.o server.o droproot.o tdlookup.o response.o qlog.o \ ++load tinydns.o server.o iopause.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 \ + socket.lib +- ./load tinydns server.o droproot.o tdlookup.o response.o \ ++ ./load tinydns server.o iopause.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 `cat socket.lib` + +@@ -1005,7 +1108,7 @@ + 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: \ +@@ -1068,12 +1171,18 @@ + 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 +1193,10 @@ + ./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 +1213,14 @@ + 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 -uNr djbdns-1.05/TARGETS djbdns-1.05-ipv6/TARGETS +--- djbdns-1.05/TARGETS 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/TARGETS 2005-09-08 21:58:08.170381500 +0200 +@@ -102,6 +102,7 @@ + dns_dtda.o + dns_ip.o + dns_ipq.o ++dns_ipq6.o + dns_mx.o + dns_name.o + dns_nd.o +@@ -180,6 +181,8 @@ + dnsip + dnsipq.o + dnsipq ++dnsip6q.o ++dnsip6q + dnsname.o + dnsname + dnstxt.o +@@ -214,3 +217,25 @@ + 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 -uNr djbdns-1.05/axfr-get.c djbdns-1.05-ipv6/axfr-get.c +--- djbdns-1.05/axfr-get.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/axfr-get.c 2005-09-08 21:58:08.170381500 +0200 +@@ -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 @@ + 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 -uNr djbdns-1.05/dns.h djbdns-1.05-ipv6/dns.h +--- djbdns-1.05/dns.h 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dns.h 2005-09-08 21:58:08.174381750 +0200 +@@ -35,7 +35,8 @@ + 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 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 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_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 -uNr djbdns-1.05/dns_ip6.c djbdns-1.05-ipv6/dns_ip6.c +--- djbdns-1.05/dns_ip6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_ip6.c 2005-09-08 21:58:08.174381750 +0200 +@@ -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 -uNr djbdns-1.05/dns_ipq6.c djbdns-1.05-ipv6/dns_ipq6.c +--- djbdns-1.05/dns_ipq6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_ipq6.c 2005-09-08 21:58:08.178382000 +0200 +@@ -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 -uNr djbdns-1.05/dns_name.c djbdns-1.05-ipv6/dns_name.c +--- djbdns-1.05/dns_name.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_name.c 2005-09-08 21:58:08.178382000 +0200 +@@ -2,6 +2,7 @@ + #include "uint16.h" + #include "byte.h" + #include "dns.h" ++#include "ip6.h" + + static char *q = 0; + +@@ -46,3 +47,24 @@ + 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 -uNr djbdns-1.05/dns_nd6.c djbdns-1.05-ipv6/dns_nd6.c +--- djbdns-1.05/dns_nd6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_nd6.c 2005-09-08 21:58:08.178382000 +0200 +@@ -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 -uNr djbdns-1.05/dns_rcip.c djbdns-1.05-ipv6/dns_rcip.c +--- djbdns-1.05/dns_rcip.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_rcip.c 2005-09-08 21:58:08.182382250 +0200 +@@ -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 @@ + 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 @@ + 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 @@ + } + + 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 @@ + } + + --uses; +- byte_copy(s,64,ip); ++ byte_copy(s,256,ip); + return 0; + } +diff -uNr djbdns-1.05/dns_resolve.c djbdns-1.05-ipv6/dns_resolve.c +--- djbdns-1.05/dns_resolve.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_resolve.c 2005-09-08 21:58:08.182382250 +0200 +@@ -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 @@ + { + 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 -uNr djbdns-1.05/dns_sortip6.c djbdns-1.05-ipv6/dns_sortip6.c +--- djbdns-1.05/dns_sortip6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_sortip6.c 2005-09-08 21:58:08.186382500 +0200 +@@ -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 -uNr djbdns-1.05/dns_transmit.c djbdns-1.05-ipv6/dns_transmit.c +--- djbdns-1.05/dns_transmit.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dns_transmit.c 2005-09-08 21:58:08.186382500 +0200 +@@ -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 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 @@ + + 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 -uNr djbdns-1.05/dnscache.c djbdns-1.05-ipv6/dnscache.c +--- djbdns-1.05/dnscache.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dnscache.c 2005-09-08 21:58:08.190382750 +0200 +@@ -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 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 @@ + 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 @@ + 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 @@ + 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 @@ + + 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 @@ + } + } + +- + static int tcp53; + + #define MAXTCP 20 +@@ -138,7 +143,7 @@ + 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 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 -uNr djbdns-1.05/dnsfilter.c djbdns-1.05-ipv6/dnsfilter.c +--- djbdns-1.05/dnsfilter.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dnsfilter.c 2005-09-08 21:58:08.190382750 +0200 +@@ -12,6 +12,7 @@ + #include "iopause.h" + #include "error.h" + #include "exit.h" ++#include "ip6.h" + + #define FATAL "dnsfilter: fatal: " + +@@ -44,7 +45,7 @@ + iopause_fd *io; + int iolen; + +-char servers[64]; ++char servers[256]; + char ip[4]; + char name[DNS_NAME4_DOMAIN]; + +@@ -191,7 +192,7 @@ + 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 -uNr djbdns-1.05/dnsip6.c djbdns-1.05-ipv6/dnsip6.c +--- djbdns-1.05/dnsip6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dnsip6.c 2005-09-08 21:58:08.190382750 +0200 +@@ -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 -uNr djbdns-1.05/dnsip6q.c djbdns-1.05-ipv6/dnsip6q.c +--- djbdns-1.05/dnsip6q.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/dnsip6q.c 2005-09-08 21:58:08.194383000 +0200 +@@ -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 -uNr djbdns-1.05/dnsname.c djbdns-1.05-ipv6/dnsname.c +--- djbdns-1.05/dnsname.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dnsname.c 2005-09-08 21:58:08.194383000 +0200 +@@ -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 @@ + 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 -uNr djbdns-1.05/dnsq.c djbdns-1.05-ipv6/dnsq.c +--- djbdns-1.05/dnsq.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dnsq.c 2005-09-08 21:58:08.198383250 +0200 +@@ -10,6 +10,7 @@ + #include "printpacket.h" + #include "parsetype.h" + #include "dns.h" ++#include "ip6.h" + + #define FATAL "dnsq: fatal: " + +@@ -24,14 +25,14 @@ + + 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 @@ + return 0; + } + +-char servers[64]; ++char servers[256]; + static stralloc ip; + static stralloc fqdn; + +@@ -73,9 +74,9 @@ + + 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 -uNr djbdns-1.05/dnstrace.c djbdns-1.05-ipv6/dnstrace.c +--- djbdns-1.05/dnstrace.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/dnstrace.c 2005-09-08 21:58:08.198383250 +0200 +@@ -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 @@ + } + + static stralloc querystr; +-char ipstr[IP4_FMT]; ++char ipstr[IP6_FMT]; + static stralloc tmp; + + void printdomain(const char *d) +@@ -42,19 +43,19 @@ + + 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 @@ + + struct address { + char *owner; +- char ip[4]; ++ char ip[16]; + } ; + + GEN_ALLOC_typedef(address_alloc,struct address,s,len,a) +@@ -117,7 +118,7 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + + 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 @@ + 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 @@ + 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 -uNr djbdns-1.05/error.h djbdns-1.05-ipv6/error.h +--- djbdns-1.05/error.h 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/error.h 2005-09-08 21:58:08.198383250 +0200 +@@ -1,7 +1,7 @@ + #ifndef ERROR_H + #define ERROR_H + +-extern int errno; ++#include + + extern int error_intr; + extern int error_nomem; +diff -uNr djbdns-1.05/fmt_xlong.c djbdns-1.05-ipv6/fmt_xlong.c +--- djbdns-1.05/fmt_xlong.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/fmt_xlong.c 2005-09-08 21:58:08.202383500 +0200 +@@ -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 -uNr djbdns-1.05/haveip6.h1 djbdns-1.05-ipv6/haveip6.h1 +--- djbdns-1.05/haveip6.h1 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/haveip6.h1 2005-09-08 21:58:08.202383500 +0200 +@@ -0,0 +1 @@ ++ +diff -uNr djbdns-1.05/haveip6.h2 djbdns-1.05-ipv6/haveip6.h2 +--- djbdns-1.05/haveip6.h2 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/haveip6.h2 2005-09-08 21:58:08.202383500 +0200 +@@ -0,0 +1 @@ ++#define LIBC_HAS_IP6 1 +diff -uNr djbdns-1.05/haven2i.h1 djbdns-1.05-ipv6/haven2i.h1 +--- djbdns-1.05/haven2i.h1 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/haven2i.h1 2005-09-08 21:58:08.206383750 +0200 +@@ -0,0 +1 @@ ++#undef HAVE_N2I +diff -uNr djbdns-1.05/haven2i.h2 djbdns-1.05-ipv6/haven2i.h2 +--- djbdns-1.05/haven2i.h2 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/haven2i.h2 2005-09-08 21:58:08.206383750 +0200 +@@ -0,0 +1 @@ ++#define HAVE_N2I +diff -uNr djbdns-1.05/hier.c djbdns-1.05-ipv6/hier.c +--- djbdns-1.05/hier.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/hier.c 2005-09-08 21:58:08.206383750 +0200 +@@ -29,7 +29,9 @@ + 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 -uNr djbdns-1.05/ip6.h djbdns-1.05-ipv6/ip6.h +--- djbdns-1.05/ip6.h 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/ip6.h 2005-09-08 21:58:08.210384000 +0200 +@@ -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 *,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 -uNr djbdns-1.05/ip6_fmt.c djbdns-1.05-ipv6/ip6_fmt.c +--- djbdns-1.05/ip6_fmt.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/ip6_fmt.c 2005-09-08 21:58:08.210384000 +0200 +@@ -0,0 +1,60 @@ ++#include "fmt.h" ++#include "byte.h" ++#include "ip4.h" ++#include "ip6.h" ++#include ++ ++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,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 -uNr djbdns-1.05/ip6_scan.c djbdns-1.05-ipv6/ip6_scan.c +--- djbdns-1.05/ip6_scan.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/ip6_scan.c 2005-09-08 21:58:08.214384250 +0200 +@@ -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='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 -uNr djbdns-1.05/log.c djbdns-1.05-ipv6/log.c +--- djbdns-1.05/log.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/log.c 2005-09-08 21:58:08.214384250 +0200 +@@ -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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + 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 -uNr djbdns-1.05/okclient.c djbdns-1.05-ipv6/okclient.c +--- djbdns-1.05/okclient.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/okclient.c 2005-09-08 21:58:08.214384250 +0200 +@@ -2,24 +2,34 @@ + #include + #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 -uNr djbdns-1.05/printrecord.c djbdns-1.05-ipv6/printrecord.c +--- djbdns-1.05/printrecord.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/printrecord.c 2005-09-08 21:58:08.218384500 +0200 +@@ -4,6 +4,7 @@ + #include "byte.h" + #include "dns.h" + #include "printrecord.h" ++#include "ip6.h" + + static char *d; + +@@ -82,6 +83,15 @@ + 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 -uNr djbdns-1.05/qlog.c djbdns-1.05-ipv6/qlog.c +--- djbdns-1.05/qlog.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/qlog.c 2005-09-08 21:58:08.218384500 +0200 +@@ -20,15 +20,15 @@ + 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 -uNr djbdns-1.05/query.c djbdns-1.05-ipv6/query.c +--- djbdns-1.05/query.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/query.c 2005-09-08 21:58:08.218384500 +0200 +@@ -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 @@ + 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 @@ + 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 @@ + int k; + int p; + int q; ++ unsigned int ii; + + errno = error_io; + if (state == 1) goto HAVEPACKET; +@@ -210,9 +214,10 @@ + + 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 @@ + 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; +@@ -326,9 +483,10 @@ + 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; +@@ -390,7 +580,7 @@ + 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; +@@ -519,7 +709,7 @@ + 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 +833,11 @@ + 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 +845,23 @@ + } + 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) { +@@ -723,9 +935,10 @@ + 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; + } + pos += datalen; +@@ -818,7 +1031,7 @@ + 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,8 +1042,9 @@ + 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; + + return doit(z,0); + } + +diff -uNr djbdns-1.05/roots.c djbdns-1.05-ipv6/roots.c +--- djbdns-1.05/roots.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/roots.c 2005-09-08 21:58:08.222384750 +0200 +@@ -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 @@ + 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 @@ + } + } + +-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 @@ + 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 @@ + 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 -uNr djbdns-1.05/scan_xlong.c djbdns-1.05-ipv6/scan_xlong.c +--- djbdns-1.05/scan_xlong.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/scan_xlong.c 2005-09-08 21:58:08.222384750 +0200 +@@ -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 -uNr djbdns-1.05/server.c djbdns-1.05-ipv6/server.c +--- djbdns-1.05/server.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/server.c 2005-09-08 21:58:08.226385000 +0200 +@@ -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 char *q; + ++void nomem() ++{ ++ strerr_die2x(111,fatal,"out of memory"); ++} ++ + static int doit(void) + { + unsigned int pos; +@@ -82,35 +91,86 @@ + 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 512) response_tc(); ++ socket_send6(udp53[i],response,response_len,ip,port,ifid); ++ /* may block for buffer space; if it fails, too bad */ ++ } + } + } +diff -uNr djbdns-1.05/sockaddr_in6.h1 djbdns-1.05-ipv6/sockaddr_in6.h1 +--- djbdns-1.05/sockaddr_in6.h1 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/sockaddr_in6.h1 2005-09-08 21:58:08.226385000 +0200 +@@ -0,0 +1,21 @@ ++#include "haveip6.h" ++#ifdef LIBC_HAS_IP6 ++#include ++#include ++#define sockaddr_in6 blub ++#include ++#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 ++#include ++#include ++#endif +diff -uNr djbdns-1.05/sockaddr_in6.h2 djbdns-1.05-ipv6/sockaddr_in6.h2 +--- djbdns-1.05/sockaddr_in6.h2 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/sockaddr_in6.h2 2005-09-08 21:58:08.226385000 +0200 +@@ -0,0 +1,4 @@ ++#include ++#include ++#include ++ +diff -uNr djbdns-1.05/socket.h djbdns-1.05-ipv6/socket.h +--- djbdns-1.05/socket.h 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/socket.h 2005-09-08 21:58:08.230385250 +0200 +@@ -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 -uNr djbdns-1.05/socket_accept6.c djbdns-1.05-ipv6/socket_accept6.c +--- djbdns-1.05/socket_accept6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_accept6.c 2005-09-08 21:58:08.230385250 +0200 +@@ -0,0 +1,43 @@ ++#include ++#include ++#include ++#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 -uNr djbdns-1.05/socket_bind.c djbdns-1.05-ipv6/socket_bind.c +--- djbdns-1.05/socket_bind.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_bind.c 2005-09-08 21:58:08.230385250 +0200 +@@ -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 -uNr djbdns-1.05/socket_bind6.c djbdns-1.05-ipv6/socket_bind6.c +--- djbdns-1.05/socket_bind6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_bind6.c 2005-09-08 21:58:08.234385500 +0200 +@@ -0,0 +1,43 @@ ++#include ++#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 -uNr djbdns-1.05/socket_connect6.c djbdns-1.05-ipv6/socket_connect6.c +--- djbdns-1.05/socket_connect6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_connect6.c 2005-09-08 21:58:32.871925250 +0200 +@@ -0,0 +1,39 @@ ++#include ++#include ++#include ++#include ++#include ++#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 -uNr djbdns-1.05/socket_getifidx.c djbdns-1.05-ipv6/socket_getifidx.c +--- djbdns-1.05/socket_getifidx.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_getifidx.c 2005-09-08 21:58:08.234385500 +0200 +@@ -0,0 +1,13 @@ ++#include ++#include ++#include ++#include "socket.h" ++#include "haven2i.h" ++ ++uint32 socket_getifidx(const char* ifname) { ++#ifdef HAVE_N2I ++ return if_nametoindex(ifname); ++#else ++ return 0; ++#endif ++} +diff -uNr djbdns-1.05/socket_noipv6.c djbdns-1.05-ipv6/socket_noipv6.c +--- djbdns-1.05/socket_noipv6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_noipv6.c 2005-09-08 21:58:08.234385500 +0200 +@@ -0,0 +1,7 @@ ++#include "haveip6.h" ++ ++#ifdef LIBC_HAS_IP6 ++int noipv6=0; ++#else ++int noipv6=1; ++#endif +diff -uNr djbdns-1.05/socket_recv6.c djbdns-1.05-ipv6/socket_recv6.c +--- djbdns-1.05/socket_recv6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_recv6.c 2005-09-08 21:58:08.238385750 +0200 +@@ -0,0 +1,42 @@ ++#include ++#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) { ++ 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 -uNr djbdns-1.05/socket_send6.c djbdns-1.05-ipv6/socket_send6.c +--- djbdns-1.05/socket_send6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_send6.c 2005-09-08 21:58:08.238385750 +0200 +@@ -0,0 +1,39 @@ ++#include ++#include ++#include ++#include ++#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 -uNr djbdns-1.05/socket_tcp6.c djbdns-1.05-ipv6/socket_tcp6.c +--- djbdns-1.05/socket_tcp6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_tcp6.c 2005-09-08 22:04:31.194319000 +0200 +@@ -0,0 +1,44 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ndelay.h" ++#include "socket.h" ++#include "haveip6.h" ++#include "error.h" ++ ++#ifndef EAFNOSUPPORT ++#define EAFNOSUPPORT EINVAL ++#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) { ++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 -uNr djbdns-1.05/socket_udp6.c djbdns-1.05-ipv6/socket_udp6.c +--- djbdns-1.05/socket_udp6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/socket_udp6.c 2005-09-08 22:04:23.577843000 +0200 +@@ -0,0 +1,43 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include "ndelay.h" ++#include "socket.h" ++#include "haveip6.h" ++#include "error.h" ++ ++#ifndef EAFNOSUPPORT ++#define EAFNOSUPPORT EINVAL ++#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) { ++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 -uNr djbdns-1.05/tdlookup.c djbdns-1.05-ipv6/tdlookup.c +--- djbdns-1.05/tdlookup.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/tdlookup.c 2005-09-08 21:58:08.242386000 +0200 +@@ -8,6 +8,7 @@ + #include "dns.h" + #include "seek.h" + #include "response.h" ++#include "ip6.h" + + static int want(const char *owner,const char type[2]) + { +@@ -119,8 +120,9 @@ + 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 +154,8 @@ + 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 +173,17 @@ + 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 +208,12 @@ + 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 +278,11 @@ + 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,7 +302,7 @@ + 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; +@@ -292,15 +316,17 @@ + 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; ++ if (byte_equal(ip,12,V4mappedprefix)) { ++ byte_copy(key + 2,4,ip+12); ++ 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); + +diff -uNr djbdns-1.05/tinydns-conf.c djbdns-1.05-ipv6/tinydns-conf.c +--- djbdns-1.05/tinydns-conf.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/tinydns-conf.c 2005-09-08 21:58:08.242386000 +0200 +@@ -82,6 +82,18 @@ + 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 -uNr djbdns-1.05/tinydns-data.c djbdns-1.05-ipv6/tinydns-data.c +--- djbdns-1.05/tinydns-data.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/tinydns-data.c 2005-09-08 21:58:08.246386250 +0200 +@@ -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" +@@ -172,6 +173,7 @@ + static char *d1; + static char *d2; + char dptr[DNS_NAME4_DOMAIN]; ++char d6ptr[DNS_NAME6_DOMAIN]; + + char strnum[FMT_ULONG]; + +@@ -193,6 +195,7 @@ + char loc[2]; + unsigned long u; + char ip[4]; ++ char ip6[16]; + char type[2]; + char soa[20]; + char buf[4]; +@@ -339,6 +342,33 @@ + } + 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 -uNr djbdns-1.05/tinydns-edit.c djbdns-1.05-ipv6/tinydns-edit.c +--- djbdns-1.05/tinydns-edit.c 2001-02-11 22:11:45.000000000 +0100 ++++ djbdns-1.05-ipv6/tinydns-edit.c 2005-09-08 21:58:08.246386250 +0200 +@@ -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 @@ + + 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 @@ + char mode; + static char *target; + char targetip[4]; ++char targetip6[16]; + + int fd; + buffer b; +@@ -61,7 +64,9 @@ + 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 @@ + 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 @@ + 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 @@ + 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 @@ + } + 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 @@ + 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 -uNr djbdns-1.05/tryip6.c djbdns-1.05-ipv6/tryip6.c +--- djbdns-1.05/tryip6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/tryip6.c 2005-09-08 21:58:08.246386250 +0200 +@@ -0,0 +1,8 @@ ++#include ++#include ++#include ++ ++main() { ++ struct sockaddr_in6 sa; ++ sa.sin6_family = PF_INET6; ++} +diff -uNr djbdns-1.05/tryn2i.c djbdns-1.05-ipv6/tryn2i.c +--- djbdns-1.05/tryn2i.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/tryn2i.c 2005-09-08 21:58:08.246386250 +0200 +@@ -0,0 +1,8 @@ ++#include ++#include ++#include ++ ++int main() { ++ static char ifname[IFNAMSIZ]; ++ char *tmp=if_indextoname(0,ifname); ++} +diff -uNr djbdns-1.05/trysa6.c djbdns-1.05-ipv6/trysa6.c +--- djbdns-1.05/trysa6.c 1970-01-01 01:00:00.000000000 +0100 ++++ djbdns-1.05-ipv6/trysa6.c 2005-09-08 21:58:08.250386500 +0200 +@@ -0,0 +1,8 @@ ++#include ++#include ++#include ++ ++main() { ++ struct sockaddr_in6 sa; ++ sa.sin6_scope_id = 1; ++}