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(); }
/** * 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; }
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); }
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); }
/** * 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(); }
/** * 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); }