home *** CD-ROM | disk | FTP | other *** search
- package org.xbill.DNS;
-
- import java.io.IOException;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Set;
-
- public class Cache extends NameSet {
- private static final int defaultCleanInterval = 30;
- private Verifier verifier;
- private boolean secure;
- private int maxncache;
- private int maxcache;
- private CacheCleaner cleaner;
- private int dclass;
-
- public Cache(int dclass, int cleanInterval) {
- super(true);
- this.maxncache = -1;
- this.maxcache = -1;
- this.dclass = dclass;
- this.setCleanInterval(cleanInterval);
- }
-
- public Cache(int dclass) {
- this(dclass, 30);
- }
-
- public Cache() {
- this(1, 30);
- }
-
- public void clearCache() {
- this.clear();
- }
-
- public Cache(String file) throws IOException {
- super(true);
- this.maxncache = -1;
- this.maxcache = -1;
- this.cleaner = new CacheCleaner(this, 30);
- Master m = new Master(file);
-
- Record record;
- while((record = m.nextRecord()) != null) {
- this.addRecord(record, 0, m);
- }
-
- }
-
- public void addRecord(Record r, int cred, Object o) {
- Name name = r.getName();
- int type = r.getRRsetType();
- if (Type.isRR(type)) {
- boolean addrrset = false;
- Element element = (Element)this.findExactSet(name, type);
- if (element != null && cred <= element.credibility) {
- if (cred == element.credibility && element instanceof PositiveElement) {
- PositiveElement pe = (PositiveElement)element;
- pe.rrset.addRR(r);
- }
- } else {
- RRset rrset = new RRset();
- rrset.addRR(r);
- this.addRRset(rrset, cred);
- }
-
- }
- }
-
- public void addRRset(RRset rrset, int cred) {
- long ttl = rrset.getTTL();
- Name name = rrset.getName();
- int type = rrset.getType();
- if (this.verifier != null) {
- rrset.setSecurity(this.verifier.verify(rrset, this));
- }
-
- if (!this.secure || rrset.getSecurity() >= 1) {
- Element element = (Element)this.findExactSet(name, type);
- if (ttl == 0L) {
- if (element != null && cred >= element.credibility) {
- this.removeSet(name, type, element);
- }
- } else if (element == null || cred >= element.credibility) {
- this.addSet(name, type, new PositiveElement(rrset, cred, (long)this.maxcache));
- }
-
- }
- }
-
- public void addNegative(Name name, int type, SOARecord soa, int cred) {
- if (this.verifier == null || !this.secure) {
- Element element = (Element)this.findExactSet(name, type);
- if ((soa == null || soa.getTTL() == 0L) && element != null && cred >= element.credibility) {
- this.removeSet(name, type, element);
- }
-
- if (element == null || cred >= element.credibility) {
- this.addSet(name, type, new NegativeElement(name, type, soa, cred, (long)this.maxncache));
- }
-
- }
- }
-
- private void logLookup(Name name, int type, String msg) {
- System.err.println("lookupRecords(" + name + " " + Type.string(type) + "): " + msg);
- }
-
- public SetResponse lookupRecords(Name name, int type, int minCred) {
- SetResponse cr = null;
- boolean verbose = Options.check("verbosecache");
- Object o = this.lookup(name, type);
- if (verbose) {
- this.logLookup(name, type, "Starting");
- }
-
- if (o != null && o != NameSet.NXRRSET) {
- Object[] objects;
- if (o instanceof Element) {
- objects = new Object[]{o};
- } else {
- objects = o;
- }
-
- int nelements = 0;
-
- for(int i = 0; i < objects.length; ++i) {
- Element element = (Element)objects[i];
- if (element.expired()) {
- if (verbose) {
- this.logLookup(name, type, element.toString());
- this.logLookup(name, type, "expired: ignoring");
- }
-
- this.removeSet(name, type, element);
- objects[i] = null;
- } else if (element.credibility < minCred) {
- if (verbose) {
- this.logLookup(name, type, element.toString());
- this.logLookup(name, type, "not credible: ignoring");
- }
-
- objects[i] = null;
- } else {
- ++nelements;
- }
- }
-
- if (nelements == 0) {
- if (verbose) {
- this.logLookup(name, type, "no useful data found");
- }
-
- return SetResponse.ofType(0);
- } else {
- for(int i = 0; i < objects.length; ++i) {
- if (objects[i] != null) {
- Element element = (Element)objects[i];
- if (verbose) {
- this.logLookup(name, type, element.toString());
- }
-
- RRset rrset = null;
- if (element instanceof PositiveElement) {
- rrset = ((PositiveElement)element).rrset;
- }
-
- if (rrset == null) {
- if (element.getType() == 0) {
- if (verbose) {
- this.logLookup(name, type, "NXDOMAIN");
- }
-
- return SetResponse.ofType(1);
- }
-
- if (type != 255) {
- if (verbose) {
- this.logLookup(name, type, "NXRRSET");
- }
-
- return SetResponse.ofType(2);
- }
-
- if (verbose) {
- this.logLookup(name, type, "ANY query; ignoring NXRRSET");
- }
- } else {
- int rtype = rrset.getType();
- Name rname = rrset.getName();
- if (name.equals(rname)) {
- if (type != 5 && type != 255 && rtype == 5) {
- if (verbose) {
- this.logLookup(name, type, "cname");
- }
-
- return new SetResponse(4, rrset);
- }
-
- if (type != 2 && type != 255 && rtype == 2) {
- if (verbose) {
- this.logLookup(name, type, "exact delegation");
- }
-
- return new SetResponse(3, rrset);
- }
-
- if (verbose) {
- this.logLookup(name, type, "exact match");
- }
-
- if (cr == null) {
- cr = new SetResponse(6);
- }
-
- cr.addRRset(rrset);
- } else if (name.subdomain(rname)) {
- if (rtype == 39) {
- if (verbose) {
- this.logLookup(name, type, "dname");
- }
-
- return new SetResponse(5, rrset);
- }
-
- if (rtype == 2) {
- if (verbose) {
- this.logLookup(name, type, "parent delegation");
- }
-
- return new SetResponse(3, rrset);
- }
-
- if (verbose) {
- this.logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
- }
- } else if (verbose) {
- this.logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
- }
- }
- }
- }
-
- if (cr == null && type == 255) {
- return SetResponse.ofType(0);
- } else if (cr == null) {
- throw new IllegalStateException("looking up (" + name + " " + Type.string(type) + "): " + "cr == null.");
- } else {
- return cr;
- }
- }
- } else {
- if (verbose) {
- this.logLookup(name, type, "no information found");
- }
-
- return SetResponse.ofType(0);
- }
- }
-
- private RRset[] findRecords(Name name, int type, int minCred) {
- SetResponse cr = this.lookupRecords(name, type, minCred);
- return cr.isSuccessful() ? cr.answers() : null;
- }
-
- public RRset[] findRecords(Name name, int type) {
- return this.findRecords(name, type, 3);
- }
-
- public RRset[] findAnyRecords(Name name, int type) {
- return this.findRecords(name, type, 2);
- }
-
- private void verifyRecords(Cache tcache) {
- Iterator it = tcache.names();
-
- while(it.hasNext()) {
- Name name = (Name)it.next();
- Object[] elements = this.findExactSets(name);
-
- for(int i = 0; i < elements.length; ++i) {
- Element element = (Element)elements[i];
- if (!(element instanceof PositiveElement)) {
- RRset rrset = ((PositiveElement)element).rrset;
- if (rrset != null) {
- if (this.verifier != null) {
- rrset.setSecurity(this.verifier.verify(rrset, this));
- }
-
- if (rrset.getSecurity() >= 1) {
- this.addSet(name, rrset.getType(), element);
- }
- }
- }
- }
- }
-
- }
-
- private final int getCred(int section, boolean isAuth) {
- if (section == 1) {
- return isAuth ? 4 : 3;
- } else if (section == 2) {
- return isAuth ? 4 : 3;
- } else if (section == 3) {
- return 1;
- } else {
- throw new IllegalArgumentException("getCred: invalid section");
- }
- }
-
- private static void markAdditional(RRset rrset, Set names) {
- Record first = rrset.first();
- if (first.getAdditionalName() != null) {
- Iterator it = rrset.rrs();
-
- while(it.hasNext()) {
- Record r = (Record)it.next();
- Name name = r.getAdditionalName();
- if (name != null) {
- names.add(name);
- }
- }
-
- }
- }
-
- public SetResponse addMessage(Message in) {
- boolean isAuth = in.getHeader().getFlag(5);
- Record question = in.getQuestion();
- int rcode = in.getHeader().getRcode();
- boolean haveAnswer = false;
- boolean completed = false;
- SetResponse response = null;
- boolean verbose = Options.check("verbosecache");
- if ((rcode == 0 || rcode == 3) && question != null) {
- Name qname = question.getName();
- int qtype = question.getType();
- int qclass = question.getDClass();
- Name curname = qname;
- HashSet additionalNames = new HashSet();
- RRset[] answers = in.getSectionRRsets(1);
-
- for(int i = 0; i < answers.length; ++i) {
- if (answers[i].getDClass() == qclass) {
- int type = answers[i].getType();
- Name name = answers[i].getName();
- int cred = this.getCred(1, isAuth);
- if ((type == qtype || qtype == 255) && name.equals(curname)) {
- this.addRRset(answers[i], cred);
- completed = true;
- haveAnswer = true;
- if (curname == qname) {
- if (response == null) {
- response = new SetResponse(6);
- }
-
- response.addRRset(answers[i]);
- }
-
- markAdditional(answers[i], additionalNames);
- } else if (type == 5 && name.equals(curname)) {
- this.addRRset(answers[i], cred);
- if (curname == qname) {
- response = new SetResponse(4, answers[i]);
- }
-
- CNAMERecord cname = (CNAMERecord)answers[i].first();
- curname = cname.getTarget();
- haveAnswer = true;
- } else if (type == 39 && curname.subdomain(name)) {
- this.addRRset(answers[i], cred);
- if (curname == qname) {
- response = new SetResponse(5, answers[i]);
- }
-
- DNAMERecord dname = (DNAMERecord)answers[i].first();
-
- try {
- curname = curname.fromDNAME(dname);
- } catch (NameTooLongException var23) {
- break;
- }
-
- haveAnswer = true;
- }
- }
- }
-
- RRset[] auth = in.getSectionRRsets(2);
- RRset soa = null;
- RRset ns = null;
-
- for(int i = 0; i < auth.length; ++i) {
- if (auth[i].getType() == 6 && curname.subdomain(auth[i].getName())) {
- soa = auth[i];
- } else if (auth[i].getType() == 2 && curname.subdomain(auth[i].getName())) {
- ns = auth[i];
- }
- }
-
- if (!completed) {
- int cachetype = rcode == 3 ? 0 : qtype;
- if (soa == null && ns != null) {
- int cred = this.getCred(2, isAuth);
- this.addRRset(ns, cred);
- markAdditional(ns, additionalNames);
- if (response == null) {
- response = new SetResponse(3, ns);
- }
- } else {
- int cred = this.getCred(2, isAuth);
- SOARecord soarec = null;
- if (soa != null) {
- soarec = (SOARecord)soa.first();
- }
-
- this.addNegative(curname, cachetype, soarec, cred);
- if (response == null) {
- int responseType;
- if (rcode == 3) {
- responseType = 1;
- } else {
- responseType = 2;
- }
-
- response = SetResponse.ofType(responseType);
- }
- }
- } else if (rcode == 0 && ns != null) {
- int cred = this.getCred(2, isAuth);
- this.addRRset(ns, cred);
- markAdditional(ns, additionalNames);
- }
-
- RRset[] addl = in.getSectionRRsets(3);
-
- for(int i = 0; i < addl.length; ++i) {
- int type = addl[i].getType();
- if (type == 1 || type == 28 || type == 38) {
- Name name = addl[i].getName();
- if (additionalNames.contains(name)) {
- int cred = this.getCred(3, isAuth);
- this.addRRset(addl[i], cred);
- }
- }
- }
-
- if (verbose) {
- System.out.println("addMessage: " + response);
- }
-
- return response;
- } else {
- return null;
- }
- }
-
- public void flushSet(Name name, int type) {
- Element element = (Element)this.findExactSet(name, type);
- if (element != null) {
- this.removeSet(name, type, element);
- }
- }
-
- public void flushName(Name name) {
- this.removeName(name);
- }
-
- public void setVerifier(Verifier v) {
- this.verifier = v;
- }
-
- public void setSecurePolicy() {
- this.secure = true;
- }
-
- public void setMaxNCache(int seconds) {
- this.maxncache = seconds;
- }
-
- public void setMaxCache(int seconds) {
- this.maxcache = seconds;
- }
-
- public void setCleanInterval(int cleanInterval) {
- if (this.cleaner != null) {
- this.cleaner.interrupt();
- }
-
- if (cleanInterval > 0) {
- this.cleaner = new CacheCleaner(this, cleanInterval);
- }
-
- }
-
- protected void finalize() {
- this.setCleanInterval(0);
- }
- }
-