/*_##########################################################################
_##
_## Copyright (C) 2012-2013 Kaito Yamada
_##
_##########################################################################
*/
package com.github.kaitoy.sneo.network;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.pcap4j.core.PacketListener;
import org.pcap4j.packet.ArpPacket;
import org.pcap4j.packet.ArpPacket.ArpHeader;
import org.pcap4j.packet.IcmpV4EchoPacket;
import org.pcap4j.packet.IcmpV6EchoRequestPacket;
import org.pcap4j.packet.IcmpV6NeighborAdvertisementPacket;
import org.pcap4j.packet.IcmpV6NeighborSolicitationPacket;
import org.pcap4j.packet.IpV4Packet;
import org.pcap4j.packet.IpV6Packet;
import org.pcap4j.packet.Packet;
import org.pcap4j.packet.UdpPacket;
import org.pcap4j.packet.UnknownPacket;
import org.pcap4j.packet.namednumber.ArpOperation;
import org.pcap4j.packet.namednumber.IcmpV4Code;
import org.pcap4j.packet.namednumber.IcmpV4Type;
import org.pcap4j.packet.namednumber.IcmpV6Code;
import org.pcap4j.packet.namednumber.IcmpV6Type;
import org.pcap4j.packet.namednumber.UdpPort;
import org.pcap4j.util.MacAddress;
import org.snmp4j.log.LogAdapter;
import org.snmp4j.log.LogFactory;
import com.github.kaitoy.sneo.agent.FileMibAgent;
import com.github.kaitoy.sneo.network.protocol.ArpHelper;
import com.github.kaitoy.sneo.network.protocol.ArpHelper.ArpCache;
import com.github.kaitoy.sneo.network.protocol.EthernetHelper;
import com.github.kaitoy.sneo.network.protocol.IcmpV4Helper;
import com.github.kaitoy.sneo.network.protocol.IcmpV6Helper;
import com.github.kaitoy.sneo.network.protocol.IcmpV6Helper.NdpCache;
import com.github.kaitoy.sneo.network.protocol.IpV4Helper;
import com.github.kaitoy.sneo.network.protocol.IpV4Helper.IpV4RoutingTable;
import com.github.kaitoy.sneo.network.protocol.IpV4Helper.IpV4RoutingTable.IpV4RoutingTableEntry;
import com.github.kaitoy.sneo.network.protocol.IpV6Helper;
import com.github.kaitoy.sneo.network.protocol.IpV6Helper.IpV6RoutingTable;
import com.github.kaitoy.sneo.network.protocol.IpV6Helper.IpV6RoutingTable.IpV6RoutingTableEntry;
import com.github.kaitoy.sneo.network.protocol.UdpHelper;
import com.github.kaitoy.sneo.transport.SneoUdpTransportMapping;
public class Node {
private static final LogAdapter LOGGER = LogFactory.getLogger(Node.class);
private static final int TRAP_SRC_PORT = 54321;
private final String name;
private final FileMibAgent agent;
protected final IpV4RoutingTable ipV4routingTable = IpV4Helper.newRoutingTable();
protected final IpV6RoutingTable ipV6routingTable = IpV6Helper.newRoutingTable();
private final int ttl;
protected final Map<String, NetworkInterface> nifs
= new ConcurrentHashMap<String, NetworkInterface>();
private final ArpCache arpCache
= ArpHelper.newArpCache(NetworkPropertiesLoader.getArpCacheLife());
private final NdpCache ndpCache
= IcmpV6Helper.newNdpCache(NetworkPropertiesLoader.getNdpCacheLife());
private final Object thisLock = new Object();
private final Object ipV4PacketIdLock = new Object();
private short ipV4PacketId = (short)0;
private volatile boolean running = false;
private volatile boolean listeningIcmp = false;
public Node(String name, FileMibAgent agent, int ttl) {
if (agent != null) {
if (!(agent.getTransportMapping() instanceof SneoUdpTransportMapping)) {
throw new IllegalArgumentException();
}
((SneoUdpTransportMapping)agent.getTransportMapping()).setNode(this);
}
this.name = name;
this.agent = agent;
this.ttl = ttl;
}
public String getName() {
return name;
}
public FileMibAgent getAgent() {
return agent;
}
public List<IpV4RoutingTableEntry> getIpV4RoutingTableEntries() {
return ipV4routingTable.getEntries();
}
public List<IpV6RoutingTableEntry> getIpV6RoutingTableEntries() {
return ipV6routingTable.getEntries();
}
public int getTtl() {
return ttl;
}
public List<NetworkInterface> getNifs() {
return new ArrayList<NetworkInterface>(nifs.values());
}
public void addNif(String ifName, boolean trunk) {
PhysicalNetworkInterface nif
= new PhysicalNetworkInterface(
ifName,
MacAddressManager.getInstance().generateVirtualMacAddress(),
trunk,
new PacketListenerImpl(ifName)
);
nifs.put(ifName, nif);
}
public void addRealNif(String ifName, MacAddress macAddr, String deviceName) {
RealNetworkInterface rnif
= new RealNetworkInterface(
ifName,
macAddr,
deviceName,
new PacketListenerImpl(ifName)
);
nifs.put(ifName, rnif);
}
public void addVlan(String ifName, int vid) {
NetworkInterface nif
= new VlanInterface(
ifName,
MacAddressManager.getInstance().generateVirtualMacAddress(),
vid,
new PacketListenerImpl(ifName)
);
nifs.put(ifName, nif);
}
public void addNifToVlan(String ifName, int vid) {
getVlanNif(vid).addNif(ifName, nifs.get(ifName));
}
public void addLag(String name, int channelGroupNumber) {
NetworkInterface nif
= new LagInterface(
name,
MacAddressManager.getInstance().generateVirtualMacAddress(),
channelGroupNumber,
new PacketListenerImpl(name)
);
nifs.put(name, nif);
}
public void addNifToLag(String ifName, int channelGroupNumber) {
getLagNif(channelGroupNumber)
.addNif(ifName, (PhysicalNetworkInterface)nifs.get(ifName));
}
public void addIpAddress(
String ifName, InetAddress addr, int prefixLength
) {
NetworkInterface target = nifs.get(ifName);
MacAddressManager.getInstance()
.registerVirtualMacAddress(addr, target.getMacAddress());
if (addr instanceof Inet4Address) {
target.addIpAddress(new NifIpV4Address((Inet4Address)addr, prefixLength));
}
else {
target.addIpAddress(new NifIpV6Address((Inet6Address)addr, prefixLength));
}
}
public void addIpAddress(
String ifName, String addr, int prefixLength
) {
InetAddress inetAddr;
try {
inetAddr = InetAddress.getByName(addr);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e);
}
addIpAddress(ifName, inetAddr, prefixLength);
}
public NetworkInterface getNif(String ifName) {
return nifs.get(ifName);
}
public VlanInterface getVlanNif(int vid) {
for (NetworkInterface nif: nifs.values()) {
if (nif instanceof VlanInterface) {
VlanInterface vNif = (VlanInterface)nif;
if (vNif.getVid() == vid) {
return vNif;
}
}
}
return null;
}
public LagInterface getLagNif(int channelGroupNumber) {
for (NetworkInterface nif: nifs.values()) {
if (nif instanceof LagInterface) {
LagInterface li = (LagInterface)nif;
if (li.getChannelGroupNumber() == channelGroupNumber) {
return li;
}
}
}
return null;
}
public void start() {
start(true);
}
public void start(boolean startAgent) {
synchronized (thisLock) {
for (NetworkInterface nif: nifs.values()) {
nif.start();
}
if (agent != null && startAgent) {
agent.start();
}
listeningIcmp = true;
running = true;
}
}
public void startAgent() {
if (agent != null) {
agent.start();
}
}
public void startListeningIcmp() {
listeningIcmp = true;
}
public void stop() {
synchronized (thisLock) {
for (NetworkInterface nif: nifs.values()) {
nif.stop();
}
if (agent != null) {
agent.stop();
}
ArpHelper.clearCache(arpCache);
listeningIcmp = false;
running = false;
}
}
public void stopAgent() {
if (agent != null) {
agent.stop();
}
}
public void stopListeningIcmp() {
listeningIcmp = false;
}
public boolean isRunning() {
return running;
}
public boolean isRunningAgent() {
return agent != null ? agent.isRunning() : false;
}
public boolean isListeningIcmp() {
return listeningIcmp;
}
public void shutdown() {
synchronized (thisLock) {
if (running) {
stop();
}
if (agent != null) {
agent.shutdown();
}
for (NetworkInterface n: nifs.values()) {
n.shutdown();
}
}
LOGGER.info("A node has been shutdown.");
}
protected void consumeIpV4(Packet packet, NetworkInterface getter) {
if (packet.contains(UdpPacket.class)) {
consumeUdp(packet, getter);
}
else if (packet.contains(IcmpV4EchoPacket.class)) {
if (!listeningIcmp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("not listening ICMP. Drop a packet: " + packet);
}
return;
}
IcmpV4Helper.reply(packet, this, getter);
}
else {
LOGGER.warn("I don't care this packet: " + packet);
}
}
protected void consumeIpV6(Packet packet, NetworkInterface getter) {
if (packet.contains(UdpPacket.class)) {
consumeUdp(packet, getter);
}
else if (packet.contains(IcmpV6EchoRequestPacket.class)) {
if (!listeningIcmp) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("not listening ICMP. Drop a packet: " + packet);
}
return;
}
IcmpV6Helper.sendEchoReply(packet, this, getter);
}
else {
LOGGER.warn("I don't care this packet: " + packet);
}
}
private void consumeUdp(Packet packet, NetworkInterface getter) {
if (agent == null || !agent.isRunning()) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Not listening SNMP. Dropped a packet: " + packet);
}
return;
}
UdpPacket udpPacket = packet.get(UdpPacket.class);
SneoUdpTransportMapping tm
= (SneoUdpTransportMapping)agent.getTransportMapping();
if (
(udpPacket.getHeader().getDstPort().value() & 0xFFFF)
== tm.getAddress().getPort()
) {
agent.getContextfulWorkerPool()
.registerContext(new SnmpContext(packet, getter));
tm.processMessage(packet);
}
else {
if (LOGGER.isDebugEnabled()) {
StringBuilder sb = new StringBuilder();
sb.append("Dropped a packet not to me(")
.append(tm.getAddress().getPort())
.append("): ")
.append(packet);
LOGGER.debug(sb.toString());
}
}
}
public NetworkInterface getNifByDstIpAddr(Inet4Address dstIpAddr) {
for (NetworkInterface nif: nifs.values()) {
if (IpV4Helper.isSameNetwork(dstIpAddr, nif)) {
return nif;
}
}
Inet4Address nextHop = IpV4Helper.getNextHop(dstIpAddr, ipV4routingTable);
if (nextHop == null) {
LOGGER.warn("Couldn't get next hop by dest IP address: " + dstIpAddr);
return null;
}
for (NetworkInterface nif: nifs.values()) {
if (IpV4Helper.isSameNetwork(nextHop, nif)) {
return nif;
}
}
LOGGER.error("Couldn't find a NIF for the next hop " + nextHop + ". Dest IP address: " + dstIpAddr);
return null;
}
public NetworkInterface getNifByDstIpAddr(Inet6Address dstIpAddr) {
for (NetworkInterface nif: nifs.values()) {
if (IpV6Helper.isSameNetwork(dstIpAddr, nif)) {
return nif;
}
}
Inet6Address nextHop = IpV6Helper.getNextHop(dstIpAddr, ipV6routingTable);
if (nextHop == null) {
LOGGER.warn("Couldn't get next hop by dest IP address: " + dstIpAddr);
return null;
}
for (NetworkInterface nif: nifs.values()) {
if (IpV6Helper.isSameNetwork(nextHop, nif)) {
return nif;
}
}
LOGGER.error("Couldn't find a NIF for the next hop " + nextHop + ". Dest IP address: " + dstIpAddr);
return null;
}
public void addIpV4Route(
Inet4Address destination,
Inet4Address subnetMask,
Inet4Address gateway,
int metric
) {
ipV4routingTable.addRoute(destination, subnetMask, gateway, metric);
}
public void addIpV4Route(
String destination,
String subnetMask,
String gateway,
int metric
) {
try {
addIpV4Route(
(Inet4Address)InetAddress.getByName(destination),
(Inet4Address)InetAddress.getByName(subnetMask),
(Inet4Address)InetAddress.getByName(gateway),
metric
);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e);
}
}
public void addIpV6Route(
Inet6Address destination,
int prefixLength,
Inet6Address gateway,
int metric
) {
ipV6routingTable.addRoute(destination, prefixLength, gateway, metric);
}
public void addIpV6Route(
String destination,
int prefixLength,
String gateway,
int metric
) {
try {
addIpV6Route(
(Inet6Address)InetAddress.getByName(destination),
prefixLength,
(Inet6Address)InetAddress.getByName(gateway),
metric
);
} catch (UnknownHostException e) {
throw new IllegalArgumentException(e);
}
}
public void sendL3Packet(Packet packet, NetworkInterface sender) throws SendPacketException {
MacAddress dstMacAddr = getDstMacAddress(packet, sender);
try {
if (
packet instanceof IpV4Packet
&& sender instanceof RealNetworkInterface
) {
List<IpV4Packet> fragmentedPackets
= org.pcap4j.util.IpV4Helper.fragment(
(IpV4Packet)packet, NetworkPropertiesLoader.getMtu()
);
for (Packet p: fragmentedPackets) {
sender.sendPacket(
EthernetHelper.pack(
p,
sender.getMacAddress(),
dstMacAddr
)
);
}
}
else {
sender.sendPacket(
EthernetHelper.pack(
packet,
sender.getMacAddress(),
dstMacAddr
)
);
}
} catch (IllegalStateException e) {
LOGGER.error(e);
}
}
private MacAddress getDstMacAddress(
Packet packet, NetworkInterface sender
) throws SendPacketException {
if (packet instanceof IpV4Packet) {
Inet4Address nextHop;
Inet4Address dstIpAddr
= packet.get(IpV4Packet.class).getHeader().getDstAddr();
if (IpV4Helper.isSameNetwork(dstIpAddr, sender)) {
nextHop = dstIpAddr;
}
else {
nextHop = IpV4Helper.getNextHop(dstIpAddr, ipV4routingTable);
if (nextHop == null) {
LOGGER.debug("Couldn't get next hop: " + packet);
throw new SendPacketException(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.DST_NETWORK_UNKNOWN
);
}
}
if (sender instanceof RealNetworkInterface){
MacAddress dstMacAddr
= ArpHelper.resolveRealAddress(
nextHop,
this,
sender,
arpCache,
NetworkPropertiesLoader.getArpResolveTimeout(),
TimeUnit.MILLISECONDS
);
if (dstMacAddr == null) {
LOGGER.debug(
"Couldn't resolve an IPv4 address to a Mac address, dropped the packet: "
+ packet
);
throw new SendPacketException(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.HOST_UNREACHABLE
);
}
return dstMacAddr;
}
else {
MacAddress dstMacAddr = ArpHelper.resolveVirtualAddress(nextHop);
if (dstMacAddr == null) {
throw new SendPacketException(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.HOST_UNREACHABLE
);
}
return dstMacAddr;
}
}
else if (packet instanceof ArpPacket) {
return ((ArpPacket)packet).getHeader().getDstHardwareAddr();
}
else if (packet instanceof IpV6Packet) {
if (packet.contains(IcmpV6NeighborSolicitationPacket.class)) {
Inet6Address dstAddr = packet.get(IpV6Packet.class).getHeader().getDstAddr();
return IpV6Helper.generateNeighborSolicitationMacAddress(dstAddr);
}
else {
Inet6Address nextHop;
Inet6Address dstIpAddr
= packet.get(IpV6Packet.class).getHeader().getDstAddr();
if (IpV6Helper.isSameNetwork(dstIpAddr, sender)) {
nextHop = dstIpAddr;
}
else {
nextHop = IpV6Helper.getNextHop(dstIpAddr, ipV6routingTable);
if (nextHop == null) {
LOGGER.debug("Couldn't get next hop: " + packet);
throw new SendPacketException(
IcmpV6Type.DESTINATION_UNREACHABLE,
IcmpV6Code.NO_ROUTE_TO_DST
);
}
}
if (sender instanceof RealNetworkInterface){
MacAddress dstMacAddr
= IcmpV6Helper.resolveRealAddress(
nextHop,
this,
sender,
ndpCache,
NetworkPropertiesLoader.getNdpResolveTimeout(),
TimeUnit.MILLISECONDS
);
if (dstMacAddr == null) {
LOGGER.warn(
"Couldn't resolve an IPv6 address to a Mac address, dropped the packet: "
+ packet
);
throw new SendPacketException(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.HOST_UNREACHABLE
);
}
return dstMacAddr;
}
else {
MacAddress dstMacAddr = IcmpV6Helper.resolveVirtualAddress(nextHop);
if (dstMacAddr == null) {
throw new SendPacketException(
IcmpV6Type.DESTINATION_UNREACHABLE,
IcmpV6Code.NO_ROUTE_TO_DST
);
}
return dstMacAddr;
}
}
}
else {
LOGGER.debug(
"Cannot get a destination MAC address for an unsupported packet: "
+ packet
);
throw new SendPacketException(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.DST_NETWORK_UNKNOWN
);
}
}
public void sendL4Packet(
Packet packet,
InetAddress srcAddr,
InetAddress dstAddr,
NetworkInterface sender,
int ttl
) throws SendPacketException {
Packet l3Packet;
if (srcAddr instanceof Inet4Address) {
l3Packet = IpV4Helper.pack(
packet,
(Inet4Address)srcAddr,
(Inet4Address)dstAddr,
ttl,
getNextIdentification()
);
}
else {
l3Packet = IpV6Helper.pack(
packet,
(Inet6Address)srcAddr,
(Inet6Address)dstAddr,
ttl,
getNextIdentification()
);
}
sendL3Packet(l3Packet, sender);
}
public void sendL4Packet(
Packet packet,
InetAddress srcAddr,
InetAddress dstAddr,
NetworkInterface sender
) throws SendPacketException {
sendL4Packet(
packet,
srcAddr,
dstAddr,
sender,
ttl
);
}
private short getNextIdentification() {
synchronized (ipV4PacketIdLock) {
ipV4PacketId = (short)(((0xFFFF) & ipV4PacketId) + 1);
return ipV4PacketId;
}
}
public void sendSnmpMessage(
InetAddress dstAddr, int dstPort,
byte[] message
) throws SendPacketException {
InetAddress srcAddr;
int srcPort;
NetworkInterface sender;
SnmpContext context = agent.getContextfulWorkerPool().unregisterContext();
if (context != null) {
// response
sender = context.getGetter();
IpV4Packet ipV4Packet = context.getRequestPacket().get(IpV4Packet.class);
if (ipV4Packet != null) {
srcAddr = context.getRequestPacket().get(IpV4Packet.class).getHeader()
.getDstAddr();
}
else {
srcAddr = context.getRequestPacket().get(IpV6Packet.class).getHeader()
.getDstAddr();
}
srcPort = context.getRequestPacket().get(UdpPacket.class).getHeader()
.getDstPort().value() & 0xFFFF;
}
else {
// trap
if (dstAddr instanceof Inet4Address) {
sender = getNifByDstIpAddr((Inet4Address)dstAddr);
}
else {
sender = getNifByDstIpAddr((Inet6Address)dstAddr);
}
srcAddr = agent.getInetAddress();
srcPort = TRAP_SRC_PORT;
}
UnknownPacket.Builder unknownb = new UnknownPacket.Builder();
unknownb.rawData(message);
UdpPacket udpp
= UdpHelper.pack(
unknownb.build(),
UdpPort.getInstance((short)srcPort),
UdpPort.getInstance((short)dstPort),
srcAddr,
dstAddr
);
sendL4Packet(udpp, srcAddr, dstAddr, sender);
}
private final class PacketListenerImpl implements PacketListener {
private final String ifName;
private PacketListenerImpl(String ifName) {
this.ifName = ifName;
}
public void gotPacket(Packet packet) {
NetworkInterface getter = nifs.get(ifName);
if (packet.contains(IpV4Packet.class)) {
handleIpV4(packet, getter);
}
if (packet.contains(IpV6Packet.class)) {
if (packet.contains(IcmpV6NeighborSolicitationPacket.class)) {
handleIcmpV6Ns(packet, getter);
}
else if (packet.contains(IcmpV6NeighborAdvertisementPacket.class)) {
handleIcmpV6Na(packet, getter);
}
else {
handleIpV6(packet, getter);
}
}
else if (packet.contains(ArpPacket.class)) {
handleArp(packet, getter);
}
}
private void handleIpV4(Packet packet, NetworkInterface getter) {
for (NetworkInterface nif: nifs.values()) {
if (IpV4Helper.matchesDestination(packet, nif)) {
consumeIpV4(packet, getter);
return;
}
}
IpV4Packet ipV4packet = packet.get(IpV4Packet.class);
NetworkInterface sender
= getNifByDstIpAddr(ipV4packet.getHeader().getDstAddr());
if (sender == null) {
IcmpV4Helper.sendErrorMessage(
IcmpV4Type.DESTINATION_UNREACHABLE,
IcmpV4Code.DST_NETWORK_UNKNOWN,
ipV4packet,
Node.this,
getter
);
return;
}
try {
ipV4packet = IpV4Helper.decrementTtl(ipV4packet);
} catch (TimeoutException e) {
IcmpV4Helper.sendErrorMessage(
IcmpV4Type.TIME_EXCEEDED,
IcmpV4Code.TIME_TO_LIVE_EXCEEDED,
ipV4packet,
Node.this,
getter
);
return;
}
try {
sendL3Packet(ipV4packet, sender);
} catch (SendPacketException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
private void handleIcmpV6Ns(Packet packet, NetworkInterface getter) {
IcmpV6Helper.cache(packet, ndpCache);
IcmpV6NeighborSolicitationPacket nsPacket
= packet.get(IcmpV6NeighborSolicitationPacket.class);
boolean toMe = false;
for (NifIpAddress nifIpAddr: getter.getIpAddresses()) {
if (nifIpAddr.getIpAddr().equals(nsPacket.getHeader().getTargetAddress())) {
toMe = true;
break;
}
}
if (!toMe) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Dropped an NS packet not to me: " + packet);
}
return;
}
IcmpV6Helper.sendSolicitedNeighborAdvertisement(
packet, Node.this, getter
);
}
private void handleIcmpV6Na(Packet packet, NetworkInterface getter) {
IcmpV6Helper.cache(packet, ndpCache);
}
private void handleIpV6(Packet packet, NetworkInterface getter) {
for (NetworkInterface nif: nifs.values()) {
if (IpV6Helper.matchesDestination(packet, nif)) {
consumeIpV6(packet, getter);
return;
}
}
IpV6Packet ipV6packet = packet.get(IpV6Packet.class);
NetworkInterface sender
= getNifByDstIpAddr(ipV6packet.getHeader().getDstAddr());
try {
ipV6packet = IpV6Helper.decrementTtl(ipV6packet);
} catch (TimeoutException e) {
IcmpV6Helper.sendErrorMessage(
IcmpV6Type.TIME_EXCEEDED,
IcmpV6Code.HOP_LIMIT_EXCEEDED,
ipV6packet,
Node.this,
getter
);
return;
}
try {
sendL3Packet(ipV6packet, sender);
} catch (SendPacketException e) {
// TODO 自動生成された catch ブロック
e.printStackTrace();
}
}
private void handleArp(Packet packet, NetworkInterface getter) {
ArpHeader ah = packet.get(ArpPacket.class).getHeader();
boolean toMe = false;
for (NifIpAddress nifIpAddr: getter.getIpAddresses()) {
if (nifIpAddr.getIpAddr().equals(ah.getDstProtocolAddr())) {
toMe = true;
break;
}
}
if (!toMe) {
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("Dropped an ARP packet not to me: " + packet);
}
return;
}
ArpOperation op = ah.getOperation();
if (op.equals(ArpOperation.REQUEST)) {
ArpHelper.cache(packet, arpCache);
ArpHelper.reply(
packet,
Node.this,
getter
);
}
else if (op.equals(ArpOperation.REPLY)) {
ArpHelper.cache(packet, arpCache);
}
else {
LOGGER.warn(
"Dropped a packet with unknown ARP operation: " + packet
);
}
}
}
}