Obter MAC de um host na rede

Olá pessoal! Estou mexendo com um projeto aqui, que conta com vários hosts em uma rede com DHCP. No meu server, eu tenho um banco onde armazeno a lista de dispositivos. A princípio tentei armazenar por IP, mas com o DHCP, quase sempre os hosts estão mudando de IP quando são desligados e ligados novamente. A alternativa seria salvar a informação do MAC de cada dispositivo, para eu saber que ele é ele. Tentei utilizar o método getHardwareAddress() da classe NetworkInterface, mas não consigo uma instância dela a partir do endereço IP (talvez ela só funcione para interfaces de rede locais?). Alguém sabe alguma forma de eu conseguir obter o MAC de um dispositivo na rede?

O serviço precisa te enviar o endereço físico por broadcast.

Procure por alguma biblioteca em Java que implemente o protocolo ARP.

Depois de ralar um pouco e perder mais um pouco dos meus cabelos ainda sobreviventes, criei uma classe que faz a busca da tabela ARP do próprio SO. Se alguém tiver algum palpite para melhorá-la, fique à vontade:

[code]package net.rafaeltoledo.util;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;

public abstract class NetworkUtils {

public static String getMacAddress(String ip) {
	String macAddr = null;
	
	try {
		// Host Windows
		String osName = System.getProperty("os.name");
		if (osName.contains("Windows")) {
			Process child = Runtime.getRuntime().exec("arp -a");
			InputStream in = child.getInputStream();
			String output = "";
			int c;
			while ((c = in.read()) != -1) {
				output += (char) c;
			}
			in.close();
			
			String line = null;
			String[] splitted = output.split("\n");
			for (String portion : splitted) {
				if (line.contains(ip)) {
					line = portion;
				}
			}
			
			splitted = line.split(" +");
			for (String portion : splitted) {
				if (portion.matches("..-..-..-..-..-..")) {
					macAddr = portion;
				}
			}
		} else {
			// Host Linux
			BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
			String line;
			while ((line = br.readLine()) != null) {
				String[] splitted = line.split(" +");
				if (splitted != null && splitted.length >= 4 && ip.equals(splitted[0])) {
					if (splitted[3].matches("..:..:..:..:..:..")) {
						macAddr = splitted[3].replace(":", "-");
					}
				}
			}
			br.close();
		}
	} catch (IOException ex) {
		System.err.println(ex.getMessage());
		macAddr = null;
	}

	return macAddr;
}

}[/code]

Dei uma googlada e achei esta biblioteca:

http://netresearch.ics.uci.edu/kfujii/Jpcap/doc/

Nunca usei…

De qualquer forma, se seu servidor suportar “automatic allocation”, então os IPs não vão ficar mudando tanto assim. Mas como você disse, se puder consultar a tabela de ARP, é uma boa alternativa.

Eu também achei, mas ela usa JNI por baixo do pano… e já tive tanto problema no projeto que estou mexendo por causa de JNI/JNA e Sistemas 64 bits, que desanimei de mexer…

Quando vai implantar o sistema, eu prefiro não contar com a sorte :slight_smile:

[quote=striker07]Depois de ralar um pouco e perder mais um pouco dos meus cabelos ainda sobreviventes, criei uma classe que faz a busca da tabela ARP do próprio SO. Se alguém tiver algum palpite para melhorá-la, fique à vontade:

[code]package net.rafaeltoledo.util;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;

public abstract class NetworkUtils {

public static String getMacAddress(String ip) {
	String macAddr = null;
	
	try {
		// Host Windows
		String osName = System.getProperty("os.name");
		if (osName.contains("Windows")) {
			Process child = Runtime.getRuntime().exec("arp -a");
			InputStream in = child.getInputStream();
			String output = "";
			int c;
			while ((c = in.read()) != -1) {
				output += (char) c;
			}
			in.close();
			
			String line = null;
			String[] splitted = output.split("\n");
			for (String portion : splitted) {
				if (line.contains(ip)) {
					line = portion;
				}
			}
			
			splitted = line.split(" +");
			for (String portion : splitted) {
				if (portion.matches("..-..-..-..-..-..")) {
					macAddr = portion;
				}
			}
		} else {
			// Host Linux
			BufferedReader br = new BufferedReader(new FileReader("/proc/net/arp"));
			String line;
			while ((line = br.readLine()) != null) {
				String[] splitted = line.split(" +");
				if (splitted != null && splitted.length >= 4 && ip.equals(splitted[0])) {
					if (splitted[3].matches("..:..:..:..:..:..")) {
						macAddr = splitted[3].replace(":", "-");
					}
				}
			}
			br.close();
		}
	} catch (IOException ex) {
		System.err.println(ex.getMessage());
		macAddr = null;
	}

	return macAddr;
}

}[/code][/quote]

você está usando um programa externo para fazer isso, mas resolve o problema.