0
# DNS Names
1
2
DNS name parsing, manipulation, and formatting functionality with full internationalization support. Handles absolute and relative names, wildcards, IDNA encoding, and all DNS name operations including comparison, concatenation, and canonicalization.
3
4
## Capabilities
5
6
### Name Creation
7
8
Parse DNS names from various formats including text, Unicode, and wire format.
9
10
```python { .api }
11
def from_text(text, origin=None, idna_codec=None):
12
"""
13
Parse a DNS name from text format.
14
15
Args:
16
text (str): Text representation of DNS name
17
origin (dns.name.Name): Origin for relative names
18
idna_codec (dns.name.IDNACodec): IDNA codec for internationalization
19
20
Returns:
21
dns.name.Name: Parsed DNS name
22
"""
23
24
def from_unicode(text, origin=None, idna_codec=None):
25
"""
26
Parse a DNS name from Unicode text.
27
28
Args:
29
text (str): Unicode representation of DNS name
30
origin (dns.name.Name): Origin for relative names
31
idna_codec (dns.name.IDNACodec): IDNA codec
32
33
Returns:
34
dns.name.Name: Parsed DNS name
35
"""
36
37
def from_wire(message, current):
38
"""
39
Parse a DNS name from wire format.
40
41
Args:
42
message (bytes): Wire format message
43
current (int): Current position in message
44
45
Returns:
46
tuple: (dns.name.Name, int) - name and new position
47
"""
48
```
49
50
### Name Class
51
52
Immutable DNS name represented as a tuple of labels with comprehensive manipulation methods.
53
54
```python { .api }
55
class Name:
56
"""
57
An immutable DNS name as a tuple of labels.
58
59
A Name is an ordered sequence of labels. Names can be absolute
60
(ending with the root label) or relative.
61
"""
62
63
def __init__(self, labels):
64
"""
65
Initialize a Name from a sequence of labels.
66
67
Args:
68
labels (iterable): Sequence of label strings
69
"""
70
71
def __str__(self):
72
"""Return text representation of name."""
73
74
def __repr__(self):
75
"""Return detailed string representation."""
76
77
def __hash__(self):
78
"""Return hash of name."""
79
80
def __len__(self):
81
"""Return number of labels in name."""
82
83
def __getitem__(self, index):
84
"""Get label by index."""
85
86
def __add__(self, other):
87
"""Concatenate names."""
88
89
def __eq__(self, other):
90
"""Test name equality."""
91
92
def __ne__(self, other):
93
"""Test name inequality."""
94
95
def __lt__(self, other):
96
"""Compare names for sorting."""
97
98
def __le__(self, other):
99
"""Compare names for sorting."""
100
101
def __gt__(self, other):
102
"""Compare names for sorting."""
103
104
def __ge__(self, other):
105
"""Compare names for sorting."""
106
```
107
108
### Name Formatting
109
110
Convert names to various output formats including text, Unicode, and wire format.
111
112
```python { .api }
113
def to_text(omit_final_dot=False):
114
"""
115
Convert name to text format.
116
117
Args:
118
omit_final_dot (bool): Omit trailing dot for absolute names
119
120
Returns:
121
str: Text representation of name
122
"""
123
124
def to_unicode(omit_final_dot=False, idna_codec=None):
125
"""
126
Convert name to Unicode text format.
127
128
Args:
129
omit_final_dot (bool): Omit trailing dot for absolute names
130
idna_codec (dns.name.IDNACodec): IDNA codec for decoding
131
132
Returns:
133
str: Unicode representation of name
134
"""
135
136
def to_wire(file=None, compress=None, origin=None):
137
"""
138
Convert name to wire format.
139
140
Args:
141
file (file-like): File to write to (None returns bytes)
142
compress (dict): Compression map for name compression
143
origin (dns.name.Name): Origin for relative names
144
145
Returns:
146
bytes or None: Wire format bytes or None if file specified
147
"""
148
149
def to_digestable(origin=None):
150
"""
151
Convert name to format suitable for cryptographic hashing.
152
153
Args:
154
origin (dns.name.Name): Origin for relative names
155
156
Returns:
157
bytes: Canonical wire format for hashing
158
"""
159
```
160
161
### Name Properties and Tests
162
163
Test name properties and relationships.
164
165
```python { .api }
166
def is_absolute():
167
"""
168
Check if name is absolute (ends with root label).
169
170
Returns:
171
bool: True if name is absolute
172
"""
173
174
def is_wild():
175
"""
176
Check if name is a wildcard (starts with '*' label).
177
178
Returns:
179
bool: True if name is wildcard
180
"""
181
182
def is_subdomain(other):
183
"""
184
Check if this name is a subdomain of another name.
185
186
Args:
187
other (dns.name.Name): Potential parent domain
188
189
Returns:
190
bool: True if this name is subdomain of other
191
"""
192
193
def is_superdomain(other):
194
"""
195
Check if this name is a superdomain of another name.
196
197
Args:
198
other (dns.name.Name): Potential subdomain
199
200
Returns:
201
bool: True if this name is superdomain of other
202
"""
203
```
204
205
### Name Manipulation
206
207
Manipulate names through concatenation, relativization, and hierarchy operations.
208
209
```python { .api }
210
def concatenate(other):
211
"""
212
Concatenate this name with another name.
213
214
Args:
215
other (dns.name.Name): Name to append
216
217
Returns:
218
dns.name.Name: Concatenated name
219
"""
220
221
def relativize(origin):
222
"""
223
Make this name relative to the specified origin.
224
225
Args:
226
origin (dns.name.Name): Origin name
227
228
Returns:
229
dns.name.Name: Relativized name
230
"""
231
232
def derelativize(origin):
233
"""
234
Make this name absolute using the specified origin.
235
236
Args:
237
origin (dns.name.Name): Origin name
238
239
Returns:
240
dns.name.Name: Absolute name
241
"""
242
243
def parent():
244
"""
245
Get the parent domain of this name.
246
247
Returns:
248
dns.name.Name: Parent domain
249
250
Raises:
251
dns.name.NoParent: If name has no parent (root or empty)
252
"""
253
254
def split(depth):
255
"""
256
Split name into prefix and suffix at specified depth.
257
258
Args:
259
depth (int): Split depth from right
260
261
Returns:
262
tuple: (prefix, suffix) as Name objects
263
"""
264
```
265
266
### Name Comparison and Canonicalization
267
268
Advanced name comparison and DNSSEC canonical form operations.
269
270
```python { .api }
271
def canonicalize():
272
"""
273
Convert name to DNSSEC canonical form (lowercase).
274
275
Returns:
276
dns.name.Name: Canonicalized name
277
"""
278
279
def fullcompare(other):
280
"""
281
Perform full comparison with relationship information.
282
283
Args:
284
other (dns.name.Name): Name to compare with
285
286
Returns:
287
tuple: (order, labels_in_common, relationship)
288
order: -1, 0, or 1 for less than, equal, greater than
289
labels_in_common: number of common labels from right
290
relationship: NAMERELN_* constant
291
"""
292
```
293
294
## Usage Examples
295
296
### Basic Name Operations
297
298
```python
299
import dns.name
300
301
# Create names from text
302
name1 = dns.name.from_text('www.example.com.') # Absolute
303
name2 = dns.name.from_text('www.example.com') # Relative
304
name3 = dns.name.from_text('sub', dns.name.from_text('example.com.'))
305
306
print(f"Name 1: {name1}")
307
print(f"Is absolute: {name1.is_absolute()}")
308
print(f"Labels: {list(name1.labels)}")
309
310
# Name comparison
311
print(f"Equal: {name1 == name2.derelativize(dns.name.root)}")
312
print(f"Is subdomain: {name1.is_subdomain(dns.name.from_text('example.com.'))}")
313
```
314
315
### Name Hierarchy Operations
316
317
```python
318
import dns.name
319
320
# Work with name hierarchy
321
fqdn = dns.name.from_text('mail.server.example.com.')
322
parent = fqdn.parent()
323
grandparent = parent.parent()
324
325
print(f"FQDN: {fqdn}")
326
print(f"Parent: {parent}")
327
print(f"Grandparent: {grandparent}")
328
329
# Split names
330
prefix, suffix = fqdn.split(2)
331
print(f"Prefix: {prefix}") # mail.server
332
print(f"Suffix: {suffix}") # example.com.
333
334
# Name concatenation
335
host = dns.name.from_text('www')
336
domain = dns.name.from_text('example.com.')
337
full_name = host.concatenate(domain)
338
print(f"Full name: {full_name}")
339
```
340
341
### Internationalized Domain Names
342
343
```python
344
import dns.name
345
346
# Handle Unicode domain names
347
unicode_name = 'тест.example.com'
348
name = dns.name.from_unicode(unicode_name)
349
350
print(f"Unicode input: {unicode_name}")
351
print(f"ASCII representation: {name.to_text()}")
352
print(f"Back to Unicode: {name.to_unicode()}")
353
354
# Specify IDNA codec
355
name_2008 = dns.name.from_unicode(unicode_name, idna_codec=dns.name.IDNA_2008)
356
name_2003 = dns.name.from_unicode(unicode_name, idna_codec=dns.name.IDNA_2003)
357
```
358
359
### Wildcard and Special Names
360
361
```python
362
import dns.name
363
364
# Wildcard names
365
wildcard = dns.name.from_text('*.example.com.')
366
print(f"Is wildcard: {wildcard.is_wild()}")
367
368
# Special names
369
root_name = dns.name.root
370
empty_name = dns.name.empty
371
372
print(f"Root name: '{root_name}'")
373
print(f"Empty name: '{empty_name}'")
374
print(f"Root is absolute: {root_name.is_absolute()}")
375
```
376
377
### Wire Format and Canonicalization
378
379
```python
380
import dns.name
381
382
name = dns.name.from_text('Example.COM.')
383
384
# Convert to wire format
385
wire_data = name.to_wire()
386
print(f"Wire format length: {len(wire_data)} bytes")
387
388
# Parse from wire format
389
parsed_name, pos = dns.name.from_wire(wire_data, 0)
390
print(f"Parsed name: {parsed_name}")
391
392
# Canonicalization for DNSSEC
393
canonical = name.canonicalize()
394
print(f"Original: {name}")
395
print(f"Canonical: {canonical}")
396
397
# Digestable format for hashing
398
digest_format = name.to_digestable()
399
print(f"Digest length: {len(digest_format)} bytes")
400
```
401
402
## Constants and Special Names
403
404
```python { .api }
405
# Special name instances
406
root = Name(()) # The root name '.'
407
empty = Name(()) # The empty name
408
409
# Name relationship constants
410
NAMERELN_NONE = 0 # No relationship
411
NAMERELN_SUPERDOMAIN = 1 # First is superdomain of second
412
NAMERELN_SUBDOMAIN = 2 # First is subdomain of second
413
NAMERELN_EQUAL = 3 # Names are equal
414
NAMERELN_COMMONANCESTOR = 4 # Names have common ancestor
415
416
# IDNA codecs
417
IDNA_2003 = ... # IDNA 2003 codec
418
IDNA_2008 = ... # IDNA 2008 codec
419
```
420
421
## Exceptions
422
423
```python { .api }
424
class EmptyLabel(DNSException):
425
"""A DNS label is empty."""
426
427
class BadEscape(DNSException):
428
"""An invalid escape sequence was encountered."""
429
430
class BadPointer(DNSException):
431
"""A compression pointer points forward instead of backward."""
432
433
class BadLabelType(DNSException):
434
"""An unknown label type was encountered."""
435
436
class NeedAbsoluteNameOrOrigin(DNSException):
437
"""An absolute name or origin is required."""
438
439
class NameTooLong(DNSException):
440
"""A DNS name is longer than 255 octets."""
441
442
class LabelTooLong(DNSException):
443
"""A DNS label is longer than 63 octets."""
444
445
class AbsoluteConcatenation(DNSException):
446
"""An attempt was made to append to an absolute name."""
447
448
class NoParent(DNSException):
449
"""An attempt was made to get the parent of the root or empty name."""
450
451
class NoIDNA2008(DNSException):
452
"""IDNA 2008 processing is not available."""
453
454
class IDNAException(DNSException):
455
"""IDNA processing raised an exception."""
456
```