How to Read All Network Cards with Java

How to enumerate IP addresses of all enabled NIC cards from Java?

This is pretty easy:

try {
InetAddress localhost = InetAddress.getLocalHost();
LOG.info(" IP Addr: " + localhost.getHostAddress());
// Just in case this host has multiple IP addresses....
InetAddress[] allMyIps = InetAddress.getAllByName(localhost.getCanonicalHostName());
if (allMyIps != null && allMyIps.length > 1) {
LOG.info(" Full list of IP addresses:");
for (int i = 0; i < allMyIps.length; i++) {
LOG.info(" " + allMyIps[i]);
}
}
} catch (UnknownHostException e) {
LOG.info(" (error retrieving server host name)");
}

try {
LOG.info("Full list of Network Interfaces:");
for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
NetworkInterface intf = en.nextElement();
LOG.info(" " + intf.getName() + " " + intf.getDisplayName());
for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
LOG.info(" " + enumIpAddr.nextElement().toString());
}
}
} catch (SocketException e) {
LOG.info(" (error retrieving network interface list)");
}

How to list all computers in network?

With the linked answers, you should be able to filter the available interfaces down to a few possible options (i.e. interfaces that are up, no loopback, have an IPv4 address, etc.).

To discover game hosts, you can do something like the following.

  • Let the game hosts listen for UDP broadcasts on a specific port.
  • Let the clients send out a UDP broadcast to the broadcast address of each of the remaining interfaces from above. The broadcast address can be determined by getBroadcast() in class InterfaceAddress.
  • The host replies, to let the client know it is waiting. When using UDP, the hosts IP is in the received DatagramPacket. When using TCP, the hosts IP can be determined from the Socket.
  • Then the client can use the address of the host to establish a direct connection and/or set up RMI.

Edit: I found this blog post, which includes code that does more or less what I described.

How to get all network interfaces in java and store the information in Java Map

`

Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();

while (interfaces.hasMoreElements())
{
NetworkInterface networkInterface = interfaces.nextElement();

Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();

}
}

`

Take a look at NetworkInterface, InterfaceInfo

More details here:
http://java.dzone.com/news/network-interface-details-java

Get name of a specific network interface in Java


Is there a reason why I am getting "eth15" as the name of my interface ?

That took some digging. In Java world, NetworkInterfaces are enumerated by java.net.NetworkInterface::getNetworkInterfaces() which calls the native java.net.NetworkInterface::getAll().

We can find the native source code for getAll() in OpenJDK 11 here where we find this comment:

/*
* Windows implementation of the java.net.NetworkInterface native methods.
* This module provides the implementations of getAll, getByName, getByIndex,
* and getByAddress.
*
* Interfaces and addresses are enumerated using the IP helper routines
* GetIfTable, GetIfAddrTable resp. These routines are available on Windows
* 98, NT SP+4, 2000, and XP. They are also available on Windows 95 if
* IE is upgraded to 5.x.
*
* Windows does not have any standard for device names so we are forced
* to use our own convention which is based on the normal Unix naming
* convention ("lo" for the loopback, eth0, eth1, .. for ethernet devices,
* tr0, tr1, .. for token ring, and so on). This convention gives us
* consistency across multiple Windows editions and also consistency with
* Solaris/Linux device names. Note that we always enumerate in index
* order and this ensures consistent device number across invocations.
*/

So once upon a time, when Windows 95 was still a thing, someone decided not to read the actual Windows interface names, and instead use "our own convention". Why? No idea. I would have preferred getting a separate deviceName() and a ourOwnConventionWhichHasNothingToDoWithTheActualNameDeviceName(), but unfortunately I wasn't consulted.

The underlying Windows API call GetIfTable does return a name for each interface in the form an array of MIB_IFROW:

typedef struct _MIB_IFROW {
WCHAR wszName[MAX_INTERFACE_NAME_LEN];
IF_INDEX dwIndex;
IFTYPE dwType;
DWORD dwMtu;
DWORD dwSpeed;
DWORD dwPhysAddrLen;
UCHAR bPhysAddr[MAXLEN_PHYSADDR];
DWORD dwAdminStatus;
INTERNAL_IF_OPER_STATUS dwOperStatus;
DWORD dwLastChange;
DWORD dwInOctets;
DWORD dwInUcastPkts;
DWORD dwInNUcastPkts;
DWORD dwInDiscards;
DWORD dwInErrors;
DWORD dwInUnknownProtos;
DWORD dwOutOctets;
DWORD dwOutUcastPkts;
DWORD dwOutNUcastPkts;
DWORD dwOutDiscards;
DWORD dwOutErrors;
DWORD dwOutQLen;
DWORD dwDescrLen;
UCHAR bDescr[MAXLEN_IFDESCR];
} MIB_IFROW, *PMIB_IFROW;

The JVM seems to read this array, then generate an "appropriate" name, and finally override the OS-provided name with the generated one.

In short, it doesn't look like the implementation has changed in many years, and it's probably impossible to change at this point without creating a completely new API. Otherwise you risk breaking people's code.

The way I see it, there are two ways to get the actual interface names:

  1. Use JNI to make the native call to GetIfTable yourself.
  2. Execute netsh and parse the response.

Both solutions are kinda ugly and require you to make sure you're running on Windows.

How to Determine Internet Network Interface in Java

On my laptop (running Windows 7, with Virtual Box and it's network interface installed) the following code prints out the name of my wireless interface along with my local address. It uses a brute force approach at the end of the day, but will only try and actually connect to addresses that are considered to be the best candidates.

// iterate over the network interfaces known to java
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
OUTER : for (NetworkInterface interface_ : Collections.list(interfaces)) {
// we shouldn't care about loopback addresses
if (interface_.isLoopback())
continue;

// if you don't expect the interface to be up you can skip this
// though it would question the usability of the rest of the code
if (!interface_.isUp())
continue;

// iterate over the addresses associated with the interface
Enumeration<InetAddress> addresses = interface_.getInetAddresses();
for (InetAddress address : Collections.list(addresses)) {
// look only for ipv4 addresses
if (address instanceof Inet6Address)
continue;

// use a timeout big enough for your needs
if (!address.isReachable(3000))
continue;

// java 7's try-with-resources statement, so that
// we close the socket immediately after use
try (SocketChannel socket = SocketChannel.open()) {
// again, use a big enough timeout
socket.socket().setSoTimeout(3000);

// bind the socket to your local interface
socket.bind(new InetSocketAddress(address, 8080));

// try to connect to *somewhere*
socket.connect(new InetSocketAddress("google.com", 80));
} catch (IOException ex) {
ex.printStackTrace();
continue;
}

System.out.format("ni: %s, ia: %s\n", interface_, address);

// stops at the first *working* solution
break OUTER;
}
}

(I've updated my answer with isReachable(...) based on Mocker Tim's answer.)

One thing to watch out for. socket.bind(...) would bark at me that the address and port is already in use if I tried to run my code too fast in succession like the connection isn't cleaned up fast enough. 8080 should be a random port maybe.

Java Server on multiple network interfaces

Finally I solved using something similar to this solution for multiple interfaces with multiple gataways:
NetworkManager: per device routing tables

In particular I divided the network in two size assigning some address to the tunneling interface and the other to the ethernet interface.

The only thing to pay attention is that instead of up the VPN uses vpn-up for his state.

How do I listen for network traffic on an interface/device using Java?

What you're looking for is simply outside of the scope for a universal java application.

If you're planning on keeping a specific OS in mind, such as Windows or Linux (my following examples), then there are a few things you can do.

For Windows, any given application will be unable to do this without driver privileges. WinPCap is probably the most widely used tool in this case, and that's what jpcap utilizes. It's a "driver" that basically just Man-in-the-middle's your traffic.

For Linux, take a look at this other post https://security.stackexchange.com/questions/13267/monitoring-outgoing-network-traffic

I know this is a sideways answer since it gives no Java code, but that's because Java simply isn't built to interface with the system in that way.



Related Topics



Leave a reply



Submit