/* * Finds the zone of a given domain name. The method is to look * for the first SOA record on the path from the given domain to * the root. This search may be partially bypassed if the zone's * SOA record is received in the authority section of a response. * If recursion is true, recursion is requested on any queries. */ DnsName findZoneName(DnsName fqdn, int rrclass, boolean recursion) throws NamingException { fqdn = (DnsName) fqdn.clone(); while (fqdn.size() > 1) { // while below root ResourceRecords rrs = null; try { rrs = query(fqdn, rrclass, ResourceRecord.TYPE_SOA, recursion, false); } catch (NameNotFoundException e) { throw e; } catch (NamingException e) { // Ignore error and keep searching up the tree. } if (rrs != null) { if (rrs.answer.size() > 0) { // found zone's SOA return fqdn; } // Look for an SOA record giving the zone's top node. for (int i = 0; i < rrs.authority.size(); i++) { ResourceRecord rr = (ResourceRecord) rrs.authority.elementAt(i); if (rr.getType() == ResourceRecord.TYPE_SOA) { DnsName zone = rr.getName(); if (fqdn.endsWith(zone)) { return zone; } } } } fqdn.remove(fqdn.size() - 1); // one step rootward } return fqdn; // no SOA found below root, so // return root }
/* * Finds a zone's SOA record. Returns null if no SOA is found (in * which case "zone" is not actually a zone). * If recursion is true, recursion is requested on the query. */ ResourceRecord findSoa(DnsName zone, int rrclass, boolean recursion) throws NamingException { ResourceRecords rrs = query(zone, rrclass, ResourceRecord.TYPE_SOA, recursion, false); for (int i = 0; i < rrs.answer.size(); i++) { ResourceRecord rr = (ResourceRecord) rrs.answer.elementAt(i); if (rr.getType() == ResourceRecord.TYPE_SOA) { return rr; } } return null; }
/* * Finds the name servers of a zone. <tt>zone</tt> is a fully-qualified * domain name at the top of a zone. * If recursion is true, recursion is requested on the query. */ private String[] findNameServers(DnsName zone, boolean recursion) throws NamingException { // %%% As an optimization, could look in authority section of // findZoneName() response first. ResourceRecords rrs = query(zone, ResourceRecord.CLASS_INTERNET, ResourceRecord.TYPE_NS, recursion, false); String[] ns = new String[rrs.answer.size()]; for (int i = 0; i < ns.length; i++) { ResourceRecord rr = (ResourceRecord) rrs.answer.elementAt(i); if (rr.getType() != ResourceRecord.TYPE_NS) { throw new CommunicationException("Corrupted DNS message"); } ns[i] = (String) rr.getRdata(); // Server name will be passed to InetAddress.getByName(), which // may not be able to handle a trailing dot. // assert ns[i].endsWith("."); ns[i] = ns[i].substring(0, ns[i].length() - 1); } return ns; }
/** * Parses given sequence of bytes and constructs a message object from it. * * @param mesBytes the byte array that should be parsed * @param startIdx an index of <code>mesBytes</code> array to start the parsing at * @param mes an object to write a result to, should already be created * @return updated index of <code>mesBytes</code> array * @throws DomainProtocolException if some error has occurred */ public static int parseMessage(byte[] mesBytes, int startIdx, Message mesObj) throws DomainProtocolException { int idx = startIdx; int tmp, tmp2; int qdCnt; int anCnt; int nsCnt; int arCnt; if (mesObj == null) { // jndi.58=The value of parameter mesObj is null throw new DomainProtocolException(Messages.getString("jndi.58")); // $NON-NLS-1$ } // header section // ID mesObj.setId(ProviderMgr.parse16Int(mesBytes, idx)); idx += 2; // QR & opCode & AA & TC & RD & RA & Z & rCode tmp = ProviderMgr.parse16Int(mesBytes, idx); idx += 2; // QR mesObj.setQR(ProviderMgr.checkBit(tmp, ProviderConstants.QR_MASK)); // OPCODE tmp2 = (tmp & ProviderConstants.OPCODE_MASK) >> ProviderConstants.OPCODE_SHIFT; mesObj.setOpCode(tmp2); // AA mesObj.setAA(ProviderMgr.checkBit(tmp, ProviderConstants.AA_MASK)); // TC mesObj.setTc(ProviderMgr.checkBit(tmp, ProviderConstants.TC_MASK)); // RD mesObj.setRD(ProviderMgr.checkBit(tmp, ProviderConstants.RD_MASK)); // RA mesObj.setRA(ProviderMgr.checkBit(tmp, ProviderConstants.RA_MASK)); // RCODE tmp2 = (tmp & ProviderConstants.RCODE_MASK) >> ProviderConstants.RCODE_SHIFT; mesObj.setRCode(tmp2); // QDCOUNT qdCnt = ProviderMgr.parse16Int(mesBytes, idx); mesObj.setQDCount(qdCnt); idx += 2; // ANCOUNT anCnt = ProviderMgr.parse16Int(mesBytes, idx); mesObj.setANCount(anCnt); idx += 2; // NSCOUNT nsCnt = ProviderMgr.parse16Int(mesBytes, idx); mesObj.setNSCount(nsCnt); idx += 2; // ARCOUNT arCnt = ProviderMgr.parse16Int(mesBytes, idx); mesObj.setARCount(arCnt); idx += 2; // question section for (int i = 0; i < qdCnt; i++) { QuestionRecord qr = new QuestionRecord(); idx = QuestionRecord.parseRecord(mesBytes, idx, qr); mesObj.addQuestionRecord(qr); } // answer section for (int i = 0; i < anCnt; i++) { ResourceRecord rr = new ResourceRecord(); idx = ResourceRecord.parseRecord(mesBytes, idx, rr); mesObj.addAnswerRR(rr); } // authority section for (int i = 0; i < nsCnt; i++) { ResourceRecord rr = new ResourceRecord(); idx = ResourceRecord.parseRecord(mesBytes, idx, rr); mesObj.addAuthorityRR(rr); } // additional section for (int i = 0; i < arCnt; i++) { ResourceRecord rr = new ResourceRecord(); idx = ResourceRecord.parseRecord(mesBytes, idx, rr); mesObj.addAdditionalRR(rr); } return idx; }
/** * Generates sequence of bytes that represents the message. * * @param buffer the buffer to write bytes into * @param startIdx the index of <code>buffer</code> to start writing at * @return updated index of the <code>buffer</code> * @throws DomainProtocolException if something went wrong */ public int writeBytes(byte[] buffer, int startIdx) throws DomainProtocolException { int idx = startIdx; int tmp = 0; // basic check if (buffer == null) { // jndi.32=buffer is null throw new DomainProtocolException(Messages.getString("jndi.32")); // $NON-NLS-1$ } // ID idx = ProviderMgr.write16Int(id, buffer, idx); // QR tmp = ProviderMgr.setBit(tmp, ProviderConstants.QR_MASK, qr); // OPCODE tmp &= ~ProviderConstants.OPCODE_MASK; tmp |= (opCode & 0xf) << ProviderConstants.OPCODE_SHIFT; // AA tmp = ProviderMgr.setBit(tmp, ProviderConstants.AA_MASK, aa); // TC tmp = ProviderMgr.setBit(tmp, ProviderConstants.TC_MASK, tc); // RD tmp = ProviderMgr.setBit(tmp, ProviderConstants.RD_MASK, rd); // RA tmp = ProviderMgr.setBit(tmp, ProviderConstants.RA_MASK, ra); // Z, drop all those bits tmp &= ~ProviderConstants.Z_MASK; // RCODE tmp &= ~ProviderConstants.RCODE_MASK; tmp |= (rCode & 0xf) << ProviderConstants.RCODE_SHIFT; // write to buffer idx = ProviderMgr.write16Int(tmp, buffer, idx); // QDCOUNT idx = ProviderMgr.write16Int(qdCount, buffer, idx); // ANCOUNT idx = ProviderMgr.write16Int(anCount, buffer, idx); // NSCOUNT idx = ProviderMgr.write16Int(nsCount, buffer, idx); // ARCOUNT idx = ProviderMgr.write16Int(arCount, buffer, idx); // question section for (int i = 0; i < questionRecords.size(); i++) { QuestionRecord qr = questionRecords.elementAt(i); idx = qr.writeBytes(buffer, idx); } // answer section for (int i = 0; i < answerRRs.size(); i++) { ResourceRecord rr = answerRRs.elementAt(i); idx = rr.writeBytes(buffer, idx); } // authority section for (int i = 0; i < authorityRRs.size(); i++) { ResourceRecord rr = answerRRs.elementAt(i); idx = rr.writeBytes(buffer, idx); } // additional section for (int i = 0; i < additionalRRs.size(); i++) { ResourceRecord rr = answerRRs.elementAt(i); idx = rr.writeBytes(buffer, idx); } return idx; }