/* * Copyright 2012 Future Systems * * 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.pcap.decoder.wlan; import org.krakenapps.pcap.decoder.ethernet.MacAddress; import org.krakenapps.pcap.decoder.wlan.tag.DsParameterSet; import org.krakenapps.pcap.decoder.wlan.tag.ErpInformation; import org.krakenapps.pcap.decoder.wlan.tag.ExtendedSupportedRates; import org.krakenapps.pcap.decoder.wlan.tag.RsnInformation; import org.krakenapps.pcap.decoder.wlan.tag.SsidParameterSet; import org.krakenapps.pcap.decoder.wlan.tag.SupportedRates; import org.krakenapps.pcap.decoder.wlan.tag.TaggedParameter; import org.krakenapps.pcap.decoder.wlan.tag.TrafficIndicationMap; import org.krakenapps.pcap.decoder.wlan.tag.UnknownParameter; import org.krakenapps.pcap.decoder.wlan.tag.WlanControlFrame; import org.krakenapps.pcap.packet.PcapPacket; import org.krakenapps.pcap.util.Buffer; import org.krakenapps.pcap.util.ByteOrderConverter; public class WlanDecoder { public WlanFrame decode(PcapPacket pkt) { Buffer buf = pkt.getPacketData(); RadiotapHeader rh = decodeRadiotapHeader(buf); WlanFrameControl frameControl = new WlanFrameControl(buf.getShort()); WlanFrame frame = null; switch (frameControl.getType()) { case 0: frame = decodeManagement(frameControl, buf); break; case 1: frame = decodeControl(frameControl, buf); break; case 2: frame = decodeData(frameControl, buf); break; } if (frame != null) { frame.setRadiotapHeader(rh); frame.setFrameControl(frameControl); } return frame; } private WlanManagementFrame decodeManagement(WlanFrameControl frameControl, Buffer buf) { byte subtype = frameControl.getSubtype(); if (subtype == 4) return decodeProbeRequest(frameControl, buf); else if (subtype == 5) return decodeProbeResponse(frameControl, buf); else if (subtype == 8) return decodeBeacon(buf); return null; } private void decodeManagementCommon(WlanManagementFrame f, Buffer buf) { byte[] dst = new byte[6]; byte[] src = new byte[6]; byte[] bssid = new byte[6]; f.setDuration(buf.getShort()); buf.gets(dst); buf.gets(src); buf.gets(bssid); f.setDestination(new MacAddress(dst)); f.setSource(new MacAddress(src)); f.setBssid(new MacAddress(bssid)); short seqfrag = ByteOrderConverter.swap(buf.getShort()); f.setSeq((seqfrag >> 4) & 0xfff); f.setFragment(seqfrag & 0xf); } private WlanProbeRequest decodeProbeRequest(WlanFrameControl frameControl, Buffer buf) { WlanProbeRequest f = new WlanProbeRequest(); decodeManagementCommon(f, buf); decodeTaggedParameters(f, buf); return f; } private WlanProbeResponse decodeProbeResponse(WlanFrameControl frameControl, Buffer buf) { WlanProbeResponse f = new WlanProbeResponse(); decodeManagementCommon(f, buf); decodeFixedParameters(f, buf); decodeTaggedParameters(f, buf); return f; } private WlanBeaconFrame decodeBeacon(Buffer buf) { WlanBeaconFrame f = new WlanBeaconFrame(); decodeManagementCommon(f, buf); decodeFixedParameters(f, buf); decodeTaggedParameters(f, buf); f.setFrameCheckSeq(buf.getInt()); return f; } private void decodeFixedParameters(WlanManagementFrame f, Buffer buf) { f.setTimestamp(buf.getLong()); f.setBeaconInterval(buf.getShort()); f.setCapabilities(buf.getShort()); } private void decodeTaggedParameters(WlanManagementFrame f, Buffer buf) { int parsed = 0; int len = buf.readableBytes() - 4; // except fcs while (parsed < len) { int type = buf.get() & 0xff; int taglen = buf.get() & 0xff; // System.out.println("type=" + type + ", len=" + taglen); byte[] data = new byte[taglen]; buf.gets(data); parsed += 2 + taglen; f.getParameters().add(decodeTaggedParameter(type, taglen, data)); } } private WlanControlFrame decodeControl(WlanFrameControl frameControl, Buffer buf) { if (frameControl.getSubtype() == 10) { byte[] bssid = new byte[6]; byte[] transmitter = new byte[6]; short assocId = buf.getShort(); buf.gets(bssid); buf.gets(transmitter); WlanPowerSavePollFrame f = new WlanPowerSavePollFrame(); f.setAssociationId(assocId); f.setBssid(new MacAddress(bssid)); f.setTransmitterAddress(new MacAddress(transmitter)); return f; } else if (frameControl.getSubtype() == 12) { int duration = ByteOrderConverter.swap(buf.getShort()) & 0xffff; byte[] receiver = new byte[6]; buf.gets(receiver); WlanCtsFrame f = new WlanCtsFrame(); f.setDuration(duration); f.setReceiver(new MacAddress(receiver)); return f; } else if (frameControl.getSubtype() == 13) { int duration = ByteOrderConverter.swap(buf.getShort()) & 0xffff; byte[] receiver = new byte[6]; buf.gets(receiver); WlanAckFrame f = new WlanAckFrame(); f.setDuration(duration); f.setReceiver(new MacAddress(receiver)); return f; } return null; } private WlanDataFrame decodeData(WlanFrameControl frameControl, Buffer buf) { // normal data frame or null data frame if (frameControl.getSubtype() == 0 || frameControl.getSubtype() == 4) { byte[] dst = new byte[6]; byte[] bssid = new byte[6]; byte[] src = new byte[6]; int duration = ByteOrderConverter.swap(buf.getShort()) & 0xffff; buf.gets(dst); buf.gets(bssid); buf.gets(src); short seqfrag = ByteOrderConverter.swap(buf.getShort()); int wepParameters = buf.getInt(); WlanDataFrame f = new WlanDataFrame(); f.setDuration(duration); f.setDestination(new MacAddress(dst)); f.setBssid(new MacAddress(bssid)); f.setSource(new MacAddress(src)); f.setSeq((seqfrag >> 4) & 0xfff); f.setFragment(seqfrag & 0xf); f.setIv((wepParameters >> 8) & 0xffffff); f.setKeyIndex(wepParameters & 0xff); return f; } return null; } private TaggedParameter decodeTaggedParameter(int type, int len, byte[] data) { switch (type) { case 0: return new SsidParameterSet(new String(data)); case 1: return new SupportedRates(); case 3: return new DsParameterSet((int) data[0]); case 48: return new RsnInformation(); case 5: return new TrafficIndicationMap(); case 42: return new ErpInformation(); case 50: return new ExtendedSupportedRates(); } return new UnknownParameter(data); } private RadiotapHeader decodeRadiotapHeader(Buffer buf) { RadiotapHeader rh = new RadiotapHeader(); buf.getShort(); // padding rh.setHeaderLength(buf.getShort()); rh.setPresentFlags(buf.getInt()); rh.setMacTimestamp(buf.getLong()); rh.setFlags(buf.get()); rh.setDataRate(buf.get()); rh.setChannelFrequency(ByteOrderConverter.swap(buf.getShort())); rh.setChannelType(ByteOrderConverter.swap(buf.getShort())); rh.setSsiSignal(buf.get()); rh.setSsiNoise(buf.get()); rh.setAntenna(buf.get()); rh.setSsiSignal2(buf.get()); return rh; } }