Class: DNS::DomainName
- Inherits:
-
Object
- Object
- DNS::DomainName
- Defined in:
- lib/faildns/domainname.rb
Overview
– Domain names in messages are expressed in terms of a sequence of labels. Each label is represented as a one octet length field followed by that number of octets. Since every domain name ends with the null label of the root, a domain name is terminated by a length byte of zero. The high order two bits of every length octet must be zero, and the remaining six bits of the length field limit the label to 63 octets or less.
To simplify implementations, the total length of a domain name (i.e., label octets and label length octets) is restricted to 255 octets or less.
Although labels can contain any 8 bit values in octets that make up a label, it is strongly recommended that labels follow the preferred syntax described elsewhere in this memo, which is compatible with existing host naming conventions. Name servers and resolvers must compare labels in a case-insensitive manner (i.e., A=a), assuming ASCII with zero parity. Non-alphabetic codes must match exactly.
In order to reduce the size of messages, the domain system utilizes a compression scheme which eliminates the repetition of domain names in a message. In this scheme, an entire domain name or a list of labels at the end of a domain name is replaced with a pointer to a prior occurance of the same name.
The pointer takes the form of a two octet sequence:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
| 1 1| OFFSET |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The first two bits are ones. This allows a pointer to be distinguished from a label, since the label must begin with two zero bits because labels are restricted to 63 octets or less. (The 10 and 01 combinations are reserved for future use.) The OFFSET field specifies an offset from the start of the message (i.e., the first octet of the ID field in the domain header). A zero offset specifies the first byte of the ID field, etc.
The compression scheme allows a domain name in a message to be represented as either:
- a sequence of labels ending in a zero octet
- a pointer
- a sequence of labels ending with a pointer
Pointers can only be used for occurances of a domain name where the format is not class specific. If this were not the case, a name server or resolver would be required to know the format of all RRs it handled. As yet, there are no such cases, but they may occur in future RDATA formats.
If a domain name is contained in a part of the message subject to a length field (such as the RDATA section of an RR), and compression is used, the length of the compressed name is used in the length calculation, rather than the length of the expanded name.
Programs are free to avoid using pointers in messages they generate, although this will reduce datagram capacity, and may cause truncation. However all programs are required to understand arriving messages that contain pointers.
For example, a datagram might need to use the domain names F.ISI.ARPA, FOO.F.ISI.ARPA, ARPA, and the root. Ignoring the other fields of the message, these domain names might be represented as:
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
20 | 1 | F |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22 | 3 | I |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
24 | S | I |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26 | 4 | A |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
28 | R | P |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
30 | A | 0 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
40 | 3 | F |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
42 | O | O |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
44 | 1 1| 20 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
64 | 1 1| 26 |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
92 | 0 | |
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
The domain name for F.ISI.ARPA is shown at offset 20. The domain name FOO.F.ISI.ARPA is shown at offset 40; this definition uses a pointer to concatenate a label for FOO to the previously defined F.ISI.ARPA. The domain name ARPA is defined at offset 64 using a pointer to the ARPA component of the name F.ISI.ARPA at 20; note that this pointer relies on ARPA being the last label in the string at 20. The root domain name is defined by a single octet of zeros at 92; the root domain name has no labels. ++
Instance Attribute Summary collapse
-
#domain ⇒ Object
Returns the value of attribute domain.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(domain) ⇒ DomainName
constructor
A new instance of DomainName.
- #pack(options = {}) ⇒ Object
- #to_s ⇒ Object (also: #to_str)
Constructor Details
#initialize(domain) ⇒ DomainName
Returns a new instance of DomainName.
194 195 196 197 198 199 200 201 202 203 204 |
# File 'lib/faildns/domainname.rb', line 194 def initialize (domain) if domain.is_a? DomainName domain = domain.domain end if !domain.is_a? String raise ArgumentError.new 'The passed value is not a string.' end @domain = domain end |
Instance Attribute Details
#domain ⇒ Object
Returns the value of attribute domain.
192 193 194 |
# File 'lib/faildns/domainname.rb', line 192 def domain @domain end |
Class Method Details
.length(string) ⇒ Object
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/faildns/domainname.rb', line 168 def self.length (string) string.force_encoding 'BINARY' string = string.clone result = 0 if string.unpack('c').first & 0xC0 == 0xC0 return 2 else while (length = string.unpack('c').first) != 0 && (length & 0xC0) == 0 result += 1 + length string[0, length + 1] = '' end if length & 0xC0 == 0xC0 result += 2 else result += 1 end end return result end |
.parse(string, whole) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/faildns/domainname.rb', line 138 def self.parse (string, whole) string.force_encoding 'BINARY' result = '' case string.unpack('c').first & 0xC0 when 0xC0 result += DomainName.parse(DomainName.pointer(whole, string), whole) string[0, 2] = '' when 0x00 while (length = string.unpack('c').first) != 0 && (length & 0xC0) == 0 result += '.' + string[1, length] string[0, length + 1] = '' end if length & 0xC0 == 0xC0 result += '.' + DomainName.parse(string, whole) string[0, 2] = '' else string[0, 1] = '' end result[0, 1] = '' end DomainName.new result end |
.pointer(string, offset) ⇒ Object
132 133 134 135 136 |
# File 'lib/faildns/domainname.rb', line 132 def self.pointer (string, offset) string.force_encoding 'BINARY' return string[offset.unpack('n').first & 0x3FFF, 512] end |
Instance Method Details
#pack(options = {}) ⇒ Object
212 213 214 215 216 217 218 219 220 |
# File 'lib/faildns/domainname.rb', line 212 def pack (={}) result = '' @domain.split('.').each {|part| result += [part.length].pack('c') + part } result += [0].pack('c') end |
#to_s ⇒ Object Also known as: to_str
206 207 208 |
# File 'lib/faildns/domainname.rb', line 206 def to_s @domain end |