Example #1
0
 Message(DNSInput in) throws IOException {
   this(new Header(in));
   boolean isUpdate = (header.getOpcode() == Opcode.UPDATE);
   boolean truncated = header.getFlag(Flags.TC);
   try {
     for (int i = 0; i < 4; i++) {
       int count = header.getCount(i);
       if (count > 0) sections[i] = new ArrayList(count);
       for (int j = 0; j < count; j++) {
         int pos = in.current();
         Record rec = Record.fromWire(in, i, isUpdate);
         sections[i].add(rec);
         if (i == Section.ADDITIONAL) {
           if (rec.getType() == Type.TSIG) tsigstart = pos;
           if (rec.getType() == Type.SIG) {
             SIGRecord sig = (SIGRecord) rec;
             if (sig.getTypeCovered() == 0) sig0start = pos;
           }
         }
       }
     }
   } catch (WireParseException e) {
     if (!truncated) throw e;
   }
   size = in.current();
 }
Example #2
0
 /**
  * Determines if an RRset with the given name and type is already present in the given section.
  *
  * @see RRset
  * @see Section
  */
 public boolean findRRset(Name name, int type, int section) {
   if (sections[section] == null) return false;
   for (int i = 0; i < sections[section].size(); i++) {
     Record r = (Record) sections[section].get(i);
     if (r.getType() == type && name.equals(r.getName())) return true;
   }
   return false;
 }
Example #3
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);
  }
Example #4
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);
  }
Example #5
0
  /**
   * Converts the given section of the Message to a String.
   *
   * @see Section
   */
  public String sectionToString(int i) {
    if (i > 3) return null;

    StringBuffer sb = new StringBuffer();

    Record[] records = getSectionArray(i);
    for (int j = 0; j < records.length; j++) {
      Record rec = records[j];
      if (i == Section.QUESTION) {
        sb.append(";;\t" + rec.name);
        sb.append(", type = " + Type.string(rec.type));
        sb.append(", class = " + DClass.string(rec.dclass));
      } else if (rec.getType() == Type.OPT) continue;
      else sb.append(rec);
      sb.append("\n");
    }
    return sb.toString();
  }
Example #6
0
 private int uniqueID(Message m) {
   Record r = m.getQuestion();
   return (((r.getName().hashCode() & 0xFFFF) << 16)
       + (r.getType() + hashCode() << 8)
       + (hashCode() & 0xFF));
 }
Example #7
0
  public static Record[] getRecords(String namestr, short type, short dclass, byte cred) {
    Message query;
    Message response;
    Record question;
    Record[] answers;
    int answerCount = 0, i = 0;
    Enumeration e;
    Name name = new Name(namestr);

    /*System.out.println("lookup of " + name + " " + Type.string(type));*/
    if (!Type.isRR(type) && type != Type.ANY) return null;

    if (res == null) {
      try {
        eres = new ExtendedResolver();
      } catch (UnknownHostException uhe) {
        System.out.println("Failed to initialize resolver");
        System.exit(-1);
      }
    }
    if (cache == null) cache = new Cache();

    CacheResponse cached = cache.lookupRecords(name, type, dclass, cred);
    /*System.out.println(cached);*/
    if (cached.isSuccessful()) {
      RRset rrset = cached.answer();
      answerCount = rrset.size();
      e = rrset.rrs();
    } else if (cached.isNegative()) {
      answerCount = 0;
      e = null;
    } else {
      question = Record.newRecord(name, type, dclass);
      query = Message.newQuery(question);

      if (res != null) response = res.send(query);
      else response = eres.send(query);

      short rcode = response.getHeader().getRcode();
      if (rcode == Rcode.NOERROR || rcode == Rcode.NXDOMAIN) cache.addMessage(response);

      if (rcode != Rcode.NOERROR) return null;

      e = response.getSection(Section.ANSWER);
      while (e.hasMoreElements()) {
        Record r = (Record) e.nextElement();
        if (matchType(r.getType(), type)) answerCount++;
      }

      e = response.getSection(Section.ANSWER);
    }

    if (answerCount == 0) return null;

    answers = new Record[answerCount];

    while (e.hasMoreElements()) {
      Record r = (Record) e.nextElement();
      if (matchType(r.getType(), type)) answers[i++] = r;
    }

    return answers;
  }
Example #8
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);
  }