97
97
public class Cache {
99
private interface Element {
100
public boolean expired();
101
public int compareCredibility(int cred);
102
public int getType();
106
limitExpire(long ttl, long maxttl) {
107
if (maxttl >= 0 && maxttl < ttl)
109
int expire = (int)((System.currentTimeMillis() / 1000) + ttl);
110
if (expire < 0 || expire > Integer.MAX_VALUE)
111
return Integer.MAX_VALUE;
115
private static class CacheRRset extends RRset implements Element {
120
CacheRRset(Record rec, int cred, long maxttl) {
122
this.credibility = cred;
123
this.expire = limitExpire(rec.getTTL(), maxttl);
128
CacheRRset(RRset rrset, int cred, long maxttl) {
130
this.credibility = cred;
131
this.expire = limitExpire(rrset.getTTL(), maxttl);
136
int now = (int)(System.currentTimeMillis() / 1000);
137
return (now >= expire);
141
compareCredibility(int cred) {
142
return credibility - cred;
147
StringBuffer sb = new StringBuffer();
148
sb.append(super.toString());
150
sb.append(credibility);
151
return sb.toString();
155
private static class NegativeElement implements Element {
163
NegativeElement(Name name, int type, SOARecord soa, int cred,
171
cttl = soa.getMinimum();
172
this.credibility = cred;
173
this.expire = limitExpire(cttl, maxttl);
183
int now = (int)(System.currentTimeMillis() / 1000);
184
return (now >= expire);
188
compareCredibility(int cred) {
189
return credibility - cred;
194
StringBuffer sb = new StringBuffer();
196
sb.append("NXDOMAIN " + name);
198
sb.append("NXRRSET " + name + " " + Type.string(type));
200
sb.append(credibility);
201
return sb.toString();
205
private static class CacheMap extends LinkedHashMap {
206
private int maxsize = -1;
208
CacheMap(int maxsize) {
209
super(16, (float) 0.75, true);
210
this.maxsize = maxsize;
219
setMaxSize(int maxsize) {
221
* Note that this doesn't shrink the size of the map if
222
* the maximum size is lowered, but it should shrink as
225
this.maxsize = maxsize;
228
protected boolean removeEldestEntry(Map.Entry eldest) {
229
return maxsize >= 0 && size() > maxsize;
233
private CacheMap data;
234
private int maxncache = -1;
235
private int maxcache = -1;
238
private static final int defaultMaxEntries = 50000;
241
* Creates an empty Cache
243
* @param dclass The DNS class of this cache
248
this.dclass = dclass;
249
data = new CacheMap(defaultMaxEntries);
253
* Creates an empty Cache for class IN.
262
* Creates a Cache which initially contains all records in the specified file.
265
Cache(String file) throws IOException {
266
data = new CacheMap(defaultMaxEntries);
267
Master m = new Master(file);
269
while ((record = m.nextRecord()) != null)
270
addRecord(record, Credibility.HINT, m);
273
private synchronized Object
274
exactName(Name name) {
275
return data.get(name);
278
private synchronized void
279
removeName(Name name) {
283
private synchronized Element []
284
allElements(Object types) {
285
if (types instanceof List) {
286
List typelist = (List) types;
287
int size = typelist.size();
288
return (Element []) typelist.toArray(new Element[size]);
290
Element set = (Element) types;
291
return new Element[] {set};
295
private synchronized Element
296
oneElement(Name name, Object types, int type, int minCred) {
297
Element found = null;
299
if (type == Type.ANY)
300
throw new IllegalArgumentException("oneElement(ANY)");
301
if (types instanceof List) {
302
List list = (List) types;
303
for (int i = 0; i < list.size(); i++) {
304
Element set = (Element) list.get(i);
305
if (set.getType() == type) {
99
private interface Element {
100
public boolean expired();
101
public int compareCredibility(int cred);
102
public int getType();
106
limitExpire(long ttl, long maxttl) {
107
if (maxttl >= 0 && maxttl < ttl)
109
int expire = (int)((System.currentTimeMillis() / 1000) + ttl);
110
if (expire < 0 || expire > Integer.MAX_VALUE)
111
return Integer.MAX_VALUE;
115
private static class CacheRRset extends RRset implements Element {
120
CacheRRset(Record rec, int cred, long maxttl) {
122
this.credibility = cred;
123
this.expire = limitExpire(rec.getTTL(), maxttl);
128
CacheRRset(RRset rrset, int cred, long maxttl) {
130
this.credibility = cred;
131
this.expire = limitExpire(rrset.getTTL(), maxttl);
136
int now = (int)(System.currentTimeMillis() / 1000);
137
return (now >= expire);
141
compareCredibility(int cred) {
142
return credibility - cred;
147
StringBuffer sb = new StringBuffer();
148
sb.append(super.toString());
150
sb.append(credibility);
151
return sb.toString();
155
private static class NegativeElement implements Element {
163
NegativeElement(Name name, int type, SOARecord soa, int cred,
171
cttl = soa.getMinimum();
172
this.credibility = cred;
173
this.expire = limitExpire(cttl, maxttl);
183
int now = (int)(System.currentTimeMillis() / 1000);
184
return (now >= expire);
188
compareCredibility(int cred) {
189
return credibility - cred;
194
StringBuffer sb = new StringBuffer();
196
sb.append("NXDOMAIN " + name);
198
sb.append("NXRRSET " + name + " " + Type.string(type));
200
sb.append(credibility);
201
return sb.toString();
205
private static class CacheMap extends LinkedHashMap {
206
private int maxsize = -1;
208
CacheMap(int maxsize) {
209
super(16, (float) 0.75, true);
210
this.maxsize = maxsize;
219
setMaxSize(int maxsize) {
221
* Note that this doesn't shrink the size of the map if
222
* the maximum size is lowered, but it should shrink as
225
this.maxsize = maxsize;
228
protected boolean removeEldestEntry(Map.Entry eldest) {
229
return maxsize >= 0 && size() > maxsize;
233
private CacheMap data;
234
private int maxncache = -1;
235
private int maxcache = -1;
238
private static final int defaultMaxEntries = 50000;
241
* Creates an empty Cache
243
* @param dclass The DNS class of this cache
248
this.dclass = dclass;
249
data = new CacheMap(defaultMaxEntries);
253
* Creates an empty Cache for class IN.
262
* Creates a Cache which initially contains all records in the specified file.
265
Cache(String file) throws IOException {
266
data = new CacheMap(defaultMaxEntries);
267
Master m = new Master(file);
269
while ((record = m.nextRecord()) != null)
270
addRecord(record, Credibility.HINT, m);
273
private synchronized Object
274
exactName(Name name) {
275
return data.get(name);
278
private synchronized void
279
removeName(Name name) {
283
private synchronized Element []
284
allElements(Object types) {
285
if (types instanceof List) {
286
List typelist = (List) types;
287
int size = typelist.size();
288
return (Element []) typelist.toArray(new Element[size]);
290
Element set = (Element) types;
291
return new Element[] {set};
295
private synchronized Element
296
oneElement(Name name, Object types, int type, int minCred) {
297
Element found = null;
299
if (type == Type.ANY)
300
throw new IllegalArgumentException("oneElement(ANY)");
301
if (types instanceof List) {
302
List list = (List) types;
303
for (int i = 0; i < list.size(); i++) {
304
Element set = (Element) list.get(i);
305
if (set.getType() == type) {
311
Element set = (Element) types;
312
if (set.getType() == type)
311
Element set = (Element) types;
312
if (set.getType() == type)
317
if (found.expired()) {
318
removeElement(name, type);
321
if (found.compareCredibility(minCred) < 0)
326
private synchronized Element
327
findElement(Name name, int type, int minCred) {
328
Object types = exactName(name);
331
return oneElement(name, types, type, minCred);
334
private synchronized void
335
addElement(Name name, Element element) {
336
Object types = data.get(name);
338
data.put(name, element);
341
int type = element.getType();
342
if (types instanceof List) {
343
List list = (List) types;
344
for (int i = 0; i < list.size(); i++) {
345
Element elt = (Element) list.get(i);
346
if (elt.getType() == type) {
347
list.set(i, element);
353
Element elt = (Element) types;
354
if (elt.getType() == type)
317
if (found.expired()) {
318
removeElement(name, type);
321
if (found.compareCredibility(minCred) < 0)
326
private synchronized Element
327
findElement(Name name, int type, int minCred) {
328
Object types = exactName(name);
331
return oneElement(name, types, type, minCred);
334
private synchronized void
335
addElement(Name name, Element element) {
336
Object types = data.get(name);
355
338
data.put(name, element);
357
LinkedList list = new LinkedList();
341
int type = element.getType();
342
if (types instanceof List) {
343
List list = (List) types;
344
for (int i = 0; i < list.size(); i++) {
345
Element elt = (Element) list.get(i);
346
if (elt.getType() == type) {
347
list.set(i, element);
359
351
list.add(element);
360
data.put(name, list);
353
Element elt = (Element) types;
354
if (elt.getType() == type)
355
data.put(name, element);
357
LinkedList list = new LinkedList();
360
data.put(name, list);
365
private synchronized void
366
removeElement(Name name, int type) {
367
Object types = data.get(name);
371
if (types instanceof List) {
372
List list = (List) types;
373
for (int i = 0; i < list.size(); i++) {
374
Element elt = (Element) list.get(i);
375
if (elt.getType() == type) {
377
if (list.size() == 0)
365
private synchronized void
366
removeElement(Name name, int type) {
367
Object types = data.get(name);
371
if (types instanceof List) {
372
List list = (List) types;
373
for (int i = 0; i < list.size(); i++) {
374
Element elt = (Element) list.get(i);
375
if (elt.getType() == type) {
377
if (list.size() == 0)
383
Element elt = (Element) types;
384
if (elt.getType() != type)
383
Element elt = (Element) types;
384
if (elt.getType() != type)
390
/** Empties the Cache. */
391
public synchronized void
397
* Adds a record to the Cache.
398
* @param r The record to be added
399
* @param cred The credibility of the record
400
* @param o The source of the record (this could be a Message, for example)
403
public synchronized void
404
addRecord(Record r, int cred, Object o) {
405
Name name = r.getName();
406
int type = r.getRRsetType();
407
if (!Type.isRR(type))
390
/** Empties the Cache. */
391
public synchronized void
397
* Adds a record to the Cache.
398
* @param r The record to be added
399
* @param cred The credibility of the record
400
* @param o The source of the record (this could be a Message, for example)
403
public synchronized void
404
addRecord(Record r, int cred, Object o) {
405
Name name = r.getName();
406
int type = r.getRRsetType();
407
if (!Type.isRR(type))
409
Element element = findElement(name, type, cred);
410
if (element == null) {
411
CacheRRset crrset = new CacheRRset(r, cred, maxcache);
412
addRRset(crrset, cred);
413
} else if (element.compareCredibility(cred) == 0) {
414
if (element instanceof CacheRRset) {
415
CacheRRset crrset = (CacheRRset) element;
422
* Adds an RRset to the Cache.
423
* @param rrset The RRset to be added
424
* @param cred The credibility of these records
427
public synchronized void
428
addRRset(RRset rrset, int cred) {
429
long ttl = rrset.getTTL();
430
Name name = rrset.getName();
431
int type = rrset.getType();
432
Element element = findElement(name, type, 0);
434
if (element != null && element.compareCredibility(cred) <= 0)
435
removeElement(name, type);
437
if (element != null && element.compareCredibility(cred) <= 0)
409
Element element = findElement(name, type, cred);
439
410
if (element == null) {
441
if (rrset instanceof CacheRRset)
442
crrset = (CacheRRset) rrset;
411
CacheRRset crrset = new CacheRRset(r, cred, maxcache);
412
addRRset(crrset, cred);
413
} else if (element.compareCredibility(cred) == 0) {
414
if (element instanceof CacheRRset) {
415
CacheRRset crrset = (CacheRRset) element;
422
* Adds an RRset to the Cache.
423
* @param rrset The RRset to be added
424
* @param cred The credibility of these records
427
public synchronized void
428
addRRset(RRset rrset, int cred) {
429
long ttl = rrset.getTTL();
430
Name name = rrset.getName();
431
int type = rrset.getType();
432
Element element = findElement(name, type, 0);
434
if (element != null && element.compareCredibility(cred) <= 0)
435
removeElement(name, type);
437
if (element != null && element.compareCredibility(cred) <= 0)
439
if (element == null) {
441
if (rrset instanceof CacheRRset)
442
crrset = (CacheRRset) rrset;
444
crrset = new CacheRRset(rrset, cred, maxcache);
445
addElement(name, crrset);
451
* Adds a negative entry to the Cache.
452
* @param name The name of the negative entry
453
* @param type The type of the negative entry
454
* @param soa The SOA record to add to the negative cache entry, or null.
455
* The negative cache ttl is derived from the SOA.
456
* @param cred The credibility of the negative entry
458
public synchronized void
459
addNegative(Name name, int type, SOARecord soa, int cred) {
463
Element element = findElement(name, type, 0);
465
if (element != null && element.compareCredibility(cred) <= 0)
466
removeElement(name, type);
468
if (element != null && element.compareCredibility(cred) <= 0)
471
addElement(name, new NegativeElement(name, type,
478
* Finds all matching sets or something that causes the lookup to stop.
480
protected synchronized SetResponse
481
lookup(Name name, int type, int minCred) {
489
labels = name.labels();
491
for (tlabels = labels; tlabels >= 1; tlabels--) {
492
boolean isRoot = (tlabels == 1);
493
boolean isExact = (tlabels == labels);
444
crrset = new CacheRRset(rrset, cred, maxcache);
445
addElement(name, crrset);
451
* Adds a negative entry to the Cache.
452
* @param name The name of the negative entry
453
* @param type The type of the negative entry
454
* @param soa The SOA record to add to the negative cache entry, or null.
455
* The negative cache ttl is derived from the SOA.
456
* @param cred The credibility of the negative entry
458
public synchronized void
459
addNegative(Name name, int type, SOARecord soa, int cred) {
463
Element element = findElement(name, type, 0);
465
if (element != null && element.compareCredibility(cred) <= 0)
466
removeElement(name, type);
468
if (element != null && element.compareCredibility(cred) <= 0)
471
addElement(name, new NegativeElement(name, type,
478
* Finds all matching sets or something that causes the lookup to stop.
480
protected synchronized SetResponse
481
lookup(Name name, int type, int minCred) {
489
labels = name.labels();
491
for (tlabels = labels; tlabels >= 1; tlabels--) {
492
boolean isRoot = (tlabels == 1);
493
boolean isExact = (tlabels == labels);
500
tname = new Name(name, labels - tlabels);
502
types = data.get(tname);
506
/* If this is an ANY lookup, return everything. */
507
if (isExact && type == Type.ANY) {
508
sr = new SetResponse(SetResponse.SUCCESSFUL);
509
Element [] elements = allElements(types);
511
for (int i = 0; i < elements.length; i++) {
512
element = elements[i];
513
if (element.expired()) {
514
removeElement(tname, element.getType());
517
if (!(element instanceof CacheRRset))
519
if (element.compareCredibility(minCred) < 0)
521
sr.addRRset((CacheRRset)element);
524
/* There were positive entries */
530
* If this is the name, look for the actual type or a CNAME.
531
* Otherwise, look for a DNAME.
534
element = oneElement(tname, types, type, minCred);
535
if (element != null &&
536
element instanceof CacheRRset)
500
tname = new Name(name, labels - tlabels);
502
types = data.get(tname);
506
/* If this is an ANY lookup, return everything. */
507
if (isExact && type == Type.ANY) {
538
508
sr = new SetResponse(SetResponse.SUCCESSFUL);
539
sr.addRRset((CacheRRset) element);
541
} else if (element != null) {
542
sr = new SetResponse(SetResponse.NXRRSET);
546
element = oneElement(tname, types, Type.CNAME, minCred);
547
if (element != null &&
548
element instanceof CacheRRset)
550
return new SetResponse(SetResponse.CNAME,
551
(CacheRRset) element);
554
element = oneElement(tname, types, Type.DNAME, minCred);
555
if (element != null &&
556
element instanceof CacheRRset)
558
return new SetResponse(SetResponse.DNAME,
559
(CacheRRset) element);
564
element = oneElement(tname, types, Type.NS, minCred);
565
if (element != null && element instanceof CacheRRset)
566
return new SetResponse(SetResponse.DELEGATION,
567
(CacheRRset) element);
569
/* Check for the special NXDOMAIN element. */
571
element = oneElement(tname, types, 0, minCred);
573
return SetResponse.ofType(SetResponse.NXDOMAIN);
577
return SetResponse.ofType(SetResponse.UNKNOWN);
581
* Looks up Records in the Cache. This follows CNAMEs and handles negatively
583
* @param name The name to look up
584
* @param type The type to look up
585
* @param minCred The minimum acceptable credibility
586
* @return A SetResponse object
591
lookupRecords(Name name, int type, int minCred) {
592
return lookup(name, type, minCred);
596
findRecords(Name name, int type, int minCred) {
597
SetResponse cr = lookupRecords(name, type, minCred);
598
if (cr.isSuccessful())
605
* Looks up credible Records in the Cache (a wrapper around lookupRecords).
606
* Unlike lookupRecords, this given no indication of why failure occurred.
607
* @param name The name to look up
608
* @param type The type to look up
609
* @return An array of RRsets, or null
613
findRecords(Name name, int type) {
614
return findRecords(name, type, Credibility.NORMAL);
618
* Looks up Records in the Cache (a wrapper around lookupRecords). Unlike
619
* lookupRecords, this given no indication of why failure occurred.
620
* @param name The name to look up
621
* @param type The type to look up
622
* @return An array of RRsets, or null
626
findAnyRecords(Name name, int type) {
627
return findRecords(name, type, Credibility.GLUE);
631
getCred(int section, boolean isAuth) {
632
if (section == Section.ANSWER) {
634
return Credibility.AUTH_ANSWER;
636
return Credibility.NONAUTH_ANSWER;
637
} else if (section == Section.AUTHORITY) {
639
return Credibility.AUTH_AUTHORITY;
641
return Credibility.NONAUTH_AUTHORITY;
642
} else if (section == Section.ADDITIONAL) {
643
return Credibility.ADDITIONAL;
645
throw new IllegalArgumentException("getCred: invalid section");
649
markAdditional(RRset rrset, Set names) {
650
Record first = rrset.first();
651
if (first.getAdditionalName() == null)
654
Iterator it = rrset.rrs();
655
while (it.hasNext()) {
656
Record r = (Record) it.next();
657
Name name = r.getAdditionalName();
664
* Adds all data from a Message into the Cache. Each record is added with
665
* the appropriate credibility, and negative answers are cached as such.
666
* @param in The Message to be added
667
* @return A SetResponse that reflects what would be returned from a cache
668
* lookup, or null if nothing useful could be cached from the message.
672
addMessage(Message in) {
673
boolean isAuth = in.getHeader().getFlag(Flags.AA);
674
Record question = in.getQuestion();
680
int rcode = in.getHeader().getRcode();
681
boolean completed = false;
682
RRset [] answers, auth, addl;
683
SetResponse response = null;
684
boolean verbose = Options.check("verbosecache");
685
HashSet additionalNames;
687
if ((rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) ||
691
qname = question.getName();
692
qtype = question.getType();
693
qclass = question.getDClass();
697
additionalNames = new HashSet();
699
answers = in.getSectionRRsets(Section.ANSWER);
700
for (int i = 0; i < answers.length; i++) {
701
if (answers[i].getDClass() != qclass)
703
int type = answers[i].getType();
704
Name name = answers[i].getName();
705
cred = getCred(Section.ANSWER, isAuth);
706
if ((type == qtype || qtype == Type.ANY) &&
707
name.equals(curname))
709
addRRset(answers[i], cred);
711
if (curname == qname) {
509
Element [] elements = allElements(types);
511
for (int i = 0; i < elements.length; i++) {
512
element = elements[i];
513
if (element.expired()) {
514
removeElement(tname, element.getType());
517
if (!(element instanceof CacheRRset))
519
if (element.compareCredibility(minCred) < 0)
521
sr.addRRset((CacheRRset)element);
524
/* There were positive entries */
530
* If this is the name, look for the actual type or a CNAME.
531
* Otherwise, look for a DNAME.
534
element = oneElement(tname, types, type, minCred);
535
if (element != null &&
536
element instanceof CacheRRset)
538
sr = new SetResponse(SetResponse.SUCCESSFUL);
539
sr.addRRset((CacheRRset) element);
541
} else if (element != null) {
542
sr = new SetResponse(SetResponse.NXRRSET);
546
element = oneElement(tname, types, Type.CNAME, minCred);
547
if (element != null &&
548
element instanceof CacheRRset)
550
return new SetResponse(SetResponse.CNAME,
551
(CacheRRset) element);
554
element = oneElement(tname, types, Type.DNAME, minCred);
555
if (element != null &&
556
element instanceof CacheRRset)
558
return new SetResponse(SetResponse.DNAME,
559
(CacheRRset) element);
564
element = oneElement(tname, types, Type.NS, minCred);
565
if (element != null && element instanceof CacheRRset)
566
return new SetResponse(SetResponse.DELEGATION,
567
(CacheRRset) element);
569
/* Check for the special NXDOMAIN element. */
571
element = oneElement(tname, types, 0, minCred);
573
return SetResponse.ofType(SetResponse.NXDOMAIN);
577
return SetResponse.ofType(SetResponse.UNKNOWN);
581
* Looks up Records in the Cache. This follows CNAMEs and handles negatively
583
* @param name The name to look up
584
* @param type The type to look up
585
* @param minCred The minimum acceptable credibility
586
* @return A SetResponse object
591
lookupRecords(Name name, int type, int minCred) {
592
return lookup(name, type, minCred);
596
findRecords(Name name, int type, int minCred) {
597
SetResponse cr = lookupRecords(name, type, minCred);
598
if (cr.isSuccessful())
605
* Looks up credible Records in the Cache (a wrapper around lookupRecords).
606
* Unlike lookupRecords, this given no indication of why failure occurred.
607
* @param name The name to look up
608
* @param type The type to look up
609
* @return An array of RRsets, or null
613
findRecords(Name name, int type) {
614
return findRecords(name, type, Credibility.NORMAL);
618
* Looks up Records in the Cache (a wrapper around lookupRecords). Unlike
619
* lookupRecords, this given no indication of why failure occurred.
620
* @param name The name to look up
621
* @param type The type to look up
622
* @return An array of RRsets, or null
626
findAnyRecords(Name name, int type) {
627
return findRecords(name, type, Credibility.GLUE);
631
getCred(int section, boolean isAuth) {
632
if (section == Section.ANSWER) {
634
return Credibility.AUTH_ANSWER;
636
return Credibility.NONAUTH_ANSWER;
637
} else if (section == Section.AUTHORITY) {
639
return Credibility.AUTH_AUTHORITY;
641
return Credibility.NONAUTH_AUTHORITY;
642
} else if (section == Section.ADDITIONAL) {
643
return Credibility.ADDITIONAL;
645
throw new IllegalArgumentException("getCred: invalid section");
649
markAdditional(RRset rrset, Set names) {
650
Record first = rrset.first();
651
if (first.getAdditionalName() == null)
654
Iterator it = rrset.rrs();
655
while (it.hasNext()) {
656
Record r = (Record) it.next();
657
Name name = r.getAdditionalName();
664
* Adds all data from a Message into the Cache. Each record is added with
665
* the appropriate credibility, and negative answers are cached as such.
666
* @param in The Message to be added
667
* @return A SetResponse that reflects what would be returned from a cache
668
* lookup, or null if nothing useful could be cached from the message.
672
addMessage(Message in) {
673
boolean isAuth = in.getHeader().getFlag(Flags.AA);
674
Record question = in.getQuestion();
680
int rcode = in.getHeader().getRcode();
681
boolean completed = false;
682
RRset [] answers, auth, addl;
683
SetResponse response = null;
684
boolean verbose = Options.check("verbosecache");
685
HashSet additionalNames;
687
if ((rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) ||
691
qname = question.getName();
692
qtype = question.getType();
693
qclass = question.getDClass();
697
additionalNames = new HashSet();
699
answers = in.getSectionRRsets(Section.ANSWER);
700
for (int i = 0; i < answers.length; i++) {
701
if (answers[i].getDClass() != qclass)
703
int type = answers[i].getType();
704
Name name = answers[i].getName();
705
cred = getCred(Section.ANSWER, isAuth);
706
if ((type == qtype || qtype == Type.ANY) &&
707
name.equals(curname))
709
addRRset(answers[i], cred);
711
if (curname != null && curname.equals(qname)) {
712
if (response == null)
713
response = new SetResponse(
714
SetResponse.SUCCESSFUL);
715
response.addRRset(answers[i]);
717
markAdditional(answers[i], additionalNames);
718
} else if (type == Type.CNAME && name.equals(curname)) {
720
addRRset(answers[i], cred);
721
if (curname != null && curname.equals(qname))
722
response = new SetResponse(SetResponse.CNAME,
724
cname = (CNAMERecord) answers[i].first();
725
curname = cname.getTarget();
726
} else if (type == Type.DNAME && curname != null && curname.subdomain(name)) {
728
addRRset(answers[i], cred);
729
if (curname.equals(qname))
730
response = new SetResponse(SetResponse.DNAME,
732
dname = (DNAMERecord) answers[i].first();
734
curname = curname.fromDNAME(dname);
736
catch (NameTooLongException e) {
742
auth = in.getSectionRRsets(Section.AUTHORITY);
743
RRset soa = null, ns = null;
744
if(curname != null) {
745
for (int i = 0; i < auth.length; i++) {
746
if (auth[i].getType() == Type.SOA &&
747
curname.subdomain(auth[i].getName()))
749
else if (auth[i].getType() == Type.NS &&
750
curname.subdomain(auth[i].getName()))
755
/* This is a negative response or a referral. */
756
int cachetype = (rcode == Rcode.NXDOMAIN) ? 0 : qtype;
757
if (rcode == Rcode.NXDOMAIN || soa != null || ns == null) {
758
/* Negative response */
759
cred = getCred(Section.AUTHORITY, isAuth);
760
SOARecord soarec = null;
762
soarec = (SOARecord) soa.first();
764
addNegative(curname, cachetype, soarec, cred);
765
if (response == null) {
767
if (rcode == Rcode.NXDOMAIN)
768
responseType = SetResponse.NXDOMAIN;
770
responseType = SetResponse.NXRRSET;
771
response = SetResponse.ofType(responseType);
773
/* DNSSEC records are not cached. */
775
/* Referral response */
776
cred = getCred(Section.AUTHORITY, isAuth);
778
markAdditional(ns, additionalNames);
712
779
if (response == null)
713
780
response = new SetResponse(
714
SetResponse.SUCCESSFUL);
715
response.addRRset(answers[i]);
717
markAdditional(answers[i], additionalNames);
718
} else if (type == Type.CNAME && name.equals(curname)) {
720
addRRset(answers[i], cred);
721
if (curname == qname)
722
response = new SetResponse(SetResponse.CNAME,
724
cname = (CNAMERecord) answers[i].first();
725
curname = cname.getTarget();
726
} else if (type == Type.DNAME && curname.subdomain(name)) {
728
addRRset(answers[i], cred);
729
if (curname == qname)
730
response = new SetResponse(SetResponse.DNAME,
732
dname = (DNAMERecord) answers[i].first();
734
curname = curname.fromDNAME(dname);
736
catch (NameTooLongException e) {
742
auth = in.getSectionRRsets(Section.AUTHORITY);
743
RRset soa = null, ns = null;
744
for (int i = 0; i < auth.length; i++) {
745
if (auth[i].getType() == Type.SOA &&
746
curname.subdomain(auth[i].getName()))
748
else if (auth[i].getType() == Type.NS &&
749
curname.subdomain(auth[i].getName()))
753
/* This is a negative response or a referral. */
754
int cachetype = (rcode == Rcode.NXDOMAIN) ? 0 : qtype;
755
if (rcode == Rcode.NXDOMAIN || soa != null || ns == null) {
756
/* Negative response */
757
cred = getCred(Section.AUTHORITY, isAuth);
758
SOARecord soarec = null;
760
soarec = (SOARecord) soa.first();
761
addNegative(curname, cachetype, soarec, cred);
762
if (response == null) {
764
if (rcode == Rcode.NXDOMAIN)
765
responseType = SetResponse.NXDOMAIN;
767
responseType = SetResponse.NXRRSET;
768
response = SetResponse.ofType(responseType);
770
/* DNSSEC records are not cached. */
772
/* Referral response */
781
SetResponse.DELEGATION,
784
} else if (rcode == Rcode.NOERROR && ns != null) {
785
/* Cache the NS set from a positive response. */
773
786
cred = getCred(Section.AUTHORITY, isAuth);
774
787
addRRset(ns, cred);
775
788
markAdditional(ns, additionalNames);
776
if (response == null)
777
response = new SetResponse(
778
SetResponse.DELEGATION,
781
} else if (rcode == Rcode.NOERROR && ns != null) {
782
/* Cache the NS set from a positive response. */
783
cred = getCred(Section.AUTHORITY, isAuth);
785
markAdditional(ns, additionalNames);
788
addl = in.getSectionRRsets(Section.ADDITIONAL);
789
for (int i = 0; i < addl.length; i++) {
790
int type = addl[i].getType();
791
if (type != Type.A && type != Type.AAAA && type != Type.A6)
793
Name name = addl[i].getName();
794
if (!additionalNames.contains(name))
796
cred = getCred(Section.ADDITIONAL, isAuth);
797
addRRset(addl[i], cred);
800
System.out.println("addMessage: " + response);
805
* Flushes an RRset from the cache
806
* @param name The name of the records to be flushed
807
* @param type The type of the records to be flushed
811
flushSet(Name name, int type) {
812
removeElement(name, type);
816
* Flushes all RRsets with a given name from the cache
817
* @param name The name of the records to be flushed
821
flushName(Name name) {
826
* Sets the maximum length of time that a negative response will be stored
827
* in this Cache. A negative value disables this feature (that is, sets
831
setMaxNCache(int seconds) {
836
* Gets the maximum length of time that a negative response will be stored
837
* in this Cache. A negative value indicates no limit.
845
* Sets the maximum length of time that records will be stored in this
846
* Cache. A negative value disables this feature (that is, sets no limit).
849
setMaxCache(int seconds) {
854
* Gets the maximum length of time that records will be stored
855
* in this Cache. A negative value indicates no limit.
863
* Gets the current number of entries in the Cache, where an entry consists
864
* of all records with a specific Name.
872
* Gets the maximum number of entries in the Cache, where an entry consists
873
* of all records with a specific Name. A negative value is treated as an
878
return data.getMaxSize();
882
* Sets the maximum number of entries in the Cache, where an entry consists
883
* of all records with a specific Name. A negative value is treated as an
886
* Note that setting this to a value lower than the current number
887
* of entries will not cause the Cache to shrink immediately.
889
* The default maximum number of entries is 50000.
891
* @param entries The maximum number of entries in the Cache.
894
setMaxEntries(int entries) {
895
data.setMaxSize(entries);
899
* Returns the DNS class of this cache.
907
* Returns the contents of the Cache as a string.
911
StringBuffer sb = new StringBuffer();
912
synchronized (this) {
913
Iterator it = data.values().iterator();
914
while (it.hasNext()) {
915
Element [] elements = allElements(it.next());
916
for (int i = 0; i < elements.length; i++) {
917
sb.append(elements[i]);
791
addl = in.getSectionRRsets(Section.ADDITIONAL);
792
for (int i = 0; i < addl.length; i++) {
793
int type = addl[i].getType();
794
if (type != Type.A && type != Type.AAAA && type != Type.A6)
796
Name name = addl[i].getName();
797
if (!additionalNames.contains(name))
799
cred = getCred(Section.ADDITIONAL, isAuth);
800
addRRset(addl[i], cred);
803
System.out.println("addMessage: " + response);
808
* Flushes an RRset from the cache
809
* @param name The name of the records to be flushed
810
* @param type The type of the records to be flushed
814
flushSet(Name name, int type) {
815
removeElement(name, type);
819
* Flushes all RRsets with a given name from the cache
820
* @param name The name of the records to be flushed
824
flushName(Name name) {
829
* Sets the maximum length of time that a negative response will be stored
830
* in this Cache. A negative value disables this feature (that is, sets
834
setMaxNCache(int seconds) {
839
* Gets the maximum length of time that a negative response will be stored
840
* in this Cache. A negative value indicates no limit.
848
* Sets the maximum length of time that records will be stored in this
849
* Cache. A negative value disables this feature (that is, sets no limit).
852
setMaxCache(int seconds) {
857
* Gets the maximum length of time that records will be stored
858
* in this Cache. A negative value indicates no limit.
866
* Gets the current number of entries in the Cache, where an entry consists
867
* of all records with a specific Name.
875
* Gets the maximum number of entries in the Cache, where an entry consists
876
* of all records with a specific Name. A negative value is treated as an
881
return data.getMaxSize();
885
* Sets the maximum number of entries in the Cache, where an entry consists
886
* of all records with a specific Name. A negative value is treated as an
889
* Note that setting this to a value lower than the current number
890
* of entries will not cause the Cache to shrink immediately.
892
* The default maximum number of entries is 50000.
894
* @param entries The maximum number of entries in the Cache.
897
setMaxEntries(int entries) {
898
data.setMaxSize(entries);
902
* Returns the DNS class of this cache.
910
* Returns the contents of the Cache as a string.
914
StringBuffer sb = new StringBuffer();
915
synchronized (this) {
916
Iterator it = data.values().iterator();
917
while (it.hasNext()) {
918
Element [] elements = allElements(it.next());
919
for (int i = 0; i < elements.length; i++) {
920
sb.append(elements[i]);
925
return sb.toString();
922
return sb.toString();