How to reliably find local IP address?

It looks easy at the first glance. Just call InetAddress.getLocalHost() to get the local IP address. However, this method will not return the correct IP address when there are virtual interfaces on the machine.

For example, for a machine with vmware installed, there are at least three IP addresses listed by ipconfig:

Wireless LAN adapter Wireless Network Connection 4:

   Connection-specific DNS Suffix  . : gateway.2wire.net
   Link-local IPv6 Address . . . . . : fe80::2d6b:91f7:5bdd:7103%21
   IPv4 Address. . . . . . . . . . . : 192.168.2.100
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 192.168.2.1

Ethernet adapter VMware Network Adapter VMnet1:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::c53a:65e3:112:731%16
   IPv4 Address. . . . . . . . . . . : 192.168.172.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 

Ethernet adapter VMware Network Adapter VMnet8:

   Connection-specific DNS Suffix  . : 
   Link-local IPv6 Address . . . . . : fe80::2119:1d74:2a9e:2c25%17
   IPv4 Address. . . . . . . . . . . : 192.168.79.1
   Subnet Mask . . . . . . . . . . . : 255.255.255.0
   Default Gateway . . . . . . . . . : 
In the above example, VMnet1 and VMnet8 are virtual interfaces created by vmware software.
The InetAddress.getLocalHost() method returns 192.168.172.1, which belongs to the VMnet1 interface whose connection status is "No network access". Apparently, it is not right especially if the local address will be used in RMI stub, which will result in unrouteable RMI invocation. If we use the isVirtual() method in java.net.NetworkInterface to check if the VMnet1 and VMnet8 are virtual interfaces, it is also disappointing to find out that both of them are not virtual interfaces. So there is no way in Java to really exclude those virtual interfaces.

The most reliable way is to use the route table. On windows, "route print" command gives us something like:

Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.2.1     192.168.2.100    25
        127.0.0.0        255.0.0.0         On-link         127.0.0.1    306
     192.168.79.1  255.255.255.255         On-link      192.168.79.1    276
    192.168.172.1  255.255.255.255         On-link     192.168.172.1    276
We can see the default route uses interface 192.168.2.100.

On linux, we can check the route table at /proc/net/route

Iface	Destination	Gateway 	Flags	RefCnt	Use	Metric	Mask		MTU	Window	IRTT                                                       
p3p1	0002A8C0	00000000	0001	0	0	1	00FFFFFF	0	0	0                                                                               
vmnet8	0052A8C0	00000000	0001	0	0	0	00FFFFFF	0	0	0                                                                             
vmnet1	002B10AC	00000000	0001	0	0	0	00FFFFFF	0	0	0                                                                             
p3p1	00000000	0102A8C0	0003	0	0	0	00000000	0	0	0    
In this example, we can see the default route uses interface p3p1.

I created ParseRoute class for retrieving local IP address and default gateway information from route table. Code for parsing route table on Windows:

    private void parseWindows()
    {
        try
        {
            Process pro = Runtime.getRuntime().exec("cmd.exe /c route print");
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(pro.getInputStream())); 

            String line;
            while((line = bufferedReader.readLine())!=null)
            {
                line = line.trim();
                String [] tokens = Tokenizer.parse(line, ' ', true , true);// line.split(" ");
                if(tokens.length == 5 && tokens[0].equals("0.0.0.0"))
                {
                    _gateway = tokens[2];
                    _ip = tokens[3];
                    return;
                }
            }
            //pro.waitFor();      
        }
        catch(IOException e)
        {
            System.err.println(e);
            e.printStackTrace();
        }
    }
Code for parsing route table on linux:
    private void parseLinux()
    {
        try
        {
            BufferedReader reader = new BufferedReader(new FileReader("/proc/net/route"));
            String line;
            while((line = reader.readLine())!=null)
            {
                line = line.trim();
                String [] tokens = Tokenizer.parse(line, '\t', true , true);// line.split(" ");
                if(tokens.length > 1 && tokens[1].equals("00000000"))
                {
                    String gateway = tokens[2]; //0102A8C0
                    if(gateway.length() == 8)
                    {
                        String[] s4 = new String[4];
                        s4[3] = String.valueOf(Integer.parseInt(gateway.substring(0, 2), 16));
                        s4[2] = String.valueOf(Integer.parseInt(gateway.substring(2, 4), 16));
                        s4[1] = String.valueOf(Integer.parseInt(gateway.substring(4, 6), 16));
                        s4[0] = String.valueOf(Integer.parseInt(gateway.substring(6, 8), 16));
                        _gateway = s4[0] + "." + s4[1] + "." + s4[2] + "." + s4[3];
                    }
                    String iface = tokens[0];
                    NetworkInterface nif = NetworkInterface.getByName(iface);
                    Enumeration addrs = nif.getInetAddresses();
                    while(addrs.hasMoreElements())
                    {
                        Object obj = addrs.nextElement();
                        if(obj instanceof Inet4Address)
                        {
                            _ip =  obj.toString();
                            if(_ip.startsWith("/")) _ip = _ip.substring(1);
                            return;
                        }
                    }
                    return;
                }
            }
            reader.close();
        }
        catch(IOException e)
        {
            System.err.println(e);
            e.printStackTrace();
        }
    }

Usage Example:

            ParseRoute pr = ParseRoute.getInstance();
            System.out.println( "Gateway: " + pr.getGateway() );
            System.out.println( "IP: " + pr.getLocalIPAddress() );
You can download source code here. Or view the main class online: ParseRoute.java

 

Please feel free to contact support@ireasoning.com if you have any questions.

 

 


Tags: Local IP Address Route Table

Home