/* * Copyright 2010 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.arpwatch.impl; import java.net.InetAddress; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.krakenapps.arpwatch.ArpCache; import org.krakenapps.arpwatch.ArpCacheListener; import org.krakenapps.arpwatch.ArpEntry; import org.krakenapps.pcap.decoder.arp.ArpPacket; public class ArpCacheImpl implements ArpCache { private Map<InetAddress, ArpEntry> entryMap; private Set<ArpCacheListener> listeners; public ArpCacheImpl() { entryMap = new ConcurrentHashMap<InetAddress, ArpEntry>(); listeners = Collections.newSetFromMap(new ConcurrentHashMap<ArpCacheListener, Boolean>()); } @Override public ArpEntry find(InetAddress ip) { return entryMap.get(ip); } @Override public Collection<ArpEntry> getCachedEntries() { return Collections.unmodifiableCollection(entryMap.values()); } @Override public void add(ArpPacket p) { if (p.getOpcode() == 2 || (p.getOpcode() == 1 && p.getSenderIp().equals(p.getTargetIp()))) { ArpEntry oldEntry = find(p.getSenderIp()); if (oldEntry == null) { addNewEntry(p); return; } if (oldEntry.getMacAddress().equals(p.getSenderMac())) { updateEntry(p, oldEntry); } else { alertEntry(p, oldEntry); } } } private void alertEntry(ArpPacket p, ArpEntry oldEntry) { ArpEntry entry = new ArpEntryImpl(p.getSenderMac(), p.getSenderIp(), new Date(), new Date()); entryMap.put(entry.getIpAddress(), entry); // alert! for (ArpCacheListener callback : listeners) { try { callback.entryChanged(oldEntry, entry); } catch (Exception e) { // should not reach } } } private void addNewEntry(ArpPacket p) { ArpEntry entry = new ArpEntryImpl(p.getSenderMac(), p.getSenderIp(), new Date(), new Date()); entryMap.put(entry.getIpAddress(), entry); for (ArpCacheListener callback : listeners) { try { callback.entryAdded(entry); } catch (Exception e) { // should not reach } } } private void updateEntry(ArpPacket p, ArpEntry oldEntry) { // extend timeout ArpEntry entry = new ArpEntryImpl(p.getSenderMac(), p.getSenderIp(), oldEntry.getFirstSeen(), new Date()); entryMap.put(entry.getIpAddress(), entry); for (ArpCacheListener callback : listeners) { try { callback.entryUpdated(entry); } catch (Exception e) { // should not reach } } } @Override public void register(ArpCacheListener listener) { listeners.add(listener); } @Override public void unregister(ArpCacheListener listener) { listeners.remove(listener); } @Override public void flush() { entryMap.clear(); } }