or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

dns-constants.mddns-exceptions.mddns-messages.mddns-names.mddns-queries.mddns-records.mddns-resolution.mddns-updates.mddns-utilities.mddns-zones.mddnssec.mdindex.mdtsig.md

dns-zones.mddocs/

0

# DNS Zones

1

2

DNS zone parsing, creation, and manipulation functionality. Provides complete zone file support including zone transfers, zone validation, and comprehensive zone data operations for authoritative DNS server implementations.

3

4

## Capabilities

5

6

### Zone Creation

7

8

Create DNS zones from text files, zone transfers, or programmatically.

9

10

```python { .api }

11

def from_text(text, origin=None, rdclass='IN', relativize=True, zone_factory=None,

12

filename=None, allow_include=False, check_origin=True):

13

"""

14

Parse a DNS zone from text format.

15

16

Args:

17

text (str): Zone file text content

18

origin (str or dns.name.Name): Zone origin (default from SOA)

19

rdclass (str or int): Record class (default 'IN')

20

relativize (bool): Make names relative to origin

21

zone_factory (class): Zone class to instantiate

22

filename (str): Filename for error reporting

23

allow_include (bool): Allow $INCLUDE directives

24

check_origin (bool): Verify zone has proper SOA and NS records

25

26

Returns:

27

dns.zone.Zone: Parsed DNS zone

28

"""

29

30

def from_file(f, origin=None, rdclass='IN', relativize=True, zone_factory=None,

31

filename=None, allow_include=True, check_origin=True):

32

"""

33

Parse a DNS zone from a file.

34

35

Args:

36

f (file-like): File object to read from

37

origin (str or dns.name.Name): Zone origin

38

rdclass (str or int): Record class

39

relativize (bool): Make names relative to origin

40

zone_factory (class): Zone class to instantiate

41

filename (str): Filename for error reporting

42

allow_include (bool): Allow $INCLUDE directives

43

check_origin (bool): Verify zone structure

44

45

Returns:

46

dns.zone.Zone: Parsed DNS zone

47

"""

48

49

def from_xfr(xfr, zone_factory=None, relativize=True, check_origin=True):

50

"""

51

Create a DNS zone from a zone transfer.

52

53

Args:

54

xfr (generator): Zone transfer message generator

55

zone_factory (class): Zone class to instantiate

56

relativize (bool): Make names relative to origin

57

check_origin (bool): Verify zone structure

58

59

Returns:

60

dns.zone.Zone: Zone created from transfer

61

"""

62

```

63

64

### Zone Class

65

66

DNS zone represented as a mapping from names to nodes containing resource record sets.

67

68

```python { .api }

69

class Zone:

70

"""

71

A DNS zone as a mapping from names to nodes.

72

73

A zone is a collection of DNS resource records with a common origin.

74

The zone is represented as a mapping from names to nodes, where each

75

node contains the resource record sets for that name.

76

77

Attributes:

78

nodes (dict): Mapping from names to nodes

79

origin (dns.name.Name): Zone origin name

80

rdclass (int): Zone record class

81

"""

82

83

def __init__(self, origin, rdclass='IN', relativize=True):

84

"""

85

Initialize a DNS zone.

86

87

Args:

88

origin (str or dns.name.Name): Zone origin

89

rdclass (str or int): Record class

90

relativize (bool): Store names relative to origin

91

"""

92

93

def __repr__(self):

94

"""Return string representation of zone."""

95

96

def __eq__(self, other):

97

"""Test zone equality."""

98

99

def __ne__(self, other):

100

"""Test zone inequality."""

101

102

def __iter__(self):

103

"""Iterate over names in zone."""

104

105

def keys(self):

106

"""Return iterator over zone names."""

107

108

def values(self):

109

"""Return iterator over zone nodes."""

110

111

def items(self):

112

"""Return iterator over (name, node) pairs."""

113

114

def __len__(self):

115

"""Return number of names in zone."""

116

117

def __getitem__(self, key):

118

"""Get node by name."""

119

120

def __setitem__(self, key, value):

121

"""Set node for name."""

122

123

def __delitem__(self, key):

124

"""Delete node by name."""

125

126

def __contains__(self, key):

127

"""Test if name exists in zone."""

128

```

129

130

### Node Operations

131

132

Find, create, and manipulate nodes within the zone.

133

134

```python { .api }

135

def find_node(name, create=False):

136

"""

137

Find a node in the zone.

138

139

Args:

140

name (str or dns.name.Name): Node name

141

create (bool): Create node if it doesn't exist

142

143

Returns:

144

dns.node.Node: Zone node

145

146

Raises:

147

KeyError: If name not found and create=False

148

"""

149

150

def get_node(name, create=False):

151

"""

152

Get a node from the zone.

153

154

Args:

155

name (str or dns.name.Name): Node name

156

create (bool): Create node if it doesn't exist

157

158

Returns:

159

dns.node.Node or None: Zone node or None if not found

160

"""

161

162

def delete_node(name):

163

"""

164

Delete a node from the zone.

165

166

Args:

167

name (str or dns.name.Name): Node name to delete

168

169

Raises:

170

KeyError: If name not found

171

"""

172

```

173

174

### RRset Operations

175

176

Find, get, and manipulate resource record sets within the zone.

177

178

```python { .api }

179

def find_rdataset(name, rdtype, covers='NONE', create=False):

180

"""

181

Find an rdataset in the zone.

182

183

Args:

184

name (str or dns.name.Name): Record name

185

rdtype (str or int): Record type

186

covers (str or int): Covered type for RRSIG records

187

create (bool): Create rdataset if not found

188

189

Returns:

190

dns.rdataset.Rdataset: Resource record set

191

"""

192

193

def get_rdataset(name, rdtype, covers='NONE', create=False):

194

"""

195

Get an rdataset from the zone.

196

197

Args:

198

name (str or dns.name.Name): Record name

199

rdtype (str or int): Record type

200

covers (str or int): Covered type for RRSIG records

201

create (bool): Create rdataset if not found

202

203

Returns:

204

dns.rdataset.Rdataset or None: Rdataset or None if not found

205

"""

206

207

def delete_rdataset(name, rdtype, covers='NONE'):

208

"""

209

Delete an rdataset from the zone.

210

211

Args:

212

name (str or dns.name.Name): Record name

213

rdtype (str or int): Record type

214

covers (str or int): Covered type for RRSIG records

215

"""

216

217

def replace_rdataset(name, replacement):

218

"""

219

Replace an rdataset in the zone.

220

221

Args:

222

name (str or dns.name.Name): Record name

223

replacement (dns.rdataset.Rdataset): Replacement rdataset

224

"""

225

```

226

227

### RRset Operations

228

229

Work with complete resource record sets including name and TTL information.

230

231

```python { .api }

232

def find_rrset(name, rdtype, covers='NONE'):

233

"""

234

Find an RRset in the zone.

235

236

Args:

237

name (str or dns.name.Name): Record name

238

rdtype (str or int): Record type

239

covers (str or int): Covered type for RRSIG records

240

241

Returns:

242

dns.rrset.RRset: Resource record set

243

"""

244

245

def get_rrset(name, rdtype, covers='NONE'):

246

"""

247

Get an RRset from the zone.

248

249

Args:

250

name (str or dns.name.Name): Record name

251

rdtype (str or int): Record type

252

covers (str or int): Covered type for RRSIG records

253

254

Returns:

255

dns.rrset.RRset or None: RRset or None if not found

256

"""

257

```

258

259

### Zone Iteration

260

261

Iterate over zone contents with filtering and processing options.

262

263

```python { .api }

264

def iterate_rdatasets(rdtype='ANY', covers='NONE'):

265

"""

266

Generate all rdatasets in the zone.

267

268

Args:

269

rdtype (str or int): Filter by record type ('ANY' for all)

270

covers (str or int): Filter by covered type for RRSIG

271

272

Yields:

273

tuple: (name, rdataset) pairs

274

"""

275

276

def iterate_rdatas(rdtype='ANY', covers='NONE'):

277

"""

278

Generate all resource records in the zone.

279

280

Args:

281

rdtype (str or int): Filter by record type ('ANY' for all)

282

covers (str or int): Filter by covered type for RRSIG

283

284

Yields:

285

tuple: (name, ttl, rdata) tuples

286

"""

287

```

288

289

### Zone Output

290

291

Convert zones to text format or write to files.

292

293

```python { .api }

294

def to_file(f, sorted=True, relativize=True, nl=None):

295

"""

296

Write zone to a file.

297

298

Args:

299

f (file-like): File to write to

300

sorted (bool): Sort records by name

301

relativize (bool): Make names relative to origin

302

nl (bytes): Line ending (default system)

303

"""

304

305

def to_text(sorted=True, relativize=True, nl=None):

306

"""

307

Convert zone to text format.

308

309

Args:

310

sorted (bool): Sort records by name

311

relativize (bool): Make names relative to origin

312

nl (str): Line ending (default system)

313

314

Returns:

315

str: Zone in text format

316

"""

317

```

318

319

### Zone Validation

320

321

Validate zone structure and check for required records.

322

323

```python { .api }

324

def check_origin():

325

"""

326

Check that the zone is properly structured.

327

328

Validates that:

329

- Zone has SOA record at origin

330

- Zone has NS records at origin

331

- SOA serial number is reasonable

332

333

Raises:

334

dns.zone.NoSOA: If no SOA at origin

335

dns.zone.NoNS: If no NS at origin

336

dns.zone.BadZone: If other structural problems

337

"""

338

```

339

340

## Usage Examples

341

342

### Loading Zone Files

343

344

```python

345

import dns.zone

346

import dns.name

347

348

# Load zone from file

349

zone = dns.zone.from_file('example.com.zone', origin='example.com.')

350

351

print(f"Zone origin: {zone.origin}")

352

print(f"Zone class: {zone.rdclass}")

353

print(f"Number of names: {len(zone)}")

354

355

# Load zone from text

356

zone_text = '''

357

$ORIGIN example.com.

358

$TTL 3600

359

@ IN SOA ns1.example.com. admin.example.com. (

360

2023010101 ; serial

361

10800 ; refresh

362

3600 ; retry

363

604800 ; expire

364

86400 ) ; minimum

365

366

IN NS ns1.example.com.

367

IN NS ns2.example.com.

368

369

www IN A 192.0.2.1

370

IN AAAA 2001:db8::1

371

mail IN A 192.0.2.2

372

'''

373

374

zone = dns.zone.from_text(zone_text)

375

```

376

377

### Zone from Transfer

378

379

```python

380

import dns.zone

381

import dns.query

382

import dns.name

383

384

# Perform zone transfer and create zone

385

zone_name = dns.name.from_text('example.com.')

386

xfr_messages = dns.query.xfr('ns1.example.com', zone_name)

387

zone = dns.zone.from_xfr(xfr_messages)

388

389

print(f"Transferred zone: {zone.origin}")

390

print(f"Zone records: {len(zone)}")

391

```

392

393

### Zone Manipulation

394

395

```python

396

import dns.zone

397

import dns.name

398

import dns.rdataset

399

import dns.rdatatype

400

import dns.rdataclass

401

import dns.rdata

402

403

# Create new zone

404

origin = dns.name.from_text('test.example.')

405

zone = dns.zone.Zone(origin)

406

407

# Add SOA record

408

soa_rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.SOA,

409

'ns1.test.example. admin.test.example. 1 3600 1800 1209600 300')

410

soa_rdataset = dns.rdataset.from_rdata(300, soa_rdata)

411

zone.replace_rdataset('@', soa_rdataset)

412

413

# Add NS records

414

ns_rdata1 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'ns1.test.example.')

415

ns_rdata2 = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.NS, 'ns2.test.example.')

416

ns_rdataset = dns.rdataset.from_rdata_list(300, [ns_rdata1, ns_rdata2])

417

zone.replace_rdataset('@', ns_rdataset)

418

419

# Add A record

420

www_name = dns.name.from_text('www', origin)

421

a_rdata = dns.rdata.from_text(dns.rdataclass.IN, dns.rdatatype.A, '192.0.2.10')

422

a_rdataset = dns.rdataset.from_rdata(300, a_rdata)

423

zone.replace_rdataset(www_name, a_rdataset)

424

```

425

426

### Zone Querying and Iteration

427

428

```python

429

import dns.zone

430

import dns.rdatatype

431

432

zone = dns.zone.from_file('example.com.zone')

433

434

# Find specific records

435

try:

436

www_a = zone.find_rdataset('www', dns.rdatatype.A)

437

print(f"www A records: {list(www_a)}")

438

except KeyError:

439

print("www A record not found")

440

441

# Get records safely

442

mx_records = zone.get_rdataset('@', dns.rdatatype.MX)

443

if mx_records:

444

print(f"MX records: {list(mx_records)}")

445

446

# Iterate over all records

447

print("All zone records:")

448

for name, rdataset in zone.iterate_rdatasets():

449

print(f"{name} {rdataset.ttl} {rdataset.rdclass} {rdataset.rdtype}")

450

for rdata in rdataset:

451

print(f" {rdata}")

452

453

# Filter by record type

454

print("Only A records:")

455

for name, rdataset in zone.iterate_rdatasets(rdtype=dns.rdatatype.A):

456

for rdata in rdataset:

457

print(f"{name} A {rdata.address}")

458

```

459

460

### Zone Validation and Output

461

462

```python

463

import dns.zone

464

465

zone = dns.zone.from_file('example.com.zone')

466

467

# Validate zone structure

468

try:

469

zone.check_origin()

470

print("Zone validation passed")

471

except dns.zone.NoSOA:

472

print("Zone missing SOA record")

473

except dns.zone.NoNS:

474

print("Zone missing NS records")

475

except dns.zone.BadZone as e:

476

print(f"Zone validation failed: {e}")

477

478

# Output zone

479

print("Zone as text:")

480

print(zone.to_text())

481

482

# Write to file

483

with open('output.zone', 'w') as f:

484

zone.to_file(f, sorted=True)

485

```

486

487

## Node Class

488

489

```python { .api }

490

class Node:

491

"""

492

A DNS node containing resource record sets.

493

494

A node represents all the resource records at a particular name

495

in a DNS zone. It contains a mapping from (rdtype, covers) tuples

496

to rdatasets.

497

"""

498

499

def __init__(self):

500

"""Initialize empty node."""

501

502

def find_rdataset(self, rdclass, rdtype, covers='NONE', create=False):

503

"""Find rdataset in node."""

504

505

def get_rdataset(self, rdclass, rdtype, covers='NONE', create=False):

506

"""Get rdataset from node."""

507

508

def delete_rdataset(self, rdclass, rdtype, covers='NONE'):

509

"""Delete rdataset from node."""

510

511

def replace_rdataset(self, replacement):

512

"""Replace rdataset in node."""

513

```

514

515

## Exceptions

516

517

```python { .api }

518

class BadZone(DNSException):

519

"""The zone is malformed."""

520

521

class NoSOA(BadZone):

522

"""The zone has no SOA RR at its origin."""

523

524

class NoNS(BadZone):

525

"""The zone has no NS RRset at its origin."""

526

527

class UnknownOrigin(DNSException):

528

"""The zone's origin is unknown."""

529

```