예제 #1
0
  /* Returns true if the message could be rendered. */
  private boolean toWire(DNSOutput out, int maxLength) {
    if (maxLength < Header.LENGTH) return false;

    Header newheader = null;

    int tempMaxLength = maxLength;
    if (tsigkey != null) tempMaxLength -= tsigkey.recordLength();

    OPTRecord opt = getOPT();
    byte[] optBytes = null;
    if (opt != null) {
      optBytes = opt.toWire(Section.ADDITIONAL);
      tempMaxLength -= optBytes.length;
    }

    int startpos = out.current();
    header.toWire(out);
    Compression c = new Compression();
    int flags = header.getFlagsByte();
    int additionalCount = 0;
    for (int i = 0; i < 4; i++) {
      int skipped;
      if (sections[i] == null) continue;
      skipped = sectionToWire(out, i, c, tempMaxLength);
      if (skipped != 0 && i != Section.ADDITIONAL) {
        flags = Header.setFlag(flags, Flags.TC, true);
        out.writeU16At(header.getCount(i) - skipped, startpos + 4 + 2 * i);
        for (int j = i + 1; j < Section.ADDITIONAL; j++) out.writeU16At(0, startpos + 4 + 2 * j);
        break;
      }
      if (i == Section.ADDITIONAL) additionalCount = header.getCount(i) - skipped;
    }

    if (optBytes != null) {
      out.writeByteArray(optBytes);
      additionalCount++;
    }

    if (flags != header.getFlagsByte()) out.writeU16At(flags, startpos + 2);

    if (additionalCount != header.getCount(Section.ADDITIONAL))
      out.writeU16At(additionalCount, startpos + 10);

    if (tsigkey != null) {
      TSIGRecord tsigrec = tsigkey.generate(this, out.toByteArray(), tsigerror, querytsig);

      tsigrec.toWire(out, Section.ADDITIONAL, c);
      out.writeU16At(additionalCount + 1, startpos + 10);
    }

    return true;
  }
예제 #2
0
파일: Message.java 프로젝트: lemmy/dnsjava
  /* Returns true if the message could be rendered. */
  private boolean toWire(DNSOutput out, int maxLength) {
    if (maxLength < Header.LENGTH) return false;

    Header newheader = null;

    int tempMaxLength = maxLength;
    if (tsigkey != null) tempMaxLength -= tsigkey.recordLength();

    int startpos = out.current();
    header.toWire(out);
    Compression c = new Compression();
    for (int i = 0; i < 4; i++) {
      int skipped;
      if (sections[i] == null) continue;
      skipped = sectionToWire(out, i, c, tempMaxLength);
      if (skipped != 0) {
        if (i != Section.ADDITIONAL) {
          if (newheader == null) newheader = (Header) header.clone();
          newheader.setFlag(Flags.TC);
          int count = newheader.getCount(i);
          newheader.setCount(i, count - skipped);
          for (int j = i + 1; j < 4; j++) newheader.setCount(j, 0);

          out.save();
          out.jump(startpos);
          newheader.toWire(out);
          out.restore();
        }
        break;
      }
    }

    if (tsigkey != null) {
      TSIGRecord tsigrec = tsigkey.generate(this, out.toByteArray(), tsigerror, querytsig);

      if (newheader == null) newheader = (Header) header.clone();
      tsigrec.toWire(out, Section.ADDITIONAL, c);
      newheader.incCount(Section.ADDITIONAL);

      out.save();
      out.jump(startpos);
      newheader.toWire(out);
      out.restore();
    }

    return true;
  }
예제 #3
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);
  }
예제 #4
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));
 }