Reputation: 99
So you have a String that is retrieved from an admin web UI (so it is definitely a String). How can you find out whether this string is an IP address or a hostname in Java?
Update: I think I didn't make myself clear, I was more asking if there is anything in the Java SDK that I can use to distinguish between IPs and hostnames? Sorry for the confusion and thanks for everybody who took/will take the time to answer this.
Upvotes: 4
Views: 4750
Reputation: 85
This code still performs the DNS lookup if a host name is specified, but at least it skips the reverse lookup that may be performed with other approaches:
...
isDottedQuad("1.2.3.4");
isDottedQuad("google.com");
...
boolean isDottedQuad(String hostOrIP) throws UnknownHostException {
InetAddress inet = InetAddress.getByName(hostOrIP);
boolean b = inet.toString().startsWith("/");
System.out.println("Is " + hostOrIP + " dotted quad? " + b + " (" + inet.toString() + ")");
return b;
}
It generates this output:
Is 1.2.3.4 dotted quad? true (/1.2.3.4)
Is google.com dotted quad? false (google.com/172.217.12.238)
Do you think we can expect the toString() behavior to change anytime soon?
Upvotes: 0
Reputation: 337
Use InetAddress#getAllByName(String hostOrIp) - if hostOrIp
is an IP-address the result is an array with single InetAddress and it's .getHostAddress()
returns the same string as hostOrIp
.
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
public class IPvsHostTest {
private static final org.slf4j.Logger LOG = org.slf4j.LoggerFactory.getLogger(IPvsHostTest.class);
@org.junit.Test
public void checkHostValidity() {
Arrays.asList("10.10.10.10", "google.com").forEach( hostname -> isHost(hostname));
}
private void isHost(String ip){
try {
InetAddress[] ips = InetAddress.getAllByName(ip);
LOG.info("IP-addresses for {}", ip);
Arrays.asList(ips).forEach( ia -> {
LOG.info(ia.getHostAddress());
});
} catch (UnknownHostException e) {
LOG.error("Invalid hostname", e);
}
}
}
The output:
IP-addresses for 10.10.10.10
10.10.10.10
IP-addresses for google.com
64.233.164.100
64.233.164.138
64.233.164.139
64.233.164.113
64.233.164.102
64.233.164.101
Upvotes: 0
Reputation: 4605
It is not as simple as it may appear, there are some ambiguities around characters like hyphens, underscore, and square brackets '-', '_', '[]'.
The Java SDK is has some limitations in this area. When using InetAddress.getByName it will go out onto the network to do a DNS name resolution and resolve the address, which is expensive and unnecessary if all you want is to detect host vs address. Also, if an address is written in a slightly different but valid format (common in IPv6) doing a string comparison on the results of InetAddress.getByName will not work.
The IPAddress Java library will do it. The javadoc is available at the link. Disclaimer: I am the project manager.
static void check(HostName host) {
try {
host.validate();
if(host.isAddress()) {
System.out.println("address: " + host.asAddress());
} else {
System.out.println("host name: " + host);
}
} catch(HostNameException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
HostName host = new HostName("1.2.3.4");
check(host);
host = new HostName("1.2.a.4");
check(host);
host = new HostName("::1");
check(host);
host = new HostName("[::1]");
check(host);
host = new HostName("1.2.?.4");
check(host);
}
Output:
address: 1.2.3.4
host name: 1.2.a.4
address: ::1
address: ::1
1.2.?.4 Host error: invalid character at index 4
Upvotes: 1
Reputation: 12684
You can use a security manager with the InetAddress.getByName(addr)
call.
If the addr is not a dotted quad, getByName
will attempt to perform a connect to do the name lookup, which the security manager can capture as a checkConnect(addr, -1)
call, resulting in a thrown SecurityException that you can catch.
You can use System.setSecurityManager()
if you're running fully privileged to insert your custom security manager before the getByName
call is made.
Upvotes: 1
Reputation: 7631
You can see if the string matches the number.number.number.number format, for example:
\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b
will match anything from 0 - 999
.
Anything else you can have it default to hostname.
Upvotes: 2
Reputation: 2201
You can use a regular expression with this pattern:
\b(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b
That will tell you if it's an IPv4 address.
Upvotes: 15
Reputation: 138874
URI validator = new URI(yourString);
That code will validate the IP address or Hostname. (It throws a malformed URI Exception if the string is invalid)
If you are trying to distinguish the two..then I miss read your question.
Upvotes: 1
Reputation: 415735
Do we get to make the assumption that it is one or the other, and not something completely different? If so, I'd probably use a regex to see if it matched the "dotted quad" format.
Upvotes: 2