pNet-DNS 0.0.1

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 (71) hide show
  1. data/README +68 -0
  2. data/lib/Net/DNS.rb +879 -0
  3. data/lib/Net/DNS/Header.rb +303 -0
  4. data/lib/Net/DNS/Nameserver.rb +601 -0
  5. data/lib/Net/DNS/Packet.rb +851 -0
  6. data/lib/Net/DNS/Question.rb +117 -0
  7. data/lib/Net/DNS/RR.rb +630 -0
  8. data/lib/Net/DNS/RR/A.rb +103 -0
  9. data/lib/Net/DNS/RR/AAAA.rb +147 -0
  10. data/lib/Net/DNS/RR/AFSDB.rb +114 -0
  11. data/lib/Net/DNS/RR/CERT.rb +191 -0
  12. data/lib/Net/DNS/RR/CNAME.rb +89 -0
  13. data/lib/Net/DNS/RR/DNAME.rb +84 -0
  14. data/lib/Net/DNS/RR/EID.rb +70 -0
  15. data/lib/Net/DNS/RR/HINFO.rb +108 -0
  16. data/lib/Net/DNS/RR/ISDN.rb +118 -0
  17. data/lib/Net/DNS/RR/LOC.rb +341 -0
  18. data/lib/Net/DNS/RR/MB.rb +92 -0
  19. data/lib/Net/DNS/RR/MG.rb +96 -0
  20. data/lib/Net/DNS/RR/MINFO.rb +109 -0
  21. data/lib/Net/DNS/RR/MR.rb +92 -0
  22. data/lib/Net/DNS/RR/MX.rb +124 -0
  23. data/lib/Net/DNS/RR/NAPTR.rb +182 -0
  24. data/lib/Net/DNS/RR/NIMLOC.rb +70 -0
  25. data/lib/Net/DNS/RR/NS.rb +100 -0
  26. data/lib/Net/DNS/RR/NSAP.rb +273 -0
  27. data/lib/Net/DNS/RR/NULL.rb +68 -0
  28. data/lib/Net/DNS/RR/OPT.rb +251 -0
  29. data/lib/Net/DNS/RR/PTR.rb +93 -0
  30. data/lib/Net/DNS/RR/PX.rb +131 -0
  31. data/lib/Net/DNS/RR/RP.rb +108 -0
  32. data/lib/Net/DNS/RR/RT.rb +115 -0
  33. data/lib/Net/DNS/RR/SOA.rb +195 -0
  34. data/lib/Net/DNS/RR/SPF.rb +46 -0
  35. data/lib/Net/DNS/RR/SRV.rb +153 -0
  36. data/lib/Net/DNS/RR/SSHFP.rb +190 -0
  37. data/lib/Net/DNS/RR/TKEY.rb +219 -0
  38. data/lib/Net/DNS/RR/TSIG.rb +358 -0
  39. data/lib/Net/DNS/RR/TXT.rb +162 -0
  40. data/lib/Net/DNS/RR/UNKNOWN.rb +76 -0
  41. data/lib/Net/DNS/RR/X25.rb +90 -0
  42. data/lib/Net/DNS/Resolver.rb +2090 -0
  43. data/lib/Net/DNS/Resolver/Recurse.rb +478 -0
  44. data/lib/Net/DNS/Update.rb +189 -0
  45. data/test/custom.txt +4 -0
  46. data/test/resolv.conf +4 -0
  47. data/test/tc_escapedchars.rb +498 -0
  48. data/test/tc_header.rb +91 -0
  49. data/test/tc_inet6.rb +169 -0
  50. data/test/tc_misc.rb +137 -0
  51. data/test/tc_online.rb +236 -0
  52. data/test/tc_packet.rb +174 -0
  53. data/test/tc_packet_unique_push.rb +126 -0
  54. data/test/tc_question.rb +49 -0
  55. data/test/tc_recurse.rb +69 -0
  56. data/test/tc_res_env.rb +59 -0
  57. data/test/tc_res_file.rb +55 -0
  58. data/test/tc_res_opt.rb +135 -0
  59. data/test/tc_resolver.rb +102 -0
  60. data/test/tc_rr-opt.rb +40 -0
  61. data/test/tc_rr-rrsort.rb +116 -0
  62. data/test/tc_rr-txt.rb +138 -0
  63. data/test/tc_rr-unknown.rb +95 -0
  64. data/test/tc_rr.rb +246 -0
  65. data/test/tc_tcp.rb +34 -0
  66. data/test/tc_tkey.rb +115 -0
  67. data/test/tc_update.rb +226 -0
  68. data/test/ts_netdns.rb +17 -0
  69. data/test/ts_offline.rb +32 -0
  70. data/test/ts_online.rb +33 -0
  71. metadata +119 -0
data/README ADDED
@@ -0,0 +1,68 @@
1
+ pNet::DNS
2
+ ---------
3
+
4
+ Ruby port of perl Net::DNS.
5
+
6
+ This project is a direct port of perl Net::DNS, version 0.57.
7
+ It has tried to stick as closely as possible to the original
8
+ perl code, to allow existing perl code to be ported quickly and
9
+ easily to Ruby. This project is not intended to be anything more
10
+ than a direct port of the perl code.
11
+
12
+ The perl test code has also been ported to Ruby, and all runs
13
+ successfully. The demo code has also been ported.
14
+
15
+ No effort has been made to fix bugs in the original perl code -
16
+ this port is as close as possible to the perl.
17
+
18
+ Author : AlexD
19
+ Contact : alexd@nominet.org.uk
20
+ Copyright (c) Nominet UK, 2006
21
+
22
+ Check out demo and test folders for examples.
23
+
24
+ Issues
25
+ ------
26
+
27
+ I've still not had a chance to test on IPv6, so the functionality in
28
+ tc_inet6.rb is untested.
29
+
30
+ Nameserver.rb is a port of the perl version - bugs and all.
31
+ It's obviously broken, but would not be hard to fix.
32
+ If you need a working version of this code, please contact me.
33
+
34
+ Licensing
35
+ ---------
36
+
37
+ This project is licensed under the Mozilla Public License.
38
+
39
+ The contents of this file are subject to the Mozilla Public Licence
40
+ Version 1.1 (the `Licence'); you may not use this file except in
41
+ compliance with the Licence. You may obtain a copy of the Licence at
42
+ http://www.mozilla.org/MPL
43
+
44
+ Software distributed under the Licence is distributed on an `AS IS'
45
+ basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
46
+ the Licence of the specific language governing rights and limitations
47
+ under the Licence.
48
+
49
+ The Original Code is pNet::DNS.
50
+
51
+ The Initial Developer of the Original Code is Nominet UK
52
+ (http://www.nominet.org.uk). Portions created by Nominet UK are
53
+ Copyright (c) Nominet UK 2006. All rights reserved.
54
+
55
+ PERL AUTHOR INFORMATION
56
+ -----------------------
57
+
58
+ Net::DNS is currently maintained at NLnet Labs (www.nlnetlabs.nl) by:
59
+ Olaf Kolkman and his team.
60
+ olaf at net-dns.org
61
+
62
+ Between 2002 and 2004 Net::DNS was maintained by:
63
+ Chris Reinhardt
64
+
65
+
66
+ Net::DNS was created by:
67
+ Michael Fuhr
68
+ mike at fuhr.org
@@ -0,0 +1,879 @@
1
+ # The contents of this file are subject to the Mozilla
2
+ # Public Licence Version 1.1 (the "Licence"); you may
3
+ # not use this file except in compliance with the
4
+ # Licence. You may obtain a copy of the Licence at
5
+ # http://www.mozilla.org/MPL
6
+ # Software distributed under the Licence is distributed
7
+ # on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
8
+ # either express or implied. See the Licence of the
9
+ # specific language governing rights and limitations
10
+ # under the Licence.
11
+ # The Original Code is pNet::DNS.
12
+ # The Initial Developer of the Original Code is
13
+ # Nominet UK (www.nominet.org.uk). Portions created by
14
+ # Nominet UK are Copyright (c) Nominet UK 2006.
15
+ # All rights reserved.
16
+ require 'Net/DNS/Resolver'
17
+ require 'Net/DNS/Nameserver'
18
+
19
+
20
+ module Net
21
+ #= NAME
22
+ #
23
+ #Net::DNS - Perl interface to the DNS resolver
24
+ #
25
+ #= SYNOPSIS
26
+ #
27
+ #<tt>use Net::DNS;</tt>
28
+ #
29
+ #= DESCRIPTION
30
+ #
31
+ #Net::DNS is a collection of modules that act as a Domain
32
+ #Name System (DNS) resolver. It is a port of the perl
33
+ #Net::DNS package.
34
+ #
35
+ #The programmer should be somewhat familiar with the format of
36
+ #a DNS packet and its various sections. See RFC 1035 or
37
+ #<em>DNS and BIND</em> (Albitz & Liu) for details.
38
+ #
39
+ #= Resolver Objects
40
+ #
41
+ #A resolver object is an instance of the
42
+ #Net::DNS::Resolver class. A program can have
43
+ #multiple resolver objects, each maintaining its own state information
44
+ #such as the nameservers to be queried, whether recursion is desired,
45
+ #etc.
46
+ #
47
+ #== Packet Objects
48
+ #
49
+ #Net::DNS::Resolver queries return
50
+ #Net::DNS::Packet objects. Packet objects have five
51
+ #sections:
52
+ #
53
+ # * The header section, a Net::DNS::Header object.
54
+ #
55
+ # * The question section, a list of Net::DNS::Question objects.
56
+ #
57
+ # * The answer section, a list of Net::DNS::RR objects.
58
+ #
59
+ # * The authority section, a list of Net::DNS::RR objects.
60
+ #
61
+ # * The additional section, a list of Net::DNS::RR objects.
62
+ #
63
+ #== Update Objects
64
+ #
65
+ #The Net::DNS::Update package is a subclass of
66
+ #Net::DNS::Packet for creating packet objects to be
67
+ #used in dynamic updates.
68
+ #
69
+ #== Header Objects
70
+ #
71
+ #Net::DNS::Header objects represent the header
72
+ #section of a DNS packet.
73
+ #
74
+ #== Question Objects
75
+ #
76
+ #Net::DNS::Question objects represent the question
77
+ #section of a DNS packet.
78
+ #
79
+ #== RR Objects
80
+ #
81
+ #Net::DNS::RR is the base class for DNS resource record
82
+ #(RR) objects in the answer, authority, and additional sections of a DNS
83
+ #packet.
84
+ #
85
+ #Don't assume that RR objects will be of the type you requested -- always
86
+ #check an RR object's type before calling any of its methods.
87
+ #
88
+ #== Sorting of RR arrays
89
+ #
90
+ #As of version 0.55 there is functionality to help you sort RR
91
+ #arrays. 'rrsort()' is the function that is available to do the
92
+ #sorting. In most cases rrsort will give you the answer that you
93
+ #want but you can specify your own sorting method by using the
94
+ #Net::DNS::RR::FOO.set_rrsort_func() class method. See Net::DNS::RR
95
+ #for details.
96
+ #
97
+ #= EXAMPLES
98
+ #
99
+ #The following examples show how to use the <tt>Net::DNS</tt> modules.
100
+ #See the other manual pages and the demo scripts included with the
101
+ #source code for additional examples.
102
+ #
103
+ #See the <tt>Net::DNS::Update</tt> manual page for an example of performing
104
+ #dynamic updates.
105
+ #
106
+ #== Look up a host's addresses.
107
+ #
108
+ # require 'Net/DNS'
109
+ # res = Net::DNS::Resolver.new
110
+ # query = res.search("host.example.com")
111
+ #
112
+ # if (query)
113
+ # query.answer.each do |rr|
114
+ # next unless rr.class == Net::DNS::RR::A
115
+ # print rr.address + "\n"
116
+ # end
117
+ # else
118
+ # print "query failed: " + res.errorstring + "\n"
119
+ # end
120
+ #
121
+ #
122
+ #== Find the nameservers for a domain.
123
+ #
124
+ # require 'Net/DNS'
125
+ # res = Net::DNS::Resolver.new
126
+ # query = res.query("example.com", "NS")
127
+ #
128
+ # if (query)
129
+ # (query.answer.select { |i| i.class == Net::DNS::RR::NS}).each do |rr|
130
+ # print rr.nsdname + "\n"
131
+ # end
132
+ # else
133
+ # print "query failed: " + res.errorstring + "\n"
134
+ # end
135
+ #
136
+ #== Find the MX records for a domain.
137
+ #
138
+ # require 'Net/DNS'
139
+ # name='ENTER_NAME_HERE'
140
+ # res = Net::DNS::Resolver.new
141
+ # mx = Net::DNS.mx(name, res, 'IN')
142
+ #
143
+ # if (mx)
144
+ # mx.each do |rr|
145
+ # print rr.preference, " ", rr.exchange, "\n"
146
+ # end
147
+ # else
148
+ # print "Can't find MX records for #{name}: " + res.errorstring + "\n"
149
+ # end
150
+ #
151
+ #== Print a domain's SOA record in zone file format.
152
+ #
153
+ # require 'Net/DNS'
154
+ # res = Net::DNS::Resolver.new
155
+ # query = res.query("example.com", "SOA")
156
+ #
157
+ # if (query)
158
+ # (query.answer)[0].print
159
+ # else
160
+ # print "query failed: ", res.errorstring, "\n"
161
+ # end
162
+ #
163
+ #== Perform a zone transfer and print all the records.
164
+ #
165
+ # require 'Net/DNS'
166
+ # res = Net::DNS::Resolver.new
167
+ # res.nameservers("ns.example.com")
168
+ #
169
+ # zone = res.axfr("example.com")
170
+ #
171
+ # zone.each do |rr|
172
+ # rr.print
173
+ # end
174
+ #
175
+ #--
176
+ #== Perform a background query and do some other work while waiting
177
+ #for the answer.
178
+ #
179
+ # require 'Net/DNS'
180
+ # res = Net::DNS::Resolver.new
181
+ # socket = res.bgsend("host.example.com")
182
+ #
183
+ # until (res.bgisready(socket))
184
+ # # do some work here while waiting for the answer
185
+ # # ...and some more here
186
+ # end
187
+ #
188
+ # packet = res.bgread(socket)
189
+ # packet.print
190
+ #
191
+ #
192
+ #== Send a background query and use select to determine when the answer
193
+ #has arrived.
194
+ #
195
+ # require 'Net/DNS'
196
+ #
197
+ # timeout = 5
198
+ # res = Net::DNS::Resolver.new
199
+ # sockets = [res.bgsend("host.example.com")]
200
+ #
201
+ # # Add more sockets to sockets if desired.
202
+ # ready = IO::select(sockets, nil, nil, timeout)[0]
203
+ # if (ready != nil)
204
+ # ready.each do { |sock|
205
+ # if (sock == bgsock)
206
+ # packet = res.bgread(bgsock)
207
+ # packet.print
208
+ # bgsock = nil
209
+ # end
210
+ # # Check for the other sockets.
211
+ # sockets.remove(sock)
212
+ # end
213
+ # else
214
+ # warn "timed out after #{timeout} seconds\n"
215
+ # end
216
+ #
217
+ #++
218
+ #
219
+ #= BUGS
220
+ #
221
+ #Net::DNS is slow.
222
+ #
223
+ #For other items to be fixed, please see the "TODO" file included with
224
+ #the source distribution.
225
+ #
226
+ #= COPYRIGHT
227
+ #
228
+ #Copyright (c) 1997-2002 Michael Fuhr.
229
+ #
230
+ #Portions Copyright (c) 2002-2004 Chris Reinhardt.
231
+ #
232
+ #Portions Copyright (c) 2005 Olaf Kolkman (RIPE NCC)
233
+ #
234
+ #Portions Copyright (c) 2006 Olaf Kolkman (NLnet Labs)
235
+ #
236
+ #Portions Copyright (c) 2006 AlexD (Nominet UK)
237
+ #
238
+ #All rights reserved. This program is distributed under the
239
+ #Mozilla Public License (MPL1.1)
240
+ #
241
+ #= AUTHOR INFORMATION
242
+ #
243
+ #Ruby port (2006) from Nominet UK by :
244
+ # Alex D
245
+ # alexd@nominet.org.uk
246
+ #
247
+ #Port from perl Net::DNS (version 0.57) maintained at NLnet Labs (www.nlnetlabs.nl) by:
248
+ # Olaf Kolkman
249
+ # olaf@net-dns.org
250
+ #
251
+ #Between 2002 and 2004 Net::DNS was maintained by:
252
+ # Chris Reinhardt
253
+ #
254
+ #
255
+ #Net::DNS was created by:
256
+ # Michael Fuhr
257
+ # mike@fuhr.org
258
+ #
259
+ #
260
+ #
261
+ #For more information see:
262
+ # http://www.net-dns.org/
263
+ #
264
+ #Stay tuned and syncicate:
265
+ # http://www.net-dns.org/blog/
266
+ #
267
+ #= SEE ALSO
268
+ #
269
+ # Net::DNS::Resolver, Net::DNS::Packet, Net::DNS::Update,
270
+ #Net::DNS::Header, Net::DNS::Question, Net::DNS::RR, RFC 1035,
271
+ #<em>DNS and BIND</em> by Paul Albitz & Cricket Liu
272
+ module DNS
273
+
274
+
275
+ #Returns the version of Net::DNS.
276
+ VERSION = '0.0.1'
277
+ #Returns the default packet size
278
+ PACKETSZ = 512
279
+ #Header size
280
+ HFIXEDSZ = 12
281
+ QFIXEDSZ = 4
282
+ RRFIXEDSZ = 10
283
+ INT32SZ = 4
284
+ INT16SZ = 2
285
+
286
+ HAVE_XS = false # @TODO
287
+ DNSSEC = false # @TODO
288
+ DN_EXPAND_ESCAPES = false # @TODO
289
+
290
+
291
+ #--
292
+ # If you implement an RR record make sure you also add it to
293
+ # Net::DNS::RR::RR hash otherwise it will be treated as unknown type.
294
+ #
295
+
296
+ # Do not use these tybesby hashes directly. Use the interface
297
+ # functions, see below.
298
+ #
299
+ Typesbyname = {
300
+ 'SIGZERO' => 0, # RFC2931 consider this a pseudo type
301
+ 'A' => 1, # RFC 1035, Section 3.4.1
302
+ 'NS' => 2, # RFC 1035, Section 3.3.11
303
+ 'MD' => 3, # RFC 1035, Section 3.3.4 (obsolete)
304
+ 'MF' => 4, # RFC 1035, Section 3.3.5 (obsolete)
305
+ 'CNAME' => 5, # RFC 1035, Section 3.3.1
306
+ 'SOA' => 6, # RFC 1035, Section 3.3.13
307
+ 'MB' => 7, # RFC 1035, Section 3.3.3
308
+ 'MG' => 8, # RFC 1035, Section 3.3.6
309
+ 'MR' => 9, # RFC 1035, Section 3.3.8
310
+ 'NULL' => 10, # RFC 1035, Section 3.3.10
311
+ 'WKS' => 11, # RFC 1035, Section 3.4.2 (deprecated)
312
+ 'PTR' => 12, # RFC 1035, Section 3.3.12
313
+ 'HINFO' => 13, # RFC 1035, Section 3.3.2
314
+ 'MINFO' => 14, # RFC 1035, Section 3.3.7
315
+ 'MX' => 15, # RFC 1035, Section 3.3.9
316
+ 'TXT' => 16, # RFC 1035, Section 3.3.14
317
+ 'RP' => 17, # RFC 1183, Section 2.2
318
+ 'AFSDB' => 18, # RFC 1183, Section 1
319
+ 'X25' => 19, # RFC 1183, Section 3.1
320
+ 'ISDN' => 20, # RFC 1183, Section 3.2
321
+ 'RT' => 21, # RFC 1183, Section 3.3
322
+ 'NSAP' => 22, # RFC 1706, Section 5
323
+ 'NSAP_PTR' => 23, # RFC 1348 (obsolete)
324
+ # The following 2 RRs are impemented in Net::DNS::SEC
325
+ 'SIG' => 24, # RFC 2535, Section 4.1
326
+ 'KEY' => 25, # RFC 2535, Section 3.1
327
+ 'PX' => 26, # RFC 2163,
328
+ 'GPOS' => 27, # RFC 1712 (obsolete)
329
+ 'AAAA' => 28, # RFC 1886, Section 2.1
330
+ 'LOC' => 29, # RFC 1876
331
+ # The following RR is impemented in Net::DNS::SEC
332
+ 'NXT' => 30, # RFC 2535, Section 5.2 obsoleted by RFC3755
333
+ 'EID' => 31, # draft-ietf-nimrod-dns-xx.txt
334
+ 'NIMLOC' => 32, # draft-ietf-nimrod-dns-xx.txt
335
+ 'SRV' => 33, # RFC 2052
336
+ 'ATMA' => 34, # ???
337
+ 'NAPTR' => 35, # RFC 2168
338
+ 'KX' => 36, # RFC 2230
339
+ 'CERT' => 37, # RFC 2538
340
+ 'DNAME' => 39, # RFC 2672
341
+ 'OPT' => 41, # RFC 2671
342
+ # The following 4 RRs are impemented in Net::DNS::SEC
343
+ 'DS' => 43, # RFC 4034
344
+ 'SSHFP' => 44, # draft-ietf-secsh-dns (No RFC # yet at time of coding)
345
+ # 'IPSECKEY' => 45, # RFC 4025
346
+ 'RRSIG' => 46, # RFC 4034
347
+ 'NSEC' => 47, # RFC 4034
348
+ 'DNSKEY' => 48, # RFC 4034
349
+ 'SPF' => 99, # rfc-schlitt-spf-classic-o2 (No RFC # yet at time of coding)
350
+ 'UINFO' => 100, # non-standard
351
+ 'UID' => 101, # non-standard
352
+ 'GID' => 102, # non-standard
353
+ 'UNSPEC' => 103, # non-standard
354
+ 'TKEY' => 249, # RFC 2930
355
+ 'TSIG' => 250, # RFC 2931
356
+ 'IXFR' => 251, # RFC 1995
357
+ 'AXFR' => 252, # RFC 1035
358
+ 'MAILB' => 253, # RFC 1035 (MB, MG, MR)
359
+ 'MAILA' => 254, # RFC 1035 (obsolete - see MX)
360
+ 'ANY' => 255, # RFC 1035
361
+ }
362
+ Typesbyval = Typesbyname.invert;
363
+
364
+ #
365
+ # Do not use these classesby hashes directly. See below.
366
+ #
367
+
368
+ Classesbyname = {
369
+ 'IN' => 1, # RFC 1035
370
+ 'CH' => 3, # RFC 1035
371
+ 'CHAOS' => 3, # RFC 1035
372
+ 'HS' => 4, # RFC 1035
373
+ 'HESIOD' => 4, # RFC 1035
374
+ 'NONE' => 254, # RFC 2136
375
+ 'ANY' => 255, # RFC 1035
376
+ }
377
+ Classesbyval = {
378
+ 1 => 'IN', # RFC 1035
379
+ 3 => 'CH', # RFC 1035
380
+ 4 => 'HS', # RFC 1035
381
+ 254 => 'NONE', # RFC 2136
382
+ 255 => 'ANY', # RFC 1035
383
+ }
384
+
385
+
386
+ # The qtypesbyval and metatypesbyval specify special typecodes
387
+ # See rfc2929 and the relevant IANA registry
388
+ # http://www.iana.org/assignments/dns-parameters
389
+
390
+
391
+ Qtypesbyname = {
392
+ 'IXFR' => 251, # incremental transfer [RFC1995]
393
+ 'AXFR' => 252, # transfer of an entire zone [RFC1035]
394
+ 'MAILB' => 253, # mailbox-related RRs (MB, MG or MR) [RFC1035]
395
+ 'MAILA' => 254, # mail agent RRs (Obsolete - see MX) [RFC1035]
396
+ 'ANY' => 255, # all records [RFC1035]
397
+ }
398
+ Qtypesbyval = Qtypesbyname.invert;
399
+
400
+
401
+ Metatypesbyname = {
402
+ 'TKEY' => 249, # Transaction Key [RFC2930]
403
+ 'TSIG' => 250, # Transaction Signature [RFC2845]
404
+ 'OPT' => 41, # RFC 2671
405
+ }
406
+ Metatypesbyval = Metatypesbyname.invert;
407
+
408
+
409
+ Opcodesbyname = {
410
+ 'QUERY' => 0, # RFC 1035
411
+ 'IQUERY' => 1, # RFC 1035
412
+ 'STATUS' => 2, # RFC 1035
413
+ 'NS_NOTIFY_OP' => 4, # RFC 1996
414
+ 'UPDATE' => 5, # RFC 2136
415
+ }
416
+ Opcodesbyval = Opcodesbyname.invert;
417
+
418
+
419
+ Rcodesbyname = {
420
+ 'NOERROR' => 0, # RFC 1035
421
+ 'FORMERR' => 1, # RFC 1035
422
+ 'SERVFAIL' => 2, # RFC 1035
423
+ 'NXDOMAIN' => 3, # RFC 1035
424
+ 'NOTIMP' => 4, # RFC 1035
425
+ 'REFUSED' => 5, # RFC 1035
426
+ 'YXDOMAIN' => 6, # RFC 2136
427
+ 'YXRRSET' => 7, # RFC 2136
428
+ 'NXRRSET' => 8, # RFC 2136
429
+ 'NOTAUTH' => 9, # RFC 2136
430
+ 'NOTZONE' => 10, # RFC 2136
431
+ }
432
+ Rcodesbyval = Rcodesbyname.invert;
433
+
434
+ #--
435
+ # typesbyval and typesbyname functions are wrappers around the similarly named
436
+ # hashes. They are used for 'unknown' DNS RR types (RFC3597)
437
+ # typesbyname returns they TYPEcode as a function of the TYPE
438
+ # mnemonic. If the TYPE mapping is not specified the generic mnemonic
439
+ # TYPE### is returned.
440
+ def DNS.typesbyname(name)
441
+ name.upcase!
442
+
443
+ if Typesbyname[name]
444
+ return Typesbyname[name]
445
+ end
446
+
447
+
448
+ if ((name =~/^\s*TYPE(\d+)\s*$/o)==nil)
449
+ raise ArgumentError, "Net::DNS::typesbyname() argument (#{name}) is not TYPE###"
450
+ end
451
+
452
+ val = $1.to_i
453
+ if val > 0xffff
454
+ raise ArgumentError, 'Net::DNS::typesbyname() argument larger than ' + 0xffff
455
+ end
456
+
457
+ return val;
458
+ end
459
+
460
+
461
+ # typesbyval returns they TYPE mnemonic as a function of the TYPE
462
+ # code. If the TYPE mapping is not specified the generic mnemonic
463
+ # TYPE### is returned.
464
+ def DNS.typesbyval(val)
465
+ if (!defined?val)
466
+ raise ArgumentError, "Net::DNS::typesbyval() argument is not defined"
467
+ end
468
+
469
+ if val.class == String
470
+ # if val.gsub!("^\s*0*(\d+)\s*$", "$1")
471
+ if ((val =~ /^\s*0*(\d+)\s*$", "$1/o) == nil)
472
+ raise ArgumentError, "Net::DNS::typesbyval() argument (#{val}) is not numeric"
473
+ # val =~s/^\s*0*(\d+)\s*$/$1/o;
474
+ end
475
+
476
+ val = $1.to_i
477
+ end
478
+
479
+
480
+ if Typesbyval[val]
481
+ return Typesbyval[val]
482
+ end
483
+
484
+ raise ArgumentError, 'Net::DNS::typesbyval() argument larger than ' + 0xffff if
485
+ val > 0xffff;
486
+
487
+ return "TYPE#{val}";
488
+ end
489
+
490
+
491
+
492
+ # classesbyval and classesbyname functions are wrappers around the
493
+ # similarly named hashes. They are used for 'unknown' DNS RR classess
494
+ # (RFC3597)
495
+ # See typesbyval and typesbyname, these beasts have the same functionality
496
+ def DNS.classesbyname(name)
497
+ name.upcase!;
498
+ if Classesbyname[name]
499
+ return Classesbyname[name]
500
+ end
501
+
502
+ if ((name =~/^\s*CLASS(\d+)\s*$/o) == nil)
503
+ raise ArgumentError, "Net::DNS::classesbyval() argument is not CLASS### (#{name})"
504
+ end
505
+
506
+ val = $1.to_i
507
+ if val > 0xffff
508
+ raise ArgumentError, 'Net::DNS::classesbyval() argument larger than ' + 0xffff
509
+ end
510
+
511
+ return val;
512
+ end
513
+
514
+
515
+
516
+ def DNS.classesbyval(val)
517
+ if (val.class == String)
518
+ if ((val =~ /^\s*0*([0-9]+)\s*$/) == nil)
519
+ raise ArgumentError, "Net::DNS::classesbybal() argument is not numeric (#{val})" # unless val.gsub!("^\s*0*([0-9]+)\s*$", "$1")
520
+ # val =~ s/^\s*0*([0-9]+)\s*$/$1/o;#
521
+ end
522
+ val = $1.to_i
523
+ end
524
+
525
+ return Classesbyval[val] if Classesbyval[val];
526
+
527
+ raise ArgumentError, 'Net::DNS::classesbyval() argument larger than ' + 0xffff if val > 0xffff;
528
+
529
+ return "CLASS#{val}";
530
+ end
531
+
532
+ # Usage:
533
+ # mxes = mx('example.com', 'IN')
534
+ #
535
+ # # Use a default resolver -- can't get an error string this way.
536
+ # require 'Net/DNS'
537
+ # mx = Net::DNS.mx("example.com")
538
+ #
539
+ # # Use your own resolver object.
540
+ # require 'Net/DNS'
541
+ # res = Net::DNS::Resolver.new
542
+ # mx = Net::DNS.mx("example.com", res)
543
+ #
544
+ #Returns a list of Net::DNS::RR::MX objects
545
+ #representing the MX records for the specified name; the list will be
546
+ #sorted by preference. Returns an empty list if the query failed or no MX
547
+ #records were found.
548
+ #
549
+ #This method does not look up A records -- it only performs MX queries.
550
+ #
551
+ #See EXAMPLES for a more complete example.
552
+ #
553
+ def DNS.mx(name, resolver=nil, klass='IN')
554
+ if resolver == nil
555
+ resolver = Net::DNS::Resolver.new
556
+ end
557
+
558
+ ans = resolver.query(name, 'MX', klass) || return;
559
+
560
+ # This construct is best read backwords.
561
+ #
562
+ # First we take the answer secion of the packet.
563
+ # Then we take just the MX records from that list
564
+ # Then we sort the list by preference
565
+ # Then we return it.
566
+ # We do this into an array to force list context.
567
+ ret = []
568
+ ans.answer.each do |rec|
569
+ if (rec.type == 'MX')
570
+ ret.push(rec)
571
+ end
572
+ end
573
+ ret.sort! { |a,b| a.preference <=> b.preference }
574
+
575
+ return ret;
576
+ end
577
+
578
+ #Use this method to add an "RRset exists" prerequisite to a dynamic
579
+ #update packet. There are two forms, value-independent and
580
+ #value-dependent:
581
+ #
582
+ # # RRset exists (value-independent)
583
+ # update.push('pre' => yxrrset("host.example.com A"))
584
+ #
585
+ #Meaning: At least one RR with the specified name and type must
586
+ #exist.
587
+ #
588
+ # # RRset exists (value-dependent)
589
+ # packet.push('pre' => yxrrset("host.example.com A 10.1.2.3"))
590
+ #
591
+ #Meaning: At least one RR with the specified name and type must
592
+ #exist and must have matching data.
593
+ #
594
+ #Returns a Net::DNS::RR object or nil if the object couldn't
595
+ #be created.
596
+ def DNS.yxrrset(arg)
597
+ return Net::DNS::RR.new_from_string(arg, 'yxrrset');
598
+ end
599
+
600
+ #Use this method to add an "RRset does not exist" prerequisite to
601
+ #a dynamic update packet.
602
+ #
603
+ # packet.push('pre' => nxrrset("host.example.com A"))
604
+ #
605
+ #Meaning: No RRs with the specified name and type can exist.
606
+ #
607
+ #Returns a Net::DNS::RR object or nil if the object couldn't
608
+ #be created.
609
+ #
610
+ def DNS.nxrrset(arg)
611
+ return Net::DNS::RR.new_from_string(arg, 'nxrrset');
612
+ end
613
+
614
+ #Use this method to add a "name is in use" prerequisite to a dynamic
615
+ #update packet.
616
+ #
617
+ # packet.push('pre' => yxdomain("host.example.com"))
618
+ #
619
+ #Meaning: At least one RR with the specified name must exist.
620
+ #
621
+ #Returns a Net::DNS::RR object or nil if the object couldn't
622
+ #be created.
623
+ def DNS.yxdomain(arg)
624
+ return Net::DNS::RR.new_from_string(arg, 'yxdomain')
625
+ end
626
+
627
+ #Use this method to add a "name is not in use" prerequisite to a
628
+ #dynamic update packet.
629
+ #
630
+ # packet.push('pre' => nxdomain("host.example.com"))
631
+ #
632
+ #Meaning: No RR with the specified name can exist.
633
+ #
634
+ #Returns a Net::DNS::RR object or nil if the object couldn't
635
+ #be created.
636
+ #
637
+ def DNS.nxdomain(arg)
638
+ return Net::DNS::RR.new_from_string(arg, 'nxdomain')
639
+ end
640
+
641
+ #Use this method to add RRs to a zone.
642
+ #
643
+ # packet.push('update' => rr_add("host.example.com A 10.1.2.3"))
644
+ #
645
+ #Meaning: Add this RR to the zone.
646
+ #
647
+ #RR objects created by this method should be added to the "update"
648
+ #section of a dynamic update packet. The TTL defaults to 86400
649
+ #seconds (24 hours) if not specified.
650
+ #
651
+ #Returns a C<Net::DNS::RR object or nil if the object couldn't
652
+ #be created.
653
+ #
654
+ def DNS.rr_add(arg)
655
+ return Net::DNS::RR.new_from_string(arg, 'rr_add');
656
+ end
657
+
658
+ #Use this method to delete RRs from a zone. There are three forms:
659
+ #delete an RRset, delete all RRsets, and delete an RR.
660
+ #
661
+ # # Delete an RRset.
662
+ # packet.push(:update => rr_del("host.example.com A"))
663
+ #
664
+ #Meaning: Delete all RRs having the specified name and type.
665
+ #
666
+ # # Delete all RRsets.
667
+ # packet.push(:update => rr_del("host.example.com"))
668
+ #
669
+ #Meaning: Delete all RRs having the specified name.
670
+ #
671
+ # # Delete an RR.
672
+ # packet.push(:update => rr_del("host.example.com A 10.1.2.3"))
673
+ #
674
+ #Meaning: Delete all RRs having the specified name, type, and data.
675
+ #
676
+ #RR objects created by this method should be added to the "update"
677
+ #section of a dynamic update packet.
678
+ #
679
+ #Returns a Net::DNS::RR object or nil if the object couldn't
680
+ #be created.
681
+ #
682
+ def DNS.rr_del(arg)
683
+ return Net::DNS::RR.new_from_string(arg, 'rr_del')
684
+ end
685
+
686
+
687
+ # Utility function
688
+ #
689
+ # name2labels to translate names from presentation format into an
690
+ # array of "wire-format" labels.
691
+ # in: dName a string with a domain name in presentation format (1035
692
+ # sect 5.1)
693
+ # out: an array of labels in wire format.
694
+ def DNS.name2labels (dName)
695
+ names=[]
696
+ j=0;
697
+ while (dName && dName.length > 0)
698
+ names[j],dName = presentation2wire(dName)
699
+ j+=1
700
+ end
701
+
702
+ return names
703
+ end
704
+
705
+
706
+ def DNS.wire2presentation(wire)
707
+ presentation=""
708
+ length=wire.length
709
+ # There must be a nice regexp to do this.. but since I failed to
710
+ # find one I scan the name string until I find a '\', at that time
711
+ # I start looking forward and do the magic.
712
+
713
+ i=0;
714
+
715
+ while (i < length )
716
+ c=wire.unpack("x#{i}C1") [0]
717
+ if ( c < 33 || c > 126 )
718
+ presentation=presentation + sprintf("\\%03u" ,c)
719
+ elsif ( c.chr == "\"" )
720
+ presentation=presentation + "\\\""
721
+ elsif ( c.chr == "\$")
722
+ presentation=presentation + "\\\$"
723
+ elsif ( c.chr == "(" )
724
+ presentation=presentation + "\\("
725
+ elsif ( c.chr == ")" )
726
+ presentation=presentation + "\\)"
727
+ elsif ( c.chr == ";" )
728
+ presentation=presentation + "\\;"
729
+ elsif ( c.chr == "@" )
730
+ presentation=presentation + "\\@"
731
+ elsif ( c.chr == "\\" )
732
+ presentation=presentation + "\\\\"
733
+ elsif ( c.chr == ".")
734
+ presentation=presentation + "\\."
735
+ else
736
+ presentation=presentation + c.chr()
737
+ end
738
+ i=i+1
739
+ end
740
+
741
+ return presentation
742
+ end
743
+
744
+
745
+
746
+ # wire,leftover=presentation2wire(leftover)
747
+ # Will parse the input presentation format and return everything before
748
+ # the first non-escaped "." in the first element of the return array and
749
+ # all that has not been parsed yet in the 2nd argument.
750
+ def DNS.presentation2wire(presentation)
751
+ wire="";
752
+ length=presentation.length;
753
+
754
+ i=0;
755
+
756
+ while (i < length )
757
+ c=presentation.unpack("x#{i}C1") [0]
758
+ if (c == 46) # ord('.')
759
+ # return (wire,substr(presentation,i+1));
760
+ # return wire,presentation[i+1, length-(i+1)]
761
+ endstring = presentation[i+1, presentation.length-(i+1)]
762
+ return wire,endstring
763
+ end
764
+ if (c == 92) # ord'\\'
765
+ #backslash found
766
+ # pos(presentation)=i+1;
767
+ pos = i+1
768
+ # pos sets where next pattern matching should start
769
+ # if (presentation=~/\G(\d\d\d)/)
770
+ if (presentation.index(/\G(\d\d\d)/o, pos))
771
+ wire=wire+[$1.to_i].pack("C")
772
+ i=i+3
773
+ # elsif(presentation=~/\Gx([0..9a..fA..F][0..9a..fA..F])/)
774
+ elsif(presentation.index(/\Gx([0..9a..fA..F][0..9a..fA..F])/o, pos))
775
+ wire=wire+[$1].pack("H*")
776
+ i=i+3
777
+ # elsif(presentation=~/\G\./)
778
+ elsif(presentation.index(/\G\./o, pos))
779
+ wire=wire+"\."
780
+ i=i+1
781
+ # elsif(presentation=~/\G@/)
782
+ elsif(presentation.index(/\G@/o,pos))
783
+ wire=wire+"@"
784
+ i=i+1
785
+ # elsif(presentation=~/\G\(/)
786
+ elsif(presentation.index(/\G\(/o, pos))
787
+ wire=wire+"("
788
+ i=i+1
789
+ # elsif(presentation=~/\G\)/)
790
+ elsif(presentation.index(/\G\)/o, pos))
791
+ wire=wire+")"
792
+ i=i+1
793
+ # elsif(presentation=~/\G\\/)
794
+ elsif(presentation.index(/\G\\/o, pos))
795
+ wire=wire+"\\"
796
+ i+=1
797
+ end
798
+ else
799
+ wire = wire + [c].pack("C")
800
+ end
801
+ i=i+1
802
+ end
803
+
804
+ return wire
805
+ end
806
+
807
+ # require 'Net::DNS'
808
+ #
809
+ # prioritysorted=rrsort("SRV","priority",rr_array)
810
+ #
811
+ #
812
+ #rrsort() selects all RRs from the input array that are of the type
813
+ #that are defined in the first argument. Those RRs are sorted based on
814
+ #the attribute that is specified as second argument.
815
+ #
816
+ #There are a number of RRs for which the sorting function is
817
+ #specifically defined for certain attributes. If such sorting function
818
+ #is defined in the code (it can be set or overwritten using the
819
+ #set_rrsort_func() class method) that function is used.
820
+ #
821
+ #For instance:
822
+ # prioritysorted=rrsort("SRV","priority",rr_array)
823
+ #returns the SRV records sorted from lowest to heighest priority and
824
+ #for equal priorities from heighes to lowes weight.
825
+ #
826
+ #If the function does not exist then a numerical sort on the attribute
827
+ #value is performed.
828
+ # portsorted=rrsort("SRV","port",rr_array)
829
+ #
830
+ #If the attribute does not exist for a certain RR than the RRs are
831
+ #sorted on string comparrisson of the rdata.
832
+ #
833
+ #If the attribute is not defined than either the default_sort function
834
+ #will be defined or "Canonical sorting" (as defined by DNSSEC) will be
835
+ #used.
836
+ #
837
+ #rrsort() returns a sorted array with only elements of the specified
838
+ #RR type or undef.
839
+ #
840
+ #rrsort() returns undef when arguments are incorrect.
841
+ #--
842
+ def DNS.rrsort(*args)
843
+ rrtype = args[0]
844
+ attribute = args[1]
845
+ rr_array = args[2]
846
+ if (args.length < 2)
847
+ return nil
848
+ elsif (args.length == 2)
849
+ rr_array = attribute
850
+ attribute = nil
851
+ end
852
+ # invalid error type
853
+ return unless (Net::DNS::typesbyname(rrtype.upcase()))
854
+ if (rr_array == nil)
855
+ rr_array = Array.new
856
+ end
857
+
858
+ # attribute is empty or not specified.
859
+ if( attribute=~/^Net::DNS::RR::.*/)
860
+ # push the attribute back on the array.
861
+ rr_array.push(attribute)
862
+ attribute=nil
863
+ end
864
+
865
+ extracted_rr=[]
866
+ rr_array.each do |rr|
867
+ extracted_rr.push(rr) if ((rr.type.upcase) == rrtype.upcase)
868
+ end
869
+ return () unless extracted_rr.size() > 0
870
+
871
+ proc = ((Net::DNS::RR.const_get(rrtype)).new).get_rrsort_func(attribute)
872
+ sorted = extracted_rr.sort{ |a,b| proc.call(a,b)}
873
+
874
+ return sorted;
875
+
876
+ end
877
+
878
+ end
879
+ end