PDA

View Full Version : Java Reverse DNS Lookup


120
11-24-2009, 07:14 PM
Hi - I've had a look around for places where I can get some help/advice on a Java issue I have? I've tried usenet but the groups look almost dead(?). Coding Forums has come highly recommended.

I'm new to Java, but have some general programming and shell experience. I was pleasantly surprised to find how quick and easy it is to get working code out of Java - but I'm struggling with DNS lookups.

Basically, I'm trying to mimic a reverse dns lookup (ip to full PTR) like I would get with:

dig -x 211.21.152.4
or
host 211.21.152.4

This code works-ish:

import java.net.*;
//.......
try {
InetAddress thost = InetAddress.getByName("211.21.152.4");
//HostName = thost.getHostName();
HostName = thost.getCanonicalHostName();
System.out.println("HOST: "+HostName);
} catch (UnknownHostException e) {
System.out.println("NO HOST");
}

NOTE: tried thost.getCanonicalHostName & getHostName
The issue I'm getting is the result is not consistent with DNS.
This code returns: HOST: 211.21.152.4

but, dig -x 211.21.152.4 returns
211-21-152-4.HINET-IP.hinet.net
AND
host 211.21.152.4 returns:
211-21-152-4.HINET-IP.hinet.net.

At first I thought the methods getHostName/getCanonicalHostName were returning what it thought was the hostname from the string, and it was extremely intelligent in finding this name. I also noted the docs warned that if there was a security manager in place, 'a textual representation of the IP address would be returned'. That was fine until I tried the code again with 80.75.69.195 and the Java code returned the full PTR as dig -x or host would:

HOST: web1.redut.net

Basically it appears that if the DNS PTR contains something that looks like an IP address, the Java methods are returning it rather than the whole pointer.

What I want is the whole pointer line from a reverse DNS lookup. I know there is an xbill dns library, but my concern is - assuming I can figure out how to install it - this will make what I am writing less portable(?) and require target JVM to have the library. I would really like to keep it to the core libraries at this stage.

Does anyone know what I can do to get the full pointer, regardless of if parts of it *look* like an IP? Any help or pointers to other places to ask would be really appreciated.

I know it must irritate regular posters here when someone new bursts in, asks a question, gets an answer and never contributes again. I promise not to do that now that I've found this forum.

Mike

TheShaner
11-24-2009, 10:12 PM
Try this instead:
byte[] ipAddr = new byte[] {211, 21, 152, 4};
InetAddress addr = InetAddress.getByAddress(ipAddr);
String hostname = addr.getCanonicalHostName();
I know both the getByName and getByAddress methods return an InetAddress object, but I'm not sure if there is a difference regarding the information put into the returned object with those methods. It's at least worth a shot.

Also, it looks as if both getHostName and getCanonicalHostName check to see whether they can establish a socket connection to the address. If it cannot, then it determines that it does not have permission to do a reverse lookup. The two commands, dig and host, do not attempt socket connections, as far as I know. So that may be the discrepancy. But again, I don't have any real knowledge in this area of Java.

Honestly, the regulars here don't mind whether you post once or 100 times, or always receive help and never reciprocate (as long as problems are stated clearly with an honest attempt in solving them yourself, which you've clearly done). If we can help you, then we've done our job. Sticking around is your choice and we always appreciate new faces. Good luck :thumbsup:

-Shane

120
11-25-2009, 06:23 AM
Thanks Shane.

Example tried but refused to compile:

rdns.java:101: possible loss of precision
found : int
required: byte
byte[] ipAddr = new byte[] {211, 21, 152, 4};
^
rdns.java:101: possible loss of precision
found : int
required: byte
byte[] ipAddr = new byte[] {211, 21, 152, 4};

Java being knew to me, I figured 'well, it's found INT but wants byte, what happens if I change the array to an INT array....


rdns.java:103: cannot find symbol
symbol : method getByAddress(int[])
location: class java.net.InetAddress
InetAddress addr = InetAddress.getByAddress(ipAddr);
^
1 error

I can't quite figure why your array of bytes throws this error? To me all the values are under 255 -hence bytes- ?

TheShaner
11-25-2009, 01:35 PM
Example tried but refused to compile:

rdns.java:101: possible loss of precision
found : int
required: byte
byte[] ipAddr = new byte[] {211, 21, 152, 4};
^
rdns.java:101: possible loss of precision
found : int
required: byte
byte[] ipAddr = new byte[] {211, 21, 152, 4};

Sorry about that. Try:
byte[] ipAddr = new byte[] {(byte)211, (byte)21, (byte)152, (byte)4};
You need to cast each number passed into the array as a byte. Without a specific typecasting, Java assumes that any whole number is an integer.

Also, the getByAddress method only accepts byte arrays, so it throws an error if you pass anything in that is not a byte array.

-Shane

120
11-25-2009, 02:34 PM
Thanks Shane, but I've solved this using JNDI-v-DNS. Here is the solution in case anyone else is trying to do reverse DNS lookups with Java:


THIS EXAMPLE {mostly stolen elsewhere from the Sun forum} WORKS FLAWLESSLY and makes use the default system DNS. The key (and like a knob I forgot this) is to reverse the octets of the IP and append the in-addr.arpa zone to them when looking for the PTR (this will *not* work InetAddress methods as far as I can tell, hence making use of JDNI)


/**

* 25 Nov 2009 REVERSE DNS LOOKUP USING JNDI

* In this example the IP being looked up is 211.21.152.4

* The octets are reversed (4.152.21.211)

* and appended to the in-addr.arpa zone:

* 4.152.21.211.in-addr.arpa

*/



import javax.naming.*;

import javax.naming.directory.*;

import java.util.*;



public class dns {

public static void main(String[] args) {

try {

Hashtable env = new Hashtable();

env.put("java.naming.factory.initial", "com.sun.jndi.dns.DnsContextFactory");

DirContext ctx = new InitialDirContext(env);



Attributes attrs = ctx.getAttributes("4.152.21.211.in-addr.arpa",new String[] {"PTR"});



for (NamingEnumeration ae = attrs.getAll();ae.hasMoreElements();) {

Attribute attr = (Attribute)ae.next();

String attrId = attr.getID();

for (Enumeration vals = attr.getAll();vals.hasMoreElements(); System.out.println(attrId + ": " + vals.nextElement()));

}



ctx.close();

}

catch(Exception e) {

System.out.println("NO REVERSE DNS");

}

}

}



OUTPUT IS NOW AS EXPECTED:
PTR: 211-21-152-4.HINET-IP.hinet.net.

Compiling may give these warnings re: generics

dns.java uses unchecked or unsafe operations.
Recompile with -Xlint:unchecked for details

These can be ignored (program will still compile) OR modify one line:

Hashtable<String,String> env = new Hashtable<String,String>()

Hope that helps someone else who is looking to solve this. Thanks for the input. Another day of learning, time for a beer :-)

120
11-25-2009, 02:38 PM
Can a MOD change the subject of the post for the benefit of others/search engines?

Something like 'REVERSE DNS LOOKUP WITH JAVA'? may be more helpful?