home *** CD-ROM | disk | FTP | other *** search
/ PC Professionell 2007 April / PCpro_2007_04.ISO / files / dsl / jNetTool.exe / org / xbill / DNS / Cache.class (.txt) < prev    next >
Encoding:
Java Class File  |  2005-06-05  |  11.9 KB  |  502 lines

  1. package org.xbill.DNS;
  2.  
  3. import java.io.IOException;
  4. import java.util.HashSet;
  5. import java.util.Iterator;
  6. import java.util.Set;
  7.  
  8. public class Cache extends NameSet {
  9.    private static final int defaultCleanInterval = 30;
  10.    private Verifier verifier;
  11.    private boolean secure;
  12.    private int maxncache;
  13.    private int maxcache;
  14.    private CacheCleaner cleaner;
  15.    private int dclass;
  16.  
  17.    public Cache(int dclass, int cleanInterval) {
  18.       super(true);
  19.       this.maxncache = -1;
  20.       this.maxcache = -1;
  21.       this.dclass = dclass;
  22.       this.setCleanInterval(cleanInterval);
  23.    }
  24.  
  25.    public Cache(int dclass) {
  26.       this(dclass, 30);
  27.    }
  28.  
  29.    public Cache() {
  30.       this(1, 30);
  31.    }
  32.  
  33.    public void clearCache() {
  34.       this.clear();
  35.    }
  36.  
  37.    public Cache(String file) throws IOException {
  38.       super(true);
  39.       this.maxncache = -1;
  40.       this.maxcache = -1;
  41.       this.cleaner = new CacheCleaner(this, 30);
  42.       Master m = new Master(file);
  43.  
  44.       Record record;
  45.       while((record = m.nextRecord()) != null) {
  46.          this.addRecord(record, 0, m);
  47.       }
  48.  
  49.    }
  50.  
  51.    public void addRecord(Record r, int cred, Object o) {
  52.       Name name = r.getName();
  53.       int type = r.getRRsetType();
  54.       if (Type.isRR(type)) {
  55.          boolean addrrset = false;
  56.          Element element = (Element)this.findExactSet(name, type);
  57.          if (element != null && cred <= element.credibility) {
  58.             if (cred == element.credibility && element instanceof PositiveElement) {
  59.                PositiveElement pe = (PositiveElement)element;
  60.                pe.rrset.addRR(r);
  61.             }
  62.          } else {
  63.             RRset rrset = new RRset();
  64.             rrset.addRR(r);
  65.             this.addRRset(rrset, cred);
  66.          }
  67.  
  68.       }
  69.    }
  70.  
  71.    public void addRRset(RRset rrset, int cred) {
  72.       long ttl = rrset.getTTL();
  73.       Name name = rrset.getName();
  74.       int type = rrset.getType();
  75.       if (this.verifier != null) {
  76.          rrset.setSecurity(this.verifier.verify(rrset, this));
  77.       }
  78.  
  79.       if (!this.secure || rrset.getSecurity() >= 1) {
  80.          Element element = (Element)this.findExactSet(name, type);
  81.          if (ttl == 0L) {
  82.             if (element != null && cred >= element.credibility) {
  83.                this.removeSet(name, type, element);
  84.             }
  85.          } else if (element == null || cred >= element.credibility) {
  86.             this.addSet(name, type, new PositiveElement(rrset, cred, (long)this.maxcache));
  87.          }
  88.  
  89.       }
  90.    }
  91.  
  92.    public void addNegative(Name name, int type, SOARecord soa, int cred) {
  93.       if (this.verifier == null || !this.secure) {
  94.          Element element = (Element)this.findExactSet(name, type);
  95.          if ((soa == null || soa.getTTL() == 0L) && element != null && cred >= element.credibility) {
  96.             this.removeSet(name, type, element);
  97.          }
  98.  
  99.          if (element == null || cred >= element.credibility) {
  100.             this.addSet(name, type, new NegativeElement(name, type, soa, cred, (long)this.maxncache));
  101.          }
  102.  
  103.       }
  104.    }
  105.  
  106.    private void logLookup(Name name, int type, String msg) {
  107.       System.err.println("lookupRecords(" + name + " " + Type.string(type) + "): " + msg);
  108.    }
  109.  
  110.    public SetResponse lookupRecords(Name name, int type, int minCred) {
  111.       SetResponse cr = null;
  112.       boolean verbose = Options.check("verbosecache");
  113.       Object o = this.lookup(name, type);
  114.       if (verbose) {
  115.          this.logLookup(name, type, "Starting");
  116.       }
  117.  
  118.       if (o != null && o != NameSet.NXRRSET) {
  119.          Object[] objects;
  120.          if (o instanceof Element) {
  121.             objects = new Object[]{o};
  122.          } else {
  123.             objects = o;
  124.          }
  125.  
  126.          int nelements = 0;
  127.  
  128.          for(int i = 0; i < objects.length; ++i) {
  129.             Element element = (Element)objects[i];
  130.             if (element.expired()) {
  131.                if (verbose) {
  132.                   this.logLookup(name, type, element.toString());
  133.                   this.logLookup(name, type, "expired: ignoring");
  134.                }
  135.  
  136.                this.removeSet(name, type, element);
  137.                objects[i] = null;
  138.             } else if (element.credibility < minCred) {
  139.                if (verbose) {
  140.                   this.logLookup(name, type, element.toString());
  141.                   this.logLookup(name, type, "not credible: ignoring");
  142.                }
  143.  
  144.                objects[i] = null;
  145.             } else {
  146.                ++nelements;
  147.             }
  148.          }
  149.  
  150.          if (nelements == 0) {
  151.             if (verbose) {
  152.                this.logLookup(name, type, "no useful data found");
  153.             }
  154.  
  155.             return SetResponse.ofType(0);
  156.          } else {
  157.             for(int i = 0; i < objects.length; ++i) {
  158.                if (objects[i] != null) {
  159.                   Element element = (Element)objects[i];
  160.                   if (verbose) {
  161.                      this.logLookup(name, type, element.toString());
  162.                   }
  163.  
  164.                   RRset rrset = null;
  165.                   if (element instanceof PositiveElement) {
  166.                      rrset = ((PositiveElement)element).rrset;
  167.                   }
  168.  
  169.                   if (rrset == null) {
  170.                      if (element.getType() == 0) {
  171.                         if (verbose) {
  172.                            this.logLookup(name, type, "NXDOMAIN");
  173.                         }
  174.  
  175.                         return SetResponse.ofType(1);
  176.                      }
  177.  
  178.                      if (type != 255) {
  179.                         if (verbose) {
  180.                            this.logLookup(name, type, "NXRRSET");
  181.                         }
  182.  
  183.                         return SetResponse.ofType(2);
  184.                      }
  185.  
  186.                      if (verbose) {
  187.                         this.logLookup(name, type, "ANY query; ignoring NXRRSET");
  188.                      }
  189.                   } else {
  190.                      int rtype = rrset.getType();
  191.                      Name rname = rrset.getName();
  192.                      if (name.equals(rname)) {
  193.                         if (type != 5 && type != 255 && rtype == 5) {
  194.                            if (verbose) {
  195.                               this.logLookup(name, type, "cname");
  196.                            }
  197.  
  198.                            return new SetResponse(4, rrset);
  199.                         }
  200.  
  201.                         if (type != 2 && type != 255 && rtype == 2) {
  202.                            if (verbose) {
  203.                               this.logLookup(name, type, "exact delegation");
  204.                            }
  205.  
  206.                            return new SetResponse(3, rrset);
  207.                         }
  208.  
  209.                         if (verbose) {
  210.                            this.logLookup(name, type, "exact match");
  211.                         }
  212.  
  213.                         if (cr == null) {
  214.                            cr = new SetResponse(6);
  215.                         }
  216.  
  217.                         cr.addRRset(rrset);
  218.                      } else if (name.subdomain(rname)) {
  219.                         if (rtype == 39) {
  220.                            if (verbose) {
  221.                               this.logLookup(name, type, "dname");
  222.                            }
  223.  
  224.                            return new SetResponse(5, rrset);
  225.                         }
  226.  
  227.                         if (rtype == 2) {
  228.                            if (verbose) {
  229.                               this.logLookup(name, type, "parent delegation");
  230.                            }
  231.  
  232.                            return new SetResponse(3, rrset);
  233.                         }
  234.  
  235.                         if (verbose) {
  236.                            this.logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
  237.                         }
  238.                      } else if (verbose) {
  239.                         this.logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
  240.                      }
  241.                   }
  242.                }
  243.             }
  244.  
  245.             if (cr == null && type == 255) {
  246.                return SetResponse.ofType(0);
  247.             } else if (cr == null) {
  248.                throw new IllegalStateException("looking up (" + name + " " + Type.string(type) + "): " + "cr == null.");
  249.             } else {
  250.                return cr;
  251.             }
  252.          }
  253.       } else {
  254.          if (verbose) {
  255.             this.logLookup(name, type, "no information found");
  256.          }
  257.  
  258.          return SetResponse.ofType(0);
  259.       }
  260.    }
  261.  
  262.    private RRset[] findRecords(Name name, int type, int minCred) {
  263.       SetResponse cr = this.lookupRecords(name, type, minCred);
  264.       return cr.isSuccessful() ? cr.answers() : null;
  265.    }
  266.  
  267.    public RRset[] findRecords(Name name, int type) {
  268.       return this.findRecords(name, type, 3);
  269.    }
  270.  
  271.    public RRset[] findAnyRecords(Name name, int type) {
  272.       return this.findRecords(name, type, 2);
  273.    }
  274.  
  275.    private void verifyRecords(Cache tcache) {
  276.       Iterator it = tcache.names();
  277.  
  278.       while(it.hasNext()) {
  279.          Name name = (Name)it.next();
  280.          Object[] elements = this.findExactSets(name);
  281.  
  282.          for(int i = 0; i < elements.length; ++i) {
  283.             Element element = (Element)elements[i];
  284.             if (!(element instanceof PositiveElement)) {
  285.                RRset rrset = ((PositiveElement)element).rrset;
  286.                if (rrset != null) {
  287.                   if (this.verifier != null) {
  288.                      rrset.setSecurity(this.verifier.verify(rrset, this));
  289.                   }
  290.  
  291.                   if (rrset.getSecurity() >= 1) {
  292.                      this.addSet(name, rrset.getType(), element);
  293.                   }
  294.                }
  295.             }
  296.          }
  297.       }
  298.  
  299.    }
  300.  
  301.    private final int getCred(int section, boolean isAuth) {
  302.       if (section == 1) {
  303.          return isAuth ? 4 : 3;
  304.       } else if (section == 2) {
  305.          return isAuth ? 4 : 3;
  306.       } else if (section == 3) {
  307.          return 1;
  308.       } else {
  309.          throw new IllegalArgumentException("getCred: invalid section");
  310.       }
  311.    }
  312.  
  313.    private static void markAdditional(RRset rrset, Set names) {
  314.       Record first = rrset.first();
  315.       if (first.getAdditionalName() != null) {
  316.          Iterator it = rrset.rrs();
  317.  
  318.          while(it.hasNext()) {
  319.             Record r = (Record)it.next();
  320.             Name name = r.getAdditionalName();
  321.             if (name != null) {
  322.                names.add(name);
  323.             }
  324.          }
  325.  
  326.       }
  327.    }
  328.  
  329.    public SetResponse addMessage(Message in) {
  330.       boolean isAuth = in.getHeader().getFlag(5);
  331.       Record question = in.getQuestion();
  332.       int rcode = in.getHeader().getRcode();
  333.       boolean haveAnswer = false;
  334.       boolean completed = false;
  335.       SetResponse response = null;
  336.       boolean verbose = Options.check("verbosecache");
  337.       if ((rcode == 0 || rcode == 3) && question != null) {
  338.          Name qname = question.getName();
  339.          int qtype = question.getType();
  340.          int qclass = question.getDClass();
  341.          Name curname = qname;
  342.          HashSet additionalNames = new HashSet();
  343.          RRset[] answers = in.getSectionRRsets(1);
  344.  
  345.          for(int i = 0; i < answers.length; ++i) {
  346.             if (answers[i].getDClass() == qclass) {
  347.                int type = answers[i].getType();
  348.                Name name = answers[i].getName();
  349.                int cred = this.getCred(1, isAuth);
  350.                if ((type == qtype || qtype == 255) && name.equals(curname)) {
  351.                   this.addRRset(answers[i], cred);
  352.                   completed = true;
  353.                   haveAnswer = true;
  354.                   if (curname == qname) {
  355.                      if (response == null) {
  356.                         response = new SetResponse(6);
  357.                      }
  358.  
  359.                      response.addRRset(answers[i]);
  360.                   }
  361.  
  362.                   markAdditional(answers[i], additionalNames);
  363.                } else if (type == 5 && name.equals(curname)) {
  364.                   this.addRRset(answers[i], cred);
  365.                   if (curname == qname) {
  366.                      response = new SetResponse(4, answers[i]);
  367.                   }
  368.  
  369.                   CNAMERecord cname = (CNAMERecord)answers[i].first();
  370.                   curname = cname.getTarget();
  371.                   haveAnswer = true;
  372.                } else if (type == 39 && curname.subdomain(name)) {
  373.                   this.addRRset(answers[i], cred);
  374.                   if (curname == qname) {
  375.                      response = new SetResponse(5, answers[i]);
  376.                   }
  377.  
  378.                   DNAMERecord dname = (DNAMERecord)answers[i].first();
  379.  
  380.                   try {
  381.                      curname = curname.fromDNAME(dname);
  382.                   } catch (NameTooLongException var23) {
  383.                      break;
  384.                   }
  385.  
  386.                   haveAnswer = true;
  387.                }
  388.             }
  389.          }
  390.  
  391.          RRset[] auth = in.getSectionRRsets(2);
  392.          RRset soa = null;
  393.          RRset ns = null;
  394.  
  395.          for(int i = 0; i < auth.length; ++i) {
  396.             if (auth[i].getType() == 6 && curname.subdomain(auth[i].getName())) {
  397.                soa = auth[i];
  398.             } else if (auth[i].getType() == 2 && curname.subdomain(auth[i].getName())) {
  399.                ns = auth[i];
  400.             }
  401.          }
  402.  
  403.          if (!completed) {
  404.             int cachetype = rcode == 3 ? 0 : qtype;
  405.             if (soa == null && ns != null) {
  406.                int cred = this.getCred(2, isAuth);
  407.                this.addRRset(ns, cred);
  408.                markAdditional(ns, additionalNames);
  409.                if (response == null) {
  410.                   response = new SetResponse(3, ns);
  411.                }
  412.             } else {
  413.                int cred = this.getCred(2, isAuth);
  414.                SOARecord soarec = null;
  415.                if (soa != null) {
  416.                   soarec = (SOARecord)soa.first();
  417.                }
  418.  
  419.                this.addNegative(curname, cachetype, soarec, cred);
  420.                if (response == null) {
  421.                   int responseType;
  422.                   if (rcode == 3) {
  423.                      responseType = 1;
  424.                   } else {
  425.                      responseType = 2;
  426.                   }
  427.  
  428.                   response = SetResponse.ofType(responseType);
  429.                }
  430.             }
  431.          } else if (rcode == 0 && ns != null) {
  432.             int cred = this.getCred(2, isAuth);
  433.             this.addRRset(ns, cred);
  434.             markAdditional(ns, additionalNames);
  435.          }
  436.  
  437.          RRset[] addl = in.getSectionRRsets(3);
  438.  
  439.          for(int i = 0; i < addl.length; ++i) {
  440.             int type = addl[i].getType();
  441.             if (type == 1 || type == 28 || type == 38) {
  442.                Name name = addl[i].getName();
  443.                if (additionalNames.contains(name)) {
  444.                   int cred = this.getCred(3, isAuth);
  445.                   this.addRRset(addl[i], cred);
  446.                }
  447.             }
  448.          }
  449.  
  450.          if (verbose) {
  451.             System.out.println("addMessage: " + response);
  452.          }
  453.  
  454.          return response;
  455.       } else {
  456.          return null;
  457.       }
  458.    }
  459.  
  460.    public void flushSet(Name name, int type) {
  461.       Element element = (Element)this.findExactSet(name, type);
  462.       if (element != null) {
  463.          this.removeSet(name, type, element);
  464.       }
  465.    }
  466.  
  467.    public void flushName(Name name) {
  468.       this.removeName(name);
  469.    }
  470.  
  471.    public void setVerifier(Verifier v) {
  472.       this.verifier = v;
  473.    }
  474.  
  475.    public void setSecurePolicy() {
  476.       this.secure = true;
  477.    }
  478.  
  479.    public void setMaxNCache(int seconds) {
  480.       this.maxncache = seconds;
  481.    }
  482.  
  483.    public void setMaxCache(int seconds) {
  484.       this.maxcache = seconds;
  485.    }
  486.  
  487.    public void setCleanInterval(int cleanInterval) {
  488.       if (this.cleaner != null) {
  489.          this.cleaner.interrupt();
  490.       }
  491.  
  492.       if (cleanInterval > 0) {
  493.          this.cleaner = new CacheCleaner(this, cleanInterval);
  494.       }
  495.  
  496.    }
  497.  
  498.    protected void finalize() {
  499.       this.setCleanInterval(0);
  500.    }
  501. }
  502.