INET Framework for OMNeT++/OMNEST
Ieee80211MgmtAP Class Reference

#include <Ieee80211MgmtAP.h>

Inheritance diagram for Ieee80211MgmtAP:
Ieee80211MgmtAPBase Ieee80211MgmtBase PassiveQueueBase INotifiable IPassiveQueue

List of all members.

Classes

struct  MAC_compare
struct  STAInfo

Public Types

enum  STAStatus { NOT_AUTHENTICATED, AUTHENTICATED, ASSOCIATED }
typedef std::map< MACAddress,
STAInfo, MAC_compare
STAList

Protected Member Functions

virtual int numInitStages () const
virtual void initialize (int)
virtual void handleTimer (cMessage *msg)
virtual void handleUpperMessage (cPacket *msg)
virtual void handleCommand (int msgkind, cPolymorphic *ctrl)
virtual void receiveChangeNotification (int category, const cPolymorphic *details)
virtual STAInfolookupSenderSTA (Ieee80211ManagementFrame *frame)
virtual void sendManagementFrame (Ieee80211ManagementFrame *frame, const MACAddress &destAddr)
virtual void sendBeacon ()
Processing of different frame types
virtual void handleDataFrame (Ieee80211DataFrame *frame)
virtual void handleAuthenticationFrame (Ieee80211AuthenticationFrame *frame)
virtual void handleDeauthenticationFrame (Ieee80211DeauthenticationFrame *frame)
virtual void handleAssociationRequestFrame (Ieee80211AssociationRequestFrame *frame)
virtual void handleAssociationResponseFrame (Ieee80211AssociationResponseFrame *frame)
virtual void handleReassociationRequestFrame (Ieee80211ReassociationRequestFrame *frame)
virtual void handleReassociationResponseFrame (Ieee80211ReassociationResponseFrame *frame)
virtual void handleDisassociationFrame (Ieee80211DisassociationFrame *frame)
virtual void handleBeaconFrame (Ieee80211BeaconFrame *frame)
virtual void handleProbeRequestFrame (Ieee80211ProbeRequestFrame *frame)
virtual void handleProbeResponseFrame (Ieee80211ProbeResponseFrame *frame)

Protected Attributes

std::string ssid
int channelNumber
simtime_t beaconInterval
int numAuthSteps
Ieee80211SupportedRatesElement supportedRates
STAList staList
 list of STAs
cMessage * beaconTimer

Detailed Description

Used in 802.11 infrastructure mode: handles management frames for an access point (AP). See corresponding NED file for a detailed description.

Author:
Andras Varga

Member Typedef Documentation


Member Enumeration Documentation

State of a STA

Enumerator:
NOT_AUTHENTICATED 
AUTHENTICATED 
ASSOCIATED 

Member Function Documentation

void Ieee80211MgmtAP::handleAssociationRequestFrame ( Ieee80211AssociationRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Processing AssociationRequest frame\n";

    // "11.3.2 AP association procedures"
    STAInfo *sta = lookupSenderSTA(frame);
    if (!sta || sta->status==NOT_AUTHENTICATED)
    {
        // STA not authenticated: send error and return
        Ieee80211DeauthenticationFrame *resp = new Ieee80211DeauthenticationFrame("Deauth");
        resp->getBody().setReasonCode(RC_NONAUTH_ASS_REQUEST);
        sendManagementFrame(resp, frame->getTransmitterAddress());
        delete frame;
        return;
    }

    delete frame;

    // mark STA as associated
    sta->status = ASSOCIATED; // XXX this should only take place when MAC receives the ACK for the response

    // send OK response
    Ieee80211AssociationResponseFrame *resp = new Ieee80211AssociationResponseFrame("AssocResp-OK");
    Ieee80211AssociationResponseFrameBody& body = resp->getBody();
    body.setStatusCode(SC_SUCCESSFUL);
    body.setAid(0); //XXX
    body.setSupportedRates(supportedRates);
    sendManagementFrame(resp, sta->address);
}
void Ieee80211MgmtAP::handleAssociationResponseFrame ( Ieee80211AssociationResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtAP::handleAuthenticationFrame ( Ieee80211AuthenticationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    int frameAuthSeq = frame->getBody().getSequenceNumber();
    EV << "Processing Authentication frame, seqNum=" << frameAuthSeq << "\n";

    // create STA entry if needed
    STAInfo *sta = lookupSenderSTA(frame);
    if (!sta)
    {
        MACAddress staAddress = frame->getTransmitterAddress();
        sta = &staList[staAddress]; // this implicitly creates a new entry
        sta->address = staAddress;
        sta->status = NOT_AUTHENTICATED;
        sta->authSeqExpected = 1;
    }

    // check authentication sequence number is OK
    if (frameAuthSeq != sta->authSeqExpected)
    {
        // wrong sequence number: send error and return
        EV << "Wrong sequence number, " << sta->authSeqExpected << " expected\n";
        Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame("Auth-ERROR");
        resp->getBody().setStatusCode(SC_AUTH_OUT_OF_SEQ);
        sendManagementFrame(resp, frame->getTransmitterAddress());
        delete frame;
        sta->authSeqExpected = 1; // go back to start square
        return;
    }

    // station is authenticated if it made it through the required number of steps
    bool isLast = (frameAuthSeq+1 == numAuthSteps);

    // send OK response (we don't model the cryptography part, just assume
    // successful authentication every time)
    EV << "Sending Authentication frame, seqNum=" << (frameAuthSeq+1) << "\n";
    Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame(isLast ? "Auth-OK" : "Auth");
    resp->getBody().setSequenceNumber(frameAuthSeq+1);
    resp->getBody().setStatusCode(SC_SUCCESSFUL);
    resp->getBody().setIsLast(isLast);
    // XXX frame length could be increased to account for challenge text length etc.
    sendManagementFrame(resp, frame->getTransmitterAddress());

    delete frame;

    // update status
    if (isLast)
    {
        sta->status = AUTHENTICATED; // XXX only when ACK of this frame arrives
        EV << "STA authenticated\n";
    }
    else
    {
        sta->authSeqExpected += 2;
        EV << "Expecting Authentication frame " << sta->authSeqExpected << "\n";
    }
}
void Ieee80211MgmtAP::handleBeaconFrame ( Ieee80211BeaconFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtAP::handleCommand ( int  msgkind,
cPolymorphic *  ctrl 
) [protected, virtual]

Implements abstract Ieee80211MgmtBase method -- throws an error (no commands supported)

Implements Ieee80211MgmtBase.

{
    error("handleCommand(): no commands supported");
}
void Ieee80211MgmtAP::handleDataFrame ( Ieee80211DataFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    // check toDS bit
    if (!frame->getToDS())
    {
        // looks like this is not for us - discard
        EV << "Frame is not for us (toDS=false) -- discarding\n";
        delete frame;
        return;
    }

    // handle broadcast frames
    if (frame->getAddress3().isBroadcast())
    {
        EV << "Handling broadcast frame\n";
        if (hasRelayUnit)
            send(convertToEtherFrame((Ieee80211DataFrame *)frame->dup()), "uppergateOut");
        distributeReceivedDataFrame(frame);
        return;
    }

    // look up destination address in our STA list
    STAList::iterator it = staList.find(frame->getAddress3());
    if (it==staList.end())
    {
        // not our STA -- pass up frame to relayUnit for LAN bridging if we have one
        if (hasRelayUnit)
            send(convertToEtherFrame(frame), "uppergateOut");
        else {
            EV << "Frame's destination address is not in our STA list -- dropping frame\n";
            delete frame;
        }
    }
    else
    {
        // dest address is our STA, but is it already associated?
        if (it->second.status == ASSOCIATED)
            distributeReceivedDataFrame(frame); // send it out to the destination STA
        else {
            EV << "Frame's destination STA is not in associated state -- dropping frame\n";
            delete frame;
        }
    }
}
void Ieee80211MgmtAP::handleDeauthenticationFrame ( Ieee80211DeauthenticationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Processing Deauthentication frame\n";

    STAInfo *sta = lookupSenderSTA(frame);
    delete frame;

    if (sta)
    {
        // mark STA as not authenticated; alternatively, it could also be removed from staList
        sta->status = NOT_AUTHENTICATED;
        sta->authSeqExpected = 1;
    }
}
void Ieee80211MgmtAP::handleDisassociationFrame ( Ieee80211DisassociationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    STAInfo *sta = lookupSenderSTA(frame);
    delete frame;

    if (sta)
    {
        sta->status = AUTHENTICATED;
    }
}
void Ieee80211MgmtAP::handleProbeRequestFrame ( Ieee80211ProbeRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Processing ProbeRequest frame\n";

    if (strcmp(frame->getBody().getSSID(),"")!=0 && strcmp(frame->getBody().getSSID(), ssid.c_str())!=0)
    {
        EV << "SSID `" << frame->getBody().getSSID() << "' does not match, ignoring frame\n";
        dropManagementFrame(frame);
        return;
    }

    MACAddress staAddress = frame->getTransmitterAddress();
    delete frame;

    EV << "Sending ProbeResponse frame\n";
    Ieee80211ProbeResponseFrame *resp = new Ieee80211ProbeResponseFrame("ProbeResp");
    Ieee80211ProbeResponseFrameBody& body = resp->getBody();
    body.setSSID(ssid.c_str());
    body.setSupportedRates(supportedRates);
    body.setBeaconInterval(beaconInterval);
    body.setChannelNumber(channelNumber);
    sendManagementFrame(resp, staAddress);
}
void Ieee80211MgmtAP::handleProbeResponseFrame ( Ieee80211ProbeResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtAP::handleReassociationRequestFrame ( Ieee80211ReassociationRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Processing ReassociationRequest frame\n";

    // "11.3.4 AP reassociation procedures" -- almost the same as AssociationRequest processing
    STAInfo *sta = lookupSenderSTA(frame);
    if (!sta || sta->status==NOT_AUTHENTICATED)
    {
        // STA not authenticated: send error and return
        Ieee80211DeauthenticationFrame *resp = new Ieee80211DeauthenticationFrame("Deauth");
        resp->getBody().setReasonCode(RC_NONAUTH_ASS_REQUEST);
        sendManagementFrame(resp, frame->getTransmitterAddress());
        delete frame;
        return;
    }

    delete frame;

    // mark STA as associated
    sta->status = ASSOCIATED; // XXX this should only take place when MAC receives the ACK for the response

    // send OK response
    Ieee80211ReassociationResponseFrame *resp = new Ieee80211ReassociationResponseFrame("ReassocResp-OK");
    Ieee80211ReassociationResponseFrameBody& body = resp->getBody();
    body.setStatusCode(SC_SUCCESSFUL);
    body.setAid(0); //XXX
    body.setSupportedRates(supportedRates);
    sendManagementFrame(resp, sta->address);
}
void Ieee80211MgmtAP::handleReassociationResponseFrame ( Ieee80211ReassociationResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtAP::handleTimer ( cMessage *  msg) [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

{
    if (msg==beaconTimer)
    {
        sendBeacon();
        scheduleAt(simTime()+beaconInterval, beaconTimer);
    }
    else
    {
        error("internal error: unrecognized timer '%s'", msg->getName());
    }
}
void Ieee80211MgmtAP::handleUpperMessage ( cPacket *  msg) [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

{
    // must be an EtherFrame frame arriving from MACRelayUnit, that is,
    // bridged from another interface of the AP (probably Ethernet).
    EtherFrame *etherframe = check_and_cast<EtherFrame *>(msg);

    // check we really have a STA with that dest address
    STAList::iterator it = staList.find(etherframe->getDest());
    if (it==staList.end() || it->second.status!=ASSOCIATED)
    {
        EV << "STA with MAC address " << etherframe->getDest() << " not associated with this AP, dropping frame\n";
        delete etherframe; // XXX count drops?
        return;
    }

    // convert Ethernet frame
    Ieee80211DataFrame *frame = convertFromEtherFrame(etherframe);
    sendOrEnqueue(frame);
}
void Ieee80211MgmtAP::initialize ( int  stage) [protected, virtual]

Reimplemented from Ieee80211MgmtAPBase.

{
    Ieee80211MgmtAPBase::initialize(stage);

    if (stage==0)
    {
        // read params and init vars
        ssid = par("ssid").stringValue();
        beaconInterval = par("beaconInterval");
        numAuthSteps = par("numAuthSteps");
        if (numAuthSteps!=2 && numAuthSteps!=4)
            error("parameter 'numAuthSteps' (number of frames exchanged during authentication) must be 2 or 4, not %d", numAuthSteps);
        channelNumber = -1;  // value will arrive from physical layer in receiveChangeNotification()
        WATCH(ssid);
        WATCH(channelNumber);
        WATCH(beaconInterval);
        WATCH(numAuthSteps);
        WATCH_MAP(staList);

        //TBD fill in supportedRates

        // subscribe for notifications
        NotificationBoard *nb = NotificationBoardAccess().get();
        nb->subscribe(this, NF_RADIO_CHANNEL_CHANGED);

        // start beacon timer (randomize startup time)
        beaconTimer = new cMessage("beaconTimer");
        scheduleAt(simTime()+uniform(0,beaconInterval), beaconTimer);
    }
}
Ieee80211MgmtAP::STAInfo * Ieee80211MgmtAP::lookupSenderSTA ( Ieee80211ManagementFrame *  frame) [protected, virtual]

Utility function: return sender STA's entry from our STA list, or NULL if not in there

Referenced by handleAssociationRequestFrame(), handleAuthenticationFrame(), handleDeauthenticationFrame(), handleDisassociationFrame(), and handleReassociationRequestFrame().

{
    STAList::iterator it = staList.find(frame->getTransmitterAddress());
    return it==staList.end() ? NULL : &(it->second);
}
virtual int Ieee80211MgmtAP::numInitStages ( ) const [inline, protected, virtual]

Reimplemented from Ieee80211MgmtAPBase.

{return 2;}
void Ieee80211MgmtAP::receiveChangeNotification ( int  category,
const cPolymorphic *  details 
) [protected, virtual]

Called by the NotificationBoard whenever a change occurs we're interested in

Implements INotifiable.

{
    Enter_Method_Silent();
    printNotificationBanner(category, details);

    if (category == NF_RADIO_CHANNEL_CHANGED)
    {
        EV << "updating channel number\n";
        channelNumber = check_and_cast<RadioState *>(details)->getChannelNumber();
    }
}
void Ieee80211MgmtAP::sendBeacon ( ) [protected, virtual]

Utility function: creates and sends a beacon frame

Referenced by handleTimer().

{
    EV << "Sending beacon\n";
    Ieee80211BeaconFrame *frame = new Ieee80211BeaconFrame("Beacon");
    Ieee80211BeaconFrameBody& body = frame->getBody();
    body.setSSID(ssid.c_str());
    body.setSupportedRates(supportedRates);
    body.setBeaconInterval(beaconInterval);
    body.setChannelNumber(channelNumber);

    frame->setReceiverAddress(MACAddress::BROADCAST_ADDRESS);
    frame->setFromDS(true);

    sendOrEnqueue(frame);
}
void Ieee80211MgmtAP::sendManagementFrame ( Ieee80211ManagementFrame *  frame,
const MACAddress destAddr 
) [protected, virtual]

Utility function: set fields in the given frame and send it out to the address

Referenced by handleAssociationRequestFrame(), handleAuthenticationFrame(), handleProbeRequestFrame(), and handleReassociationRequestFrame().

{
    frame->setFromDS(true);
    frame->setReceiverAddress(destAddr);
    frame->setAddress3(myAddress);
    sendOrEnqueue(frame);
}

Member Data Documentation

cMessage* Ieee80211MgmtAP::beaconTimer [protected]

Referenced by handleTimer(), and initialize().

std::string Ieee80211MgmtAP::ssid [protected]

The documentation for this class was generated from the following files: