1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
|
module Net # :nodoc:
module DNS
module Names
# Base error class.
class Error < StandardError
end
# Generic Names Error.
class ExpandError < Error
end
INT16SZ = 2
# Expand a compressed name in a DNS Packet object. Please
# see RFC1035 for an explanation of how the compression
# in DNS packets works, how may it be useful and how should
# be handled.
#
# This method accept two parameters: a raw packet data and an
# offset, which indicates the point in the packet in which the
# parsing has arrived.
#
def dn_expand(packet, offset)
name = ""
packetlen = packet.size
loop do
raise ExpandError, "Offset is greater than packet length!" if packetlen < (offset + 1)
len = packet.unpack("@#{offset} C")[0]
if len == 0
offset += 1
break
elsif (len & 0xC0) == 0xC0
raise ExpandError, "Packet ended before offset expand" if packetlen < (offset + INT16SZ)
ptr = packet.unpack("@#{offset} n")[0]
ptr &= 0x3FFF
name2 = dn_expand(packet, ptr)[0]
raise ExpandError, "Packet is malformed!" if name2.nil?
name += name2
offset += INT16SZ
break
else
offset += 1
raise ExpandError, "No expansion found" if packetlen < (offset + len)
elem = packet[offset..offset + len - 1]
name += "#{elem}."
offset += len
end
end
[name, offset] # name.chomp(".") if trailing dot has to be omitted
end
def pack_name(name)
if name.size > 255
raise ArgumentError, "Name may not exceed 255 chars"
end
arr = name.split(".")
str = ""
arr.each do |elem|
if elem.size > 63
raise ArgumentError, "Label may not exceed 63 chars"
end
str += [elem.size, elem].pack("Ca*")
end
str += [0].pack("C")
str
end
def names_array(name)
arr = name.split(".")
ar = []
string = ""
arr.size.times do |i|
x = i + 1
elem = arr[-x]
len = elem.size
string = (string.reverse + [len, elem].pack("Ca*").reverse).reverse
ar.unshift(string)
end
ar
end
def dn_comp(name, offset, compnames)
names = {}
ptr = 0
str = ""
arr = names_array(name)
arr.each do |entry|
if compnames.key?(entry)
ptr = 0xC000 | compnames[entry]
str += [ptr].pack("n")
offset += INT16SZ
break
else
len = entry.unpack("C")[0]
elem = entry[1..len]
str += [len, elem].pack("Ca*")
names.update(entry.to_s => offset)
offset += len
end
end
[str, offset, names]
end
def valid?(name)
if name =~ /^([a-z0-9]([-a-z0-9]*[a-z0-9])?\.)+((a[cdefgilmnoqrstuwxz]|aero|arpa)|(b[abdefghijmnorstvwyz]|biz)|(c[acdfghiklmnorsuvxyz]|cat|com|coop)|d[ejkmoz]|(e[ceghrstu]|edu)|f[ijkmor]|(g[abdefghilmnpqrstuwy]|gov)|h[kmnrtu]|(i[delmnoqrst]|info|int)|(j[emop]|jobs)|k[eghimnprwyz]|l[abcikrstuvy]|(m[acdghklmnopqrstuvwxyz]|mil|mobi|museum)|(n[acefgilopruz]|name|net)|(om|org)|(p[aefghklmnrstwy]|pro)|qa|r[eouw]|s[abcdeghijklmnortvyz]|(t[cdfghjklmnoprtvwz]|travel)|u[agkmsyz]|v[aceginu]|w[fs]|y[etu]|z[amw])$/i
name
else
raise ArgumentError, "Invalid FQDN: #{name}"
end
end
end
end
end
|