package com.opensoc.pcap; import java.util.BitSet; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import org.krakenapps.pcap.decoder.ethernet.EthernetDecoder; import org.krakenapps.pcap.decoder.ethernet.EthernetFrame; import org.krakenapps.pcap.decoder.ethernet.EthernetProcessor; import org.krakenapps.pcap.decoder.ethernet.MacAddress; import org.krakenapps.pcap.packet.PcapPacket; import org.krakenapps.pcap.util.Buffer; public class OpenSocEthernetDecoder extends EthernetDecoder { private Set<EthernetProcessor> callbacks; private Map<Integer, Set<EthernetProcessor>> typeCallbacks; public OpenSocEthernetDecoder() { callbacks = new CopyOnWriteArraySet<EthernetProcessor>(); typeCallbacks = new ConcurrentHashMap<Integer, Set<EthernetProcessor>>(); } public void register(EthernetProcessor processor) { this.callbacks.add(processor); } public void register(int type, EthernetProcessor processor) { Set<EthernetProcessor> processors = typeCallbacks.get(type); if (processors == null) { processors = new HashSet<EthernetProcessor>(); typeCallbacks.put(type, processors); } processors.add(processor); } public void unregister(EthernetProcessor processor) { this.callbacks.remove(processor); } public void unregister(int type, EthernetProcessor processor) { Set<EthernetProcessor> processors = typeCallbacks.get(type); if (processors == null) return; processors.remove(processor); } public void decode(PcapPacket packet) { // do not reorder following codes (parse sequence) MacAddress destination = getMacAddress(packet.getPacketData()); MacAddress source = getMacAddress(packet.getPacketData()); int type = getEtherType(packet.getPacketData()); if (type == 0x8100) { // It is 802.1Q VLAN tag IEEE_802_1Q iee802_1qTag = get802_1qTag(packet.getPacketData()); // Now get the type type = getEtherType(packet.getPacketData()); } Buffer buffer = packet.getPacketData(); buffer.discardReadBytes(); EthernetFrame frame = new EthernetFrame(source, destination, type, buffer); frame.setPcapPacket(packet); dispatch(frame); } private MacAddress getMacAddress(Buffer data) { byte[] mac = new byte[6]; data.gets(mac, 0, 6); return new MacAddress(mac); } private int getEtherType(Buffer data) { return ((int) data.getShort()) & 0x0000FFFF; } private IEEE_802_1Q get802_1qTag(Buffer data) { // reference http://en.wikipedia.org/wiki/EtherType & // http://en.wikipedia.org/wiki/IEEE_802.1Q byte[] b802_1qTag = new byte[2]; data.gets(b802_1qTag, 0, 2); BitSet bits = BitSet.valueOf(b802_1qTag); int pcp = convertBitToInt(bits.get(0, 3)); int dei = convertBitToInt(bits.get(3, 4)); int vid = convertBitToInt(bits.get(4, 16)); return new IEEE_802_1Q(pcp, dei, vid); } public static int convertBitToInt(BitSet bits) { int value = 0; for (int i = 0; i < bits.length(); ++i) { value += bits.get(i) ? (1 << i) : 0; } return value; } private void dispatch(EthernetFrame frame) { for (EthernetProcessor processor : callbacks) processor.process(frame); Set<EthernetProcessor> processors = typeCallbacks.get(frame.getType()); if (processors == null) return; for (EthernetProcessor processor : processors) processor.process(frame.dup()); } }