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