INET Framework for OMNeT++/OMNEST
Ieee80211MgmtSTA Class Reference

#include <Ieee80211MgmtSTA.h>

Inheritance diagram for Ieee80211MgmtSTA:
Ieee80211MgmtBase PassiveQueueBase INotifiable IPassiveQueue

List of all members.

Classes

struct  APInfo
struct  AssociatedAPInfo
struct  ScanningInfo

Protected Types

typedef std::list< APInfoAccessPointList

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 Ieee80211DataFrame * encapsulate (cPacket *msg)
virtual void startAuthentication (APInfo *ap, simtime_t timeout)
virtual void startAssociation (APInfo *ap, simtime_t timeout)
virtual APInfolookupAP (const MACAddress &address)
virtual void clearAPList ()
virtual void changeChannel (int channelNum)
virtual void storeAPInfo (const MACAddress &address, const Ieee80211BeaconFrameBody &body)
virtual bool scanNextChannel ()
virtual void sendProbeRequest ()
virtual void beaconLost ()
virtual void sendScanConfirm ()
virtual void sendAuthenticationConfirm (APInfo *ap, int resultCode)
virtual void sendAssociationConfirm (APInfo *ap, int resultCode)
virtual void disassociate ()
virtual void sendConfirm (Ieee80211PrimConfirm *confirm, int resultCode)
virtual void sendManagementFrame (Ieee80211ManagementFrame *frame, const MACAddress &address)
virtual void receiveChangeNotification (int category, const cPolymorphic *details)
virtual int statusCodeToPrimResultCode (int statusCode)
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)
Processing of different agent commands
virtual void processScanCommand (Ieee80211Prim_ScanRequest *ctrl)
virtual void processAuthenticateCommand (Ieee80211Prim_AuthenticateRequest *ctrl)
virtual void processDeauthenticateCommand (Ieee80211Prim_DeauthenticateRequest *ctrl)
virtual void processAssociateCommand (Ieee80211Prim_AssociateRequest *ctrl)
virtual void processReassociateCommand (Ieee80211Prim_ReassociateRequest *ctrl)
virtual void processDisassociateCommand (Ieee80211Prim_DisassociateRequest *ctrl)

Protected Attributes

NotificationBoardnb
int numChannels
bool isScanning
ScanningInfo scanning
AccessPointList apList
bool isAssociated
cMessage * assocTimeoutMsg
AssociatedAPInfo assocAP

Detailed Description

Used in 802.11 infrastructure mode: handles management frames for a station (STA). See corresponding NED file for a detailed description.

Author:
Andras Varga

Member Typedef Documentation

typedef std::list<APInfo> Ieee80211MgmtSTA::AccessPointList [protected]

Member Function Documentation

void Ieee80211MgmtSTA::beaconLost ( ) [protected, virtual]

Missed a few consecutive beacons

Referenced by handleTimer().

{
    EV << "Missed a few consecutive beacons -- AP is considered lost\n";
    nb->fireChangeNotification(NF_L2_BEACON_LOST, NULL);  //XXX use InterfaceEntry as detail, etc...
}
void Ieee80211MgmtSTA::changeChannel ( int  channelNum) [protected, virtual]

Utility function: switches to the given radio channel.

Referenced by scanNextChannel(), startAssociation(), and startAuthentication().

{
    EV << "Tuning to channel #" << channelNum << "\n";

    // sending PHY_C_CONFIGURERADIO command to MAC
    PhyControlInfo *phyCtrl = new PhyControlInfo();
    phyCtrl->setChannelNumber(channelNum);
    cMessage *msg = new cMessage("changeChannel", PHY_C_CONFIGURERADIO);
    msg->setControlInfo(phyCtrl);
    send(msg, "macOut");
}
void Ieee80211MgmtSTA::clearAPList ( ) [protected, virtual]

Utility function: clear the AP list, and cancel any pending authentications.

Referenced by processScanCommand().

{
    for (AccessPointList::iterator it=apList.begin(); it!=apList.end(); ++it)
        if (it->authTimeoutMsg)
            delete cancelEvent(it->authTimeoutMsg);
    apList.clear();
}
void Ieee80211MgmtSTA::disassociate ( ) [protected, virtual]

Utility function: Cancel the existing association

Referenced by processDeauthenticateCommand(), processDisassociateCommand(), and processScanCommand().

{
    EV << "Disassociating from AP address=" << assocAP.address << "\n";
    ASSERT(isAssociated);
    isAssociated = false;
    delete cancelEvent(assocAP.beaconTimeoutMsg);
    assocAP.beaconTimeoutMsg = NULL;
    assocAP = AssociatedAPInfo(); // clear it
}
Ieee80211DataFrame * Ieee80211MgmtSTA::encapsulate ( cPacket *  msg) [protected, virtual]

Utility function for handleUpperMessage()

Referenced by handleUpperMessage().

{
    Ieee80211DataFrame *frame = new Ieee80211DataFrame(msg->getName());

    // frame goes to the AP
    frame->setToDS(true);

    // receiver is the AP
    frame->setReceiverAddress(assocAP.address);

    // destination address is in address3
    Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->removeControlInfo());
    frame->setAddress3(ctrl->getDest());
    delete ctrl;

    frame->encapsulate(msg);
    return frame;
}
void Ieee80211MgmtSTA::handleAssociationRequestFrame ( Ieee80211AssociationRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtSTA::handleAssociationResponseFrame ( Ieee80211AssociationResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Association Response frame\n";

    if (!assocTimeoutMsg)
    {
        EV << "No association in progress, ignoring frame\n";
        delete frame;
        return;
    }

    // extract frame contents
    MACAddress address = frame->getTransmitterAddress();
    int statusCode = frame->getBody().getStatusCode();
    //XXX short aid;
    //XXX Ieee80211SupportedRatesElement supportedRates;
    delete frame;

    // look up AP data structure
    APInfo *ap = lookupAP(address);
    if (!ap)
        error("handleAssociationResponseFrame: AP not known: address=%s", address.str().c_str());

    if (isAssociated)
    {
        EV << "Breaking existing association with AP address=" << assocAP.address << "\n";
        isAssociated = false;
        delete cancelEvent(assocAP.beaconTimeoutMsg);
        assocAP.beaconTimeoutMsg = NULL;
        assocAP = AssociatedAPInfo();
    }

    delete cancelEvent(assocTimeoutMsg);
    assocTimeoutMsg = NULL;

    if (statusCode!=SC_SUCCESSFUL)
    {
        EV << "Association failed with AP address=" << ap->address << "\n";
    }
    else
    {
        EV << "Association successful, AP address=" << ap->address << "\n";

        // change our state to "associated"
        isAssociated = true;
        (APInfo&)assocAP = (*ap);

        nb->fireChangeNotification(NF_L2_ASSOCIATED, NULL); //XXX detail: InterfaceEntry?

        assocAP.beaconTimeoutMsg = new cMessage("beaconTimeout", MK_BEACON_TIMEOUT);
        scheduleAt(simTime()+MAX_BEACONS_MISSED*assocAP.beaconInterval, assocAP.beaconTimeoutMsg);
    }

    // report back to agent
    sendAssociationConfirm(ap, statusCodeToPrimResultCode(statusCode));
}
void Ieee80211MgmtSTA::handleAuthenticationFrame ( Ieee80211AuthenticationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    MACAddress address = frame->getTransmitterAddress();
    int frameAuthSeq = frame->getBody().getSequenceNumber();
    EV << "Received Authentication frame from address=" << address << ", seqNum=" << frameAuthSeq << "\n";

    APInfo *ap = lookupAP(address);
    if (!ap)
    {
        EV << "AP not known, discarding authentication frame\n";
        delete frame;
        return;
    }

    // what if already authenticated with AP
    if (ap->isAuthenticated)
    {
        EV << "AP already authenticated, ignoring frame\n";
        delete frame;
        return;
    }

    // is authentication is in progress with this AP?
    if (!ap->authTimeoutMsg)
    {
        EV << "No authentication in progress with AP, ignoring frame\n";
        delete frame;
        return;
    }

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

        // cancel timeout, send error to agent
        delete cancelEvent(ap->authTimeoutMsg);
        ap->authTimeoutMsg = NULL;
        sendAuthenticationConfirm(ap, PRC_REFUSED); //XXX or what resultCode?
        return;
    }

    // check if more exchanges are needed for auth to be complete
    int statusCode = frame->getBody().getStatusCode();

    if (statusCode==SC_SUCCESSFUL && !frame->getBody().getIsLast())
    {
        EV << "More steps required, sending another Authentication frame\n";

        // more steps required, send another Authentication frame
        Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame("Auth");
        resp->getBody().setSequenceNumber(frameAuthSeq+1);
        resp->getBody().setStatusCode(SC_SUCCESSFUL);
        // XXX frame length could be increased to account for challenge text length etc.
        sendManagementFrame(resp, address);
        ap->authSeqExpected += 2;
    }
    else
    {
        if (statusCode==SC_SUCCESSFUL)
            EV << "Authentication successful\n";
        else
            EV << "Authentication failed\n";

        // authentication completed
        ap->isAuthenticated = (statusCode==SC_SUCCESSFUL);
        delete cancelEvent(ap->authTimeoutMsg);
        ap->authTimeoutMsg = NULL;
        sendAuthenticationConfirm(ap, statusCodeToPrimResultCode(statusCode));
    }

    delete frame;
}
void Ieee80211MgmtSTA::handleBeaconFrame ( Ieee80211BeaconFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Beacon frame\n";
    storeAPInfo(frame->getTransmitterAddress(), frame->getBody());

    // if it is out associate AP, restart beacon timeout
    if (isAssociated && frame->getTransmitterAddress()==assocAP.address)
    {
        EV << "Beacon is from associated AP, restarting beacon timeout timer\n";
        ASSERT(assocAP.beaconTimeoutMsg!=NULL);
        cancelEvent(assocAP.beaconTimeoutMsg);
        scheduleAt(simTime()+MAX_BEACONS_MISSED*assocAP.beaconInterval, assocAP.beaconTimeoutMsg);

        //APInfo *ap = lookupAP(frame->getTransmitterAddress());
        //ASSERT(ap!=NULL);
    }

    delete frame;
}
void Ieee80211MgmtSTA::handleCommand ( int  msgkind,
cPolymorphic *  ctrl 
) [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

{
    if (dynamic_cast<Ieee80211Prim_ScanRequest *>(ctrl))
        processScanCommand((Ieee80211Prim_ScanRequest *)ctrl);
    else if (dynamic_cast<Ieee80211Prim_AuthenticateRequest *>(ctrl))
        processAuthenticateCommand((Ieee80211Prim_AuthenticateRequest *)ctrl);
    else if (dynamic_cast<Ieee80211Prim_DeauthenticateRequest *>(ctrl))
        processDeauthenticateCommand((Ieee80211Prim_DeauthenticateRequest *)ctrl);
    else if (dynamic_cast<Ieee80211Prim_AssociateRequest *>(ctrl))
        processAssociateCommand((Ieee80211Prim_AssociateRequest *)ctrl);
    else if (dynamic_cast<Ieee80211Prim_ReassociateRequest *>(ctrl))
        processReassociateCommand((Ieee80211Prim_ReassociateRequest *)ctrl);
    else if (dynamic_cast<Ieee80211Prim_DisassociateRequest *>(ctrl))
        processDisassociateCommand((Ieee80211Prim_DisassociateRequest *)ctrl);
    else if (ctrl)
        error("handleCommand(): unrecognized control info class `%s'", ctrl->getClassName());
    else
        error("handleCommand(): control info is NULL");
    delete ctrl;
}
void Ieee80211MgmtSTA::handleDataFrame ( Ieee80211DataFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    sendUp(decapsulate(frame));
}
void Ieee80211MgmtSTA::handleDeauthenticationFrame ( Ieee80211DeauthenticationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Deauthentication frame\n";
    const MACAddress& address = frame->getAddress3();  // source address
    APInfo *ap = lookupAP(address);
    if (!ap || !ap->isAuthenticated)
    {
        EV << "Unknown AP, or not authenticated with that AP -- ignoring frame\n";
        delete frame;
        return;
    }
    if (ap->authTimeoutMsg)
    {
        delete cancelEvent(ap->authTimeoutMsg);
        ap->authTimeoutMsg = NULL;
        EV << "Cancelling pending authentication\n";
        delete frame;
        return;
    }

    EV << "Setting isAuthenticated flag for that AP to false\n";
    ap->isAuthenticated = false;
}
void Ieee80211MgmtSTA::handleDisassociationFrame ( Ieee80211DisassociationFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Disassociation frame\n";
    const MACAddress& address = frame->getAddress3();  // source address

    if (assocTimeoutMsg)
    {
        // pending association
        delete cancelEvent(assocTimeoutMsg);
        assocTimeoutMsg = NULL;
    }
    if (!isAssociated || address!=assocAP.address)
    {
        EV << "Not associated with that AP -- ignoring frame\n";
        delete frame;
        return;
    }

    EV << "Setting isAssociated flag to false\n";
    isAssociated = false;
    delete cancelEvent(assocAP.beaconTimeoutMsg);
    assocAP.beaconTimeoutMsg = NULL;
}
void Ieee80211MgmtSTA::handleProbeRequestFrame ( Ieee80211ProbeRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtSTA::handleProbeResponseFrame ( Ieee80211ProbeResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Probe Response frame\n";
    storeAPInfo(frame->getTransmitterAddress(), frame->getBody());
    delete frame;
}
void Ieee80211MgmtSTA::handleReassociationRequestFrame ( Ieee80211ReassociationRequestFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    dropManagementFrame(frame);
}
void Ieee80211MgmtSTA::handleReassociationResponseFrame ( Ieee80211ReassociationResponseFrame *  frame) [protected, virtual]

Implements Ieee80211MgmtBase.

{
    EV << "Received Reassociation Response frame\n";
    //TBD handle with the same code as Association Response?
}
void Ieee80211MgmtSTA::handleTimer ( cMessage *  msg) [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

{
    if (msg->getKind()==MK_AUTH_TIMEOUT)
    {
        // authentication timed out
        APInfo *ap = (APInfo *)msg->getContextPointer();
        EV << "Authentication timed out, AP address = " << ap->address << "\n";

        // send back failure report to agent
        sendAuthenticationConfirm(ap, PRC_TIMEOUT);
    }
    else if (msg->getKind()==MK_ASSOC_TIMEOUT)
    {
        // association timed out
        APInfo *ap = (APInfo *)msg->getContextPointer();
        EV << "Association timed out, AP address = " << ap->address << "\n";

        // send back failure report to agent
        sendAssociationConfirm(ap, PRC_TIMEOUT);
    }
    else if (msg->getKind()==MK_SCAN_MAXCHANNELTIME)
    {
        // go to next channel during scanning
        bool done = scanNextChannel();
        if (done)
            sendScanConfirm(); // send back response to agents' "scan" command
        delete msg;
    }
    else if (msg->getKind()==MK_SCAN_SENDPROBE)
    {
        // Active Scan: send a probe request, then wait for minChannelTime (11.1.3.2.2)
        delete msg;
        sendProbeRequest();
        cMessage *timerMsg = new cMessage("minChannelTime", MK_SCAN_MINCHANNELTIME);
        scheduleAt(simTime()+scanning.minChannelTime, timerMsg); //XXX actually, we should start waiting after ProbeReq actually got transmitted
    }
    else if (msg->getKind()==MK_SCAN_MINCHANNELTIME)
    {
        // Active Scan: after minChannelTime, possibly listen for the remaining time until maxChannelTime
        delete msg;
        if (scanning.busyChannelDetected)
        {
            EV << "Busy channel detected during minChannelTime, continuing listening until maxChannelTime elapses\n";
            cMessage *timerMsg = new cMessage("maxChannelTime", MK_SCAN_MAXCHANNELTIME);
            scheduleAt(simTime()+scanning.maxChannelTime - scanning.minChannelTime, timerMsg);
        }
        else
        {
            EV << "Channel was empty during minChannelTime, going to next channel\n";
            bool done = scanNextChannel();
            if (done)
                sendScanConfirm(); // send back response to agents' "scan" command
        }
    }
    else if (msg->getKind()==MK_BEACON_TIMEOUT)
    {
        // missed a few consecutive beacons
        beaconLost();
    }
    else
    {
        error("internal error: unrecognized timer '%s'", msg->getName());
    }
}
void Ieee80211MgmtSTA::handleUpperMessage ( cPacket *  msg) [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

{
    Ieee80211DataFrame *frame = encapsulate(msg);
    sendOrEnqueue(frame);
}
void Ieee80211MgmtSTA::initialize ( int  stage) [protected, virtual]

Reimplemented from Ieee80211MgmtBase.

{
    Ieee80211MgmtBase::initialize(stage);
    if (stage==0)
    {
        isScanning = false;
        isAssociated = false;
        assocTimeoutMsg = NULL;

        nb = NotificationBoardAccess().get();

        // determine numChannels (needed when we're told to scan "all" channels)
        //XXX find a better way than directly accessing channelControl
        cModule *cc = ChannelControl::get();
        numChannels = cc->par("numChannels");

        WATCH(isScanning);
        WATCH(isAssociated);

        WATCH(scanning);
        WATCH(assocAP);
        WATCH_LIST(apList);
    }
}
Ieee80211MgmtSTA::APInfo * Ieee80211MgmtSTA::lookupAP ( const MACAddress address) [protected, virtual]

Utility function: looks up AP in our AP list. Returns NULL if not found.

Referenced by handleAssociationResponseFrame(), handleAuthenticationFrame(), handleDeauthenticationFrame(), processAssociateCommand(), processAuthenticateCommand(), processDeauthenticateCommand(), and storeAPInfo().

{
    for (AccessPointList::iterator it=apList.begin(); it!=apList.end(); ++it)
        if (it->address == address)
            return &(*it);
    return NULL;
}
virtual int Ieee80211MgmtSTA::numInitStages ( ) const [inline, protected, virtual]

Reimplemented from Ieee80211MgmtBase.

{return 2;}
void Ieee80211MgmtSTA::processAssociateCommand ( Ieee80211Prim_AssociateRequest *  ctrl) [protected, virtual]

Referenced by handleCommand(), and processReassociateCommand().

{
    const MACAddress& address = ctrl->getAddress();
    APInfo *ap = lookupAP(address);
    if (!ap)
        error("processAssociateCommand: AP not known: address = %s", address.str().c_str());
    startAssociation(ap, ctrl->getTimeout());
}
void Ieee80211MgmtSTA::processAuthenticateCommand ( Ieee80211Prim_AuthenticateRequest *  ctrl) [protected, virtual]

Referenced by handleCommand().

{
    const MACAddress& address = ctrl->getAddress();
    APInfo *ap = lookupAP(address);
    if (!ap)
        error("processAuthenticateCommand: AP not known: address = %s", address.str().c_str());
    startAuthentication(ap, ctrl->getTimeout());
}
void Ieee80211MgmtSTA::processDeauthenticateCommand ( Ieee80211Prim_DeauthenticateRequest *  ctrl) [protected, virtual]

Referenced by handleCommand().

{
    const MACAddress& address = ctrl->getAddress();
    APInfo *ap = lookupAP(address);
    if (!ap)
        error("processDeauthenticateCommand: AP not known: address = %s", address.str().c_str());

    if (isAssociated && assocAP.address==address)
        disassociate();

    if (ap->isAuthenticated)
        ap->isAuthenticated = false;

    // cancel possible pending authentication timer
    if (ap->authTimeoutMsg)
    {
        delete cancelEvent(ap->authTimeoutMsg);
        ap->authTimeoutMsg = NULL;
    }

    // create and send deauthentication request
    Ieee80211DeauthenticationFrame *frame = new Ieee80211DeauthenticationFrame("Deauth");
    frame->getBody().setReasonCode(ctrl->getReasonCode());
    sendManagementFrame(frame, address);
}
void Ieee80211MgmtSTA::processDisassociateCommand ( Ieee80211Prim_DisassociateRequest *  ctrl) [protected, virtual]

Referenced by handleCommand().

{
    const MACAddress& address = ctrl->getAddress();

    if (isAssociated && address==assocAP.address)
    {
        disassociate();
    }
    else if (assocTimeoutMsg)
    {
        // pending association
        delete cancelEvent(assocTimeoutMsg);
        assocTimeoutMsg = NULL;
    }

    // create and send disassociation request
    Ieee80211DisassociationFrame *frame = new Ieee80211DisassociationFrame("Disass");
    frame->getBody().setReasonCode(ctrl->getReasonCode());
    sendManagementFrame(frame, address);
}
void Ieee80211MgmtSTA::processReassociateCommand ( Ieee80211Prim_ReassociateRequest *  ctrl) [protected, virtual]

Referenced by handleCommand().

{
    // treat the same way as association
    //XXX refine
    processAssociateCommand(ctrl);
}
void Ieee80211MgmtSTA::processScanCommand ( Ieee80211Prim_ScanRequest *  ctrl) [protected, virtual]

Referenced by handleCommand().

{
    EV << "Received Scan Request from agent, clearing AP list and starting scanning...\n";

    if (isScanning)
        error("processScanCommand: scanning already in progress");
    if (isAssociated)
    {
        disassociate();
    }
    else if (assocTimeoutMsg)
    {
        EV << "Cancelling ongoing association process\n";
        delete cancelEvent(assocTimeoutMsg);
        assocTimeoutMsg = NULL;
    }

    // clear existing AP list (and cancel any pending authentications) -- we want to start with a clean page
    clearAPList();

    // fill in scanning state
    ASSERT(ctrl->getBSSType()==BSSTYPE_INFRASTRUCTURE);
    scanning.bssid = ctrl->getBSSID().isUnspecified() ? MACAddress::BROADCAST_ADDRESS : ctrl->getBSSID();
    scanning.ssid = ctrl->getSSID();
    scanning.activeScan = ctrl->getActiveScan();
    scanning.probeDelay = ctrl->getProbeDelay();
    scanning.channelList.clear();
    scanning.minChannelTime = ctrl->getMinChannelTime();
    scanning.maxChannelTime = ctrl->getMaxChannelTime();
    ASSERT(scanning.minChannelTime <= scanning.maxChannelTime);

    // channel list to scan (default: all channels)
    for (int i=0; i<(int)ctrl->getChannelListArraySize(); i++)
        scanning.channelList.push_back(ctrl->getChannelList(i));
    if (scanning.channelList.empty())
        for (int i=0; i<numChannels; i++)
            scanning.channelList.push_back(i);

    // start scanning
    if (scanning.activeScan)
        nb->subscribe(this, NF_RADIOSTATE_CHANGED);
    scanning.currentChannelIndex = -1; // so we'll start with index==0
    isScanning = true;
    scanNextChannel();
}
void Ieee80211MgmtSTA::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);

    // Note that we are only subscribed during scanning!
    if (category==NF_RADIOSTATE_CHANGED)
    {
        RadioState::State radioState = check_and_cast<RadioState *>(details)->getState();
        if (radioState==RadioState::RECV)
        {
            EV << "busy radio channel detected during scanning\n";
            scanning.busyChannelDetected = true;
        }
    }
}
bool Ieee80211MgmtSTA::scanNextChannel ( ) [protected, virtual]

Switches to the next channel to scan; returns true if done (there wasn't any more channel to scan).

Referenced by handleTimer(), and processScanCommand().

{
    // if we're already at the last channel, we're through
    if (scanning.currentChannelIndex==(int)scanning.channelList.size()-1)
    {
        EV << "Finished scanning last channel\n";
        if (scanning.activeScan)
            nb->unsubscribe(this, NF_RADIOSTATE_CHANGED);
        isScanning = false;
        return true; // we're done
    }

    // tune to next channel
    int newChannel = scanning.channelList[++scanning.currentChannelIndex];
    changeChannel(newChannel);
    scanning.busyChannelDetected = false;

    if (scanning.activeScan)
    {
        // Active Scan: first wait probeDelay, then send a probe. Listening
        // for minChannelTime or maxChannelTime takes place after that. (11.1.3.2)
        scheduleAt(simTime()+scanning.probeDelay, new cMessage("sendProbe", MK_SCAN_SENDPROBE));
    }
    else
    {
        // Passive Scan: spend maxChannelTime on the channel (11.1.3.1)
        cMessage *timerMsg = new cMessage("maxChannelTime", MK_SCAN_MAXCHANNELTIME);
        scheduleAt(simTime()+scanning.maxChannelTime, timerMsg);
    }

    return false;
}
void Ieee80211MgmtSTA::sendAssociationConfirm ( APInfo ap,
int  resultCode 
) [protected, virtual]

Sends back result of association to the agent

Referenced by handleAssociationResponseFrame(), and handleTimer().

{
    sendConfirm(new Ieee80211Prim_AssociateConfirm(), resultCode);
}
void Ieee80211MgmtSTA::sendAuthenticationConfirm ( APInfo ap,
int  resultCode 
) [protected, virtual]

Sends back result of authentication to the agent

Referenced by handleAuthenticationFrame(), and handleTimer().

{
    Ieee80211Prim_AuthenticateConfirm *confirm = new Ieee80211Prim_AuthenticateConfirm();
    confirm->setAddress(ap->address);
    sendConfirm(confirm, resultCode);
}
void Ieee80211MgmtSTA::sendConfirm ( Ieee80211PrimConfirm *  confirm,
int  resultCode 
) [protected, virtual]

Utility function: sends a confirmation to the agent

Referenced by sendAssociationConfirm(), sendAuthenticationConfirm(), and sendScanConfirm().

{
    confirm->setResultCode(resultCode);
    cMessage *msg = new cMessage(confirm->getClassName());
    msg->setControlInfo(confirm);
    send(msg, "agentOut");
}
void Ieee80211MgmtSTA::sendManagementFrame ( Ieee80211ManagementFrame *  frame,
const MACAddress address 
) [protected, virtual]

Utility function: sends a management frame

Referenced by handleAuthenticationFrame(), processDeauthenticateCommand(), processDisassociateCommand(), sendProbeRequest(), startAssociation(), and startAuthentication().

{
    // frame goes to the specified AP
    frame->setToDS(true);
    frame->setReceiverAddress(address);
    //XXX set sequenceNumber?

    sendOrEnqueue(frame);
}
void Ieee80211MgmtSTA::sendProbeRequest ( ) [protected, virtual]

Broadcasts a Probe Request

Referenced by handleTimer().

{
    EV << "Sending Probe Request, BSSID=" << scanning.bssid << ", SSID=\"" << scanning.ssid << "\"\n";
    Ieee80211ProbeRequestFrame *frame = new Ieee80211ProbeRequestFrame("ProbeReq");
    frame->getBody().setSSID(scanning.ssid.c_str());
    sendManagementFrame(frame, scanning.bssid);
}
void Ieee80211MgmtSTA::sendScanConfirm ( ) [protected, virtual]

Sends back result of scanning to the agent

Referenced by handleTimer().

{
    EV << "Scanning complete, found " << apList.size() << " APs, sending confirmation to agent\n";

    // copy apList contents into a ScanConfirm primitive and send it back
    int n = apList.size();
    Ieee80211Prim_ScanConfirm *confirm = new Ieee80211Prim_ScanConfirm();
    confirm->setBssListArraySize(n);
    AccessPointList::iterator it = apList.begin();
    //XXX filter for req'd bssid and ssid
    for (int i=0; i<n; i++, it++)
    {
        APInfo *ap = &(*it);
        Ieee80211Prim_BSSDescription& bss = confirm->getBssList(i);
        bss.setChannelNumber(ap->channel);
        bss.setBSSID(ap->address);
        bss.setSSID(ap->ssid.c_str());
        bss.setSupportedRates(ap->supportedRates);
        bss.setBeaconInterval(ap->beaconInterval);
        bss.setRxPower(ap->rxPower);
    }
    sendConfirm(confirm, PRC_SUCCESS);
}
void Ieee80211MgmtSTA::startAssociation ( APInfo ap,
simtime_t  timeout 
) [protected, virtual]

Utility function: sends association request

Referenced by processAssociateCommand().

{
    if (isAssociated || assocTimeoutMsg)
        error("startAssociation: already associated or association currently in progress");
    if (!ap->isAuthenticated)
        error("startAssociation: not yet authenticated with AP address=", ap->address.str().c_str());

    // switch to that channel
    changeChannel(ap->channel);

    // create and send association request
    Ieee80211AssociationRequestFrame *frame = new Ieee80211AssociationRequestFrame("Assoc");

    //XXX set the following too?
    // string SSID
    // Ieee80211SupportedRatesElement supportedRates;

    sendManagementFrame(frame, ap->address);

    // schedule timeout
    ASSERT(assocTimeoutMsg==NULL);
    assocTimeoutMsg = new cMessage("assocTimeout", MK_ASSOC_TIMEOUT);
    assocTimeoutMsg->setContextPointer(ap);
    scheduleAt(simTime()+timeout, assocTimeoutMsg);
}
void Ieee80211MgmtSTA::startAuthentication ( APInfo ap,
simtime_t  timeout 
) [protected, virtual]

Utility function: sends authentication request

Referenced by processAuthenticateCommand().

{
    if (ap->authTimeoutMsg)
        error("startAuthentication: authentication currently in progress with AP address=", ap->address.str().c_str());
    if (ap->isAuthenticated)
        error("startAuthentication: already authenticated with AP address=", ap->address.str().c_str());

    changeChannel(ap->channel);

    EV << "Sending initial Authentication frame with seqNum=1\n";

    // create and send first authentication frame
    Ieee80211AuthenticationFrame *frame = new Ieee80211AuthenticationFrame("Auth");
    frame->getBody().setSequenceNumber(1);
    //XXX frame length could be increased to account for challenge text length etc.
    sendManagementFrame(frame, ap->address);

    ap->authSeqExpected = 2;

    // schedule timeout
    ASSERT(ap->authTimeoutMsg==NULL);
    ap->authTimeoutMsg = new cMessage("authTimeout", MK_AUTH_TIMEOUT);
    ap->authTimeoutMsg->setContextPointer(ap);
    scheduleAt(simTime()+timeout, ap->authTimeoutMsg);
}
int Ieee80211MgmtSTA::statusCodeToPrimResultCode ( int  statusCode) [protected, virtual]

Utility function: converts Ieee80211StatusCode (->frame) to Ieee80211PrimResultCode (->primitive)

Referenced by handleAssociationResponseFrame(), and handleAuthenticationFrame().

{
    return statusCode==SC_SUCCESSFUL ? PRC_SUCCESS : PRC_REFUSED;
}
void Ieee80211MgmtSTA::storeAPInfo ( const MACAddress address,
const Ieee80211BeaconFrameBody &  body 
) [protected, virtual]

Stores AP info received in a beacon or probe response

Referenced by handleBeaconFrame(), and handleProbeResponseFrame().

{
    APInfo *ap = lookupAP(address);
    if (ap)
    {
        EV << "AP address=" << address << ", SSID=" << body.getSSID() << " already in our AP list, refreshing the info\n";
    }
    else
    {
        EV << "Inserting AP address=" << address << ", SSID=" << body.getSSID() << " into our AP list\n";
        apList.push_back(APInfo());
        ap = &apList.back();
    }

    ap->channel = body.getChannelNumber();
    ap->address = address;
    ap->ssid = body.getSSID();
    ap->supportedRates = body.getSupportedRates();
    ap->beaconInterval = body.getBeaconInterval();

    //XXX where to get this from?
    //ap->rxPower = ...
}

Member Data Documentation


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