Query ARP cache to get MAC ID

I need to get the MAC ID of a host in my network. For that, if I ping to that IP and query the ARP cache arp -a, I am able to get the MAC ID. I just wonder if I can get any API to query the ARP and get the MAC id.

Also, if there is a better method to get the MAC ID from IP address, please suggest.

P.S: I am working in JAVA.

Thanks.


Java provides no direct way to query the MAC address of a host in your network, as this is abstracted away by Java's socket libraries.

In a way, this makes sense, because the MAC address of a host actually says very little. There is no such thing as "the" MAC address of a host.

  • Many hosts will have several NICs, all with a separate MAC address, with which they can connect to the network. The computer I'm on at the moment has a wired ethernet adapter, a WiFi adapter, and a Firewire adapter, and they all have their own MAC address. This means that there is no definitive MAC address for a host.
  • If the host is on a different subnet, ARP will actually give you the MAC address for the last router your packet passed through, instead of the MAC address of the host you're scanning.

Put both of these issues together, and that means that one host may have many different MAC addresses (if it has more than one NIC), and one MAC address may represent many different hosts (if traffic passes through a router).

Assuming you know all this and you still need to get the MAC address of a host, the only way to do that in Java is by "going native":

  • Native to the client that runs your program:
    • You could launch an ARP command-line tool and parse its output.
    • You could use some sort of JNI call. I'm not too familiar with JNI, though, so I can't help you with that.
    • Write a separate, small native app that you can access from Java via Telnet or some such protocol, and which will run the ARP command for you.
  • Native to the host that you want to scan:
    • You could use SNMP, as some of the other answers to this thread suggest. I defer to these answers for making that work for you. SNMP is a great protocol, but be aware that SNMP's OIDs can be both platform-dependent and vendor-dependent. OIDs that work for Windows don't always work for Linux and vice versa.
    • If you know that your host runs Windows, you could use WMI. The Win32_NetworkAdapter class holds the information you want, but be aware that this returns all of the hosts NICs, even the ones Windows makes up. Also, it requires administrator credentials to the host you are scanning. Google will tell you how to connect to WMI from Java.
    • If you know your host runs OS X, you might be able to SSH into the machine and parse the output of the system_profile command.
    • For Linux, a tool similar to OS X's system_profile probably exists.

There is a much simpler way:

private static final String ARP_GET_IP_HW = "arp -a";

public String getARPTable(String cmd) throws IOException {
           Scanner s = new Scanner(Runtime.getRuntime().exec(cmd).getInputStream()).useDelimiter("\\A");
                return s.hasNext() ? s.next() : "";
    }

System.out.println(getARPTable(ARP_GET_IP_HW ));

And you get the eintire ARP Table with IP and HW sorted on each row.

Then you can split the table into separate String rows and use regular expressions on each row to match both HW and IP Adress. And you're done.


ARP is the way to map IP addresses to MAC addresses. That's how the IP stack does it.

I'm not sure there is a portable way to get that info, since it is typically only important for kernel developers and system administrators.

From a lot of web searching, it looks like it is possible to get a router's ARP table using SNMP, but I didn't find a lot of specific info on how to do it. I did find a free Java library for SNMP here though. Some spelunking through there might prove productive.


You can get your own MAC address via:

Enumeration<NetworkInterface> it = NetworkInterface.getNetworkInterfaces();
while ( it.hasMoreElements() ) {
    byte[] macAddress = it.nextElement().getHardwareAddress();
}

There is definitely no way you can get the MAC address of another host via vanilla java. You'd have to use Process execution or a native library to do it.

If you control the other machines, you can let them query their own MAC and send it back across a TCP/IP channel, but I'm guessing that's not what you want. For more details, see jqno's answer.