dnsruby 1.55 → 1.56.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (158) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +96 -0
  3. data/Rakefile +30 -29
  4. data/demo/axfr.rb +93 -93
  5. data/demo/check_soa.rb +99 -99
  6. data/demo/check_zone.rb +59 -59
  7. data/demo/digdlv.rb +43 -43
  8. data/demo/digroot.rb +34 -34
  9. data/demo/example_recurse.rb +14 -14
  10. data/demo/mresolv.rb +30 -30
  11. data/demo/mx.rb +31 -31
  12. data/demo/rubydig.rb +37 -37
  13. data/demo/to_resolve.txt +3088 -3088
  14. data/demo/trace_dns.rb +46 -46
  15. data/lib/dnsruby.rb +161 -526
  16. data/lib/dnsruby/DNS.rb +305 -0
  17. data/lib/{Dnsruby/Cache.rb → dnsruby/cache.rb} +152 -152
  18. data/lib/{Dnsruby → dnsruby}/code_mapper.rb +48 -52
  19. data/lib/dnsruby/code_mappers.rb +295 -0
  20. data/lib/{Dnsruby/Config.rb → dnsruby/config.rb} +454 -454
  21. data/lib/{Dnsruby → dnsruby}/dnssec.rb +91 -91
  22. data/lib/{Dnsruby/Hosts.rb → dnsruby/hosts.rb} +125 -125
  23. data/lib/{Dnsruby → dnsruby}/ipv4.rb +26 -26
  24. data/lib/{Dnsruby → dnsruby}/ipv6.rb +42 -42
  25. data/lib/{Dnsruby → dnsruby}/key_cache.rb +29 -29
  26. data/lib/dnsruby/message/decoder.rb +164 -0
  27. data/lib/dnsruby/message/encoder.rb +75 -0
  28. data/lib/dnsruby/message/header.rb +249 -0
  29. data/lib/dnsruby/message/message.rb +629 -0
  30. data/lib/dnsruby/message/question.rb +86 -0
  31. data/lib/dnsruby/message/section.rb +96 -0
  32. data/lib/{Dnsruby → dnsruby}/name.rb +141 -141
  33. data/lib/dnsruby/packet_sender.rb +661 -0
  34. data/lib/{Dnsruby/Recursor.rb → dnsruby/recursor.rb} +235 -233
  35. data/lib/dnsruby/resolv.rb +113 -0
  36. data/lib/dnsruby/resolver.rb +1192 -0
  37. data/lib/dnsruby/resource/A.rb +56 -0
  38. data/lib/dnsruby/resource/AAAA.rb +54 -0
  39. data/lib/{Dnsruby → dnsruby}/resource/AFSDB.rb +68 -68
  40. data/lib/{Dnsruby → dnsruby}/resource/CERT.rb +105 -105
  41. data/lib/{Dnsruby → dnsruby}/resource/DHCID.rb +54 -54
  42. data/lib/dnsruby/resource/DLV.rb +27 -0
  43. data/lib/{Dnsruby → dnsruby}/resource/DNSKEY.rb +372 -372
  44. data/lib/{Dnsruby → dnsruby}/resource/DS.rb +255 -255
  45. data/lib/{Dnsruby → dnsruby}/resource/HINFO.rb +71 -71
  46. data/lib/{Dnsruby → dnsruby}/resource/HIP.rb +29 -29
  47. data/lib/{Dnsruby → dnsruby}/resource/IN.rb +30 -30
  48. data/lib/{Dnsruby → dnsruby}/resource/IPSECKEY.rb +31 -31
  49. data/lib/{Dnsruby → dnsruby}/resource/ISDN.rb +62 -62
  50. data/lib/{Dnsruby → dnsruby}/resource/KX.rb +65 -65
  51. data/lib/{Dnsruby → dnsruby}/resource/LOC.rb +263 -263
  52. data/lib/{Dnsruby → dnsruby}/resource/MINFO.rb +69 -69
  53. data/lib/{Dnsruby → dnsruby}/resource/MX.rb +65 -65
  54. data/lib/{Dnsruby → dnsruby}/resource/NAPTR.rb +98 -98
  55. data/lib/{Dnsruby → dnsruby}/resource/NSAP.rb +171 -171
  56. data/lib/dnsruby/resource/NSEC.rb +275 -0
  57. data/lib/dnsruby/resource/NSEC3.rb +332 -0
  58. data/lib/dnsruby/resource/NSEC3PARAM.rb +135 -0
  59. data/lib/dnsruby/resource/OPT.rb +272 -0
  60. data/lib/{Dnsruby → dnsruby}/resource/PX.rb +70 -70
  61. data/lib/{Dnsruby → dnsruby}/resource/RP.rb +75 -75
  62. data/lib/dnsruby/resource/RR.rb +421 -0
  63. data/lib/dnsruby/resource/RRSIG.rb +275 -0
  64. data/lib/dnsruby/resource/RRSet.rb +190 -0
  65. data/lib/{Dnsruby → dnsruby}/resource/RT.rb +67 -67
  66. data/lib/{Dnsruby → dnsruby}/resource/SOA.rb +94 -94
  67. data/lib/dnsruby/resource/SPF.rb +29 -0
  68. data/lib/dnsruby/resource/SRV.rb +112 -0
  69. data/lib/{Dnsruby → dnsruby}/resource/SSHFP.rb +14 -14
  70. data/lib/dnsruby/resource/TKEY.rb +163 -0
  71. data/lib/dnsruby/resource/TSIG.rb +593 -0
  72. data/lib/{Dnsruby → dnsruby}/resource/TXT.rb +191 -191
  73. data/lib/dnsruby/resource/X25.rb +55 -0
  74. data/lib/{Dnsruby → dnsruby}/resource/domain_name.rb +25 -25
  75. data/lib/{Dnsruby → dnsruby}/resource/generic.rb +80 -80
  76. data/lib/dnsruby/resource/resource.rb +25 -0
  77. data/lib/{Dnsruby → dnsruby}/select_thread.rb +148 -148
  78. data/lib/{Dnsruby/SingleResolver.rb → dnsruby/single_resolver.rb} +60 -60
  79. data/lib/{Dnsruby → dnsruby}/single_verifier.rb +344 -344
  80. data/lib/dnsruby/the_log.rb +44 -0
  81. data/lib/dnsruby/update.rb +278 -0
  82. data/lib/dnsruby/validator_thread.rb +124 -0
  83. data/lib/dnsruby/version.rb +3 -0
  84. data/lib/{Dnsruby → dnsruby}/zone_reader.rb +93 -93
  85. data/lib/{Dnsruby → dnsruby}/zone_transfer.rb +377 -377
  86. data/test/spec_helper.rb +16 -0
  87. data/test/tc_axfr.rb +31 -34
  88. data/test/tc_cache.rb +32 -32
  89. data/test/tc_dlv.rb +28 -28
  90. data/test/tc_dns.rb +73 -76
  91. data/test/tc_dnskey.rb +31 -32
  92. data/test/tc_dnsruby.rb +50 -44
  93. data/test/tc_ds.rb +36 -36
  94. data/test/tc_escapedchars.rb +252 -255
  95. data/test/tc_hash.rb +17 -21
  96. data/test/tc_header.rb +48 -57
  97. data/test/tc_hip.rb +19 -22
  98. data/test/tc_ipseckey.rb +18 -21
  99. data/test/tc_keith.rb +300 -0
  100. data/test/tc_message.rb +87 -0
  101. data/test/tc_misc.rb +83 -87
  102. data/test/tc_name.rb +81 -84
  103. data/test/tc_naptr.rb +18 -21
  104. data/test/tc_nsec.rb +55 -55
  105. data/test/tc_nsec3.rb +23 -24
  106. data/test/tc_nsec3param.rb +20 -21
  107. data/test/tc_packet.rb +90 -93
  108. data/test/tc_packet_unique_push.rb +48 -51
  109. data/test/tc_question.rb +30 -33
  110. data/test/tc_queue.rb +16 -17
  111. data/test/tc_recur.rb +16 -17
  112. data/test/tc_res_config.rb +38 -41
  113. data/test/tc_res_env.rb +29 -32
  114. data/test/tc_res_file.rb +26 -29
  115. data/test/tc_res_opt.rb +62 -65
  116. data/test/tc_resolver.rb +287 -242
  117. data/test/tc_rr-opt.rb +70 -63
  118. data/test/tc_rr-txt.rb +68 -71
  119. data/test/tc_rr-unknown.rb +45 -48
  120. data/test/tc_rr.rb +76 -70
  121. data/test/tc_rrset.rb +21 -22
  122. data/test/tc_rrsig.rb +19 -20
  123. data/test/tc_single_resolver.rb +294 -297
  124. data/test/tc_soak.rb +199 -202
  125. data/test/tc_soak_base.rb +29 -34
  126. data/test/tc_sshfp.rb +20 -23
  127. data/test/tc_tcp.rb +32 -35
  128. data/test/tc_tkey.rb +41 -44
  129. data/test/tc_tsig.rb +81 -84
  130. data/test/tc_update.rb +108 -111
  131. data/test/tc_validator.rb +29 -29
  132. data/test/tc_verifier.rb +81 -82
  133. data/test/ts_dnsruby.rb +16 -15
  134. data/test/ts_offline.rb +62 -63
  135. data/test/ts_online.rb +115 -115
  136. metadata +155 -90
  137. data/README +0 -59
  138. data/lib/Dnsruby/DNS.rb +0 -305
  139. data/lib/Dnsruby/PacketSender.rb +0 -656
  140. data/lib/Dnsruby/Resolver.rb +0 -1189
  141. data/lib/Dnsruby/TheLog.rb +0 -44
  142. data/lib/Dnsruby/message.rb +0 -1230
  143. data/lib/Dnsruby/resource/A.rb +0 -56
  144. data/lib/Dnsruby/resource/AAAA.rb +0 -54
  145. data/lib/Dnsruby/resource/DLV.rb +0 -27
  146. data/lib/Dnsruby/resource/NSEC.rb +0 -298
  147. data/lib/Dnsruby/resource/NSEC3.rb +0 -340
  148. data/lib/Dnsruby/resource/NSEC3PARAM.rb +0 -135
  149. data/lib/Dnsruby/resource/OPT.rb +0 -213
  150. data/lib/Dnsruby/resource/RRSIG.rb +0 -275
  151. data/lib/Dnsruby/resource/SPF.rb +0 -29
  152. data/lib/Dnsruby/resource/SRV.rb +0 -112
  153. data/lib/Dnsruby/resource/TKEY.rb +0 -163
  154. data/lib/Dnsruby/resource/TSIG.rb +0 -593
  155. data/lib/Dnsruby/resource/X25.rb +0 -55
  156. data/lib/Dnsruby/resource/resource.rb +0 -678
  157. data/lib/Dnsruby/update.rb +0 -278
  158. data/lib/Dnsruby/validator_thread.rb +0 -124
@@ -1,172 +1,172 @@
1
- #--
2
- #Copyright 2007 Nominet UK
3
- #
4
- #Licensed under the Apache License, Version 2.0 (the "License");
5
- #you may not use this file except in compliance with the License.
6
- #You may obtain a copy of the License at
7
- #
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
- #
10
- #Unless required by applicable law or agreed to in writing, software
11
- #distributed under the License is distributed on an "AS IS" BASIS,
12
- #WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
- #See the License for the specific language governing permissions and
14
- #limitations under the License.
15
- #++
16
- module Dnsruby
17
- class RR
18
- #Class for DNS Network Service Access Point (NSAP) resource records.
19
- #RFC 1706.
20
- class NSAP < RR
21
- ClassValue = nil #:nodoc: all
22
- TypeValue= Types::NSAP #:nodoc: all
23
- #The RR's authority and format identifier. Dnsruby
24
- #currently supports only AFI 47 (GOSIP Version 2).
25
- attr_accessor :afi
26
- #The RR's initial domain identifier.
27
- attr_accessor :idi
28
- #The RR's DSP format identifier.
29
- attr_accessor :dfi
30
- #The RR's administrative authority.
31
- attr_accessor :aa
32
- #The RR's routing domain identifier.
33
- attr_accessor :rd
34
- #The RR's area identifier.
35
- attr_accessor :area
36
- #The RR's system identifier.
37
- attr_accessor :id
38
- #The RR's NSAP selector.
39
- attr_accessor :sel
40
-
41
- #The RR's reserved field.
42
- attr_writer :rsvd
43
-
44
- #The RR's initial domain part (the AFI and IDI fields).
45
- def idp
46
- ret = [@afi, @idi].join('')
47
- return ret
48
- end
49
-
50
- #The RR's domain specific part (the DFI, AA, Rsvd, RD, Area,
51
- #ID, and SEL fields).
52
- def dsp
53
- ret = [@dfi,@aa,rsvd,@rd,@area,@id,@sel].join('')
54
- return ret
55
- end
56
-
57
- def rsvd
58
- if (@rsvd==nil)
59
- return "0000"
60
- else
61
- return @rsvd
62
- end
63
- end
64
-
65
- #------------------------------------------------------------------------------
66
- # Usage: str2bcd(STRING, NUM_BYTES)
67
- #
68
- # Takes a string representing a hex number of arbitrary length and
69
- # returns an equivalent BCD string of NUM_BYTES length (with
70
- # NUM_BYTES * 2 digits), adding leading zeros if necessary.
71
- #------------------------------------------------------------------------------
72
- def str2bcd(s, bytes)
73
- retval = "";
74
-
75
- digits = bytes * 2;
76
- string = sprintf("%#{digits}s", s);
77
- string.tr!(" ","0");
78
-
79
- i=0;
80
- bytes.times do
81
- bcd = string[i*2, 2];
82
- retval += [bcd.to_i(16)].pack("C");
83
- i+=1
84
- end
85
-
86
- return retval;
87
- end
88
-
89
-
90
- def from_data(data) #:nodoc: all
91
- @afi, @idi, @dfi, @aa, @rsvd, @rd, @area, @id, @sel = data
92
- end
93
-
94
- def from_string(s) #:nodoc: all
95
- if (s)
96
- string = s.gsub(/\./, ""); # remove all dots.
97
- string.gsub!(/^0x/,""); # remove leading 0x
98
-
99
- if (string =~ /^[a-zA-Z0-9]{40}$/)
100
- (@afi, @idi, @dfi, @aa, @rsvd, @rd, @area, @id, @sel) = string.unpack("A2A4A2A6A4A4A4A12A2")
101
- end
102
- end
103
-
104
- end
105
-
106
- def rdata_to_string #:nodoc: all
107
- rdatastr=""
108
-
109
- if (defined?@afi)
110
- if (@afi == "47")
111
- rdatastr = [idp, dsp].join('')
112
- else
113
- rdatastr = "; AFI #{@afi} not supported"
114
- end
115
- else
116
- rdatastr = ''
117
- end
118
-
119
- return rdatastr
120
- end
121
-
122
- def encode_rdata(msg, canonical=false) #:nodoc: all
123
- if (defined?@afi)
124
- msg.put_pack("C", @afi.to_i(16))
125
-
126
- if (@afi == "47")
127
- msg.put_bytes(str2bcd(@idi, 2))
128
- msg.put_bytes(str2bcd(@dfi, 1))
129
- msg.put_bytes(str2bcd(@aa, 3))
130
- msg.put_bytes(str2bcd(0, 2)) # rsvd)
131
- msg.put_bytes(str2bcd(@rd, 2))
132
- msg.put_bytes(str2bcd(@area, 2))
133
- msg.put_bytes(str2bcd(@id, 6))
134
- msg.put_bytes(str2bcd(@sel, 1))
135
- end
136
- # Checks for other versions would go here.
137
- end
138
-
139
- return rdata
140
- end
141
-
142
- def self.decode_rdata(msg) #:nodoc: all
143
- afi = msg.get_unpack("C")[0]
144
- afi = sprintf("%02x", afi)
145
-
146
- if (afi == "47")
147
- idi = msg.get_unpack("CC")
148
- dfi = msg.get_unpack("C")[0]
149
- aa = msg.get_unpack("CCC")
150
- rsvd = msg.get_unpack("CC")
151
- rd = msg.get_unpack("CC")
152
- area = msg.get_unpack("CC")
153
- id = msg.get_unpack("CCCCCC")
154
- sel = msg.get_unpack("C")[0]
155
-
156
- idi = sprintf("%02x%02x", idi[0], idi[1])
157
- dfi = sprintf("%02x", dfi)
158
- aa = sprintf("%02x%02x%02x", aa[0], aa[1], aa[2])
159
- rsvd = sprintf("%02x%02x", rsvd[0],rsvd[1])
160
- rd = sprintf("%02x%02x", rd[0],rd[1])
161
- area = sprintf("%02x%02x", area[0],area[1])
162
- id = sprintf("%02x%02x%02x%02x%02x%02x", id[0],id[1],id[2],id[3],id[4],id[5])
163
- sel = sprintf("%02x", sel)
164
-
165
- else
166
- # What to do for unsupported versions?
167
- end
168
- return self.new([afi, idi, dfi, aa, rsvd, rd, area, id, sel])
169
- end
170
- end
171
- end
1
+ # --
2
+ # Copyright 2007 Nominet UK
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+ module Dnsruby
17
+ class RR
18
+ # Class for DNS Network Service Access Point (NSAP) resource records.
19
+ # RFC 1706.
20
+ class NSAP < RR
21
+ ClassValue = nil #:nodoc: all
22
+ TypeValue= Types::NSAP #:nodoc: all
23
+ # The RR's authority and format identifier. Dnsruby
24
+ # currently supports only AFI 47 (GOSIP Version 2).
25
+ attr_accessor :afi
26
+ # The RR's initial domain identifier.
27
+ attr_accessor :idi
28
+ # The RR's DSP format identifier.
29
+ attr_accessor :dfi
30
+ # The RR's administrative authority.
31
+ attr_accessor :aa
32
+ # The RR's routing domain identifier.
33
+ attr_accessor :rd
34
+ # The RR's area identifier.
35
+ attr_accessor :area
36
+ # The RR's system identifier.
37
+ attr_accessor :id
38
+ # The RR's NSAP selector.
39
+ attr_accessor :sel
40
+
41
+ # The RR's reserved field.
42
+ attr_writer :rsvd
43
+
44
+ # The RR's initial domain part (the AFI and IDI fields).
45
+ def idp
46
+ ret = [@afi, @idi].join('')
47
+ return ret
48
+ end
49
+
50
+ # The RR's domain specific part (the DFI, AA, Rsvd, RD, Area,
51
+ # ID, and SEL fields).
52
+ def dsp
53
+ ret = [@dfi,@aa,rsvd,@rd,@area,@id,@sel].join('')
54
+ return ret
55
+ end
56
+
57
+ def rsvd
58
+ if (@rsvd==nil)
59
+ return "0000"
60
+ else
61
+ return @rsvd
62
+ end
63
+ end
64
+
65
+ # ------------------------------------------------------------------------------
66
+ # Usage: str2bcd(STRING, NUM_BYTES)
67
+ #
68
+ # Takes a string representing a hex number of arbitrary length and
69
+ # returns an equivalent BCD string of NUM_BYTES length (with
70
+ # NUM_BYTES * 2 digits), adding leading zeros if necessary.
71
+ # ------------------------------------------------------------------------------
72
+ def str2bcd(s, bytes)
73
+ retval = "";
74
+
75
+ digits = bytes * 2;
76
+ string = sprintf("%#{digits}s", s);
77
+ string.tr!(" ","0");
78
+
79
+ i=0;
80
+ bytes.times do
81
+ bcd = string[i*2, 2];
82
+ retval += [bcd.to_i(16)].pack("C");
83
+ i+=1
84
+ end
85
+
86
+ return retval;
87
+ end
88
+
89
+
90
+ def from_data(data) #:nodoc: all
91
+ @afi, @idi, @dfi, @aa, @rsvd, @rd, @area, @id, @sel = data
92
+ end
93
+
94
+ def from_string(s) #:nodoc: all
95
+ if (s)
96
+ string = s.gsub(/\./, ""); # remove all dots.
97
+ string.gsub!(/^0x/,""); # remove leading 0x
98
+
99
+ if (string =~ /^[a-zA-Z0-9]{40}$/)
100
+ (@afi, @idi, @dfi, @aa, @rsvd, @rd, @area, @id, @sel) = string.unpack("A2A4A2A6A4A4A4A12A2")
101
+ end
102
+ end
103
+
104
+ end
105
+
106
+ def rdata_to_string #:nodoc: all
107
+ rdatastr=""
108
+
109
+ if (defined?@afi)
110
+ if (@afi == "47")
111
+ rdatastr = [idp, dsp].join('')
112
+ else
113
+ rdatastr = "; AFI #{@afi} not supported"
114
+ end
115
+ else
116
+ rdatastr = ''
117
+ end
118
+
119
+ return rdatastr
120
+ end
121
+
122
+ def encode_rdata(msg, canonical=false) #:nodoc: all
123
+ if (defined?@afi)
124
+ msg.put_pack("C", @afi.to_i(16))
125
+
126
+ if (@afi == "47")
127
+ msg.put_bytes(str2bcd(@idi, 2))
128
+ msg.put_bytes(str2bcd(@dfi, 1))
129
+ msg.put_bytes(str2bcd(@aa, 3))
130
+ msg.put_bytes(str2bcd(0, 2)) # rsvd)
131
+ msg.put_bytes(str2bcd(@rd, 2))
132
+ msg.put_bytes(str2bcd(@area, 2))
133
+ msg.put_bytes(str2bcd(@id, 6))
134
+ msg.put_bytes(str2bcd(@sel, 1))
135
+ end
136
+ # Checks for other versions would go here.
137
+ end
138
+
139
+ return rdata
140
+ end
141
+
142
+ def self.decode_rdata(msg) #:nodoc: all
143
+ afi = msg.get_unpack("C")[0]
144
+ afi = sprintf("%02x", afi)
145
+
146
+ if (afi == "47")
147
+ idi = msg.get_unpack("CC")
148
+ dfi = msg.get_unpack("C")[0]
149
+ aa = msg.get_unpack("CCC")
150
+ rsvd = msg.get_unpack("CC")
151
+ rd = msg.get_unpack("CC")
152
+ area = msg.get_unpack("CC")
153
+ id = msg.get_unpack("CCCCCC")
154
+ sel = msg.get_unpack("C")[0]
155
+
156
+ idi = sprintf("%02x%02x", idi[0], idi[1])
157
+ dfi = sprintf("%02x", dfi)
158
+ aa = sprintf("%02x%02x%02x", aa[0], aa[1], aa[2])
159
+ rsvd = sprintf("%02x%02x", rsvd[0],rsvd[1])
160
+ rd = sprintf("%02x%02x", rd[0],rd[1])
161
+ area = sprintf("%02x%02x", area[0],area[1])
162
+ id = sprintf("%02x%02x%02x%02x%02x%02x", id[0],id[1],id[2],id[3],id[4],id[5])
163
+ sel = sprintf("%02x", sel)
164
+
165
+ else
166
+ # What to do for unsupported versions?
167
+ end
168
+ return self.new([afi, idi, dfi, aa, rsvd, rd, area, id, sel])
169
+ end
170
+ end
171
+ end
172
172
  end
@@ -0,0 +1,275 @@
1
+ # --
2
+ # Copyright 2007 Nominet UK
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ # ++
16
+ module Dnsruby
17
+ class RR
18
+ # RFC4034, section 4
19
+ # The NSEC resource record lists two separate things: the next owner
20
+ # name (in the canonical ordering of the zone) that contains
21
+ # authoritative data or a delegation point NS RRset, and the set of RR
22
+ # types present at the NSEC RR's owner name [RFC3845]. The complete
23
+ # set of NSEC RRs in a zone indicates which authoritative RRsets exist
24
+ # in a zone and also form a chain of authoritative owner names in the
25
+ # zone. This information is used to provide authenticated denial of
26
+ # existence for DNS data, as described in [RFC4035].
27
+ class NSEC < RR
28
+ ClassValue = nil #:nodoc: all
29
+ TypeValue = Types::NSEC #:nodoc: all
30
+
31
+ # The next name which exists after this NSEC
32
+ # The Next Domain field contains the next owner name (in the canonical
33
+ # ordering of the zone) that has authoritative data or contains a
34
+ # delegation point NS RRset
35
+ attr_reader :next_domain
36
+ # The Type Bit Maps field identifies the RRset types that exist at the
37
+ # NSEC RR's owner name
38
+ attr_reader :types
39
+
40
+ def next_domain=(n)
41
+ nxt = Name.create(n)
42
+ @next_domain = nxt
43
+ end
44
+
45
+ def check_name_in_range(n)
46
+ # Check if the name is covered by this record
47
+ @name.wild? \
48
+ ? check_name_in_wildcard_range(n) \
49
+ : name.canonically_before(n) && n.canonically_before(next_domain)
50
+ end
51
+
52
+ def check_name_in_wildcard_range(n)
53
+ # Check if the name is covered by this record
54
+ return false unless @name.wild?
55
+ return false if @next_domain.canonically_before(n)
56
+ # Now just check that the wildcard is *before* the name
57
+ # Strip the first label ("*") and then compare
58
+ n2 = Name.create(@name)
59
+ n2.labels.delete_at(0)
60
+ ! n.canonically_before(n2)
61
+ end
62
+
63
+ def types=(t)
64
+ @types = (t && t.length > 0) ? NSEC.get_types(t) : []
65
+ end
66
+
67
+ def self.get_types(t)
68
+ if t.instance_of?(Array)
69
+ # from the wire, already decoded
70
+ types = t
71
+ elsif t.instance_of?(String)
72
+ if (index = t.index(/[;)]/)) # check for ; or )
73
+ t = t[0, index]
74
+ end
75
+ # List of mnemonics
76
+ types = []
77
+ mnemonics = t.split(' ')
78
+ mnemonics.each { |m| types << Types.new(m) }
79
+ else
80
+ raise DecodeError.new('Unknown format of types for Dnsruby::RR::NSEC')
81
+ end
82
+ types
83
+ end
84
+
85
+ def add_type(t)
86
+ self.types = (@types + [t])
87
+ end
88
+
89
+ def self.decode_types(bytes)
90
+ types = []
91
+ # RFC4034 section 4.1.2
92
+ # The RR type space is split into 256 window blocks, each representing
93
+ # the low-order 8 bits of the 16-bit RR type space. Each block that
94
+ # has at least one active RR type is encoded using a single octet
95
+ # window number (from 0 to 255), a single octet bitmap length (from 1
96
+ # to 32) indicating the number of octets used for the window block's
97
+ # bitmap, and up to 32 octets (256 bits) of bitmap.
98
+
99
+ # Blocks are present in the NSEC RR RDATA in increasing numerical
100
+ # order.
101
+
102
+ # Type Bit Maps Field = ( Window Block # | Bitmap Length | Bitmap )+
103
+
104
+ # where "|" denotes concatenation.
105
+
106
+ pos = 0
107
+ while pos < bytes.length
108
+ # So, read the first two octets
109
+ if bytes.length - pos < 2
110
+ raise DecodeError.new("NSEC : Expected window number and bitmap length octets")
111
+ end
112
+ window_number = bytes[pos]
113
+ bitmap_length = bytes[pos+1]
114
+ if window_number.class == String # Ruby 1.9
115
+ window_number = window_number.getbyte(0)
116
+ bitmap_length = bitmap_length.getbyte(0)
117
+ end
118
+ pos += 2
119
+ bitmap = bytes[pos,bitmap_length]
120
+ pos += bitmap_length
121
+ # Each bitmap encodes the low-order 8 bits of RR types within the
122
+ # window block, in network bit order. The first bit is bit 0. For
123
+ # window block 0, bit 1 corresponds to RR type 1 (A), bit 2 corresponds
124
+ # to RR type 2 (NS), and so forth. For window block 1, bit 1
125
+ # corresponds to RR type 257, and bit 2 to RR type 258. If a bit is
126
+ # set, it indicates that an RRset of that type is present for the NSEC
127
+ # RR's owner name. If a bit is clear, it indicates that no RRset of
128
+ # that type is present for the NSEC RR's owner name.
129
+ index = 0
130
+ bitmap.each_byte do |char|
131
+ if char.to_i != 0
132
+ # decode these RR types
133
+ 8.times do |i|
134
+ if ((1 << (7-i)) & char) == (1 << (7-i))
135
+ type = Types.new((256 * window_number) + (8 * index) + i)
136
+ # Bits representing pseudo-types MUST be clear, as they do not appear
137
+ # in zone data. If encountered, they MUST be ignored upon being read.
138
+ unless [Types::OPT, Types::TSIG].include?(type)
139
+ types << type
140
+ end
141
+ end
142
+ end
143
+ end
144
+ index += 1
145
+ end
146
+ end
147
+ return types
148
+ end
149
+
150
+ def encode_types
151
+ NSEC.encode_types(self)
152
+ end
153
+
154
+ def self.encode_types(nsec)
155
+ output = ''
156
+ # types represents all 65536 possible RR types.
157
+ # Split up types into sets of 256 different types.
158
+ type_codes = []
159
+ nsec.types.each { |type| type_codes << type.code }
160
+ type_codes.sort!
161
+ window = -1
162
+ 0.step(65536,256) { |step|
163
+ # Gather up the RR types for this set of 256
164
+ types_to_go = []
165
+ while (!type_codes.empty? && type_codes[0] < step)
166
+ types_to_go << type_codes[0]
167
+ # And delete them from type_codes
168
+ type_codes = type_codes.last(type_codes.length - 1)
169
+ break if type_codes.empty?
170
+ end
171
+
172
+ unless types_to_go.empty?
173
+ # Then create the bitmap for them
174
+ bitmap = ''
175
+ # keep on adding them until there's none left
176
+ pos = 0
177
+ bitmap_pos = 0
178
+ while (!types_to_go.empty?)
179
+
180
+ # Check the next eight
181
+ byte = 0
182
+ pos += 8
183
+ while types_to_go[0] < (pos + step - 256)
184
+ byte = byte | (1 << (pos - 1 - (types_to_go[0] - (step - 256))))
185
+ # Add it to the list
186
+ # And remove it from the to_go queue
187
+ types_to_go = types_to_go.last(types_to_go.length - 1)
188
+ break if types_to_go.empty?
189
+ end
190
+ bitmap << ' '
191
+ if bitmap[bitmap_pos].class == String
192
+ bitmap.setbyte(bitmap_pos, byte) # Ruby 1.9
193
+ else
194
+ bitmap[bitmap_pos] = byte
195
+ end
196
+ bitmap_pos += 1
197
+ end
198
+
199
+ # Now add data to output bytes
200
+ start = output.length
201
+ output << (' ' * (2 + bitmap.length))
202
+
203
+ if output[start].class == String
204
+ output.setbyte(start, window)
205
+ output.setbyte(start + 1, bitmap.length)
206
+ bitmap.length.times do |i|
207
+ output.setbyte(start + 2 + i, bitmap[i].getbyte(0))
208
+ end
209
+ else
210
+ output[start] = window
211
+ output[start + 1] = bitmap.length
212
+ bitmap.length.times do |i|
213
+ output[start + 2 + i] = bitmap[i]
214
+ end
215
+ end
216
+ end
217
+ window += 1
218
+
219
+ # Are there any more types after this?
220
+ if type_codes.empty?
221
+ # If not, then break (so we don't add more zeros)
222
+ break
223
+ end
224
+ }
225
+ if output[0].class == String
226
+ output = output.force_encoding("ascii-8bit")
227
+ end
228
+ output
229
+ end
230
+
231
+ def from_data(data) #:nodoc: all
232
+ next_domain, types = data
233
+ self.next_domain = next_domain
234
+ self.types = types
235
+ end
236
+
237
+ def from_string(input)
238
+ if input.length > 0
239
+ data = input.split(' ')
240
+ self.next_domain = data[0]
241
+ len = data[0].length+ 1
242
+ if data[1] == '('
243
+ len += data[1].length
244
+ end
245
+ self.types = input[len, input.length-len]
246
+ @types = NSEC.get_types(input[len, input.length-len])
247
+ end
248
+ end
249
+
250
+ def rdata_to_string #:nodoc: all
251
+ if @next_domain
252
+ type_strings = []
253
+ @types.each { |t| type_strings << t.string }
254
+ types = type_strings.join(' ')
255
+ "#{@next_domain.to_s(true)} ( #{types} )"
256
+ else
257
+ ''
258
+ end
259
+ end
260
+
261
+ def encode_rdata(msg, canonical=false) #:nodoc: all
262
+ # Canonical
263
+ msg.put_name(@next_domain, canonical, false) # dnssec-bis-updates says NSEC should not be downcased
264
+ types = encode_types
265
+ msg.put_bytes(types)
266
+ end
267
+
268
+ def self.decode_rdata(msg) #:nodoc: all
269
+ next_domain = msg.get_name
270
+ types = decode_types(msg.get_bytes)
271
+ return self.new([next_domain, types])
272
+ end
273
+ end
274
+ end
275
+ end