/* This file is part of PacketDotNet PacketDotNet is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. PacketDotNet is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with PacketDotNet. If not, see . */ /* * Copyright 2010 Chris Morgan */ using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace PacketDotNet { namespace Ieee80211 { /// /// Every 802.11 frame has a control field that contains information about the frame including /// the 802.11 protocol version, frame type, and various indicators, such as whether WEP is on, /// power management is active. /// public class FrameControlField { /// /// Protocol version /// public byte ProtocolVersion { get { return (byte)((Field >> 0x8) & 0x3); } set { if ((value < 0) || (value > 3)) { throw new ArgumentException("Invalid protocol version value. Value must be in the range 0-3."); } //unset the two bits before setting them to the value Field &= unchecked((UInt16)~(0x0300)); Field |= (UInt16)(value << 0x8); } } /// /// Specifies the main frame type: Control, Management or Data. /// public enum FrameTypes { /// /// Management frame. /// Management = 0, /// /// Control frame. /// Control = 1, /// /// Data frame. /// Data = 2 } /// /// Sepcifies the frame types down to the sub type level. /// public enum FrameSubTypes { /// /// Association request /// ManagementAssociationRequest = 0x00, /// /// Association response /// ManagementAssociationResponse = 0x01, /// /// Reassociation request /// ManagementReassociationRequest = 0x02, /// /// Reassociation response /// ManagementReassociationResponse = 0x03, /// /// Probe request /// ManagementProbeRequest = 0x04, /// /// Probe response /// ManagementProbeResponse = 0x5, /// /// Reserved 0 /// ManagementReserved0 = 0x6, /// /// Reserved 1 /// ManagementReserved1 = 0x7, /// /// Beacon /// ManagementBeacon = 0x8, /// /// ATIM /// ManagementATIM = 0x9, /// /// Disassociation /// ManagementDisassociation = 0xA, /// /// Authentication /// ManagementAuthentication = 0xB, /// /// Deauthentication /// ManagementDeauthentication = 0xC, /// /// Reserved 2 /// ManagementAction = 0xD, /// /// Reserved 3 /// ManagementReserved3 = 0xE, /// /// Blck Acknowledgment Request (QOS) /// ControlBlockAcknowledgmentRequest = 0x18, /// /// Blck Acknowledgment (QOS) /// ControlBlockAcknowledgment = 0x19, /// /// PS poll /// ControlPSPoll = 0x1A, /// /// RTS /// ControlRTS = 0x1B, /// /// CTS /// ControlCTS = 0x1C, /// /// ACK /// ControlACK = 0x1D, /// /// CF-End /// ControlCFEnd = 0x1E, /// /// CF-End CF-Ack /// ControlCFEndCFACK = 0x1F, /// /// Data /// Data = 0x20, /// /// CF-ACK /// DataCFACK = 0x21, /// /// CF-Poll /// DataCFPoll = 0x22, /// /// CF-Ack CF-Poll /// DataCFAckCFPoll = 0x23, /// /// Null function no data /// DataNullFunctionNoData = 0x24, /// /// CF-Ack No data /// DataCFAckNoData = 0x25, /// /// CF-Poll no data /// DataCFPollNoData = 0x26, /// /// CF-Ack CF-Poll no data /// DataCFAckCFPollNoData = 0x27, /// /// Constant qos data. /// QosData = 0x28, /// /// Constant qos data and CF ack. /// QosDataAndCFAck = 0x29, /// /// Constant qos data and CF poll. /// QosDataAndCFPoll = 0x2A, /// /// Constant qos data and CF ack and CF poll. /// QosDataAndCFAckAndCFPoll = 0x2B, /// /// Constant qos null data. /// QosNullData = 0x2C, /// /// Constant qos CF ack. /// QosCFAck = 0x2D, /// /// Constant qos CF poll. /// QosCFPoll = 0x2E, /// /// Constant qos CF ack and CF poll. /// QosCFAckAndCFPoll = 0x2F }; /// /// Gets the type of the frame. /// /// /// The type. /// public FrameTypes Type { get { int typeAndSubtype = (Field >> 8); //get rid of the flags int type = ((typeAndSubtype & 0xC) >> 2); return (FrameTypes)type; } } /// /// Helps to identify the type of WLAN frame, control data and management are /// the various frame types defined in IEEE 802.11 /// public FrameSubTypes SubType { get { int typeAndSubtype = (Field >> 8); //get rid of the flags int type = (((typeAndSubtype & 0x0C) << 2) | (typeAndSubtype >> 4)); return (FrameSubTypes)type; } set { uint val = (uint)value; uint typeAndSubtype = ((val & 0x0F) << 4) | ((val >> 4) << 2); //shift it into the right position in the field typeAndSubtype = typeAndSubtype << 0x8; //Unset all the bits related to the type and subtype Field &= 0x03FF; //Set the type bits Field |= (UInt16)typeAndSubtype; } } /// /// Is set to 1 when the frame is sent to Distribution System (DS) /// public bool ToDS { get { return ((Field & 0x1) == 1) ? true : false; } set { if (value) { Field |= 0x1; } else { Field &= unchecked((UInt16)~(0x1)); } } } /// /// Is set to 1 when the frame is received from the Distribution System (DS) /// public bool FromDS { get { return (((Field >> 1) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x1); } else { Field &= unchecked((UInt16)~(1 << 0x1)); } } } /// /// More Fragment is set to 1 when there are more fragments belonging to the same /// frame following the current fragment /// public bool MoreFragments { get { return (((Field >> 2) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x2); } else { Field &= unchecked((UInt16)~(1 << 0x2)); } } } /// /// Indicates that this fragment is a retransmission of a previously transmitted fragment. /// (For receiver to recognize duplicate transmissions of frames) /// public bool Retry { get { return (((Field >> 3) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x3); } else { Field &= unchecked((UInt16)~(1 << 0x3)); } } } /// /// Indicates the power management mode that the station will be in after the transmission of the frame /// public bool PowerManagement { get { return (((Field >> 4) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x4); } else { Field &= unchecked((UInt16)~(1 << 0x4)); } } } /// /// Indicates that there are more frames buffered for this station /// public bool MoreData { get { return (((Field >> 5) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x5); } else { Field &= unchecked((UInt16)~(1 << 0x5)); } } } /// /// Indicates that the frame body is encrypted according to the WEP (wired equivalent privacy) algorithm /// public bool Wep { get { return (((Field >> 6) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x6); } else { Field &= unchecked((UInt16)~(1 << 0x6)); } } } /// /// Bit is set when the "strict ordering" delivery method is employed. Frames and /// fragments are not always sent in order as it causes a transmission performance penalty. /// public bool Order { get { return (((Field >> 0x7) & 0x1) == 1) ? true : false; } set { if (value) { Field |= (1 << 0x7); } else { Field &= unchecked((UInt16)~(1 << 0x7)); } } } /// /// Gets or sets the field. /// /// /// The field. /// public UInt16 Field { get; set; } /// /// Initializes a new instance of the class. /// public FrameControlField() { } /// /// Constructor /// /// /// A /// public FrameControlField(UInt16 field) { this.Field = field; } /// /// Returns a that represents the current . /// /// /// A that represents the current . /// public override string ToString () { var flags = new List(); flags.Add(SubType.ToString()); if (ToDS) { flags.Add("ToDS"); } if (FromDS) { flags.Add("FromDS"); } if (Retry) { flags.Add("Retry"); } if (PowerManagement) { flags.Add("PowerManagement"); } if (MoreData) { flags.Add("MoreData"); } if (Wep) { flags.Add("Wep"); } if (Order) { flags.Add("Order"); } return String.Join(" ", flags.ToArray()); } } } }