net-dns 0.6.1 → 0.7.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 (53) hide show
  1. data/.gitignore +8 -6
  2. data/.travis.yml +14 -0
  3. data/CHANGELOG.md +79 -0
  4. data/Gemfile +4 -0
  5. data/Rakefile +56 -66
  6. data/demo/check_soa.rb +1 -1
  7. data/demo/threads.rb +1 -1
  8. data/lib/net/dns.rb +24 -22
  9. data/lib/net/dns/header.rb +77 -103
  10. data/lib/net/dns/{names/names.rb → names.rb} +19 -20
  11. data/lib/net/dns/packet.rb +231 -256
  12. data/lib/net/dns/question.rb +11 -40
  13. data/lib/net/dns/resolver.rb +248 -250
  14. data/lib/net/dns/resolver/socks.rb +6 -6
  15. data/lib/net/dns/resolver/timeouts.rb +1 -1
  16. data/lib/net/dns/rr.rb +112 -117
  17. data/lib/net/dns/rr/a.rb +98 -89
  18. data/lib/net/dns/rr/aaaa.rb +84 -68
  19. data/lib/net/dns/rr/classes.rb +91 -106
  20. data/lib/net/dns/rr/cname.rb +64 -45
  21. data/lib/net/dns/rr/hinfo.rb +90 -50
  22. data/lib/net/dns/rr/mr.rb +61 -44
  23. data/lib/net/dns/rr/mx.rb +73 -48
  24. data/lib/net/dns/rr/ns.rb +60 -46
  25. data/lib/net/dns/rr/null.rb +11 -12
  26. data/lib/net/dns/rr/ptr.rb +47 -34
  27. data/lib/net/dns/rr/soa.rb +5 -6
  28. data/lib/net/dns/rr/srv.rb +1 -4
  29. data/lib/net/dns/rr/txt.rb +14 -14
  30. data/lib/net/dns/rr/types.rb +13 -13
  31. data/lib/net/dns/version.rb +8 -14
  32. data/net-dns.gemspec +35 -0
  33. data/setup.rb +3 -2
  34. data/test/header_test.rb +18 -18
  35. data/test/names_test.rb +21 -0
  36. data/test/packet_test.rb +38 -31
  37. data/test/question_test.rb +23 -24
  38. data/test/resolver/timeouts_test.rb +13 -13
  39. data/test/resolver_test.rb +28 -20
  40. data/test/rr/a_test.rb +70 -23
  41. data/test/rr/aaaa_test.rb +109 -0
  42. data/test/rr/classes_test.rb +61 -49
  43. data/test/rr/cname_test.rb +97 -0
  44. data/test/rr/hinfo_test.rb +117 -0
  45. data/test/rr/mr_test.rb +105 -0
  46. data/test/rr/mx_test.rb +112 -0
  47. data/test/rr/ns_test.rb +34 -12
  48. data/test/rr/types_test.rb +4 -4
  49. data/test/rr_test.rb +1 -1
  50. metadata +77 -52
  51. data/AUTHORS.rdoc +0 -7
  52. data/CHANGELOG.rdoc +0 -46
  53. data/VERSION.yml +0 -5
@@ -1,87 +1,103 @@
1
- require 'ipaddr'
2
-
3
-
4
- module Net
5
- module DNS
6
-
7
- class RR
1
+ module Net
2
+ module DNS
3
+ class RR
8
4
 
9
5
  #
10
- # RR type AAAA
6
+ # = IPv6 Address Record (AAAA)
7
+ #
8
+ # Class for DNS IPv6 Address (AAAA) resource records.
11
9
  #
12
10
  class AAAA < RR
13
- attr_reader :address
14
11
 
15
- # Assign to the RR::AAAA object a new IPv6 address, which can be in the
16
- # form of a string or an IPAddr object
12
+ # Gets the current IPv6 address for this record.
13
+ #
14
+ # Returns an instance of IPAddr.
15
+ def address
16
+ @address
17
+ end
18
+
19
+ # Assigns a new IPv6 address to this record, which can be in the
20
+ # form of a <tt>String</tt> or an <tt>IPAddr</tt> object.
17
21
  #
18
- # a.address = "::1"
19
- # a.address = IPAddr.new("::1")
22
+ # Examples
20
23
  #
21
- def address=(addr)
22
- @address = check_address addr
24
+ # a.address = "192.168.0.1"
25
+ # a.address = IPAddr.new("10.0.0.1")
26
+ #
27
+ # Returns the new allocated instance of IPAddr.
28
+ def address=(string_or_ipaddr)
29
+ @address = check_address(string_or_ipaddr)
23
30
  build_pack
24
- end # address=
25
-
26
- private
27
-
28
- def check_address(addr)
29
- address = ""
30
- case addr
31
- when String
32
- address = IPAddr.new addr
33
- when IPAddr
34
- address = addr
35
- else
36
- raise ArgumentError, "Unknown address type: #{addr.inspect}"
37
- end
38
- raise ArgumentError, "Must specify an IPv6 address" unless address.ipv6?
39
- address
40
- rescue ArgumentError
41
- raise ArgumentError, "Invalid address #{addr.inspect}"
42
- end
43
-
44
- def build_pack
45
- @address_pack = @address.hton
46
- @rdlength = @address_pack.size
47
- end
48
-
49
- def get_data
50
- @address_pack
31
+ @address
51
32
  end
52
33
 
53
- def get_inspect
54
- "#@address"
55
- end
56
-
57
- def subclass_new_from_hash(args)
58
- if args.has_key? :address
59
- @address = check_address args[:address]
60
- else
61
- raise ArgumentError, ":address field is mandatory but missing"
62
- end
63
- end
64
-
65
- def subclass_new_from_string(str)
66
- @address = check_address(str)
67
- end
68
-
69
- def subclass_new_from_binary(data,offset)
70
- arr = data.unpack("@#{offset} n8")
71
- @address = IPAddr.new sprintf("%x:%x:%x:%x:%x:%x:%x:%x",*arr)
72
- return offset + 16
34
+ # Gets the standardized value for this record,
35
+ # represented by the value of <tt>address</tt>.
36
+ #
37
+ # Returns a String.
38
+ def value
39
+ address.to_s
73
40
  end
74
-
41
+
42
+
75
43
  private
76
-
44
+
45
+ def subclass_new_from_hash(options)
46
+ if options.has_key?(:address)
47
+ @address = check_address(options[:address])
48
+ else
49
+ raise ArgumentError, ":address field is mandatory"
50
+ end
51
+ end
52
+
53
+ def subclass_new_from_string(str)
54
+ @address = check_address(str)
55
+ end
56
+
57
+ def subclass_new_from_binary(data, offset)
58
+ tokens = data.unpack("@#{offset} n8")
59
+ @address = IPAddr.new(sprintf("%x:%x:%x:%x:%x:%x:%x:%x", *tokens))
60
+ offset + 16
61
+ end
62
+
63
+
77
64
  def set_type
78
65
  @type = Net::DNS::RR::Types.new("AAAA")
79
66
  end
80
-
67
+
68
+ def get_inspect
69
+ value
70
+ end
71
+
72
+
73
+ def check_address(input)
74
+ address = case input
75
+ when IPAddr
76
+ input
77
+ when String
78
+ IPAddr.new(input)
79
+ else
80
+ raise ArgumentError, "Invalid IP address `#{input}'"
81
+ end
82
+
83
+ if !address.ipv6?
84
+ raise(ArgumentError, "Must specify an IPv6 address")
85
+ end
86
+
87
+ address
88
+ end
89
+
90
+ def build_pack
91
+ @address_pack = @address.hton
92
+ @rdlength = @address_pack.size
93
+ end
94
+
95
+ def get_data
96
+ @address_pack
97
+ end
98
+
81
99
  end
82
-
100
+
83
101
  end
84
102
  end
85
103
  end
86
-
87
-
@@ -1,148 +1,133 @@
1
- module Net # :nodoc:
2
- module DNS
3
-
1
+ module Net
2
+ module DNS
3
+
4
4
  class RR
5
-
5
+
6
6
  #
7
- # This is an auxiliary class to hadle RR class field in a DNS packet.
7
+ # = Net::DNS::Classes
8
+ #
9
+ # This is an auxiliary class to handle <tt>Net::DNS::RR</tt>
10
+ # class field in a DNS packet.
8
11
  #
9
12
  class Classes
10
-
11
- # An hash with the values of each RR class stored with the
12
- # respective id number
13
- Classes = {
13
+
14
+ # Hash with the values of each RR class stored with the
15
+ # respective id number.
16
+ CLASSES = {
14
17
  'IN' => 1, # RFC 1035
15
18
  'CH' => 3, # RFC 1035
16
19
  'HS' => 4, # RFC 1035
17
20
  'NONE' => 254, # RFC 2136
18
21
  'ANY' => 255, # RFC 1035
19
22
  }
20
-
21
- # The default value when class is nil in Resource Records
22
- @@default = Classes["IN"]
23
23
 
24
- # Be able to control the default class to assign when
25
- # cls argument is +nil+. Default to +IN+
26
- def self.default=(str)
27
- if Classes.has_key? str
28
- @@default = Classes[str]
29
- else
30
- raise ClassArgumentError, "Unknown class #{str}"
31
- end
32
- end
33
-
34
- # Checks whether +cls+ is a valid RR class.
35
- def self.valid?(cls)
36
- case cls
37
- when String
38
- return Classes.has_key?(cls)
39
- when Fixnum
40
- return Classes.invert.has_key?(cls)
41
- else
42
- raise ClassArgumentError, "Wrong cls class: #{cls.class}"
43
- end
44
- end
45
-
46
- # Returns the class in string format, as "IN" or "CH",
47
- # given the numeric value
48
- def self.to_str(cls)
49
- case cls
50
- when Fixnum
51
- if Classes.invert.has_key? cls
52
- return Classes.invert[cls]
53
- else
54
- raise ClassArgumentError, "Unknown class number #{cls}"
55
- end
56
- else
57
- raise ClassArgumentError, "Wrong cls class: #{cls.class}"
58
- end
59
- end
24
+ # The default value when class is nil in Resource Records
25
+ @@default = CLASSES["IN"]
60
26
 
61
- # Gives in output the keys from the +Classes+ hash
62
- # in a format suited for regexps
63
- def self.regexp
64
- Classes.keys.sort.join("|")
65
- end
66
27
 
67
28
  # Creates a new object representing an RR class. Performs some
68
29
  # checks on the argument validity too. Il +cls+ is +nil+, the
69
30
  # default value is +ANY+ or the one set with Classes.default=
70
31
  def initialize(cls)
71
32
  case cls
72
- when String
73
- # type in the form "A" or "NS"
74
- new_from_string(cls.upcase)
75
- when Fixnum
76
- # type in numeric form
77
- new_from_num(cls)
78
- when nil
79
- # default type, control with Classes.default=
80
- @str = Classes.invert[@@default]
81
- @num = @@default
82
- else
83
- raise ClassArgumentError, "Wrong cls class: #{cls.class}"
33
+ when String
34
+ initialize_from_str(cls)
35
+ when Fixnum
36
+ initialize_from_num(cls)
37
+ when nil
38
+ initialize_from_num(@@default)
84
39
  end
85
- end
86
40
 
87
- # Constructor for string data class,
88
- # *PRIVATE* method
89
- def new_from_string(cls)
90
- case cls
91
- when /^CLASS\\d+/
92
- # TODO!!!
93
- else
94
- # String with name of class
95
- if Classes.has_key? cls
96
- @str = cls
97
- @num = Classes[cls]
98
- else
99
- raise ClassesArgumentError, "Unknown cls #{cls}"
100
- end
41
+ if @str.nil? || @num.nil?
42
+ raise ArgumentError, "Unable to create a `Classes' from `#{cls}'"
101
43
  end
102
44
  end
103
45
 
104
- # Contructor for numeric data class
105
- # *PRIVATE* method
106
- def new_from_num(cls)
107
- if Classes.invert.has_key? cls
108
- @num = cls
109
- @str = Classes.invert[cls]
110
- else
111
- raise ClassesArgumentError, "Unkown cls number #{cls}"
112
- end
113
- end
114
-
115
- # Returns the class in number format
46
+ # Returns the class in number format
116
47
  # (default for normal use)
48
+ #
49
+ # FIXME: inspect must return a String.
50
+ #
117
51
  def inspect
118
52
  @num
119
53
  end
120
54
 
121
55
  # Returns the class in string format,
122
- # i.d. "IN" or "CH" or such a string.
56
+ # ex. "IN" or "CH" or such a string.
123
57
  def to_s
124
- @str
58
+ @str.to_s
125
59
  end
126
-
60
+
127
61
  # Returns the class in numeric format,
128
- # usable by the pack methods for data transfers
62
+ # usable by the pack methods for data transfers.
129
63
  def to_i
130
64
  @num.to_i
131
65
  end
132
66
 
133
67
 
134
- # Should be used only for testing purpouses
135
- def to_str
136
- @num.to_s
68
+
69
+ # Be able to control the default class to assign when
70
+ # cls argument is +nil+. Default to +IN+
71
+ def self.default=(str)
72
+ if CLASSES[str]
73
+ @@default = CLASSES[str]
74
+ else
75
+ raise ArgumentError, "Unknown class `#{str}'"
76
+ end
77
+ end
78
+
79
+ # Returns whether <tt>cls</tt> is a valid RR class.
80
+ #
81
+ # Net::DNS::RR::Classes.valid?("IN")
82
+ # # => true
83
+ # Net::DNS::RR::Classes.valid?(1)
84
+ # # => true
85
+ # Net::DNS::RR::Classes.valid?("Q")
86
+ # # => false
87
+ # Net::DNS::RR::Classes.valid?(256)
88
+ # # => false
89
+ # Net::DNS::RR::Classes.valid?(Hash.new)
90
+ # # => ArgumentError
91
+ #
92
+ # FIXME: valid? should never raise.
93
+ #
94
+ # ==== Raises
95
+ # ArgumentError:: if <tt>cls</tt> isn't either a String or a Fixnum
96
+ #
97
+ def self.valid?(cls)
98
+ case cls
99
+ when String
100
+ CLASSES.has_key?(cls)
101
+ when Fixnum
102
+ CLASSES.invert.has_key?(cls)
103
+ else
104
+ raise ArgumentError, "Wrong cls class: #{cls.class}"
105
+ end
106
+ end
107
+
108
+ # Gives in output the keys from the +Classes+ hash
109
+ # in a format suited for regexps
110
+ def self.regexp
111
+ CLASSES.keys.sort.join("|")
112
+ end
113
+
114
+
115
+ private
116
+
117
+ # Initialize a new instance from a Class name.
118
+ def initialize_from_str(str)
119
+ key = str.to_s.upcase
120
+ @num, @str = CLASSES[key], key
137
121
  end
138
122
 
139
- private :new_from_num, :new_from_string
123
+ # Initialize a new instance from the Class value.
124
+ def initialize_from_num(num)
125
+ key = num.to_i
126
+ @num, @str = key, CLASSES.invert[key]
127
+ end
140
128
 
141
- end # class Classes
142
-
143
- end # class RR
144
- end # module DNS
145
- end # module Net
129
+ end
146
130
 
147
- class ClassArgumentError < ArgumentError # :nodoc:
131
+ end
132
+ end
148
133
  end
@@ -1,63 +1,82 @@
1
- module Net
1
+ module Net # :nodoc:
2
2
  module DNS
3
-
4
3
  class RR
5
-
6
- #------------------------------------------------------------
7
- # RR type CNAME
8
- #------------------------------------------------------------
4
+
5
+ #
6
+ # = Canonical Name Record (CNAME)
7
+ #
8
+ # Class for DNS CNAME resource records.
9
+ #
10
+ # A CNAME record maps an alias or nickname to the real or Canonical name
11
+ # which may lie outside the current zone.
12
+ # Canonical means expected or real name.
13
+ #
9
14
  class CNAME < RR
10
- attr_reader :cname
11
15
 
12
- private
13
-
14
- def check_name(name)
15
- unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
16
- raise ArgumentError, "Canonical Name not valid: #{name}"
17
- end
18
- name
16
+ # Gets the canonical name value.
17
+ #
18
+ # Returns a String.
19
+ def cname
20
+ @cname
19
21
  end
20
22
 
21
- def build_pack
22
- @cname_pack = pack_name(@cname)
23
- @rdlength = @cname_pack.size
23
+ # Gets the standardized value for this record,
24
+ # represented by the value of <tt>cname</tt>.
25
+ #
26
+ # Returns a String.
27
+ def value
28
+ cname.to_s
24
29
  end
25
30
 
26
- def get_data
27
- @cname_pack
28
- end
29
31
 
30
- def get_inspect
31
- "#@cname"
32
- end
32
+ private
33
33
 
34
- def subclass_new_from_hash(args)
35
- if args.has_key? :cname
36
- @cname = check_name args[:cname]
37
- else
38
- raise ArgumentError, ":cname field is mandatory but missing"
34
+ def subclass_new_from_hash(options)
35
+ if options.has_key?(:cname)
36
+ @cname = check_name(options[:cname])
37
+ else
38
+ raise ArgumentError, ":cname field is mandatory"
39
+ end
40
+ end
41
+
42
+ def subclass_new_from_string(str)
43
+ @cname = check_name(str)
44
+ end
45
+
46
+ def subclass_new_from_binary(data, offset)
47
+ @cname, offset = dn_expand(data, offset)
48
+ offset
39
49
  end
40
- end
41
50
 
42
- def subclass_new_from_string(str)
43
- @cname = check_name(str)
44
- end
45
51
 
46
- def subclass_new_from_binary(data,offset)
47
- @cname,offset = dn_expand(data,offset)
48
- return offset
49
- end
50
-
51
- private
52
-
53
52
  def set_type
54
53
  @type = Net::DNS::RR::Types.new("CNAME")
55
54
  end
56
-
57
- end # class CNAME
58
-
59
- end # class RR
60
- end # module DNS
61
- end # module Net
62
55
 
56
+ def get_inspect
57
+ value
58
+ end
59
+
60
+
61
+ def check_name(input)
62
+ name = input.to_s
63
+ unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
64
+ raise ArgumentError, "Invalid Canonical Name `#{name}'"
65
+ end
66
+ name
67
+ end
68
+
69
+ def build_pack
70
+ @cname_pack = pack_name(@cname)
71
+ @rdlength = @cname_pack.size
72
+ end
73
+
74
+ def get_data
75
+ @cname_pack
76
+ end
77
+
78
+ end
63
79
 
80
+ end
81
+ end
82
+ end