how to get the ip address of the connected interface - java

the way how we get Ip address using java code is clear and many questions about this subject were answered.
but assuming that you have Vmware or VirtualBox on your machine,so you will have extra virtual network cards each one have its own Ip Address.
when executing a little program the result was like 192.168.x.x which belongs to one of my virtual network adapters.
but using "What Is My IP" the result was like 197.x.x.x
so how can i get the ip adress of the connected interface ?

this should do the trick:
import java.io.*;
import java.util.*;
public class ExecTest {
public static void main(String[] args) throws IOException {
Process result = Runtime.getRuntime().exec("traceroute -m 1 www.amazon.com");
BufferedReader output = new BufferedReader(new InputStreamReader(result.getInputStream()));
String thisLine = output.readLine();
StringTokenizer st = new StringTokenizer(thisLine);
st.nextToken();
String gateway = st.nextToken();
System.out.printf("The gateway is %s\n", gateway);
}
}
Courtesy of Chris Bunch from: How can I determine the IP of my router/gateway in Java?
Greets!

Your interface IP 192.168.x.x is your local adapter interface. The prefix 192.168 indicates that this is a private non-routable address that is valid only behind a NAT firewall.
The IP returned by WhatIsMyIP is the external address of the firewall/gateway through which you access the Internet. Unless your computer is connected directly to the Internet these two addresses will never be the same.

Related

Why does HttpServletRequest.getRemoteAddr() with IPv6 address return extra characters

In my Tomcat-hosted web app, the first two lines in a doGet(...) method are:
String ip = request.getRemoteAddr();
System.out.println("ip = " + ip);
With an IPv6 address on our local network, it outputs:
ip = fe80:0:0:0:ac40:98cb:ca2e:c03c%4
The %4 at the end seems extraneous. It is causing requests to our geolocation service to fail. Is this %4 supposed to be there? If so, what does it signify? Is there a reliable way to get a IPv6 address from an HttpServletRequest instance that does NOT have the %4?
It's the scope ID. Using native APIs, your best bet to get rid of it would be as below with help of java.net.InetAddress and Inet6Address#getScopeId():
String ip = request.getRemoteAddr();
InetAddress inetAddress = InetAddress.getByName(ip);
if (inetAddress instanceof Inet6Address) {
Inet6Address inet6Address = (Inet6Address) inetAddress;
int scopeId = inet6Address.getScopeId();
if (scopeId > 0) {
ip = inet6Address.getHostName().replaceAll("%" + scopeId + "$", "");
}
}
This clumsiness is because the standard java.net.Inet6Address API doesn't have any method which returns the bare hostname without scope ID.
On the other hand, I'd wonder if the geolocation service in question should in turn not already be taking that into account. If the support for IPv6 scopes is even not explicitly excluded in their API documentation, then I'd file an issue at their issue tracker.

Get the name and IP of devices on a Wifi network

I know this question has been asked here but it didn't get answered.
I'm writing a simple Java Swing application in which I want to show the name and IP address of each and every device that is connected to my wireless network.
I want to show this list in a JFrame. I searched a lot on the web but couldn't find a way to achieve this. Please help me out Java masters!
Thanks in advance!
I found this code after looking a little bit. It works, but it is slow, and probably not the best way to do it, but it works.
import java.io.IOException;
import java.net.InetAddress;
public class NetworkPing {
/**
* JavaProgrammingForums.com
*/
public static void main(String[] args) throws IOException {
InetAddress localhost = InetAddress.getLocalHost();
// this code assumes IPv4 is used
byte[] ip = localhost.getAddress();
for (int i = 1; i <= 254; i++)
{
ip[3] = (byte)i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(1000))
{
System.out.println(address + " machine is turned on and can be pinged");
}
else if (!address.getHostAddress().equals(address.getHostName()))
{
System.out.println(address + " machine is known in a DNS lookup");
}
else
{
System.out.println(address + " the host address and host name are equal, meaning the host name could not be resolved");
}
}
}
}
Couple things to note, address.getHostAddress() returns the 192.168.0.xxx
and address.getHostName() returns the name of the device like "Kevins-PC"
It's a pretty simple piece of code, but I'll walk through it real fast.
It starts off by getting your localhost IP address (which on a normal household network would be 192.168.0.xxx) and it stores that in a byte[] so it looks something like {192, 168, 0, xxx}.
Then it creates a for loop starting at 1 and going to 254 (because this code assumes a /24 subnet mask (255.255.255.0) but if its running a different subnet mask then it might not be 1-254).
Then in the for loop it sets the third index of the ip to i.
It then creates an InetAddress from that address.
Then it tries to reach it in 1000 milliseconds (1 second), and if it succeeds then it prints the address and says its reachable.
Else if the machine host address (the 192.168.0.xxx) does not equal the host name (like the name of your computer like Kevins-PC), then it says that the machine is known in a DNS lookup meaning it is found in a DNS lookup but it wasnt reachable (so its probably off or not connected, but it has been before), DNS is Domain Name Service. The DNS basically stores the information (your router probably does this).
Finally, else it just says it couldn't be resolved which means it wasnt reachable nor was it found looking in the DNS.
I found this code here and here
UPDATE
So if you run this and you just keep getting something like "192.168.0.5/192.168.0.5 the host address and host name are equal, meaning the host name could not be resolved"
That means that your router (your local DNS) just isn't storing the information OR those devices just choose not to submit their host name to the router, and that is why you will continually get that message. As far as I am aware, there isn't a way around this because those device names literally aren't stored
Try this :)
import java.io.IOException;
import java.net.*;
import java.util.Vector;
public class search {
public static void main(String args[]) throws UnknownHostException{
Vector<String> Available_Devices=new Vector<>();
String myip=InetAddress.getLocalHost().getHostAddress();
String mynetworkips=new String();
for(int i=myip.length();i>0;--i) {
if(myip.charAt(i-1)=='.'){ mynetworkips=myip.substring(0,i); break; }
}
System.out.println("My Device IP: " + myip+"\n");
System.out.println("Search log:");
for(int i=1;i<=254;++i){
try {
InetAddress addr=InetAddress.getByName(mynetworkips + new Integer(i).toString());
if (addr.isReachable(1000)){
System.out.println("Available: " + addr.getHostAddress());
Available_Devices.add(addr.getHostAddress());
}
else System.out.println("Not available: "+ addr.getHostAddress());
}catch (IOException ioex){}
}
System.out.println("\nAll Connected devices(" + Available_Devices.size() +"):");
for(int i=0;i<Available_Devices.size();++i) System.out.println(Available_Devices.get(i));
}
}

How to put in an entry into dnsjava cache to override DNS lookup

In trying to avoid having a hostname looked up from the public DNS for testing purposes, I need to essentially set /etc/hosts file, but I don't always know what hostnames I'll need to override the IP address for, so I'm trying to use dnsjava since the default Java DNS resolving doesn't allow for inserting directly into the cache.
Basically, you need to grab the correct DNS Type cache for dnsjava (A, AAAA, etc). Most likely A (for IPv4) or AAAA (for IPv6) is what you should use, although all of the other DNS entry types are also supported. You'll need to create a Name instance, and from that an ARecord which will be inserted into the Cache. Example is as below:
public void addHostToCacheAs(String hostname, String ipAddress) throws UnknownHostException, TextParseException {
//add an ending period assuming the hostname is truly an absolute hostname
Name host = new Name(hostname + ".");
//putting in a good long TTL, and using an A record, but AAAA might be desired as well for IPv6
Record aRec = new ARecord(host, Type.A, 9999999, getInetAddressFromString(ipAddress));
Lookup.getDefaultCache(Type.A).addRecord(aRec, Credibility.NORMAL,this);
}
public InetAddress getInetAddressFromString(String ip) throws UnknownHostException {
//Assume we are using IPv4
byte[] bytes = new byte[4];
String[] ipParts = ip.split("\\.");
InetAddress addr = null;
//if we only have one part, it must actually be a hostname, rather than a real IP
if (ipParts.length <= 1) {
addr = InetAddress.getByName(ip);
} else {
for (int i = 0; i < ipParts.length; i++) {
bytes[i] = Byte.parseByte(ipParts[i]);
}
addr = InetAddress.getByAddress(bytes);
}
return addr
}

Retrieving a MAC address from a PING sweep

i have developed a code which enables me to ping a range of IP addresses. The results from my ping sweep identifies what local machines are reachable, if reachable there hostname and also if they are not reachable.
I am having trouble at the moment retrieving the MAC address of the reachable IP addresses. Has anyone got a solution for this?
package networkping;
import java.io.IOException;
import java.net.InetAddress;
/**
*
* #author Learner
*/
public class Networkping {
public static void main(String[] args) throws IOException {
InetAddress localhost = InetAddress.getLocalHost();
// this code assumes IPv4 is used
byte[] ip = localhost.getAddress();
for (int i = 1; i <= 254; i++)
{
ip[3] = (byte)i;
InetAddress address = InetAddress.getByAddress(ip);
if (address.isReachable(1000))
{
System.out.println(address + " Address is reachable" );
}
else if (!address.getHostAddress().equals(address.getHostName()))
{
System.out.println(address + " Address is known in a DNS lookup and is reachable ");
}
else
{
System.out.println(address + " Address is unreachable");
}
}
}
Thanks
You cannot do this just using java.
There are two options:
Execute another process through java and communicate through standard output with your original java application. Such a process is ARP for example.
use JNI as suggested in the comments.
Have a look also at the following resources/answers:
https://stackoverflow.com/a/14650693
https://stackoverflow.com/a/14857412/1688441
The second resource even has an implemented method calling ARP named private String getMac(String ip)

How do you tell whether a string is an IP or a hostname

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.
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.
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.
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.
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.
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.
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
Couldn't you just to a regexp match on it?
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
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?

Categories