dnsruby 1.55 → 1.56.0

Sign up to get free protection for your applications and to get access to all the features.
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