net-dns 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,121 @@
1
+ ##
2
+ #
3
+ # Net::DNS::RR::A
4
+ #
5
+ # $id$
6
+ #
7
+ ##
8
+
9
+ require 'ipaddr'
10
+
11
+ module Net # :nodoc:
12
+ module DNS
13
+
14
+ class RR
15
+
16
+ # =Name
17
+ #
18
+ # Net::DNS::RR::A DNS A resource record
19
+ #
20
+ # =Synopsis
21
+ #
22
+ # require "net/dns/rr"
23
+ #
24
+ # =Description
25
+ #
26
+ # Net::DNS::RR::A is the class to handle resource records of type A, the
27
+ # most common in a DNS query. Its resource data is an IPv4 (i.e. 32 bit
28
+ # long) address, hold in the instance variable +address+.
29
+ # a = Net::DNS::RR::A.new("localhost.movie.edu. 360 IN A 127.0.0.1")
30
+ #
31
+ # a = Net::DNS::RR::A.new(:name => "localhost.movie.edu.",
32
+ # :ttl => 360,
33
+ # :cls => Net::DNS::IN,
34
+ # :type => Net::DNS::A,
35
+ # :address => "127.0.0.1")
36
+ #
37
+ # When computing binary data to trasmit the RR, the RDATA section is an
38
+ # Internet address expressed as four decimal numbers separated by dots
39
+ # without any imbedded spaces (e.g.,"10.2.0.52" or "192.0.5.6").
40
+ #
41
+ class A < RR
42
+ attr_reader :address
43
+
44
+ # Assign to the RR::A object a new IPv4 address, which can be in the
45
+ # form of a string or an IPAddr object
46
+ #
47
+ # a.address = "192.168.0.1"
48
+ # a.address = IPAddr.new("10.0.0.1")
49
+ #
50
+ def address=(addr)
51
+ @address = check_address addr
52
+ build_pack
53
+ end # address=
54
+
55
+ private
56
+
57
+ def check_address(addr)
58
+ address = ""
59
+ case addr
60
+ when String
61
+ address = IPAddr.new addr
62
+ when Integer # Address in numeric form
63
+ tempAddr = [(addr>>24),(addr>>16)&0xFF,(addr>>8)&0xFF,addr&0xFF]
64
+ tempAddr = tempAddr.collect {|x| x.to_s}.join(".")
65
+ address = IPAddr.new tempAddr
66
+ when IPAddr
67
+ address = addr
68
+ else
69
+ raise RRArgumentError, "Unknown address type: #{addr}"
70
+ end
71
+ raise RRArgumentError, "Must specify an IPv4 address" unless address.ipv4?
72
+ address
73
+ rescue ArgumentError
74
+ raise RRArgumentError, "Invalid address #{addr}"
75
+ end
76
+
77
+ def build_pack
78
+ @address_pack = @address.hton
79
+ @rdlength = @address_pack.size
80
+ end
81
+
82
+ def set_type
83
+ @type = Net::DNS::RR::Types.new("A")
84
+ end
85
+
86
+ def get_data
87
+ @address_pack
88
+ end
89
+
90
+ def get_inspect
91
+ "#@address"
92
+ end
93
+
94
+ def subclass_new_from_hash(args)
95
+ if args.has_key? :address
96
+ @address = check_address args[:address]
97
+ elsif args.has_key? :rdata
98
+ @address = check_address args[:rdata]
99
+ else
100
+ # Address field is mandatory
101
+ raise RRArgumentError, ":address field is mandatory but missing"
102
+ end
103
+ end
104
+
105
+ def subclass_new_from_string(str)
106
+ @address = check_address(str)
107
+ end
108
+
109
+ def subclass_new_from_binary(data,offset)
110
+ a,b,c,d = data.unpack("@#{offset} CCCC")
111
+ @address = IPAddr.new "#{a}.#{b}.#{c}.#{d}"
112
+ return offset + 4
113
+ end
114
+
115
+ end # class A
116
+
117
+ end # class RR
118
+ end # module DNS
119
+ end # module Net
120
+
121
+
@@ -0,0 +1,92 @@
1
+ ##
2
+ #
3
+ # Net::DNS::RR::AAAA
4
+ #
5
+ # $id$
6
+ #
7
+ ##
8
+
9
+ require 'ipaddr'
10
+
11
+ module Net
12
+ module DNS
13
+
14
+ class RR
15
+
16
+ #
17
+ # RR type AAAA
18
+ #
19
+ class AAAA < RR
20
+ attr_reader :address
21
+
22
+ # Assign to the RR::AAAA object a new IPv6 address, which can be in the
23
+ # form of a string or an IPAddr object
24
+ #
25
+ # a.address = "::1"
26
+ # a.address = IPAddr.new("::1")
27
+ #
28
+ def address=(addr)
29
+ @address = check_address addr
30
+ build_pack
31
+ end # address=
32
+
33
+ private
34
+
35
+ def check_address(addr)
36
+ address = ""
37
+ case addr
38
+ when String
39
+ address = IPAddr.new addr
40
+ when IPAddr
41
+ address = addr
42
+ else
43
+ raise RRArgumentError, "Unknown address type: #{addr.inspect}"
44
+ end
45
+ raise RRArgumentError, "Must specify an IPv6 address" unless address.ipv6?
46
+ address
47
+ rescue ArgumentError
48
+ raise RRArgumentError, "Invalid address #{addr.inspect}"
49
+ end
50
+
51
+ def build_pack
52
+ @address_pack = @address.hton
53
+ @rdlength = @address_pack.size
54
+ end
55
+
56
+ def set_type
57
+ @type = Net::DNS::RR::Types.new("AAAA")
58
+ end
59
+
60
+ def get_data
61
+ @address_pack
62
+ end
63
+
64
+ def get_inspect
65
+ "#@address"
66
+ end
67
+
68
+ def subclass_new_from_hash(args)
69
+ if args.has_key? :address
70
+ @address = check_address args[:address]
71
+ else
72
+ raise RRArgumentError, ":address field is mandatory but missing"
73
+ end
74
+ end
75
+
76
+ def subclass_new_from_string(str)
77
+ @address = check_address(str)
78
+ end
79
+
80
+ def subclass_new_from_binary(data,offset)
81
+ arr = data.unpack("@#{offset} n8")
82
+ @address = IPAddr.new sprintf("%x:%x:%x:%x:%x:%x:%x:%x",*arr)
83
+ return offset + 16
84
+ end
85
+
86
+ end # class AAAA
87
+
88
+ end # class RR
89
+ end # module DNS
90
+ end # module Net
91
+
92
+
@@ -0,0 +1,148 @@
1
+ module Net # :nodoc:
2
+ module DNS
3
+
4
+ class RR
5
+
6
+ #
7
+ # This is an auxiliary class to hadle RR class field in a DNS packet.
8
+ #
9
+ class Classes
10
+
11
+ # An hash with the values of each RR class stored with the
12
+ # respective id number
13
+ Classes = {
14
+ 'IN' => 1, # RFC 1035
15
+ 'CH' => 3, # RFC 1035
16
+ 'HS' => 4, # RFC 1035
17
+ 'NONE' => 254, # RFC 2136
18
+ 'ANY' => 255, # RFC 1035
19
+ }
20
+
21
+ # The default value when class is nil in Resource Records
22
+ @@default = Classes["IN"]
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
60
+
61
+ # Gives in output the keys from the +Classes+ hash
62
+ # in a format suited for regexps
63
+ def self.regexp
64
+ Classes.keys.join("|")
65
+ end
66
+
67
+ # Creates a new object representing an RR class. Performs some
68
+ # checks on the argument validity too. Il +cls+ is +nil+, the
69
+ # default value is +ANY+ or the one set with Classes.default=
70
+ def initialize(cls)
71
+ 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}"
84
+ end
85
+ end
86
+
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
101
+ end
102
+ end
103
+
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
116
+ # (default for normal use)
117
+ def inspect
118
+ @num
119
+ end
120
+
121
+ # Returns the class in string format,
122
+ # i.d. "IN" or "CH" or such a string.
123
+ def to_s
124
+ @str
125
+ end
126
+
127
+ # Returns the class in numeric format,
128
+ # usable by the pack methods for data transfers
129
+ def to_i
130
+ @num.to_i
131
+ end
132
+
133
+
134
+ # Should be used only for testing purpouses
135
+ def to_str
136
+ @num.to_s
137
+ end
138
+
139
+ private :new_from_num, :new_from_string
140
+
141
+ end # class Classes
142
+
143
+ end # class RR
144
+ end # module DNS
145
+ end # module Net
146
+
147
+ class ClassArgumentError < ArgumentError # :nodoc:
148
+ end
@@ -0,0 +1,69 @@
1
+ ##
2
+ #
3
+ # Net::DNS::RR::CNAME
4
+ #
5
+ # $Id: CNAME.rb,v 1.7 2006/07/28 07:33:36 bluemonk Exp $
6
+ #
7
+ ##
8
+
9
+ module Net
10
+ module DNS
11
+
12
+ class RR
13
+
14
+ #------------------------------------------------------------
15
+ # RR type CNAME
16
+ #------------------------------------------------------------
17
+ class CNAME < RR
18
+ attr_reader :cname
19
+
20
+ private
21
+
22
+ def check_name(name)
23
+ unless name =~ /(\w\.?)+\s*$/ and name =~ /[a-zA-Z]/
24
+ raise RRArgumentError, "Canonical Name not valid: #{name}"
25
+ end
26
+ name
27
+ end
28
+
29
+ def build_pack
30
+ @cname_pack = pack_name(@cname)
31
+ @rdlength = @cname_pack.size
32
+ end
33
+
34
+ def set_type
35
+ @type = Net::DNS::RR::Types.new("CNAME")
36
+ end
37
+
38
+ def get_data
39
+ @cname_pack
40
+ end
41
+
42
+ def get_inspect
43
+ "#@cname"
44
+ end
45
+
46
+ def subclass_new_from_hash(args)
47
+ if args.has_key? :cname
48
+ @cname = check_name args[:cname]
49
+ else
50
+ raise RRArgumentError, ":cname field is mandatory but missing"
51
+ end
52
+ end
53
+
54
+ def subclass_new_from_string(str)
55
+ @cname = check_name(str)
56
+ end
57
+
58
+ def subclass_new_from_binary(data,offset)
59
+ @cname,offset = dn_expand(data,offset)
60
+ return offset
61
+ end
62
+
63
+ end # class CNAME
64
+
65
+ end # class RR
66
+ end # module DNS
67
+ end # module Net
68
+
69
+
@@ -0,0 +1,74 @@
1
+ ##
2
+ #
3
+ # Net::DNS::RR::HINFO
4
+ #
5
+ # $Id: HINFO.rb,v 1.4 2006/07/28 07:33:36 bluemonk Exp $
6
+ #
7
+ ##
8
+
9
+ module Net
10
+ module DNS
11
+ class RR
12
+
13
+ #------------------------------------------------------------
14
+ # RR type HINFO
15
+ #------------------------------------------------------------
16
+ class HINFO < RR
17
+ attr_reader :cpu, :os
18
+
19
+ private
20
+
21
+ def check_hinfo(str)
22
+ if str.strip =~ /^["'](.*?)["']\s+["'](.*?)["']$/
23
+ return $1,$2
24
+ else
25
+ raise RRArgumentError, "HINFO section not valid: #{str.inspect}"
26
+ end
27
+ end
28
+
29
+ def build_pack
30
+ @hinfo_pack = [@cpu.size].pack("C") + @cpu
31
+ @hinfo_pack += [@os.size].pack("C") + @os
32
+ @rdlength = @hinfo_pack.size
33
+ end
34
+
35
+ def set_type
36
+ @type = Net::DNS::RR::Types.new("HINFO")
37
+ end
38
+
39
+ def get_data
40
+ @hinfo_pack
41
+ end
42
+
43
+ def get_inspect
44
+ "#@cpu #@os"
45
+ end
46
+
47
+ def subclass_new_from_hash(args)
48
+ if args.has_key? :cpu and args.has_key? :os
49
+ @cpu = args[:cpu]
50
+ @os = args[:os]
51
+ else
52
+ raise RRArgumentError, ":cpu and :os fields are mandatory but missing"
53
+ end
54
+ end
55
+
56
+ def subclass_new_from_string(str)
57
+ @cpu,@os = check_hinfo(str)
58
+ end
59
+
60
+ def subclass_new_from_binary(data,offset)
61
+ len = data.unpack("@#{offset} C")[0]
62
+ @cpu = data[offset+1..offset+1+len]
63
+ offset += len+1
64
+ len = @data.unpack("@#{offset} C")[0]
65
+ @os = data[offset+1..offset+1+len]
66
+ return offset += len+1
67
+ end
68
+
69
+ end # class HINFO
70
+
71
+ end # class RR
72
+ end # module DNS
73
+ end # module Net
74
+