package com.netifera.platform.net.internal.daemon.sniffing;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import com.netifera.platform.api.log.ILogger;
import com.netifera.platform.net.daemon.sniffing.IArpSniffer;
import com.netifera.platform.net.daemon.sniffing.IIPSniffer;
import com.netifera.platform.net.daemon.sniffing.IRawSniffer;
import com.netifera.platform.net.daemon.sniffing.ISniffingModule;
import com.netifera.platform.net.daemon.sniffing.ITCPBlockSniffer;
import com.netifera.platform.net.daemon.sniffing.ITCPStreamSniffer;
import com.netifera.platform.net.packets.IPacketHeader;
import com.netifera.platform.net.packets.link.ARP;
import com.netifera.platform.net.packets.tcpip.IPv4;
import com.netifera.platform.net.packets.tcpip.IPv6;
import com.netifera.platform.net.pcap.ICaptureInterface;
import com.netifera.platform.net.sniffing.IPacketContext;
import com.netifera.platform.net.sniffing.IPacketSniffer;
import com.netifera.platform.net.sniffing.ISnifferHandle;
import com.netifera.platform.net.sniffing.ISniffingEngineService;
import com.netifera.platform.net.sniffing.stream.IBlockSniffer;
import com.netifera.platform.net.sniffing.stream.IBlockSnifferHandle;
import com.netifera.platform.net.sniffing.stream.ISessionContext;
/**
* This class wraps an instance of <code>ISniffingModule</code> which is enabled and
* prepared to run (or actively running). It allows registering a sniffing module on
* multiple interfaces and manages the sniffing handles returned from the sniffing engine.
*/
class EnabledSniffingModule {
/**
* Set containing handles returned from the sniffing engine.
*/
private final Set<ISnifferHandle> activeHandles = new HashSet<ISnifferHandle>();
/**
* Flag indicating that the managed sniffing module is currently running
*/
private boolean running;
/**
* Reference to the managed sniffing module instance.
*/
private final ISniffingModule moduleInstance;
private final ISniffingModuleOutput output;
private final ILogger logger;
EnabledSniffingModule(ISniffingModule module, ISniffingModuleOutput output, ILogger logger) {
this.moduleInstance = module;
this.output = output;
this.logger = logger;
}
public ISniffingModule getModule() {
return moduleInstance;
}
@Override
public boolean equals(Object obj) {
if (this == obj){
return true;
}
if (!(obj instanceof EnabledSniffingModule)){
return false;
}
return moduleInstance.getName().equals(
((EnabledSniffingModule)obj).moduleInstance.getName());
}
@Override
public int hashCode() {
return moduleInstance.getName().hashCode();
}
@Override
public String toString() {
return moduleInstance == null ? "" : moduleInstance.getName();
}
/**
* Start this module by creating sniffing handles for each type of packet handled
* by the module and on each listed interface.
*
* @param interfaces Interfaces to sniff on.
*/
public synchronized void start(ISniffingEngineService sniffingEngine, Collection<SniffingDaemonInterface> interfaces, long spaceId) {
assert(activeHandles.isEmpty());
assert(!running);
for(SniffingDaemonInterface iface : interfaces) {
startInterface(sniffingEngine, iface.getInterface(), iface.getRealm(), spaceId);
}
running = true;
}
/*
* Start this module on a single interface.
*/
private void startInterface(ISniffingEngineService sniffingEngine, ICaptureInterface iface, long realm, long spaceId) {
if(moduleInstance instanceof IRawSniffer) {
register( createRawHandle(sniffingEngine, iface, (IRawSniffer) moduleInstance, spaceId), realm);
}
if(moduleInstance instanceof IIPSniffer) {
register( createIPv4Handle(sniffingEngine, iface, (IIPSniffer) moduleInstance, spaceId), realm);
register( createIPv6Handle(sniffingEngine, iface, (IIPSniffer) moduleInstance, spaceId), realm);
}
if(moduleInstance instanceof IArpSniffer) {
register( createArpHandle(sniffingEngine, iface, (IArpSniffer) moduleInstance, spaceId), realm);
}
if(moduleInstance instanceof ITCPBlockSniffer) {
register( createTcpBlockHandle(sniffingEngine, iface, (ITCPBlockSniffer) moduleInstance, spaceId), realm);
}
if(moduleInstance instanceof ITCPStreamSniffer) {
register( createTcpStreamHandle(sniffingEngine, iface, (ITCPStreamSniffer) moduleInstance, spaceId), realm);
}
}
/*
* Register a single handle, and save it in the set of active handles.
*/
private void register(ISnifferHandle handle, long realmId) {
activeHandles.add(handle);
handle.setDefaultTag(new Long(realmId));
handle.register();
}
/*
* Create and return sniffing engine handle for receiving raw packets on the specified interface.
*/
private ISnifferHandle createRawHandle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final IRawSniffer sniffer, final long spaceId) {
return sniffingEngine.createRawHandle(iface, moduleInstance.getFilter(),
new IPacketSniffer<IPacketHeader>() {
public void handlePacket(IPacketHeader packet,
final IPacketContext ctx) {
try {
sniffer.handleRawPacket(packet, new PacketModuleContext(ctx, spaceId, output));
} catch (Exception e) {
logger.warning("Exception processing raw packet", e);
}
}
});
}
/*
* Create and return a sniffing engine handle for receiving IPv4 packets on the specified interface.
*/
private ISnifferHandle createIPv4Handle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final IIPSniffer sniffer, final long spaceId) {
return sniffingEngine.createIPv4Handle(iface, moduleInstance.getFilter(),
new IPacketSniffer<IPv4>() {
public void handlePacket(IPv4 packet, IPacketContext ctx) {
try {
sniffer.handleIPv4Packet(packet, new PacketModuleContext(ctx, spaceId, output));
} catch (Exception e) {
logger.warning("Exception processing IPv4 packet", e);
}
}
});
}
/*
* Create and return a sniffing engine handle for receiving IPv6 packets on the specified interface.
*/
private ISnifferHandle createIPv6Handle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final IIPSniffer sniffer, final long spaceId) {
return sniffingEngine.createIPv6Handle(iface, moduleInstance.getFilter(),
new IPacketSniffer<IPv6>() {
public void handlePacket(IPv6 packet, IPacketContext ctx) {
try {
sniffer.handleIPv6Packet(packet, new PacketModuleContext(ctx, spaceId, output));
} catch (Exception e) {
logger.warning("Exception processing IPv6 packet", e);
}
}
});
}
/*
* Create and return a sniffing engine handle for receiving ARP packets on the specificed interface.
*/
private ISnifferHandle createArpHandle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final IArpSniffer sniffer, final long spaceId) {
return sniffingEngine.createArpHandle(iface, moduleInstance.getFilter(),
new IPacketSniffer<ARP>() {
public void handlePacket(final ARP packet, final IPacketContext ctx) {
try {
sniffer.handleArpPacket(packet, new PacketModuleContext(ctx, spaceId, output));
} catch (Exception e) {
logger.warning("Exception processing ARP packet", e);
}
}
});
}
private ISnifferHandle createTcpBlockHandle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final ITCPBlockSniffer sniffer, final long spaceId) {
final IBlockSnifferHandle handle = sniffingEngine.createTcpBlockHandle(iface, moduleInstance.getFilter(), new IBlockSniffer() {
public void handleBlock(final ISessionContext ctx, final ByteBuffer clientData,
final ByteBuffer serverData) {
try {
sniffer.handleBlock(new StreamModuleContext(ctx, spaceId, output), clientData, serverData);
} catch (Exception e) {
logger.warning("Exception processing assembled TCP block", e);
}
}
});
sniffer.initialize(handle);
return handle;
}
private ISnifferHandle createTcpStreamHandle(ISniffingEngineService sniffingEngine, ICaptureInterface iface, final ITCPStreamSniffer sniffer, long spaceId) {
return sniffingEngine.createTcpStreamHandle(iface, moduleInstance.getFilter(),
new StreamHandler(spaceId, sniffer, output));
}
/**
* Stop this module by unregistering all active sniffer engine handles.
*/
public synchronized void stop() {
assert(running);
for(ISnifferHandle handle : activeHandles) {
handle.unregister();
}
activeHandles.clear();
running = false;
}
}