Module: Net::DNS::Names

Included in:
Packet, Question, RR
Defined in:
lib/net/dns/names.rb

Defined Under Namespace

Classes: Error, ExpandError

Constant Summary collapse

INT16SZ =
2

Instance Method Summary collapse

Instance Method Details

#dn_comp(name, offset, compnames) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# File 'lib/net/dns/names.rb', line 89

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.unpack1("C")
      elem = entry[1..len]
      str += [len, elem].pack("Ca*")
      names.update(entry.to_s => offset)
      offset += len
    end
  end
  [str, offset, names]
end

#dn_expand(packet, offset) ⇒ Object

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.



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
# File 'lib/net/dns/names.rb', line 23

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.unpack1("@#{offset} C")

    if len == 0
      offset += 1
      break
    elsif (len & 0xC0) == 0xC0
      raise ExpandError, "Packet ended before offset expand" if packetlen < (offset + INT16SZ)

      ptr = packet.unpack1("@#{offset} n")
      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

#names_array(name) ⇒ Object



75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/net/dns/names.rb', line 75

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

#pack_name(name) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/net/dns/names.rb', line 57

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

#valid?(name) ⇒ Boolean

Returns:

  • (Boolean)

Raises:

  • (ArgumentError)


111
112
113
114
115
# File 'lib/net/dns/names.rb', line 111

def valid?(name)
  raise ArgumentError, "Invalid FQDN: #{name}" unless 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
end