Beispiel #1
0
  private final void maybeAddRecord(Record record) throws IOException {
    int rtype = record.getType();
    Name name = record.getName();

    if (rtype == Type.SOA && !name.equals(origin)) {
      throw new IOException("SOA owner " + name + " does not match zone origin " + origin);
    }
    if (name.subdomain(origin)) addRecord(record);
  }
Beispiel #2
0
  private final void maybeAddRecord(Record record, Cache cache, Object source) throws IOException {
    int type = record.getType();
    Name name = record.getName();

    if (type == Type.SOA) {
      if (!name.equals(origin))
        throw new IOException("SOA owner " + name + " does not match zone origin " + origin);
      else {
        setOrigin(origin);
        dclass = record.getDClass();
      }
    }
    if (origin == null && type != Type.SOA)
      throw new IOException("non-SOA record seen at " + name + " with no origin set");
    if (name.subdomain(origin)) addRecord(record);
    else if (cache != null) cache.addRecord(record, Credibility.GLUE, source);
  }
Beispiel #3
0
  /**
   * Adds all data from a Message into the Cache. Each record is added with the appropriate
   * credibility, and negative answers are cached as such.
   *
   * @param in The Message to be added
   * @see Message
   */
  public void addMessage(Message in) {
    boolean isAuth = in.getHeader().getFlag(Flags.AA);
    Name qname = in.getQuestion().getName();
    Name curname = qname;
    short qtype = in.getQuestion().getType();
    short qclass = in.getQuestion().getDClass();
    byte cred;
    short rcode = in.getHeader().getRcode();
    boolean haveAnswer = false;
    boolean completed = false;
    boolean restart = false;
    RRset[] answers, auth, addl;

    if (rcode != Rcode.NOERROR && rcode != Rcode.NXDOMAIN) return;

    if (secure) {
      Cache c = new Cache(dclass);
      c.addMessage(in);
      verifyRecords(c);
      return;
    }

    answers = in.getSectionRRsets(Section.ANSWER);
    for (int i = 0; i < answers.length; i++) {
      if (answers[i].getDClass() != qclass) continue;
      short type = answers[i].getType();
      Name name = answers[i].getName();
      cred = getCred(Section.ANSWER, isAuth);
      if (type == Type.CNAME && name.equals(curname)) {
        CNAMERecord cname;
        addRRset(answers[i], cred);
        cname = (CNAMERecord) answers[i].first();
        curname = cname.getTarget();
        restart = true;
        haveAnswer = true;
      } else if (type == Type.DNAME && curname.subdomain(name)) {
        DNAMERecord dname;
        addRRset(answers[i], cred);
        dname = (DNAMERecord) answers[i].first();
        try {
          curname = curname.fromDNAME(dname);
        } catch (NameTooLongException e) {
          break;
        }
        restart = true;
        haveAnswer = true;
      } else if ((type == qtype || qtype == Type.ANY) && name.equals(curname)) {
        addRRset(answers[i], cred);
        completed = true;
        haveAnswer = true;
      }
      if (restart) {
        restart = false;
        i = 0;
      }
    }

    auth = in.getSectionRRsets(Section.AUTHORITY);
    if (!completed) {
      /* This is a negative response or a referral. */
      RRset soa = null, ns = null;
      for (int i = 0; i < auth.length; i++) {
        if (auth[i].getType() == Type.SOA && curname.subdomain(auth[i].getName())) soa = auth[i];
        else if (auth[i].getType() == Type.NS && curname.subdomain(auth[i].getName())) ns = auth[i];
      }
      short cachetype = (rcode == Rcode.NXDOMAIN) ? (short) 0 : qtype;
      if (soa != null || ns == null) {
        /* Negative response */
        cred = getCred(Section.AUTHORITY, isAuth);
        SOARecord soarec = null;
        if (soa != null) soarec = (SOARecord) soa.first();
        addNegative(curname, cachetype, soarec, cred);
        /* NXT records are not cached yet. */
      } else {
        /* Referral response */
        cred = getCred(Section.AUTHORITY, isAuth);
        addRRset(ns, cred);
      }
    }

    addl = in.getSectionRRsets(Section.ADDITIONAL);
    for (int i = 0; i < addl.length; i++) {
      short type = addl[i].getType();
      if (type != Type.A && type != Type.AAAA && type != Type.A6) continue;
      /* XXX check the name */
      Name name = addl[i].getName();
      cred = getCred(Section.ADDITIONAL, isAuth);
      addRRset(addl[i], cred);
    }
  }
Beispiel #4
0
  /**
   * Looks up Records in the Cache. This follows CNAMEs and handles negatively cached data.
   *
   * @param name The name to look up
   * @param type The type to look up
   * @param minCred The minimum acceptable credibility
   * @return A SetResponse object
   * @see SetResponse
   * @see Credibility
   */
  public SetResponse lookupRecords(Name name, short type, byte minCred) {
    SetResponse cr = null;
    boolean verbose = Options.check("verbosecache");
    Object o = lookup(name, type);

    if (verbose) logLookup(name, type, "Starting");

    if (o == null || o == NXRRSET) {
      /*
       * The name exists, but the type was not found.  Or, the
       * name does not exist and no parent does either.  Punt.
       */
      if (verbose) logLookup(name, type, "no information found");
      return SetResponse.ofType(SetResponse.UNKNOWN);
    }

    Object[] objects;
    if (o instanceof Element) objects = new Object[] {o};
    else objects = (Object[]) o;

    int nelements = 0;
    for (int i = 0; i < objects.length; i++) {
      Element element = (Element) objects[i];
      if (element.expired()) {
        if (verbose) {
          logLookup(name, type, element.toString());
          logLookup(name, type, "expired: ignoring");
        }
        removeSet(name, type, element);
        objects[i] = null;
      } else if (element.credibility < minCred) {
        if (verbose) {
          logLookup(name, type, element.toString());
          logLookup(name, type, "not credible: ignoring");
        }
        objects[i] = null;
      } else {
        nelements++;
      }
    }
    if (nelements == 0) {
      /* We have data, but can't use it.  Punt. */
      if (verbose) logLookup(name, type, "no useful data found");
      return SetResponse.ofType(SetResponse.UNKNOWN);
    }

    /*
     * We have something at the name.  It could be the answer,
     * a CNAME, DNAME, or NS, or a negative cache entry.
     *
     * Ignore wildcards, since it's pretty unlikely that any will be
     * cached.  The occasional extra query is easily balanced by the
     * reduced number of lookups.
     */

    for (int i = 0; i < objects.length; i++) {
      if (objects[i] == null) continue;
      Element element = (Element) objects[i];
      if (verbose) logLookup(name, type, element.toString());
      RRset rrset = null;
      if (element instanceof PositiveElement) rrset = ((PositiveElement) element).rrset;

      /* Is this a negatively cached entry? */
      if (rrset == null) {
        /*
         * If this is an NXDOMAIN entry, return NXDOMAIN.
         */
        if (element.getType() == 0) {
          if (verbose) logLookup(name, type, "NXDOMAIN");
          return SetResponse.ofType(SetResponse.NXDOMAIN);
        }

        /*
         * If we're not looking for type ANY, return NXRRSET.
         * Otherwise ignore this.
         */
        if (type != Type.ANY) {
          if (verbose) logLookup(name, type, "NXRRSET");
          return SetResponse.ofType(SetResponse.NXRRSET);
        } else {
          if (verbose) logLookup(name, type, "ANY query; " + "ignoring NXRRSET");
          continue;
        }
      }

      short rtype = rrset.getType();
      Name rname = rrset.getName();
      if (name.equals(rname)) {
        if (type != Type.CNAME && type != Type.ANY && rtype == Type.CNAME) {
          if (verbose) logLookup(name, type, "cname");
          return new SetResponse(SetResponse.CNAME, rrset);
        } else if (type != Type.NS && type != Type.ANY && rtype == Type.NS) {
          if (verbose) logLookup(name, type, "exact delegation");
          return new SetResponse(SetResponse.DELEGATION, rrset);
        } else {
          if (verbose) logLookup(name, type, "exact match");
          if (cr == null) cr = new SetResponse(SetResponse.SUCCESSFUL);
          cr.addRRset(rrset);
        }
      } else if (name.subdomain(rname)) {
        if (rtype == Type.DNAME) {
          if (verbose) logLookup(name, type, "dname");
          return new SetResponse(SetResponse.DNAME, rrset);
        } else if (rtype == Type.NS) {
          if (verbose) logLookup(name, type, "parent delegation");
          return new SetResponse(SetResponse.DELEGATION, rrset);
        } else {
          if (verbose)
            logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
        }
      } else {
        if (verbose)
          logLookup(name, type, "ignoring rrset (" + rname + " " + Type.string(rtype) + ")");
      }
    }

    /*
     * As far as I can tell, the only legitimate time cr will be null is
     * if we queried for ANY and only saw negative responses, but not an
     * NXDOMAIN.  Return UNKNOWN.
     */
    if (cr == null && type == Type.ANY) return SetResponse.ofType(SetResponse.UNKNOWN);
    else if (cr == null)
      throw new IllegalStateException(
          "looking up (" + name + " " + Type.string(type) + "): " + "cr == null.");
    return cr;
  }
Beispiel #5
0
  private synchronized SetResponse lookup(Name name, int type) {
    int labels;
    int olabels;
    int tlabels;
    RRset rrset;
    Name tname;
    Object types;
    SetResponse sr;

    if (!name.subdomain(origin)) return SetResponse.ofType(SetResponse.NXDOMAIN);

    labels = name.labels();
    olabels = origin.labels();

    for (tlabels = olabels; tlabels <= labels; tlabels++) {
      boolean isOrigin = (tlabels == olabels);
      boolean isExact = (tlabels == labels);

      if (isOrigin) tname = origin;
      else if (isExact) tname = name;
      else tname = new Name(name, labels - tlabels);

      types = exactName(tname);
      if (types == null) continue;

      /* If this is a delegation, return that. */
      if (!isOrigin) {
        RRset ns = oneRRset(types, Type.NS);
        if (ns != null) return new SetResponse(SetResponse.DELEGATION, ns);
      }

      /* If this is an ANY lookup, return everything. */
      if (isExact && type == Type.ANY) {
        sr = new SetResponse(SetResponse.SUCCESSFUL);
        RRset[] sets = allRRsets(types);
        for (int i = 0; i < sets.length; i++) sr.addRRset(sets[i]);
        return sr;
      }

      /*
       * If this is the name, look for the actual type or a CNAME.
       * Otherwise, look for a DNAME.
       */
      if (isExact) {
        rrset = oneRRset(types, type);
        if (rrset != null) {
          sr = new SetResponse(SetResponse.SUCCESSFUL);
          sr.addRRset(rrset);
          return sr;
        }
        rrset = oneRRset(types, Type.CNAME);
        if (rrset != null) return new SetResponse(SetResponse.CNAME, rrset);
      } else {
        rrset = oneRRset(types, Type.DNAME);
        if (rrset != null) return new SetResponse(SetResponse.DNAME, rrset);
      }

      /* We found the name, but not the type. */
      if (isExact) return SetResponse.ofType(SetResponse.NXRRSET);
    }

    if (hasWild) {
      for (int i = 0; i < labels - olabels; i++) {
        tname = name.wild(i + 1);

        types = exactName(tname);
        if (types == null) continue;

        rrset = oneRRset(types, type);
        if (rrset != null) {
          sr = new SetResponse(SetResponse.SUCCESSFUL);
          sr.addRRset(rrset);
          return sr;
        }
      }
    }

    return SetResponse.ofType(SetResponse.NXDOMAIN);
  }