1
1
/*******************************************************************************
2
*Copyright (c) 2009 Eucalyptus Systems, Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, only version 3 of the License.
9
* This file is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Please contact Eucalyptus Systems, Inc., 130 Castilian
18
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
* if you need additional information or have any questions.
21
* This file may incorporate work covered under the following copyright and
24
* Software License Agreement (BSD License)
26
* Copyright (c) 2008, Regents of the University of California
27
* All rights reserved.
29
* Redistribution and use of this software in source and binary forms, with
30
* or without modification, are permitted provided that the following
33
* Redistributions of source code must retain the above copyright notice,
34
* this list of conditions and the following disclaimer.
36
* Redistributions in binary form must reproduce the above copyright
37
* notice, this list of conditions and the following disclaimer in the
38
* documentation and/or other materials provided with the distribution.
40
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
* THE REGENTSā DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
* ANY SUCH LICENSES OR RIGHTS.
60
*******************************************************************************/
2
*Copyright (c) 2009 Eucalyptus Systems, Inc.
4
* This program is free software: you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation, only version 3 of the License.
9
* This file is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* You should have received a copy of the GNU General Public License along
15
* with this program. If not, see <http://www.gnu.org/licenses/>.
17
* Please contact Eucalyptus Systems, Inc., 130 Castilian
18
* Dr., Goleta, CA 93101 USA or visit <http://www.eucalyptus.com/licenses/>
19
* if you need additional information or have any questions.
21
* This file may incorporate work covered under the following copyright and
24
* Software License Agreement (BSD License)
26
* Copyright (c) 2008, Regents of the University of California
27
* All rights reserved.
29
* Redistribution and use of this software in source and binary forms, with
30
* or without modification, are permitted provided that the following
33
* Redistributions of source code must retain the above copyright notice,
34
* this list of conditions and the following disclaimer.
36
* Redistributions in binary form must reproduce the above copyright
37
* notice, this list of conditions and the following disclaimer in the
38
* documentation and/or other materials provided with the distribution.
40
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
41
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
42
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
43
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
44
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
45
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
46
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
47
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
48
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
49
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
50
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. USERS OF
51
* THIS SOFTWARE ACKNOWLEDGE THE POSSIBLE PRESENCE OF OTHER OPEN SOURCE
52
* LICENSED MATERIAL, COPYRIGHTED MATERIAL OR PATENTED MATERIAL IN THIS
53
* SOFTWARE, AND IF ANY SUCH MATERIAL IS DISCOVERED THE PARTY DISCOVERING
54
* IT MAY INFORM DR. RICH WOLSKI AT THE UNIVERSITY OF CALIFORNIA, SANTA
55
* BARBARA WHO WILL THEN ASCERTAIN THE MOST APPROPRIATE REMEDY, WHICH IN
56
* THE REGENTSā DISCRETION MAY INCLUDE, WITHOUT LIMITATION, REPLACEMENT
57
* OF THE CODE SO IDENTIFIED, LICENSING OF THE CODE SO IDENTIFIED, OR
58
* WITHDRAWAL OF THE CODE CAPABILITY TO THE EXTENT NEEDED TO COMPLY WITH
59
* ANY SUCH LICENSES OR RIGHTS.
60
*******************************************************************************/
61
61
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
63
63
package com.eucalyptus.dns;
87
87
public class Zone {
90
public static final int PRIMARY = 1;
92
/** A secondary zone */
93
public static final int SECONDARY = 2;
97
private Object originNode;
98
private int dclass = DClass.IN;
100
private SOARecord SOA;
101
private boolean hasWild;
103
class ZoneIterator implements Iterator {
104
private Iterator zentries;
105
private RRset [] current;
107
private boolean wantLastSOA;
109
ZoneIterator(boolean axfr) {
110
zentries = data.entrySet().iterator();
112
RRset [] sets = allRRsets(originNode);
113
current = new RRset[sets.length];
114
for (int i = 0, j = 2; i < sets.length; i++) {
115
int type = sets[i].getType();
116
if (type == Type.SOA)
117
current[0] = sets[i];
118
else if (type == Type.NS)
119
current[1] = sets[i];
121
current[j++] = sets[i];
127
return (current != null || wantLastSOA);
133
throw new NoSuchElementException();
135
if (current == null && wantLastSOA) {
137
return oneRRset(originNode, Type.SOA);
139
Object set = current[count++];
140
if (count == current.length) {
142
while (zentries.hasNext()) {
143
Map.Entry entry = (Map.Entry) zentries.next();
144
if (entry.getKey().equals(origin))
146
RRset [] sets = allRRsets(entry.getValue());
147
if (sets.length == 0)
159
throw new UnsupportedOperationException();
164
validate() throws IOException {
165
originNode = exactName(origin);
166
if (originNode == null)
167
throw new IOException(origin + ": no data specified");
169
RRset rrset = oneRRset(originNode, Type.SOA);
170
if (rrset == null || rrset.size() != 1)
171
throw new IOException(origin +
172
": exactly 1 SOA must be specified");
173
Iterator it = rrset.rrs();
174
SOA = (SOARecord) it.next();
176
NS = oneRRset(originNode, Type.NS);
178
throw new IOException(origin + ": no NS set specified");
182
maybeAddRecord(Record record) throws IOException {
183
int rtype = record.getType();
184
Name name = record.getName();
186
if (rtype == Type.SOA && !name.equals(origin)) {
187
throw new IOException("SOA owner " + name +
188
" does not match zone origin " +
191
if (name.subdomain(origin))
196
* Creates a Zone from the records in the specified master file.
197
* @param zone The name of the zone.
198
* @param file The master file to read from.
202
Zone(Name zone, String file) throws IOException {
203
data = new HashMap();
206
throw new IllegalArgumentException("no zone name specified");
207
Master m = new Master(file, zone);
211
while ((record = m.nextRecord()) != null)
212
maybeAddRecord(record);
217
* Creates a Zone from an array of records.
218
* @param zone The name of the zone.
219
* @param records The records to add to the zone.
223
Zone(Name zone, Record [] records) throws IOException {
224
data = new HashMap();
227
throw new IllegalArgumentException("no zone name specified");
229
for (int i = 0; i < records.length; i++)
230
maybeAddRecord(records[i]);
235
fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
236
data = new HashMap();
238
origin = xfrin.getName();
239
List records = xfrin.run();
240
for (Iterator it = records.iterator(); it.hasNext(); ) {
241
Record record = (Record) it.next();
242
maybeAddRecord(record);
245
throw new IllegalArgumentException("zones can only be " +
246
"created from AXFRs");
251
* Creates a Zone by doing the specified zone transfer.
252
* @param xfrin The incoming zone transfer to execute.
253
* @see ZoneTransferIn
256
Zone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
261
* Creates a Zone by performing a zone transfer to the specified host.
262
* @see ZoneTransferIn
265
Zone(Name zone, int dclass, String remote)
266
throws IOException, ZoneTransferException
268
ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(zone, remote, null);
269
xfrin.setDClass(dclass);
273
/** Returns the Zone's origin */
279
/** Returns the Zone origin's NS records */
285
/** Returns the Zone's SOA record */
291
/** Returns the Zone's class */
297
private synchronized Object
298
exactName(Name name) {
299
return data.get(name);
302
private synchronized RRset []
303
allRRsets(Object types) {
304
if (types instanceof List) {
305
List typelist = (List) types;
306
return (RRset []) typelist.toArray(new RRset[typelist.size()]);
308
RRset set = (RRset) types;
309
return new RRset [] {set};
313
private synchronized RRset
314
oneRRset(Object types, int type) {
315
if (type == Type.ANY)
316
throw new IllegalArgumentException("oneRRset(ANY)");
317
if (types instanceof List) {
318
List list = (List) types;
319
for (int i = 0; i < list.size(); i++) {
320
RRset set = (RRset) list.get(i);
90
public static final int PRIMARY = 1;
92
/** A secondary zone */
93
public static final int SECONDARY = 2;
97
private Object originNode;
98
private int dclass = DClass.IN;
100
private SOARecord SOA;
101
private boolean hasWild;
103
class ZoneIterator implements Iterator {
104
private Iterator zentries;
105
private RRset [] current;
107
private boolean wantLastSOA;
109
ZoneIterator(boolean axfr) {
110
zentries = data.entrySet().iterator();
112
RRset [] sets = allRRsets(originNode);
113
current = new RRset[sets.length];
114
for (int i = 0, j = 2; i < sets.length; i++) {
115
int type = sets[i].getType();
116
if (type == Type.SOA)
117
current[0] = sets[i];
118
else if (type == Type.NS)
119
current[1] = sets[i];
121
current[j++] = sets[i];
127
return (current != null || wantLastSOA);
133
throw new NoSuchElementException();
135
if (current == null && wantLastSOA) {
137
return oneRRset(originNode, Type.SOA);
139
if(current != null) {
140
Object set = current[count++];
141
if (count == current.length) {
143
while (zentries.hasNext()) {
144
Map.Entry entry = (Map.Entry) zentries.next();
145
if (entry.getKey().equals(origin))
147
RRset [] sets = allRRsets(entry.getValue());
148
if (sets.length == 0)
162
throw new UnsupportedOperationException();
167
validate() throws IOException {
168
originNode = exactName(origin);
169
if (originNode == null)
170
throw new IOException(origin + ": no data specified");
172
RRset rrset = oneRRset(originNode, Type.SOA);
173
if (rrset == null || rrset.size() != 1)
174
throw new IOException(origin +
175
": exactly 1 SOA must be specified");
176
Iterator it = rrset.rrs();
177
SOA = (SOARecord) it.next();
179
NS = oneRRset(originNode, Type.NS);
181
throw new IOException(origin + ": no NS set specified");
185
maybeAddRecord(Record record) throws IOException {
186
int rtype = record.getType();
187
Name name = record.getName();
189
if (rtype == Type.SOA && !name.equals(origin)) {
190
throw new IOException("SOA owner " + name +
191
" does not match zone origin " +
194
if (name.subdomain(origin))
199
* Creates a Zone from the records in the specified master file.
200
* @param zone The name of the zone.
201
* @param file The master file to read from.
205
Zone(Name zone, String file) throws IOException {
206
data = new HashMap();
209
throw new IllegalArgumentException("no zone name specified");
210
Master m = new Master(file, zone);
214
while ((record = m.nextRecord()) != null)
215
maybeAddRecord(record);
220
* Creates a Zone from an array of records.
221
* @param zone The name of the zone.
222
* @param records The records to add to the zone.
226
Zone(Name zone, Record [] records) throws IOException {
227
data = new HashMap();
230
throw new IllegalArgumentException("no zone name specified");
232
for (int i = 0; i < records.length; i++)
233
maybeAddRecord(records[i]);
238
fromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
239
data = new HashMap();
241
origin = xfrin.getName();
242
List records = xfrin.run();
243
for (Iterator it = records.iterator(); it.hasNext(); ) {
244
Record record = (Record) it.next();
245
maybeAddRecord(record);
248
throw new IllegalArgumentException("zones can only be " +
249
"created from AXFRs");
254
* Creates a Zone by doing the specified zone transfer.
255
* @param xfrin The incoming zone transfer to execute.
256
* @see ZoneTransferIn
259
Zone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
264
* Creates a Zone by performing a zone transfer to the specified host.
265
* @see ZoneTransferIn
268
Zone(Name zone, int dclass, String remote)
269
throws IOException, ZoneTransferException
271
ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(zone, remote, null);
272
xfrin.setDClass(dclass);
276
/** Returns the Zone's origin */
282
/** Returns the Zone origin's NS records */
288
/** Returns the Zone's SOA record */
294
/** Returns the Zone's class */
300
private synchronized Object
301
exactName(Name name) {
302
return data.get(name);
305
private synchronized RRset []
306
allRRsets(Object types) {
307
if (types instanceof List) {
308
List typelist = (List) types;
309
return (RRset []) typelist.toArray(new RRset[typelist.size()]);
311
RRset set = (RRset) types;
312
return new RRset [] {set};
316
private synchronized RRset
317
oneRRset(Object types, int type) {
318
if (type == Type.ANY)
319
throw new IllegalArgumentException("oneRRset(ANY)");
320
if (types instanceof List) {
321
List list = (List) types;
322
for (int i = 0; i < list.size(); i++) {
323
RRset set = (RRset) list.get(i);
324
if (set.getType() == type)
328
RRset set = (RRset) types;
321
329
if (set.getType() == type)
325
RRset set = (RRset) types;
326
if (set.getType() == type)
332
private synchronized RRset
333
findRRset(Name name, int type) {
334
Object types = exactName(name);
337
return oneRRset(types, type);
340
private synchronized void
341
addRRset(Name name, RRset rrset) {
342
if (!hasWild && name.isWild())
344
Object types = data.get(name);
346
data.put(name, rrset);
349
int rtype = rrset.getType();
350
if (types instanceof List) {
351
List list = (List) types;
352
for (int i = 0; i < list.size(); i++) {
353
RRset set = (RRset) list.get(i);
354
if (set.getType() == rtype) {
361
RRset set = (RRset) types;
362
if (set.getType() == rtype)
335
private synchronized RRset
336
findRRset(Name name, int type) {
337
Object types = exactName(name);
340
return oneRRset(types, type);
343
private synchronized void
344
addRRset(Name name, RRset rrset) {
345
if (!hasWild && name.isWild())
347
Object types = data.get(name);
363
349
data.put(name, rrset);
365
LinkedList list = new LinkedList();
352
int rtype = rrset.getType();
353
if (types instanceof List) {
354
List list = (List) types;
355
for (int i = 0; i < list.size(); i++) {
356
RRset set = (RRset) list.get(i);
357
if (set.getType() == rtype) {
368
data.put(name, list);
364
RRset set = (RRset) types;
365
if (set.getType() == rtype)
366
data.put(name, rrset);
368
LinkedList list = new LinkedList();
371
data.put(name, list);
373
private synchronized void
374
removeRRset(Name name, int type) {
375
Object types = data.get(name);
379
if (types instanceof List) {
380
List list = (List) types;
381
for (int i = 0; i < list.size(); i++) {
382
RRset set = (RRset) list.get(i);
383
if (set.getType() == type) {
385
if (list.size() == 0)
376
private synchronized void
377
removeRRset(Name name, int type) {
378
Object types = data.get(name);
382
if (types instanceof List) {
383
List list = (List) types;
384
for (int i = 0; i < list.size(); i++) {
385
RRset set = (RRset) list.get(i);
386
if (set.getType() == type) {
388
if (list.size() == 0)
394
RRset set = (RRset) types;
395
if (set.getType() != type)
391
RRset set = (RRset) types;
392
if (set.getType() != type)
398
private synchronized SetResponse
399
lookup(Name name, int type) {
408
if (!name.subdomain(origin))
409
return SetResponse.ofType(SetResponse.NXDOMAIN);
411
labels = name.labels();
412
olabels = origin.labels();
414
for (tlabels = olabels; tlabels <= labels; tlabels++) {
415
boolean isOrigin = (tlabels == olabels);
416
boolean isExact = (tlabels == labels);
423
tname = new Name(name, labels - tlabels);
425
types = exactName(tname);
429
/* If this is a delegation, return that. */
431
RRset ns = oneRRset(types, Type.NS);
433
return new SetResponse(SetResponse.DELEGATION,
437
/* If this is an ANY lookup, return everything. */
438
if (isExact && type == Type.ANY) {
439
sr = new SetResponse(SetResponse.SUCCESSFUL);
440
RRset [] sets = allRRsets(types);
441
for (int i = 0; i < sets.length; i++)
442
sr.addRRset(sets[i]);
447
* If this is the name, look for the actual type or a CNAME.
448
* Otherwise, look for a DNAME.
451
rrset = oneRRset(types, type);
453
sr = new SetResponse(SetResponse.SUCCESSFUL);
457
rrset = oneRRset(types, Type.CNAME);
459
return new SetResponse(SetResponse.CNAME,
462
rrset = oneRRset(types, Type.DNAME);
464
return new SetResponse(SetResponse.DNAME,
468
/* We found the name, but not the type. */
470
return SetResponse.ofType(SetResponse.NXRRSET);
474
for (int i = 0; i < labels - olabels; i++) {
475
tname = name.wild(i + 1);
401
private synchronized SetResponse
402
lookup(Name name, int type) {
411
if (!name.subdomain(origin))
412
return SetResponse.ofType(SetResponse.NXDOMAIN);
414
labels = name.labels();
415
olabels = origin.labels();
417
for (tlabels = olabels; tlabels <= labels; tlabels++) {
418
boolean isOrigin = (tlabels == olabels);
419
boolean isExact = (tlabels == labels);
426
tname = new Name(name, labels - tlabels);
477
428
types = exactName(tname);
478
429
if (types == null)
481
rrset = oneRRset(types, type);
432
/* If this is a delegation, return that. */
434
RRset ns = oneRRset(types, Type.NS);
436
return new SetResponse(SetResponse.DELEGATION,
440
/* If this is an ANY lookup, return everything. */
441
if (isExact && type == Type.ANY) {
483
442
sr = new SetResponse(SetResponse.SUCCESSFUL);
443
RRset [] sets = allRRsets(types);
444
for (int i = 0; i < sets.length; i++)
445
sr.addRRset(sets[i]);
490
return SetResponse.ofType(SetResponse.NXDOMAIN);
494
* Looks up Records in the Zone. This follows CNAMEs and wildcards.
495
* @param name The name to look up
496
* @param type The type to look up
497
* @return A SetResponse object
501
findRecords(Name name, int type) {
502
return lookup(name, type);
506
* Looks up Records in the zone, finding exact matches only.
507
* @param name The name to look up
508
* @param type The type to look up
509
* @return The matching RRset
513
findExactMatch(Name name, int type) {
514
Object types = exactName(name);
517
return oneRRset(types, type);
521
* Adds an RRset to the Zone
522
* @param rrset The RRset to be added
526
addRRset(RRset rrset) {
527
Name name = rrset.getName();
528
addRRset(name, rrset);
532
* Adds a Record to the Zone
533
* @param r The record to be added
537
addRecord(Record r) {
538
Name name = r.getName();
539
int rtype = r.getRRsetType();
540
synchronized (this) {
541
RRset rrset = findRRset(name, rtype);
543
rrset = new RRset(r);
544
addRRset(name, rrset);
552
* Removes a record from the Zone
553
* @param r The record to be removed
557
removeRecord(Record r) {
558
Name name = r.getName();
559
int rtype = r.getRRsetType();
560
synchronized (this) {
561
RRset rrset = findRRset(name, rtype);
564
if (rrset.size() == 1 && rrset.first().equals(r))
565
removeRRset(name, rtype);
572
* Returns an Iterator over the RRsets in the zone.
576
return new ZoneIterator(false);
580
* Returns an Iterator over the RRsets in the zone that can be used to
581
* construct an AXFR response. This is identical to {@link #iterator} except
582
* that the SOA is returned at the end as well as the beginning.
586
return new ZoneIterator(true);
590
nodeToString(StringBuffer sb, Object node) {
591
RRset [] sets = allRRsets(node);
592
for (int i = 0; i < sets.length; i++) {
593
RRset rrset = sets[i];
594
Iterator it = rrset.rrs();
596
sb.append(it.next() + "\n");
599
sb.append(it.next() + "\n");
604
* Returns the contents of the Zone in master file format.
608
Iterator zentries = data.entrySet().iterator();
609
StringBuffer sb = new StringBuffer();
610
nodeToString(sb, originNode);
611
while (zentries.hasNext()) {
612
Map.Entry entry = (Map.Entry) zentries.next();
613
if (!origin.equals(entry.getKey()))
614
nodeToString(sb, entry.getValue());
616
return sb.toString();
620
* Returns the contents of the Zone as a string (in master file format).
624
return toMasterFile();
450
* If this is the name, look for the actual type or a CNAME.
451
* Otherwise, look for a DNAME.
454
rrset = oneRRset(types, type);
456
sr = new SetResponse(SetResponse.SUCCESSFUL);
460
rrset = oneRRset(types, Type.CNAME);
462
return new SetResponse(SetResponse.CNAME,
465
rrset = oneRRset(types, Type.DNAME);
467
return new SetResponse(SetResponse.DNAME,
471
/* We found the name, but not the type. */
473
return SetResponse.ofType(SetResponse.NXRRSET);
477
for (int i = 0; i < labels - olabels; i++) {
478
tname = name.wild(i + 1);
480
types = exactName(tname);
484
rrset = oneRRset(types, type);
486
sr = new SetResponse(SetResponse.SUCCESSFUL);
493
return SetResponse.ofType(SetResponse.NXDOMAIN);
497
* Looks up Records in the Zone. This follows CNAMEs and wildcards.
498
* @param name The name to look up
499
* @param type The type to look up
500
* @return A SetResponse object
504
findRecords(Name name, int type) {
505
return lookup(name, type);
509
* Looks up Records in the zone, finding exact matches only.
510
* @param name The name to look up
511
* @param type The type to look up
512
* @return The matching RRset
516
findExactMatch(Name name, int type) {
517
Object types = exactName(name);
520
return oneRRset(types, type);
524
* Adds an RRset to the Zone
525
* @param rrset The RRset to be added
529
addRRset(RRset rrset) {
530
Name name = rrset.getName();
531
addRRset(name, rrset);
535
* Adds a Record to the Zone
536
* @param r The record to be added
540
addRecord(Record r) {
541
Name name = r.getName();
542
int rtype = r.getRRsetType();
543
synchronized (this) {
544
RRset rrset = findRRset(name, rtype);
546
rrset = new RRset(r);
547
addRRset(name, rrset);
555
* Removes a record from the Zone
556
* @param r The record to be removed
560
removeRecord(Record r) {
561
Name name = r.getName();
562
int rtype = r.getRRsetType();
563
synchronized (this) {
564
RRset rrset = findRRset(name, rtype);
567
if (rrset.size() == 1 && rrset.first().equals(r))
568
removeRRset(name, rtype);
575
* Returns an Iterator over the RRsets in the zone.
579
return new ZoneIterator(false);
583
* Returns an Iterator over the RRsets in the zone that can be used to
584
* construct an AXFR response. This is identical to {@link #iterator} except
585
* that the SOA is returned at the end as well as the beginning.
589
return new ZoneIterator(true);
593
nodeToString(StringBuffer sb, Object node) {
594
RRset [] sets = allRRsets(node);
595
for (int i = 0; i < sets.length; i++) {
596
RRset rrset = sets[i];
597
Iterator it = rrset.rrs();
599
sb.append(it.next() + "\n");
602
sb.append(it.next() + "\n");
607
* Returns the contents of the Zone in master file format.
611
Iterator zentries = data.entrySet().iterator();
612
StringBuffer sb = new StringBuffer();
613
nodeToString(sb, originNode);
614
while (zentries.hasNext()) {
615
Map.Entry entry = (Map.Entry) zentries.next();
616
if (!origin.equals(entry.getKey()))
617
nodeToString(sb, entry.getValue());
619
return sb.toString();
623
* Returns the contents of the Zone as a string (in master file format).
627
return toMasterFile();