NetworkInterface.getNetworkInterfaces() not listing all interfaces
java
Solution
Obviously, I was wrong in the first place: even though both `ifconfig` and the Java API are using the same `ioctl()` syscalls, they behave differently.
First of all, the `SIOCGIFCONF ioctl()` is documented as follows (see http://linux.die.net/man/7/netdevice):
SIOCGIFCONF
Return a list of interface (transport layer) addresses.
...
The kernel fills the ifreqs with all current L3 interface
addresses that are running.
So, the `SIOCGIFCONF ioctl()` which is used by both `ifconfig` and the JAVA API only returns the running interfaces. This can also be seen in the `strace ifconfig ...` output from the question - the very first `ioctl` only returns `lo` and `wlan0`, but not eth0.
Then, where does `ifconfig` get the `eth0` from at all? Checking the `ifconfig` source code (from the `net-tools` package on Debian/Ubuntu), we see that `ifconfig` is not using the result from the `ioctl()` as the basis for the network device enumeration, but first of all reads the `/proc` filesystem to determine all network interfaces. Then, it uses the `ioctl()` syscalls to determine further information about each interface.
Unfortunately, the `java.net.NetworkInterface.getByName()` method does not even return a network interface object for an unconfigured interface if we explicitly pass the name, like `eth0`.
Essentially, there remain three different approaches to get the hardware addresses of all devices on Linux:
- Call `ifconfig` and parse the output (should be last resort)
- Implement a JNI library to do the same what `ifconfig` does (requires an architecture dependent shared library)
- Read the data directly from the `/proc` and the `/sys` filesystems.
All of these approaches are system dependant and not portable. The benefit of the third approach is that it can be implemented in pure Java. The following is a sample implementation of the third approach which worked well in my environment:
static void printHardwareAddresses() throws SocketException {
if (System.getProperty("os.name").equals("Linux")) {
// Read all available device names
List<String> devices = new ArrayList<>();
Pattern pattern = Pattern.compile("^ *(.*):");
try (FileReader reader = new FileReader("/proc/net/dev")) {
BufferedReader in = new BufferedReader(reader);
String line = null;
while( (line = in.readLine()) != null) {
Matcher m = pattern.matcher(line);
if (m.find()) {
devices.add(m.group(1));
}
}
} catch (IOException e) {
e.printStackTrace();
}
// read the hardware address for each device
for (String device : devices) {
try (FileReader reader = new FileReader("/sys/class/net/" + device + "/address")) {
BufferedReader in = new BufferedReader(reader);
String addr = in.readLine();
System.out.println(String.format("%5s: %s", device, addr));
} catch (IOException e) {
e.printStackTrace();
}
}
} else {
// use standard API for Windows & Others (need to test on each platform, though!!)
...
}
}
Problem
I have three interfaces `(eth0,Loopback,wlan0)` on my machine and i want to get use Java-API to get the mac address. I use this code. ``` Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces(); for (NetworkInterface netint : Collections.list(nets)) displayInterfaceInformation(netint); } static void displayInterfaceInformation(NetworkInterface netint) throws SocketException { System.out.println("Display name: " + netint.getDisplayName()); System.out.println("Hardware address: " + Arrays.toString(netint.getHardwareAddress())); } ``` But that code print `wlan0,loopback`, but missed eth0 . - My OS Ubuntu, any help. Update The o/p (`strace -f java Networks 2>&1| grep ioctl`).. blank(empty). `java -version` java version "1.7.0_21" Java(TM) SE Runtime Environment (build 1.7.0_21-b11) Java HotSpot(TM) 64-Bit Server VM (build 23.21-b01, mixed mode) - strace ifconfig 2>&1 | grep ioctl ` ``` ioctl(4, SIOCGIFCONF, {80, {{"lo", {AF_INET, inet_addr("127.0.0.1")}}, {"wlan0", {AF_INET, inet_addr("192.168.1.101")}}}}) = 0 ioctl(5, SIOCGIFFLAGS, {ifr_name="eth0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_MULTICAST}) = 0 ioctl(5, SIOCGIFHWADDR, {ifr_name="eth0", ifr_hwaddr=-----------------}) = 0 ioctl(5, SIOCGIFMETRIC, {ifr_name="eth0", ifr_metric=0}) = 0 ioctl(5, SIOCGIFMTU, {ifr_name="eth0", ifr_mtu=1500}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="eth0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFTXQLEN, {ifr_name="eth0", ifr_qlen=1000}) = 0 ioctl(4, SIOCGIFADDR, {ifr_name="eth0", ???}) = -1 EADDRNOTAVAIL (Cannot assign requested address) ioctl(5, SIOCGIFFLAGS, {ifr_name="lo", ifr_flags=IFF_UP|IFF_LOOPBACK|IFF_RUNNING}) = 0 ioctl(5, SIOCGIFHWADDR, {ifr_name="lo", ifr_hwaddr=00:00:00:00:00:00}) = 0 ioctl(5, SIOCGIFMETRIC, {ifr_name="lo", ifr_metric=0}) = 0 ioctl(5, SIOCGIFMTU, {ifr_name="lo", ifr_mtu=16436}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="lo", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="lo", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFTXQLEN, {ifr_name="lo", ifr_qlen=0}) = 0 ioctl(4, SIOCGIFADDR, {ifr_name="lo", ifr_addr={AF_INET, inet_addr("127.0.0.1")}}) = 0 ioctl(4, SIOCGIFDSTADDR, {ifr_name="lo", ifr_dstaddr={AF_INET, inet_addr("127.0.0.1")}}) = 0 ioctl(4, SIOCGIFBRDADDR, {ifr_name="lo", ifr_broadaddr={AF_INET, inet_addr("0.0.0.0")}}) = 0 ioctl(4, SIOCGIFNETMASK, {ifr_name="lo", ifr_netmask={AF_INET, inet_addr("255.0.0.0")}}) = 0 ioctl(5, SIOCGIFFLAGS, {ifr_name="wlan0", ifr_flags=IFF_UP|IFF_BROADCAST|IFF_RUNNING|IFF_MULTICAST}) = 0 ioctl(5, SIOCGIFHWADDR, {ifr_name="wlan0", ifr_hwaddr=---------------}) = 0 ioctl(5, SIOCGIFMETRIC, {ifr_name="wlan0", ifr_metric=0}) = 0 ioctl(5, SIOCGIFMTU, {ifr_name="wlan0", ifr_mtu=1500}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="wlan0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFMAP, {ifr_name="wlan0", ifr_map={mem_start=0, mem_end=0, base_addr=0, irq=0, dma=0, port=0}}) = 0 ioctl(5, SIOCGIFTXQLEN, {ifr_name="wlan0", ifr_qlen=1000}) = 0 ioctl(4, SIOCGIFADDR, {ifr_name="wlan0", ifr_addr={AF_INET, inet_addr("192.168.1.101")}}) = 0 ioctl(4, SIOCGIFDSTADDR, {ifr_name="wlan0", ifr_dstaddr={AF_INET, inet_addr("192.168.1.101")}}) = 0 ioctl(4, SIOCGIFBRDADDR, {ifr_name="wlan0", ifr_broadaddr={AF_INET, inet_addr("192.168.1.255")}}) = 0 ioctl(4, SIOCGIFNETMASK, {ifr_name="wlan0", ifr_netmask={AF_INET, inet_addr("255.255.255.0")}}) = 0 ``` ` ifconfig ``` $ ifconfig eth0 Link encap:Ethernet HWaddr ------------- UP BROADCAST MULTICAST MTU:1500 Metric:1 RX packets:0 errors:0 dropped:0 overruns:0 frame:0 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:0 (0.0 B) TX bytes:0 (0.0 B) lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 inet6 addr: ::1/128 Scope:Host UP LOOPBACK RUNNING MTU:16436 Metric:1 RX packets:1695 errors:0 dropped:0 overruns:0 frame:0 TX packets:1695 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:0 RX bytes:129949 (129.9 KB) TX bytes:129949 (129.9 KB) wlan0 Link encap:Ethernet HWaddr ------------------- inet addr:192.168.1.101 Bcast:192.168.1.255 Mask:255.255.255.0 inet6 addr: fe80::-------------- Scope:Link UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:8396 errors:0 dropped:0 overruns:0 frame:0 TX packets:5524 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000 RX bytes:3959941 (3.9 MB) TX bytes:1513934 (1.5 MB) ```