CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/net/dns/question.rb
Views: 11780
1
# -*- coding: binary -*-
2
#---
3
# $Id: Question.rb,v 1.8 2006/07/28 19:00:03 bluemonk Exp $
4
#+++
5
6
require 'net/dns/dns'
7
require 'net/dns/names/names'
8
require 'net/dns/rr/types'
9
require 'net/dns/rr/classes'
10
11
module Net # :nodoc:
12
module DNS
13
14
#
15
# =Name
16
#
17
# Net::DNS::Question - DNS packet question class
18
#
19
# =Synopsis
20
#
21
# require 'net/dns/question'
22
#
23
# =Description
24
#
25
# This class represent the Question portion of a DNS packet. The number
26
# of question entries is stored in the +qdCount+ variable of an Header
27
# object.
28
#
29
# A new object can be created passing the name of the query and the type
30
# of answer desired, plus an optional argument containing the class:
31
#
32
# question = Net::DNS::Question.new("google.com.", Net::DNS::A)
33
# #=> "google.com. A IN"
34
#
35
# Alternatevly, a new object is created when processing a binary
36
# packet, as when an answer is received.
37
# To obtain the binary data from a question object you can use
38
# the method Question#data:
39
#
40
# question.data
41
# #=> "\006google\003com\000\000\001\000\001"
42
#
43
# A lot of methods were written to keep a compatibility layer with
44
# the Perl version of the library, as long as methods name which are
45
# more or less the same.
46
#
47
# =Error classes
48
#
49
# Some error classes has been defined for the Net::DNS::Header class,
50
# which are listed here to keep a light and browsable main documentation.
51
# We have:
52
#
53
# * QuestionArgumentError: generic argument error
54
# * QuestionNameError: an error in the +name+ part of a Question entry
55
#
56
# =Copyright
57
#
58
# Copyright (c) 2006 Marco Ceresa
59
#
60
# All rights reserved. This program is free software; you may redistribute
61
# it and/or modify it under the same terms as Ruby itself.
62
#
63
class Question
64
65
include Net::DNS::Names
66
67
# +name+ part of a Question entry
68
attr_reader :qName
69
# +type+ part of a Question entry
70
attr_reader :qType
71
# +class+ part of a Question entry
72
attr_reader :qClass
73
74
# Creates a new Net::DNS::Question object:
75
#
76
# question = Net::DNS::Question.new("example.com")
77
# #=> "example.com A IN"
78
# question = Net::DNS::Question.new("example.com", Net::DNS::MX)
79
# #=> "example.com MX IN"
80
# question = Net::DNS::Question.new("example.com", Net::DNS::TXT, Net::DNS::HS)
81
# #=> "example.com TXT HS"
82
83
# If not specified, +type+ and +cls+ arguments defaults
84
# to Net::DNS::A and Net::DNS::IN respectively.
85
#
86
def initialize(name,type=Net::DNS::A,cls=Net::DNS::IN)
87
@qName = check_name name
88
@qType = Net::DNS::RR::Types.new type
89
@qClass = Net::DNS::RR::Classes.new cls
90
end
91
92
# Return a new Net::DNS::Question object created by
93
# parsing binary data, such as an answer from the
94
# nameserver.
95
#
96
# question = Net::DNS::Question.parse(data)
97
# puts "Queried for #{question.qName} type #{question.qType.to_s}"
98
# #=> Queried for example.com type A
99
#
100
def self.parse(arg)
101
if arg.kind_of? String
102
o = allocate
103
o.send(:new_from_binary,arg)
104
o
105
else
106
raise QuestionArgumentError, "Wrong argument format, must be a String"
107
end
108
end
109
110
# Known inspect method with nice formatting
111
def inspect
112
if @qName.size > 29 then
113
len = @qName.size + 1
114
else
115
len = 29
116
end
117
[@qName,@qClass.to_s,@qType.to_s].pack("A#{len} A8 A8")
118
end
119
120
# Outputs binary data from a Question object
121
#
122
# question.data
123
# #=> "\006google\003com\000\000\001\000\001"
124
#
125
def data
126
[pack_name(@qName),@qType.to_i,@qClass.to_i].pack("a*nn")
127
end
128
129
# Return the binary data of the objects, plus an offset
130
# and an Hash with references to compressed names. For use in
131
# Net::DNS::Packet compressed packet creation.
132
#
133
def comp_data
134
arr = @qName.split(".")
135
str = pack_name(@qName)
136
string = ""
137
names = {}
138
offset = Net::DNS::HFIXEDSZ
139
arr.size.times do |i|
140
x = i+1
141
elem = arr[-x]
142
len = elem.size
143
string = ((string.reverse)+([len,elem].pack("Ca*")).reverse).reverse
144
names[string] = offset
145
offset += len
146
end
147
offset += 2 * Net::DNS::INT16SZ
148
str += "\000"
149
[[str,@qType.to_i,@qClass.to_i].pack("a*nn"),offset,names]
150
end
151
152
private
153
154
def build_qName(str)
155
result = ""
156
offset = 0
157
loop do
158
len = str.unpack("@#{offset} C")[0]
159
break if len == 0
160
offset += 1
161
result += str[offset..offset+len-1]
162
result += "."
163
offset += len
164
end
165
result
166
end
167
168
def check_name(name)
169
name.strip!
170
if name =~ /[^\w\.\-_]/
171
raise QuestionNameError, "Question name #{name.inspect} not valid"
172
else
173
name
174
end
175
rescue
176
raise QuestionNameError, "Question name #{name.inspect} not valid"
177
end
178
179
def new_from_binary(data)
180
str,type,cls = data.unpack("a#{data.size-4}nn")
181
@qName = build_qName(str)
182
@qType = Net::DNS::RR::Types.new type
183
@qClass = Net::DNS::RR::Classes.new cls
184
rescue StandardError => e
185
raise QuestionArgumentError, "Invalid data: #{data.inspect}\n{e.backtrace}"
186
end
187
188
end # class Question
189
190
end # class DNS
191
end # module Net
192
193
class QuestionArgumentError < ArgumentError # :nodoc:
194
end
195
class QuestionNameError < StandardError # :nodoc:
196
end
197
198