Ejemplo n.º 1
0
 /** Converts the RRSIG/SIG Record to a String */
 public String rdataToString() {
   StringBuffer sb = new StringBuffer();
   if (signature != null) {
     sb.append(Type.string(covered));
     sb.append(" ");
     sb.append(alg);
     sb.append(" ");
     sb.append(labels);
     sb.append(" ");
     sb.append(origttl);
     sb.append(" ");
     if (Options.check("multiline")) sb.append("(\n\t");
     sb.append(FormattedTime.format(expire));
     sb.append(" ");
     sb.append(FormattedTime.format(timeSigned));
     sb.append(" ");
     sb.append(footprint);
     sb.append(" ");
     sb.append(signer);
     if (Options.check("multiline")) {
       sb.append("\n");
       sb.append(base64.formatString(signature, 64, "\t", true));
     } else {
       sb.append(" ");
       sb.append(base64.toString(signature));
     }
   }
   return sb.toString();
 }
Ejemplo n.º 2
0
 private Message parseMessage(byte[] b) throws WireParseException {
   try {
     return (new Message(b));
   } catch (IOException e) {
     if (Options.check("verbose")) e.printStackTrace();
     if (!(e instanceof WireParseException)) e = new WireParseException("Error parsing message");
     throw (WireParseException) e;
   }
 }
Ejemplo n.º 3
0
 private static void addSearch(String search, List list) {
   Name name;
   if (Options.check("verbose")) System.out.println("adding search " + search);
   try {
     name = Name.fromString(search, Name.root);
   } catch (TextParseException e) {
     return;
   }
   if (list.contains(name)) return;
   list.add(name);
 }
Ejemplo n.º 4
0
 /** Converts a Record into a String representation */
 public String toString() {
   StringBuffer sb = new StringBuffer();
   sb.append(name);
   if (sb.length() < 8) sb.append("\t");
   if (sb.length() < 16) sb.append("\t");
   sb.append("\t");
   if (Options.check("BINDTTL")) sb.append(TTL.format(ttl));
   else sb.append(ttl);
   sb.append("\t");
   if (dclass != DClass.IN || !Options.check("noPrintIN")) {
     sb.append(DClass.string(dclass));
     sb.append("\t");
   }
   sb.append(Type.string(type));
   String rdata = rrToString();
   if (!rdata.equals("")) {
     sb.append("\t");
     sb.append(rdata);
   }
   return sb.toString();
 }
 /*
  * Receive an exception.  If the resolution has been completed,
  * do nothing.  Otherwise make progress.
  */
 public void handleException(Object id, Exception e) {
   if (Options.check("verbose")) System.err.println("ExtendedResolver: got " + e);
   synchronized (this) {
     outstanding--;
     if (done) return;
     int n;
     for (n = 0; n < inprogress.length; n++) if (inprogress[n] == id) break;
     /* If we don't know what this is, do nothing. */
     if (n == inprogress.length) return;
     boolean startnext = false;
     boolean waiting = false;
     /*
      * If this is the first response from server n,
      * we should start sending queries to server n + 1.
      */
     if (sent[n] == 1 && n < resolvers.length - 1) startnext = true;
     if (e instanceof InterruptedIOException) {
       /* Got a timeout; resend */
       if (sent[n] < retries) send(n);
       if (thrown == null) thrown = e;
     } else if (e instanceof SocketException) {
       /*
        * Problem with the socket; don't resend
        * on it
        */
       if (thrown == null || thrown instanceof InterruptedIOException) thrown = e;
     } else {
       /*
        * Problem with the response; don't resend
        * on the same socket.
        */
       thrown = e;
     }
     if (done) return;
     if (startnext) send(n + 1);
     if (done) return;
     if (outstanding == 0) {
       /*
        * If we're done and this is synchronous,
        * wake up the blocking thread.
        */
       done = true;
       if (listener == null) {
         notifyAll();
         return;
       }
     }
     if (!done) return;
   }
   /* If we're done and this is asynchronous, call the callback. */
   if (!(thrown instanceof Exception)) thrown = new RuntimeException(thrown.getMessage());
   listener.handleException(this, (Exception) thrown);
 }
 /*
  * Receive a response.  If the resolution hasn't been completed,
  * either wake up the blocking thread or call the callback.
  */
 public void receiveMessage(Object id, Message m) {
   if (Options.check("verbose")) System.err.println("ExtendedResolver: " + "received message");
   synchronized (this) {
     if (done) return;
     response = m;
     done = true;
     if (listener == null) {
       notifyAll();
       return;
     }
   }
   listener.receiveMessage(this, response);
 }
Ejemplo n.º 7
0
 /**
  * Converts the generate specification to a string containing the corresponding $GENERATE
  * statement.
  */
 public String toString() {
   StringBuffer sb = new StringBuffer();
   sb.append("$GENERATE ");
   sb.append(start + "-" + end);
   if (step > 1) sb.append("/" + step);
   sb.append(" ");
   sb.append(namePattern + " ");
   sb.append(ttl + " ");
   if (dclass != DClass.IN || !Options.check("noPrintIN")) sb.append(DClass.string(dclass) + " ");
   sb.append(Type.string(type) + " ");
   sb.append(rdataPattern + " ");
   return sb.toString();
 }
Ejemplo n.º 8
0
  private static final Record getTypedObject(int type) {
    if (type < 0 || type > knownRecords.length) return unknownRecord.getObject();
    if (knownRecords[type] != null) return knownRecords[type];

    /* Construct the class name by putting the type before "Record". */
    String s =
        Record.class.getPackage().getName() + "." + Type.string(type).replace('-', '_') + "Record";
    try {
      Class c = Class.forName(s);
      Constructor m = c.getDeclaredConstructor(emptyClassArray);
      knownRecords[type] = (Record) m.newInstance(emptyObjectArray);
    } catch (ClassNotFoundException e) {
      /* This is normal; do nothing */
    } catch (Exception e) {
      if (Options.check("verbose")) System.err.println(e);
    }
    if (knownRecords[type] == null) knownRecords[type] = unknownRecord.getObject();
    return knownRecords[type];
  }
Ejemplo n.º 9
0
 /** Converts to a String */
 public String toString() {
   StringBuffer sb = toStringNoData();
   if (key != null || (flags & (FLAG_NOKEY)) == (FLAG_NOKEY)) {
     if (!Options.check("nohex")) {
       sb.append("0x");
       sb.append(Integer.toHexString(flags & 0xFFFF));
     } else sb.append(flags & 0xFFFF);
     sb.append(" ");
     sb.append(proto);
     sb.append(" ");
     sb.append(alg);
     if (key != null) {
       sb.append(" (\n");
       sb.append(base64.formatString(key, 64, "\t", true));
       sb.append(" ; key_tag= ");
       sb.append(getFootprint());
     }
   }
   return sb.toString();
 }
Ejemplo n.º 10
0
 /**
  * Creates a Zone by performing a zone transfer to the specified host. All records that do not
  * belong in the Zone are added to the specified Cache.
  *
  * @see Cache
  * @see Master
  */
 public Zone(Name zone, short dclass, String remote, Cache cache) throws IOException {
   super(false);
   origin = zone;
   this.dclass = dclass;
   type = SECONDARY;
   Resolver res = new SimpleResolver(remote);
   Record rec = Record.newRecord(zone, Type.AXFR, dclass);
   Message query = Message.newQuery(rec);
   Message response = res.send(query);
   Record[] recs = response.getSectionArray(Section.ANSWER);
   for (int i = 0; i < recs.length; i++) {
     if (!recs[i].getName().subdomain(origin)) {
       if (Options.check("verbose"))
         System.err.println(recs[i].getName() + "is not in zone " + origin);
       continue;
     }
     addRecord(recs[i]);
   }
   if (cache != null) {
     recs = response.getSectionArray(Section.ADDITIONAL);
     for (int i = 0; i < recs.length; i++) cache.addRecord(recs[i], Credibility.GLUE, recs);
   }
   validate();
 }
Ejemplo n.º 11
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;
  }
Ejemplo n.º 12
0
 private static void addServer(String server, List list) {
   if (list.contains(server)) return;
   if (Options.check("verbose")) System.out.println("adding server " + server);
   list.add(server);
 }
Ejemplo n.º 13
0
  /**
   * Sends a message to a single server and waits for a response. No checking is done to ensure that
   * the response is associated with the query.
   *
   * @param query The query to send.
   * @return The response.
   * @throws IOException An error occurred while sending or receiving.
   */
  public Message send(Message query) throws IOException {
    if (Options.check("verbose"))
      System.err.println(
          "Sending to " + address.getAddress().getHostAddress() + ":" + address.getPort());

    if (query.getHeader().getOpcode() == Opcode.QUERY) {
      Record question = query.getQuestion();
      if (question != null && question.getType() == Type.AXFR) return sendAXFR(query);
    }

    query = (Message) query.clone();
    applyEDNS(query);
    if (tsig != null) {
      tsig.apply(query, null);
    }

    byte[] out = query.toWire(Message.MAXLENGTH);
    int udpSize = maxUDPSize(query);
    boolean tcp = false;
    long endTime = System.currentTimeMillis() + timeoutValue;
    do {
      byte[] b_in;

      if (useTCP || out.length > udpSize) {
        tcp = true;
      }
      if (tcp) {
        b_in = TCPClient.sendrecv(localAddress, address, out, endTime);
      } else {
        b_in = UDPClient.sendrecv(localAddress, address, out, udpSize, endTime);
      }

      /*
       * Check that the response is long enough.
       */
      if (b_in.length < Header.LENGTH) {
        throw new WireParseException("invalid DNS header - " + "too short");
      }
      /*
       * Check that the response ID matches the query ID.  We want
       * to check this before actually parsing the message, so that
       * if there's a malformed response that's not ours, it
       * doesn't confuse us.
       */
      int id = ((b_in[0] & 0xFF) << 8) + (b_in[1] & 0xFF);
      int qid = query.getHeader().getID();
      if (id != qid) {
        String error = "invalid message id: expected " + qid + "; got id " + id;
        if (tcp) {
          throw new WireParseException(error);
        } else {
          if (Options.check("verbose")) {
            System.err.println(error);
          }
          continue;
        }
      }
      Message response = parseMessage(b_in);
      verifyTSIG(query, response, b_in, tsig);
      if (!tcp && !ignoreTruncation && response.getHeader().getFlag(Flags.TC)) {
        tcp = true;
        continue;
      }
      return response;
    } while (true);
  }
Ejemplo n.º 14
0
 private void verifyTSIG(Message query, Message response, byte[] b, TSIG tsig) {
   if (tsig == null) return;
   int error = tsig.verify(response, b, query.getTSIG());
   if (Options.check("verbose")) System.err.println("TSIG verify: " + Rcode.TSIGstring(error));
 }