chiark / gitweb /
src/: Support IPv6 reverse queries.
authorMark Wooding <mdw@distorted.org.uk>
Sat, 24 May 2014 13:00:03 +0000 (14:00 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 19 Oct 2014 20:09:54 +0000 (21:09 +0100)
This involves moving most of the label parser in ckl_ptr, and the
reverse-domain constructor, into addrfam and teaching them about IPv6.

The label parser is a little tricky because it involves keeping track of
a parse state for each possible address family until we run out of
possibilities or the parse is complete.

Moving the reverse-domain constructor introduces a slightly unpleasant
hack: because knowledge of the right reverse-lookup zone belongs in
addrfam, we get adns_submit_reverse to pass a sentinel through
_reverse_any to addrfam.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
19 files changed:
regress/case-dh-ptr-aaaa.err [new file with mode: 0644]
regress/case-dh-ptr-aaaa.out [new file with mode: 0644]
regress/case-dh-ptr-aaaa.sys [new file with mode: 0644]
regress/case-ptr-aaaa-check.err [new file with mode: 0644]
regress/case-ptr-aaaa-check.out [new file with mode: 0644]
regress/case-ptr-aaaa-check.sys [new file with mode: 0644]
regress/case-ptr-aaaa-mismatch.err [new file with mode: 0644]
regress/case-ptr-aaaa-mismatch.out [new file with mode: 0644]
regress/case-ptr-aaaa-mismatch.sys [new file with mode: 0644]
regress/case-ptr-aaaa-plain.err [new file with mode: 0644]
regress/case-ptr-aaaa-plain.out [new file with mode: 0644]
regress/case-ptr-aaaa-plain.sys [new file with mode: 0644]
regress/case-ptr-aaaa.err [new file with mode: 0644]
regress/case-ptr-aaaa.out [new file with mode: 0644]
regress/case-ptr-aaaa.sys [new file with mode: 0644]
src/addrfam.c
src/internal.h
src/query.c
src/types.c

diff --git a/regress/case-dh-ptr-aaaa.err b/regress/case-dh-ptr-aaaa.err
new file mode 100644 (file)
index 0000000..67419fb
--- /dev/null
@@ -0,0 +1 @@
+adns debug: using nameserver 172.29.199.224
diff --git a/regress/case-dh-ptr-aaaa.out b/regress/case-dh-ptr-aaaa.out
new file mode 100644 (file)
index 0000000..64060d2
--- /dev/null
@@ -0,0 +1,2 @@
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa PTR stratocaster.distorted.org.uk
+rc=0
diff --git a/regress/case-dh-ptr-aaaa.sys b/regress/case-dh-ptr-aaaa.sys
new file mode 100644 (file)
index 0000000..5b9f983
--- /dev/null
@@ -0,0 +1,68 @@
+./adnshost distorted
+-i2001:ba8:1d9:2::4
+ start 1401919808.588362
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000058
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000031
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000026
+ sendto fd=6 addr=172.29.199.224:53
+     311f0100 00010000 00000000 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001.
+ sendto=90
+ +0.000233
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999767
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.004488
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     311f8580 00010001 00040008 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001c00c 000c0001
+     00003840 001f0c73 74726174 6f636173 74657209 64697374 6f727465 64036f72
+     6702756b 00c03400 02000100 00384000 0d0a7465 6c656361 73746572 c073c034
+     00020001 00003840 00090672 61646975 73c073c0 34000200 01000038 40000c09
+     70726563 6973696f 6ec073c0 34000200 01000038 40000a07 76616d70 697265c0
+     73c0aa00 01000100 00384000 04ac1dc7 01c0aa00 1c000100 00384000 10200104
+     70974000 01000000 00000000 01c0d700 01000100 00384000 04ac1dc7 05c0d700
+     1c000100 00384000 10200104 70974000 01000000 00000000 05c0bf00 01000100
+     00384000 04ac1dc7 b2c0bf00 1c000100 00384000 1020010b a801d900 02000000
+     00000000 02c09100 01000100 00384000 04ac1dc7 b3c09100 1c000100 00384000
+     1020010b a801d900 02000000 00000000 03.
+ +0.000405
+ sendto fd=6 addr=172.29.199.224:53
+     31200100 00010000 00000000 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001.
+ sendto=47
+ +0.000175
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000040
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999380
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.002002
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31208580 00010001 00040008 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001c0 0c001c00 01000038 40001020 010ba801
+     d9000200 00000000 000004c0 19000200 01000038 4000100a 74656c65 63617374
+     6572026e 73c019c0 19000200 01000038 40000c09 70726563 6973696f 6ec062c0
+     19000200 01000038 40000906 72616469 7573c062 c0190002 00010000 3840000a
+     0776616d 70697265 c062c08b 00010001 00003840 0004ac1d c701c08b 001c0001
+     00003840 00102001 04709740 00010000 00000000 0001c0a0 00010001 00003840
+     0004ac1d c705c0a0 001c0001 00003840 00102001 04709740 00010000 00000000
+     0005c073 00010001 00003840 0004ac1d c7b2c073 001c0001 00003840 00102001
+     0ba801d9 00020000 00000000 0002c057 00010001 00003840 0004ac1d c7b3c057
+     001c0001 00003840 00102001 0ba801d9 00020000 00000000 0003.
+ +0.000280
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000051
+ close fd=6
+ close=OK
+ +0.000134
diff --git a/regress/case-ptr-aaaa-check.err b/regress/case-ptr-aaaa-check.err
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/regress/case-ptr-aaaa-check.out b/regress/case-ptr-aaaa-check.out
new file mode 100644 (file)
index 0000000..b2c9af8
--- /dev/null
@@ -0,0 +1,5 @@
+adns debug: using nameserver 172.29.199.224
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type 65548 PTR(checked) submitted
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type PTR(checked): OK; nrrs=1; cname=$; owner=$; ttl=14400
+ stratocaster.distorted.org.uk
+rc=0
diff --git a/regress/case-ptr-aaaa-check.sys b/regress/case-ptr-aaaa-check.sys
new file mode 100644 (file)
index 0000000..c536b5f
--- /dev/null
@@ -0,0 +1,68 @@
+./adnstest distorted
+:65548 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa
+ start 1401919115.064959
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000064
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000031
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000027
+ sendto fd=6 addr=172.29.199.224:53
+     311f0100 00010000 00000000 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001.
+ sendto=90
+ +0.000266
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999734
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.003844
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     311f8580 00010001 00040008 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001c00c 000c0001
+     00003840 001f0c73 74726174 6f636173 74657209 64697374 6f727465 64036f72
+     6702756b 00c03400 02000100 00384000 0c097072 65636973 696f6ec0 73c03400
+     02000100 00384000 09067261 64697573 c073c034 00020001 00003840 000d0a74
+     656c6563 61737465 72c073c0 34000200 01000038 40000a07 76616d70 697265c0
+     73c0a900 01000100 00384000 04ac1dc7 01c0a900 1c000100 00384000 10200104
+     70974000 01000000 00000000 01c0d700 01000100 00384000 04ac1dc7 05c0d700
+     1c000100 00384000 10200104 70974000 01000000 00000000 05c09100 01000100
+     00384000 04ac1dc7 b2c09100 1c000100 00384000 1020010b a801d900 02000000
+     00000000 02c0be00 01000100 00384000 04ac1dc7 b3c0be00 1c000100 00384000
+     1020010b a801d900 02000000 00000000 03.
+ +0.000334
+ sendto fd=6 addr=172.29.199.224:53
+     31200100 00010000 00000000 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001.
+ sendto=47
+ +0.000139
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000032
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999495
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.001799
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31208580 00010001 00040008 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001c0 0c001c00 01000038 40001020 010ba801
+     d9000200 00000000 000004c0 19000200 01000038 40000d07 76616d70 69726502
+     6e73c019 c0190002 00010000 3840000d 0a74656c 65636173 746572c0 5fc01900
+     02000100 00384000 0c097072 65636973 696f6ec0 5fc01900 02000100 00384000
+     09067261 64697573 c05fc0a1 00010001 00003840 0004ac1d c701c0a1 001c0001
+     00003840 00102001 04709740 00010000 00000000 0001c057 00010001 00003840
+     0004ac1d c705c057 001c0001 00003840 00102001 04709740 00010000 00000000
+     0005c089 00010001 00003840 0004ac1d c7b2c089 001c0001 00003840 00102001
+     0ba801d9 00020000 00000000 0002c070 00010001 00003840 0004ac1d c7b3c070
+     001c0001 00003840 00102001 0ba801d9 00020000 00000000 0003.
+ +0.000284
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000046
+ close fd=6
+ close=OK
+ +0.000075
diff --git a/regress/case-ptr-aaaa-mismatch.err b/regress/case-ptr-aaaa-mismatch.err
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/regress/case-ptr-aaaa-mismatch.out b/regress/case-ptr-aaaa-mismatch.out
new file mode 100644 (file)
index 0000000..04f1f2b
--- /dev/null
@@ -0,0 +1,4 @@
+adns debug: using nameserver 172.29.199.224
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.b.d.0.1.0.0.2.ip6.arpa flags 0 type 65548 PTR(checked) submitted
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.b.d.0.1.0.0.2.ip6.arpa flags 0 type PTR(checked): Inconsistent resource records in DNS; nrrs=0; cname=$; owner=$; ttl=14400
+rc=0
diff --git a/regress/case-ptr-aaaa-mismatch.sys b/regress/case-ptr-aaaa-mismatch.sys
new file mode 100644 (file)
index 0000000..057f06c
--- /dev/null
@@ -0,0 +1,68 @@
+./adnstest distorted
+:65548 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.b.d.0.1.0.0.2.ip6.arpa
+ start 1401919322.902230
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000061
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000031
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000026
+ sendto fd=6 addr=172.29.199.224:53
+     311f0100 00010000 00000000 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380162
+     01640130 01310130 01300132 03697036 04617270 6100000c 0001.
+ sendto=90
+ +0.000410
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999590
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.003725
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     311f8580 00010001 00040008 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380162
+     01640130 01310130 01300132 03697036 04617270 6100000c 0001c00c 000c0001
+     00003840 001f0c73 74726174 6f636173 74657209 64697374 6f727465 64036f72
+     6702756b 00c03400 02000100 00384000 0c097072 65636973 696f6ec0 73c03400
+     02000100 00384000 0d0a7465 6c656361 73746572 c073c034 00020001 00003840
+     00090672 61646975 73c073c0 34000200 01000038 40000a07 76616d70 697265c0
+     73c0c200 01000100 00384000 04ac1dc7 01c0c200 1c000100 00384000 10200104
+     70974000 01000000 00000000 01c0d700 01000100 00384000 04ac1dc7 05c0d700
+     1c000100 00384000 10200104 70974000 01000000 00000000 05c09100 01000100
+     00384000 04ac1dc7 b2c09100 1c000100 00384000 1020010b a801d900 02000000
+     00000000 02c0a900 01000100 00384000 04ac1dc7 b3c0a900 1c000100 00384000
+     1020010b a801d900 02000000 00000000 03.
+ +0.000340
+ sendto fd=6 addr=172.29.199.224:53
+     31200100 00010000 00000000 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001.
+ sendto=47
+ +0.000244
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000035
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999381
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.001587
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31208580 00010001 00040008 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001c0 0c001c00 01000038 40001020 010ba801
+     d9000200 00000000 000004c0 19000200 01000038 40000c06 72616469 7573026e
+     73c019c0 19000200 01000038 40000a07 76616d70 697265c0 5ec01900 02000100
+     00384000 0c097072 65636973 696f6ec0 5ec01900 02000100 00384000 0d0a7465
+     6c656361 73746572 c05ec057 00010001 00003840 0004ac1d c701c057 001c0001
+     00003840 00102001 04709740 00010000 00000000 0001c06f 00010001 00003840
+     0004ac1d c705c06f 001c0001 00003840 00102001 04709740 00010000 00000000
+     0005c085 00010001 00003840 0004ac1d c7b2c085 001c0001 00003840 00102001
+     0ba801d9 00020000 00000000 0002c09d 00010001 00003840 0004ac1d c7b3c09d
+     001c0001 00003840 00102001 0ba801d9 00020000 00000000 0003.
+ +0.000289
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000048
+ close fd=6
+ close=OK
+ +0.000546
diff --git a/regress/case-ptr-aaaa-plain.err b/regress/case-ptr-aaaa-plain.err
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/regress/case-ptr-aaaa-plain.out b/regress/case-ptr-aaaa-plain.out
new file mode 100644 (file)
index 0000000..63e72ad
--- /dev/null
@@ -0,0 +1,5 @@
+adns debug: using nameserver 172.29.199.224
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type 12 PTR(raw) submitted
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type PTR(raw): OK; nrrs=1; cname=$; owner=$; ttl=14400
+ stratocaster.distorted.org.uk
+rc=0
diff --git a/regress/case-ptr-aaaa-plain.sys b/regress/case-ptr-aaaa-plain.sys
new file mode 100644 (file)
index 0000000..d09ce17
--- /dev/null
@@ -0,0 +1,43 @@
+./adnstest distorted
+:12 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa
+ start 1401918956.635299
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000060
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000032
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000026
+ sendto fd=6 addr=172.29.199.224:53
+     311f0100 00010000 00000000 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001.
+ sendto=90
+ +0.000219
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999781
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.002107
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     311f8580 00010001 00040008 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001c00c 000c0001
+     00003840 001f0c73 74726174 6f636173 74657209 64697374 6f727465 64036f72
+     6702756b 00c03400 02000100 00384000 0a077661 6d706972 65c073c0 34000200
+     01000038 40000d0a 74656c65 63617374 6572c073 c0340002 00010000 3840000c
+     09707265 63697369 6f6ec073 c0340002 00010000 38400009 06726164 697573c0
+     73c0d800 01000100 00384000 04ac1dc7 01c0d800 1c000100 00384000 10200104
+     70974000 01000000 00000000 01c09100 01000100 00384000 04ac1dc7 05c09100
+     1c000100 00384000 10200104 70974000 01000000 00000000 05c0c000 01000100
+     00384000 04ac1dc7 b2c0c000 1c000100 00384000 1020010b a801d900 02000000
+     00000000 02c0a700 01000100 00384000 04ac1dc7 b3c0a700 1c000100 00384000
+     1020010b a801d900 02000000 00000000 03.
+ +0.000349
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000072
+ close fd=6
+ close=OK
+ +0.000081
diff --git a/regress/case-ptr-aaaa.err b/regress/case-ptr-aaaa.err
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/regress/case-ptr-aaaa.out b/regress/case-ptr-aaaa.out
new file mode 100644 (file)
index 0000000..b2c9af8
--- /dev/null
@@ -0,0 +1,5 @@
+adns debug: using nameserver 172.29.199.224
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type 65548 PTR(checked) submitted
+4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa flags 0 type PTR(checked): OK; nrrs=1; cname=$; owner=$; ttl=14400
+ stratocaster.distorted.org.uk
+rc=0
diff --git a/regress/case-ptr-aaaa.sys b/regress/case-ptr-aaaa.sys
new file mode 100644 (file)
index 0000000..60fa010
--- /dev/null
@@ -0,0 +1,68 @@
+./adnstest distorted
+:65548 4.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.2.0.0.0.9.d.1.0.8.a.b.0.1.0.0.2.ip6.arpa
+ start 1401919090.054985
+ socket type=SOCK_DGRAM
+ socket=6
+ +0.000061
+ fcntl fd=6 cmd=F_GETFL
+ fcntl=~O_NONBLOCK&...
+ +0.000030
+ fcntl fd=6 cmd=F_SETFL O_NONBLOCK|...
+ fcntl=OK
+ +0.000026
+ sendto fd=6 addr=172.29.199.224:53
+     311f0100 00010000 00000000 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001.
+ sendto=90
+ +0.000227
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999773
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.003800
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     311f8580 00010001 00040008 01340130 01300130 01300130 01300130 01300130
+     01300130 01300130 01300130 01320130 01300130 01390164 01310130 01380161
+     01620130 01310130 01300132 03697036 04617270 6100000c 0001c00c 000c0001
+     00003840 001f0c73 74726174 6f636173 74657209 64697374 6f727465 64036f72
+     6702756b 00c03400 02000100 00384000 0c097072 65636973 696f6ec0 73c03400
+     02000100 00384000 0a077661 6d706972 65c073c0 34000200 01000038 40000906
+     72616469 7573c073 c0340002 00010000 3840000d 0a74656c 65636173 746572c0
+     73c0bf00 01000100 00384000 04ac1dc7 01c0bf00 1c000100 00384000 10200104
+     70974000 01000000 00000000 01c0a900 01000100 00384000 04ac1dc7 05c0a900
+     1c000100 00384000 10200104 70974000 01000000 00000000 05c09100 01000100
+     00384000 04ac1dc7 b2c09100 1c000100 00384000 1020010b a801d900 02000000
+     00000000 02c0d400 01000100 00384000 04ac1dc7 b3c0d400 1c000100 00384000
+     1020010b a801d900 02000000 00000000 03.
+ +0.000338
+ sendto fd=6 addr=172.29.199.224:53
+     31200100 00010000 00000000 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001.
+ sendto=47
+ +0.000129
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000031
+ select max=7 rfds=[6] wfds=[] efds=[] to=1.999502
+ select=1 rfds=[6] wfds=[] efds=[]
+ +0.001827
+ recvfrom fd=6 buflen=512
+ recvfrom=OK addr=172.29.199.224:53
+     31208580 00010001 00040008 0c737472 61746f63 61737465 72096469 73746f72
+     74656403 6f726702 756b0000 1c0001c0 0c001c00 01000038 40001020 010ba801
+     d9000200 00000000 000004c0 19000200 01000038 4000100a 74656c65 63617374
+     6572026e 73c019c0 19000200 01000038 40000906 72616469 7573c062 c0190002
+     00010000 3840000a 0776616d 70697265 c062c019 00020001 00003840 000c0970
+     72656369 73696f6e c062c073 00010001 00003840 0004ac1d c701c073 001c0001
+     00003840 00102001 04709740 00010000 00000000 0001c088 00010001 00003840
+     0004ac1d c705c088 001c0001 00003840 00102001 04709740 00010000 00000000
+     0005c09e 00010001 00003840 0004ac1d c7b2c09e 001c0001 00003840 00102001
+     0ba801d9 00020000 00000000 0002c057 00010001 00003840 0004ac1d c7b3c057
+     001c0001 00003840 00102001 0ba801d9 00020000 00000000 0003.
+ +0.000308
+ recvfrom fd=6 buflen=512
+ recvfrom=EAGAIN
+ +0.000056
+ close fd=6
+ close=OK
+ +0.000088
index 28bf128..3bddabd 100644 (file)
@@ -455,3 +455,181 @@ char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf) {
   assert(!err);
   return buf;
 }
+
+/*
+ * Reverse-domain parsing and construction.
+ */
+
+int adns__make_reverse_domain(const struct sockaddr *sa, const char *zone,
+                             char **buf_io, size_t bufsz,
+                             char **buf_free_r) {
+  size_t req;
+  char *p;
+  unsigned c, y;
+  unsigned long aa;
+  const unsigned char *ap;
+  int i, j;
+
+  switch (sa->sa_family) {
+  AF_CASES(af);
+  af_inet:
+    req= 4 * 4;
+    if (!zone) zone= "in-addr.arpa";
+    break;
+  af_inet6:
+    req = 2 * 32;
+    if (!zone) zone= "ip6.arpa";
+    break;
+  default:
+    return ENOSYS;
+  }
+
+  req += strlen(zone) + 1;
+  if (req <= bufsz)
+    p= *buf_io;
+  else {
+    p= malloc(req); if (!p) return errno;
+    *buf_free_r = p;
+  }
+
+  *buf_io= p;
+  switch (sa->sa_family) {
+  AF_CASES(bf);
+  bf_inet:
+    aa= ntohl(CSIN(sa)->sin_addr.s_addr);
+    for (i=0; i<4; i++) {
+      p += sprintf(p, "%d", (int)(aa & 0xff));
+      *p++= '.';
+      aa >>= 8;
+    }
+    break;
+  bf_inet6:
+    ap= CSIN6(sa)->sin6_addr.s6_addr + 16;
+    for (i=0; i<16; i++) {
+      c= *--ap;
+      for (j=0; j<2; j++) {
+       y= c & 0xf;
+       *p++= (y < 10) ? y + '0' : y - 10 + 'a';
+       c >>= 4;
+       *p++= '.';
+      }
+    }
+    break;
+  default:
+    unknown_af(sa->sa_family);
+  }
+
+  strcpy(p, zone);
+  return 0;
+}
+
+
+static int inet_rev_parsecomp(const char *p, size_t n) {
+  int i= 0;
+  if (n > 3) return -1;
+
+  while (n--) {
+    if ('0' <= *p && *p <= '9') i= 10*i + *p++ - '0';
+    else return -1;
+  }
+  return i;
+}
+
+static void inet_rev_mkaddr(union gen_addr *addr, const byte *ipv) {
+  addr->v4.s_addr= htonl((ipv[3]<<24) | (ipv[2]<<16) |
+                        (ipv[1]<<8) | (ipv[0]));
+}
+
+static int inet6_rev_parsecomp(const char *p, size_t n) {
+  if (n != 1) return -1;
+  else if ('0' <= *p && *p <= '9') return *p - '0';
+  else if ('a' <= *p && *p <= 'f') return *p - 'a' + 10;
+  else if ('A' <= *p && *p <= 'F') return *p - 'a' + 10;
+  else return -1;
+}
+
+static void inet6_rev_mkaddr(union gen_addr *addr, const byte *ipv) {
+  unsigned char *a= addr->v6.s6_addr;
+  int i;
+
+  for (i=0; i<16; i++)
+    a[i]= (ipv[31-2*i] << 4) | (ipv[30-2*i] << 0);
+}
+
+static const struct revparse_domain {
+  int af;                              /* address family */
+  int nrevlab;                         /* n of reverse-address labels */
+  adns_rrtype rrtype;                  /* forward-lookup type */
+
+  int (*rev_parsecomp)(const char *p, size_t n);
+  /* parse a single component from a label; return the integer value, or -1
+   * if it was unintelligible.
+   */
+
+  void (*rev_mkaddr)(union gen_addr *addr, const byte *ipv);
+  /* write out the parsed address from a vector of parsed components */
+
+  const char *const tail[3];           /* tail label names */
+} revparse_domains[NREVDOMAINS] = {
+  { AF_INET, 4, adns_r_a, inet_rev_parsecomp, inet_rev_mkaddr,
+    { DNS_INADDR_ARPA, 0 } },
+  { AF_INET6, 32, adns_r_aaaa, inet6_rev_parsecomp, inet6_rev_mkaddr,
+    { DNS_IP6_ARPA, 0 } },
+};
+
+#define REVDOMAIN_MAP(rps, labnum)                                     \
+  ((labnum) ? (rps)->map : (1 << NREVDOMAINS) - 1)
+
+int adns__revparse_label(struct revparse_state *rps, int labnum,
+                        const char *label, int lablen) {
+  unsigned f= REVDOMAIN_MAP(rps, labnum);
+  const struct revparse_domain *rpd;
+  const char *tp;
+  unsigned d;
+  int i, ac;
+
+  for (rpd=revparse_domains, i=0, d=1; i<NREVDOMAINS; rpd++, i++, d <<= 1) {
+    if (!(f & d)) continue;
+    if (labnum >= rpd->nrevlab) {
+      tp = rpd->tail[labnum - rpd->nrevlab];
+      if (!tp || strncmp(label, tp, lablen) != 0 || tp[lablen])
+       goto mismatch;
+    } else {
+      ac= rpd->rev_parsecomp(label, lablen);
+      if (ac < 0) goto mismatch;
+      assert(labnum < sizeof(rps->ipv[i]));
+      rps->ipv[i][labnum]= ac;
+    }
+    continue;
+
+  mismatch:
+    f &= ~d;
+    if (!f) return -1;
+  }
+
+  rps->map= f;
+  return 0;
+}
+
+int adns__revparse_done(struct revparse_state *rps, int nlabels,
+                       adns_rrtype *rrtype_r, struct af_addr *addr_r) {
+  unsigned f= REVDOMAIN_MAP(rps, nlabels);
+  const struct revparse_domain *rpd;
+  unsigned d;
+  int i, found= -1;
+
+  for (rpd=revparse_domains, i=0, d=1; i<NREVDOMAINS; rpd++, i++, d <<= 1) {
+    if (!(f & d)) continue;
+    if (nlabels >= rpd->nrevlab && !rpd->tail[nlabels - rpd->nrevlab])
+      { found = i; continue; }
+    f &= ~d;
+    if (!f) return -1;
+  }
+  assert(found >= 0); assert(f == (1 << found));
+
+  rpd= &revparse_domains[found];
+  *rrtype_r= rpd->rrtype;
+  addr_r->af= rpd->af;
+  rpd->rev_mkaddr(&addr_r->addr, rps->ipv[found]);
+  return 0;
+}
index 6c6a77e..baf2a29 100644 (file)
@@ -69,6 +69,7 @@ typedef unsigned char byte;
 #define DNS_CLASS_IN 1
 
 #define DNS_INADDR_ARPA "in-addr", "arpa"
+#define DNS_IP6_ARPA "ip6", "arpa"
 
 #define MAX_POLLFDS  ADNS_POLLFDS_RECOMMENDED
 
@@ -131,8 +132,14 @@ union gen_addr {
 
 struct af_addr { int af; union gen_addr addr; };
 
+#define NREVDOMAINS 2                  /* keep in sync with addrfam! */
+struct revparse_state {
+  unsigned map;                                /* which domains are still live */
+  byte ipv[NREVDOMAINS][32];           /* address components so far */
+};
+
 union checklabel_state {
-  struct { byte ipv[4]; } ptr;
+  struct revparse_state ptr;
 };
 
 typedef struct {
@@ -141,6 +148,7 @@ typedef struct {
 
   union {
     struct {
+      adns_rrtype rev_rrtype;
       struct af_addr addr;
     } ptr;
   } tinfo; /* type-specific state for the query itself: zero-init if you
@@ -438,6 +446,40 @@ char *adns__sockaddr_ntoa(const struct sockaddr *sa, char *buf);
  * ADNS_ADDR2TEXT_BUFLEN bytes long (unchecked).  Return buf; can't fail.
  */
 
+extern int adns__make_reverse_domain(const struct sockaddr *sa,
+                                    const char *zone,
+                                    char **buf_io, size_t bufsz,
+                                    char **buf_free_r);
+/* Construct a reverse domain string, given a socket address and a parent
+ * zone.  If zone is null, then use the standard reverse-lookup zone for the
+ * address family.  If the length of the resulting string is no larger than
+ * bufsz, then the result is stored starting at *buf_io; otherwise a new
+ * buffer is allocated is used, and a pointer to it is stored in both *buf_io
+ * and *buf_free_r (the latter of which should be null on entry).  If
+ * something goes wrong, then an errno value is returned: ENOSYS if the
+ * address family of sa isn't recognized, or ENOMEM if the attempt to
+ * allocate an output buffer failed.
+ */
+
+extern int adns__revparse_label(struct revparse_state *rps, int labnum,
+                               const char *label, int lablen);
+/* Parse a label in a reverse-domain name, given its index labnum (starting
+ * from zero), a pointer to its contents (which need not be null-terminated),
+ * and its length.  The state in *rps is initialized implicitly when labnum
+ * is zero.
+ *
+ * Returns zero if the parse was successful, nonzero if the domain name is
+ * definitely invalid and the parse must be abandoned.
+ */
+
+extern int adns__revparse_done(struct revparse_state *rps, int nlabels,
+                              adns_rrtype *rrtype_r, struct af_addr *addr_r);
+/* Finishes parsing a reverse-domain name, given the total number of labels
+ * in the name.  On success, fills in the address in *addr_r, and the forward
+ * query type in *rrtype_r (because that turns out to be useful).  Returns
+ * nonzero if the parse must be abandoned.
+ */
+
 /* From setup.c: */
 
 int adns__setnonblock(adns_state ads, int fd); /* => errno value */
index 717cac0..c32acba 100644 (file)
@@ -331,28 +331,15 @@ int adns_submit_reverse_any(adns_state ads,
                            adns_queryflags flags,
                            void *context,
                            adns_query *query_r) {
-  const unsigned char *iaddr;
-  char *buf, *buf_free;
+  char *buf, *buf_free = 0;
   char shortbuf[100];
-  int r, lreq;
+  int r;
 
   flags &= ~adns_qf_search;
 
-  if (addr->sa_family != AF_INET) return ENOSYS;
-  iaddr= (const unsigned char*)
-    &(((const struct sockaddr_in*)addr) -> sin_addr);
-
-  lreq= strlen(zone) + 4*4 + 1;
-  if (lreq > sizeof(shortbuf)) {
-    buf= malloc(strlen(zone) + 4*4 + 1);
-    if (!buf) return errno;
-    buf_free= buf;
-  } else {
-    buf= shortbuf;
-    buf_free= 0;
-  }
-  sprintf(buf, "%d.%d.%d.%d.%s", iaddr[3], iaddr[2], iaddr[1], iaddr[0], zone);
-
+  buf = shortbuf;
+  r= adns__make_reverse_domain(addr,zone, &buf,sizeof(shortbuf),&buf_free);
+  if (r) return r;
   r= adns_submit(ads,buf,type,flags,context,query_r);
   free(buf_free);
   return r;
@@ -367,8 +354,7 @@ int adns_submit_reverse(adns_state ads,
   if (((type^adns_r_ptr) & adns_rrt_reprmask) &&
       ((type^adns_r_ptr_raw) & adns_rrt_reprmask))
     return EINVAL;
-  return adns_submit_reverse_any(ads,addr,"in-addr.arpa",
-                                type,flags,context,query_r);
+  return adns_submit_reverse_any(ads,addr,0,type,flags,context,query_r);
 }
 
 int adns_synchronous(adns_state ads,
index abe0c88..ac6b310 100644 (file)
@@ -765,29 +765,14 @@ static adns_status cs_inthost(vbuf *vb, const void *datap) {
 static adns_status ckl_ptr(adns_state ads, adns_queryflags flags,
                           union checklabel_state *cls, qcontext *ctx,
                           int labnum, const char *label, int lablen) {
-  static const char *const (expectdomain[])= { DNS_INADDR_ARPA };
-  char *ep;
-  const char *ed;
-  char labbuf[4];
-  int l;
-
-  if (labnum < 4) {
-    if (lablen<=0 || lablen>3) return adns_s_querydomainwrong;
-    memcpy(labbuf, label, lablen);
-    labbuf[lablen]= 0;
-    cls->ptr.ipv[3-labnum]= strtoul(labbuf,&ep,10);
-    if (*ep) return adns_s_querydomainwrong;
-    if (lablen>1 && *label=='0') return adns_s_querydomainwrong;
-  } else if (labnum < 4 + sizeof(expectdomain)/sizeof(*expectdomain)) {
-    ed= expectdomain[labnum-4];
-    l= strlen(ed);
-    if (lablen != l || memcmp(label, ed, l)) return adns_s_querydomainwrong;
+  if (lablen) {
+    if (adns__revparse_label(&cls->ptr, labnum, label,lablen))
+      return adns_s_querydomainwrong;
   } else {
-    if (lablen) return adns_s_querydomainwrong;
-    ctx->tinfo.ptr.addr.af= AF_INET;
-    ctx->tinfo.ptr.addr.addr.v4.s_addr=
-      htonl((cls->ptr.ipv[0]<<24) | (cls->ptr.ipv[1]<<16) |
-           (cls->ptr.ipv[2]<< 8) | (cls->ptr.ipv[3]));
+    if (adns__revparse_done(&cls->ptr, labnum,
+                           &ctx->tinfo.ptr.rev_rrtype,
+                           &ctx->tinfo.ptr.addr))
+      return adns_s_querydomainwrong;
   }
   return adns_s_ok;
 }
@@ -808,9 +793,9 @@ static void icb_ptr(adns_query parent, adns_query child) {
   }
 
   queried= &parent->ctx.tinfo.ptr.addr;
-  assert(cans->type == adns_r_a);
   for (i=0, found=cans->rrs.bytes; i<cans->nrrs; i++, found+=cans->rrsz) {
-    if (adns__genaddr_equal_p(queried->af,&queried->addr, AF_INET,found)) {
+    if (adns__genaddr_equal_p(queried->af,&queried->addr,
+                             parent->ctx.tinfo.ptr.addr.af,found)) {
       if (!parent->children.head) {
        adns__query_done(parent);
        return;
@@ -828,6 +813,7 @@ static adns_status pa_ptr(const parseinfo *pai, int dmstart,
                          int max, void *datap) {
   char **rrp= datap;
   adns_status st;
+  adns_rrtype rrtype= pai->qu->ctx.tinfo.ptr.rev_rrtype;
   int cbyte, id;
   adns_query nqu;
   qcontext ctx;
@@ -840,16 +826,16 @@ static adns_status pa_ptr(const parseinfo *pai, int dmstart,
 
   st= adns__mkquery_frdgram(pai->ads, &pai->qu->vb, &id,
                            pai->dgram, pai->dglen, dmstart,
-                           adns_r_a, adns_qf_quoteok_query);
+                           rrtype, adns_qf_quoteok_query);
   if (st) return st;
 
   ctx.ext= 0;
   ctx.callback= icb_ptr;
   memset(&ctx.pinfo,0,sizeof(ctx.pinfo));
   memset(&ctx.tinfo,0,sizeof(ctx.tinfo));
-  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(adns_r_a),
-                           adns_r_a, &pai->qu->vb, id, adns_qf_quoteok_query,
-                           pai->now, &ctx);
+  st= adns__internal_submit(pai->ads, &nqu, adns__findtype(rrtype),
+                           rrtype, &pai->qu->vb, id,
+                           adns_qf_quoteok_query, pai->now, &ctx);
   if (st) return st;
 
   nqu->parent= pai->qu;