/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
// Some of this code began life as part of sun.javaos.net.DnsClient
// originally by sritchie@eng 1/96. It was first hacked up for JNDI
// use by caveh@eng 6/97.
/**
* The DnsClient class performs DNS client operations in support of DnsContext.
*
*/
public class DnsClient {
// DNS packet header field offsets
// DNS response codes
"No error",
"DNS format error",
"DNS server failure",
"DNS name not found",
"DNS operation not supported",
"DNS service refused"
};
private int[] serverPorts;
// Requests sent
// Responses received
//-------------------------------------------------------------------------
/*
* Each server is of the form "server[:port]". IPv6 literal host names
* include delimiting brackets.
* "timeout" is the initial timeout interval (in ms) for UDP queries,
* and "retries" gives the number of retries per server.
*/
throws NamingException {
try {
udpSocket = new DatagramSocket();
ne.setRootCause(e);
throw ne;
}
// Is optional port given?
? servers[i]
try {
"Unknown DNS server: " + server);
ne.setRootCause(e);
throw ne;
}
}
}
protected void finalize() {
close();
}
// A lock to access the request and response queues in tandem.
public void close() {
synchronized (queuesLock) {
}
}
/*
* If recursion is true, recursion is requested on the query.
* If auth is true, only authoritative responses are accepted; other
* responses throw NameNotFoundException.
*/
throws NamingException {
int xid;
synchronized (identLock) {
}
// enqueue the outstanding request
//
// The UDP retry strategy is to try the 1st server, and then
// each server in order. If no answer, double the timeout
// and try each server again.
//
// Try each name server.
if (doNotRetry[i]) {
continue;
}
// send the request packet and wait for a response.
try {
if (debug) {
}
//
// If the matching response is not got within the
// given timeout, check if the response was enqueued
// by some other thread, if not proceed with the next
// server or retry.
//
}
continue;
}
}
"DNS response not authoritative");
doNotRetry[i] = true;
continue;
}
// Try each server, starting with the one that just
// provided the truncated message.
if (doNotRetry[ij]) {
continue;
}
try {
byte[] msg2;
try {
} finally {
}
throw new CommunicationException(
"DNS error: expecting response");
}
// Got a valid response
break;
} else {
doNotRetry[ij] = true;
}
} catch (Exception e) {
// Try next server, or use UDP response
}
} // servers
}
} catch (IOException e) {
if (debug) {
dprint("Caught IOException:" + e);
}
if (caughtException == null) {
caughtException = e;
}
// Use reflection to allow pre-1.4 compilation.
// This won't be needed much longer.
"java.net.PortUnreachableException")) {
doNotRetry[i] = true;
}
} catch (NameNotFoundException e) {
throw e;
} catch (CommunicationException e) {
if (caughtException == null) {
caughtException = e;
}
} catch (NamingException e) {
if (caughtException == null) {
caughtException = e;
}
doNotRetry[i] = true;
}
} // servers
} // retries
if (caughtException instanceof NamingException) {
throw (NamingException) caughtException;
}
// A network timeout or other error occurred.
throw ne;
}
throws NamingException {
int xid;
synchronized (identLock) {
}
// Try each name server.
try {
byte[] msg;
try {
// Check only rcode as per
// draft-ietf-dnsext-axfr-clarify-04
throw new CommunicationException(
"DNS error: zone xfer doesn't begin with SOA");
}
// The response is split into multiple DNS messages.
do {
throw new CommunicationException(
"DNS error: incomplete zone transfer");
}
} while (rrs.getLastAnsType() !=
}
// Delete the duplicate SOA record.
return rrs;
} finally {
}
} catch (IOException e) {
caughtException = e;
} catch (NameNotFoundException e) {
throw e;
} catch (NamingException e) {
caughtException = e;
}
}
if (caughtException instanceof NamingException) {
throw (NamingException) caughtException;
}
"DNS error during zone transfer");
throw ne;
}
/**
* Tries to retreive an UDP packet matching the given xid
* received within the timeout.
* If a packet with different xid is received, the received packet
* is enqueued with the corresponding xid in 'resps'.
*/
throws IOException, NamingException {
synchronized (udpSocket) {
try {
// timeout remaining after successive 'receive()'
int timeoutLeft = pktTimeout;
int cnt = 0;
do {
if (debug) {
cnt++;
dprint("Trying RECEIVE(" +
timeoutLeft + " ms.");
}
return data;
}
} while (timeoutLeft > minTimeout);
} finally {
}
return null; // no matching packet received within the timeout
}
}
/*
* Sends a TCP query, and returns the first DNS message in the response.
*/
// Send 2-byte message length, then send message.
throw new IOException("DNS error: no response");
}
return msg;
}
/*
* Returns the next DNS message from the TCP socket, or null on EOF.
*/
if (lenHi == -1) {
return null; // EOF
}
if (lenLo == -1) {
throw new IOException("Corrupted DNS response: bad length");
}
while (len > 0) {
if (n == -1) {
throw new IOException(
"Corrupted DNS response: too little data");
}
len -= n;
pos += n;
}
return msg;
}
return pkt;
}
// Builds a query name in pkt according to the RFC spec.
// Loop through labels, least-significant first.
for (int j = 0; j < len; j++) {
}
}
if (!fqdn.hasRootLabel()) {
}
}
//-------------------------------------------------------------------------
//
// Check the queued responses: some other thread in between
// received the response for this request.
//
if (debug) {
"\tResponse Q:" + resps);
}
byte[] pkt;
synchronized (queuesLock) {
}
if (debug) {
") for:" + xid);
}
}
return pkt;
}
/*
* Checks the header of an incoming DNS response.
* Returns true if it matches the given xid and throws a naming
* exception, if appropriate, based on the response code.
*/
throws NamingException {
throw new CommunicationException("DNS error: expecting response");
}
return false;
}
// common case- the request sent matches the subsequent response read
if (debug) {
}
// remove the response for the xid if received by some other thread.
synchronized (queuesLock) {
}
return true;
}
//
// xid mis-match: enqueue the response, it may belong to some other
// thread that has not yet had a chance to read its response.
// enqueue only the first response, responses for retries are ignored.
//
synchronized (queuesLock) {
}
}
if (debug) {
dprint("NO-MATCH SEND ID:" +
" Response Q:" + resps +
}
return false;
}
/*
* Throws an exception if appropriate for the response code of a
* given header.
*/
return;
}
: "DNS error";
switch (rcode) {
case SERVER_FAILURE:
throw new ServiceUnavailableException(msg);
case NAME_ERROR:
throw new NameNotFoundException(msg);
case NOT_IMPL:
case REFUSED:
throw new OperationNotSupportedException(msg);
case FORMAT_ERROR:
default:
throw new NamingException(msg);
}
}
//-------------------------------------------------------------------------
private static final boolean debug = false;
if (debug) {
}
}
}
class Tcp {
sock.setTcpNoDelay(true);
}
}
}
/*
* javaos emulation -cj
*/
class Packet {
byte buf[];
}
}
}
}
}
}
int length() {
}
byte[] getData() {
return buf;
}
}