📄 zonetransferin.java
字号:
private voidsendQuery() throws IOException { Record question = Record.newRecord(zname, qtype, dclass); Message query = new Message(); query.getHeader().setOpcode(Opcode.QUERY); query.addRecord(question, Section.QUESTION); if (qtype == Type.IXFR) { Record soa = new SOARecord(zname, dclass, 0, Name.root, Name.root, ixfr_serial, 0, 0, 0, 0); query.addRecord(soa, Section.AUTHORITY); } if (tsig != null) { tsig.apply(query, null); verifier = new TSIG.StreamVerifier(tsig, query.getTSIG()); } byte [] out = query.toWire(Message.MAXLENGTH); client.send(out);}private longgetSOASerial(Record rec) { SOARecord soa = (SOARecord) rec; return soa.getSerial();}private voidlogxfr(String s) { if (Options.check("verbose")) System.out.println(zname + ": " + s);}private voidfail(String s) throws ZoneTransferException { throw new ZoneTransferException(s);}private voidfallback() throws ZoneTransferException { if (!want_fallback) fail("server doesn't support IXFR"); logxfr("falling back to AXFR"); qtype = Type.AXFR; state = INITIALSOA;}private voidparseRR(Record rec) throws ZoneTransferException { Name name = rec.getName(); int type = rec.getType(); Delta delta; switch (state) { case INITIALSOA: if (type != Type.SOA) fail("missing initial SOA"); initialsoa = rec; // Remember the serial number in the intial SOA; we need it // to recognize the end of an IXFR. end_serial = getSOASerial(rec); if (qtype == Type.IXFR && end_serial <= ixfr_serial) { logxfr("up to date"); state = END; break; } state = FIRSTDATA; break; case FIRSTDATA: // If the transfer begins with 1 SOA, it's an AXFR. // If it begins with 2 SOAs, it's an IXFR. if (qtype == Type.IXFR && type == Type.SOA && getSOASerial(rec) == ixfr_serial) { rtype = Type.IXFR; ixfr = new ArrayList(); logxfr("got incremental response"); state = IXFR_DELSOA; } else { rtype = Type.AXFR; axfr = new ArrayList(); axfr.add(initialsoa); logxfr("got nonincremental response"); state = AXFR; } parseRR(rec); // Restart... return; case IXFR_DELSOA: delta = new Delta(); ixfr.add(delta); delta.start = getSOASerial(rec); delta.deletes.add(rec); state = IXFR_DEL; break; case IXFR_DEL: if (type == Type.SOA) { current_serial = getSOASerial(rec); state = IXFR_ADDSOA; parseRR(rec); // Restart... return; } delta = (Delta) ixfr.get(ixfr.size() - 1); delta.deletes.add(rec); break; case IXFR_ADDSOA: delta = (Delta) ixfr.get(ixfr.size() - 1); delta.end = getSOASerial(rec); delta.adds.add(rec); state = IXFR_ADD; break; case IXFR_ADD: if (type == Type.SOA) { long soa_serial = getSOASerial(rec); if (soa_serial == end_serial) { state = END; break; } else if (soa_serial != current_serial) { fail("IXFR out of sync: expected serial " + current_serial + " , got " + soa_serial); } else { state = IXFR_DELSOA; parseRR(rec); // Restart... return; } } delta = (Delta) ixfr.get(ixfr.size() - 1); delta.adds.add(rec); break; case AXFR: // Old BINDs sent cross class A records for non IN classes. if (type == Type.A && rec.getDClass() != dclass) break; axfr.add(rec); if (type == Type.SOA) { state = END; } break; case END: fail("extra data"); break; default: fail("invalid state"); break; }}private voidcloseConnection() { try { client.cleanup(); } catch (IOException e) { }}private MessageparseMessage(byte [] b) throws WireParseException { try { return new Message(b); } catch (IOException e) { if (e instanceof WireParseException) throw (WireParseException) e; throw new WireParseException("Error parsing message"); }}private voiddoxfr() throws IOException, ZoneTransferException { sendQuery(); while (state != END) { byte [] in = client.recv(); Message response = parseMessage(in); if (response.getHeader().getRcode() == Rcode.NOERROR && verifier != null) { TSIGRecord tsigrec = response.getTSIG(); int error = verifier.verify(response, in); if (error == Rcode.NOERROR && tsigrec != null) response.tsigState = Message.TSIG_VERIFIED; else if (error == Rcode.NOERROR) response.tsigState = Message.TSIG_INTERMEDIATE; else fail("TSIG failure"); } Record [] answers = response.getSectionArray(Section.ANSWER); if (state == INITIALSOA) { int rcode = response.getRcode(); if (rcode != Rcode.NOERROR) { if (qtype == Type.IXFR && rcode == Rcode.NOTIMP) { fallback(); doxfr(); return; } fail(Rcode.string(rcode)); } Record question = response.getQuestion(); if (question != null && question.getType() != qtype) { fail("invalid question section"); } if (answers.length == 0 && qtype == Type.IXFR) { fallback(); doxfr(); return; } } for (int i = 0; i < answers.length; i++) { parseRR(answers[i]); } if (state == END && response.tsigState == Message.TSIG_INTERMEDIATE) fail("last message must be signed"); }}/** * Does the zone transfer. * @return A list, which is either an AXFR-style response (List of Records), * and IXFR-style response (List of Deltas), or null, which indicates that * an IXFR was performed and the zone is up to date. * @throws IOException The zone transfer failed to due an IO problem. * @throws ZoneTransferException The zone transfer failed to due a problem * with the zone transfer itself. */public Listrun() throws IOException, ZoneTransferException { openConnection(); try { doxfr(); } finally { closeConnection(); } if (axfr != null) return axfr; return ixfr;}/** * Returns true if the response is an AXFR-style response (List of Records). * This will be true if either an IXFR was performed, an IXFR was performed * and the server provided a full zone transfer, or an IXFR failed and * fallback to AXFR occurred. */public booleanisAXFR() { return (rtype == Type.AXFR);}/** * Gets the AXFR-style response. */public ListgetAXFR() { return axfr;}/** * Returns true if the response is an IXFR-style response (List of Deltas). * This will be true only if an IXFR was performed and the server provided * an incremental zone transfer. */public booleanisIXFR() { return (rtype == Type.IXFR);}/** * Gets the IXFR-style response. */public ListgetIXFR() { return ixfr;}/** * Returns true if the response indicates that the zone is up to date. * This will be true only if an IXFR was performed. */public booleanisCurrent() { return (axfr == null && ixfr == null);}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -