/*_##########################################################################
_##
_## Copyright (C) 2011-2013 Kaito Yamada
_##
_##########################################################################
*/
package com.github.kaitoy.sneo.network.protocol;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.util.concurrent.TimeUnit;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.namednumber.ArpHardwareType;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.EtherType;
import org.pcap4j.util.ByteArrays;
import org.pcap4j.util.MacAddress;
import com.github.kaitoy.sneo.network.NetworkInterface;
import com.github.kaitoy.sneo.network.NifIpAddress;
import com.github.kaitoy.sneo.network.Node;
import com.github.kaitoy.sneo.network.SendPacketException;
public final class ArpHelper extends NeighborDiscoveryHelper {
private static ArpRequestSender reqSender = new ArpRequestSender();
private ArpHelper() { throw new AssertionError(); }
public static boolean matchesDestination(Packet packet, InetAddress addr) {
ArpPacket arpPacket = packet.get(ArpPacket.class);
if (arpPacket == null) {
throw new IllegalArgumentException(packet.toString());
}
return addr.equals(arpPacket.getHeader().getDstProtocolAddr());
}
public static ArpCache newArpCache(long cacheLife) {
return new ArpCache(cacheLife);
}
public static MacAddress resolveVirtualAddress(InetAddress ipAddress) {
return NeighborDiscoveryHelper.resolveVirtualAddress(ipAddress);
}
public static MacAddress resolveRealAddress(
InetAddress targetIpAddr,
Node node,
NetworkInterface nif,
ArpCache arpCache,
long resolveTimeout,
TimeUnit unit
) {
return resolveRealAddress(
reqSender,
targetIpAddr,
node,
nif,
arpCache,
resolveTimeout,
unit
);
}
public static void cache(Packet packet, ArpCache arpCache) {
ArpPacket arpPacket = packet.get(ArpPacket.class);
if (arpPacket == null) {
throw new IllegalArgumentException(packet.toString());
}
InetAddress ipAddr
= arpPacket.getHeader().getSrcProtocolAddr();
MacAddress macAddr
= arpPacket.getHeader().getSrcHardwareAddr();
NeighborDiscoveryHelper.cache(arpCache, ipAddr, macAddr);
}
public static void clearCache(ArpCache arpCache) {
NeighborDiscoveryHelper.clearCache(arpCache);
}
public static void reply(Packet packet, Node node, NetworkInterface nif) {
ArpPacket arpPacket = packet.get(ArpPacket.class);
if (arpPacket == null) {
throw new IllegalArgumentException(packet.toString());
}
InetAddress srcIpAddr
= arpPacket.getHeader().getSrcProtocolAddr();
MacAddress srcMacAddr
= arpPacket.getHeader().getSrcHardwareAddr();
InetAddress dstIpAddr
= arpPacket.getHeader().getDstProtocolAddr();
ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
arpBuilder.hardwareType(ArpHardwareType.ETHERNET)
.protocolType(EtherType.IPV4)
.hardwareLength((byte)MacAddress.SIZE_IN_BYTES)
.protocolLength((byte)ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES)
.operation(ArpOperation.REPLY)
.srcHardwareAddr(nif.getMacAddress())
.srcProtocolAddr(dstIpAddr)
.dstHardwareAddr(srcMacAddr)
.dstProtocolAddr(srcIpAddr);
try {
node.sendL3Packet(arpBuilder.build(), nif);
} catch (SendPacketException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
private static class ArpRequestSender implements RequestSender {
public void sendRequest(
InetAddress targetIpAddr,
Node node,
NetworkInterface nif
) {
InetAddress srcIpAddr = null;
for (NifIpAddress addr: nif.getIpAddresses()) {
if (addr.getIpAddr() instanceof Inet4Address) {
srcIpAddr = addr.getIpAddr();
}
}
if (srcIpAddr == null) {
throw new IllegalArgumentException("No IPv4 address is found in " + nif);
}
MacAddress srcMacAddr = nif.getMacAddress();
ArpPacket.Builder arpBuilder = new ArpPacket.Builder();
arpBuilder.hardwareType(ArpHardwareType.ETHERNET)
.protocolType(EtherType.IPV4)
.hardwareLength((byte)MacAddress.SIZE_IN_BYTES)
.protocolLength((byte)ByteArrays.INET4_ADDRESS_SIZE_IN_BYTES)
.operation(ArpOperation.REQUEST)
.srcHardwareAddr(srcMacAddr)
.srcProtocolAddr(srcIpAddr)
.dstHardwareAddr(MacAddress.ETHER_BROADCAST_ADDRESS)
.dstProtocolAddr(targetIpAddr);
try {
node.sendL3Packet(arpBuilder.build(), nif);
} catch (SendPacketException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
}
public static class ArpCache extends NeighborCache {
private ArpCache(long cacheLife) {
super(cacheLife);
}
}
}