Ieee80211MgmtSTA Class Reference

#include <Ieee80211MgmtSTA.h>

Inheritance diagram for Ieee80211MgmtSTA:

Ieee80211MgmtBase PassiveQueueBase INotifiable IPassiveQueue List of all members.

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


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 (cMessage *msg)
virtual void handleCommand (int msgkind, cPolymorphic *ctrl)
virtual Ieee80211DataFrameencapsulate (cMessage *msg)
virtual void startAuthentication (APInfo *ap, double timeout)
virtual void startAssociation (APInfo *ap, double timeout)
APInfolookupAP (const MACAddress &address)
void clearAPList ()
void changeChannel (int channelNum)
void storeAPInfo (const MACAddress &address, const Ieee80211BeaconFrameBody &body)
bool scanNextChannel ()
virtual void sendProbeRequest ()
virtual void beaconLost ()
void sendScanConfirm ()
void sendAuthenticationConfirm (APInfo *ap, int resultCode)
void sendAssociationConfirm (APInfo *ap, int resultCode)
void disassociate ()
void sendConfirm (Ieee80211PrimConfirm *confirm, int resultCode)
void sendManagementFrame (Ieee80211ManagementFrame *frame, const MACAddress &address)
virtual void receiveChangeNotification (int category, 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

Classes

struct  APInfo
struct  AssociatedAPInfo
struct  ScanningInfo


Member Typedef Documentation

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


Member Function Documentation

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

Missed a few consecutive beacons

00251 {
00252     EV << "Missed a few consecutive beacons -- AP is considered lost\n";
00253     nb->fireChangeNotification(NF_L2_BEACON_LOST, NULL);  //XXX use InterfaceEntry as detail, etc...
00254 }

void Ieee80211MgmtSTA::changeChannel ( int  channelNum  )  [protected]

Utility function: switches to the given radio channel.

00239 {
00240     EV << "Tuning to channel #" << channelNum << "\n";
00241 
00242     // sending PHY_C_CONFIGURERADIO command to MAC
00243     PhyControlInfo *phyCtrl = new PhyControlInfo();
00244     phyCtrl->setChannelNumber(channelNum);
00245     cMessage *msg = new cMessage("changeChannel", PHY_C_CONFIGURERADIO);
00246     msg->setControlInfo(phyCtrl);
00247     send(msg, "macOut");
00248 }

void Ieee80211MgmtSTA::clearAPList (  )  [protected]

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

00231 {
00232     for (AccessPointList::iterator it=apList.begin(); it!=apList.end(); ++it)
00233         if (it->authTimeoutMsg)
00234             delete cancelEvent(it->authTimeoutMsg);
00235     apList.clear();
00236 }

void Ieee80211MgmtSTA::disassociate (  )  [protected]

Utility function: Cancel the existing association

00519 {
00520     EV << "Disassociating from AP address=" << assocAP.address << "\n";
00521     ASSERT(isAssociated);
00522     isAssociated = false;
00523     delete cancelEvent(assocAP.beaconTimeoutMsg);
00524     assocAP.beaconTimeoutMsg = NULL;
00525     assocAP = AssociatedAPInfo(); // clear it
00526 }

Ieee80211DataFrame * Ieee80211MgmtSTA::encapsulate ( cMessage *  msg  )  [protected, virtual]

Utility function for handleUpperMessage()

00204 {
00205     Ieee80211DataFrame *frame = new Ieee80211DataFrame(msg->name());
00206 
00207     // frame goes to the AP
00208     frame->setToDS(true);
00209 
00210     // receiver is the AP
00211     frame->setReceiverAddress(assocAP.address);
00212 
00213     // destination address is in address3
00214     Ieee802Ctrl *ctrl = check_and_cast<Ieee802Ctrl *>(msg->removeControlInfo());
00215     frame->setAddress3(ctrl->getDest());
00216     delete ctrl;
00217 
00218     frame->encapsulate(msg);
00219     return frame;
00220 }

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

Implements Ieee80211MgmtBase.

00662 {
00663     dropManagementFrame(frame);
00664 }

void Ieee80211MgmtSTA::handleAssociationResponseFrame ( Ieee80211AssociationResponseFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00667 {
00668     EV << "Received Association Response frame\n";
00669 
00670     if (!assocTimeoutMsg)
00671     {
00672         EV << "No association in progress, ignoring frame\n";
00673         delete frame;
00674         return;
00675     }
00676 
00677     // extract frame contents
00678     MACAddress address = frame->getTransmitterAddress();
00679     int statusCode = frame->getBody().getStatusCode();
00680     //XXX short aid;
00681     //XXX Ieee80211SupportedRatesElement supportedRates;
00682     delete frame;
00683 
00684     // look up AP data structure
00685     APInfo *ap = lookupAP(address);
00686     if (!ap)
00687         error("handleAssociationResponseFrame: AP not known: address=%s", address.str().c_str());
00688 
00689     if (isAssociated)
00690     {
00691         EV << "Breaking existing association with AP address=" << assocAP.address << "\n";
00692         isAssociated = false;
00693         delete cancelEvent(assocAP.beaconTimeoutMsg);
00694         assocAP.beaconTimeoutMsg = NULL;
00695         assocAP = AssociatedAPInfo();
00696     }
00697 
00698     delete cancelEvent(assocTimeoutMsg);
00699     assocTimeoutMsg = NULL;
00700 
00701     if (statusCode!=SC_SUCCESSFUL)
00702     {
00703         EV << "Association failed with AP address=" << ap->address << "\n";
00704     }
00705     else
00706     {
00707         EV << "Association successful, AP address=" << ap->address << "\n";
00708 
00709         // change our state to "associated"
00710         isAssociated = true;
00711         (APInfo&)assocAP = (*ap);
00712 
00713         nb->fireChangeNotification(NF_L2_ASSOCIATED, NULL); //XXX detail: InterfaceEntry?
00714 
00715         assocAP.beaconTimeoutMsg = new cMessage("beaconTimeout", MK_BEACON_TIMEOUT);
00716         scheduleAt(simTime()+MAX_BEACONS_MISSED*assocAP.beaconInterval, assocAP.beaconTimeoutMsg);
00717     }
00718 
00719     // report back to agent
00720     sendAssociationConfirm(ap, statusCodeToPrimResultCode(statusCode));
00721 }

void Ieee80211MgmtSTA::handleAuthenticationFrame ( Ieee80211AuthenticationFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00559 {
00560     MACAddress address = frame->getTransmitterAddress();
00561     int frameAuthSeq = frame->getBody().getSequenceNumber();
00562     EV << "Received Authentication frame from address=" << address << ", seqNum=" << frameAuthSeq << "\n";
00563 
00564     APInfo *ap = lookupAP(address);
00565     if (!ap)
00566     {
00567         EV << "AP not known, discarding authentication frame\n";
00568         delete frame;
00569         return;
00570     }
00571 
00572     // what if already authenticated with AP
00573     if (ap->isAuthenticated)
00574     {
00575         EV << "AP already authenticated, ignoring frame\n";
00576         delete frame;
00577         return;
00578     }
00579 
00580     // is authentication is in progress with this AP?
00581     if (!ap->authTimeoutMsg)
00582     {
00583         EV << "No authentication in progress with AP, ignoring frame\n";
00584         delete frame;
00585         return;
00586     }
00587 
00588     // check authentication sequence number is OK
00589     if (frameAuthSeq != ap->authSeqExpected)
00590     {
00591         // wrong sequence number: send error and return
00592         EV << "Wrong sequence number, " << ap->authSeqExpected << " expected\n";
00593         Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame("Auth-ERROR");
00594         resp->getBody().setStatusCode(SC_AUTH_OUT_OF_SEQ);
00595         sendManagementFrame(resp, frame->getTransmitterAddress());
00596         delete frame;
00597 
00598         // cancel timeout, send error to agent
00599         delete cancelEvent(ap->authTimeoutMsg);
00600         ap->authTimeoutMsg = NULL;
00601         sendAuthenticationConfirm(ap, PRC_REFUSED); //XXX or what resultCode?
00602         return;
00603     }
00604 
00605     // check if more exchanges are needed for auth to be complete
00606     int statusCode = frame->getBody().getStatusCode();
00607 
00608     if (statusCode==SC_SUCCESSFUL && !frame->getBody().getIsLast())
00609     {
00610         EV << "More steps required, sending another Authentication frame\n";
00611 
00612         // more steps required, send another Authentication frame
00613         Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame("Auth");
00614         resp->getBody().setSequenceNumber(frameAuthSeq+1);
00615         resp->getBody().setStatusCode(SC_SUCCESSFUL);
00616         // XXX frame length could be increased to account for challenge text length etc.
00617         sendManagementFrame(resp, address);
00618         ap->authSeqExpected += 2;
00619     }
00620     else
00621     {
00622         if (statusCode==SC_SUCCESSFUL)
00623             EV << "Authentication successful\n";
00624         else
00625             EV << "Authentication failed\n";
00626 
00627         // authentication completed
00628         ap->isAuthenticated = (statusCode==SC_SUCCESSFUL);
00629         delete cancelEvent(ap->authTimeoutMsg);
00630         ap->authTimeoutMsg = NULL;
00631         sendAuthenticationConfirm(ap, statusCodeToPrimResultCode(statusCode));
00632     }
00633 
00634     delete frame;
00635 }

void Ieee80211MgmtSTA::handleBeaconFrame ( Ieee80211BeaconFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00759 {
00760     EV << "Received Beacon frame\n";
00761     storeAPInfo(frame->getTransmitterAddress(), frame->getBody());
00762 
00763     // if it is out associate AP, restart beacon timeout
00764     if (isAssociated && frame->getTransmitterAddress()==assocAP.address)
00765     {
00766         EV << "Beacon is from associated AP, restarting beacon timeout timer\n";
00767         ASSERT(assocAP.beaconTimeoutMsg!=NULL);
00768         cancelEvent(assocAP.beaconTimeoutMsg);
00769         scheduleAt(simTime()+MAX_BEACONS_MISSED*assocAP.beaconInterval, assocAP.beaconTimeoutMsg);
00770 
00771         //APInfo *ap = lookupAP(frame->getTransmitterAddress());
00772         //ASSERT(ap!=NULL);
00773     }
00774 
00775     delete frame;
00776 }

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

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

00183 {
00184     if (dynamic_cast<Ieee80211Prim_ScanRequest *>(ctrl))
00185         processScanCommand((Ieee80211Prim_ScanRequest *)ctrl);
00186     else if (dynamic_cast<Ieee80211Prim_AuthenticateRequest *>(ctrl))
00187         processAuthenticateCommand((Ieee80211Prim_AuthenticateRequest *)ctrl);
00188     else if (dynamic_cast<Ieee80211Prim_DeauthenticateRequest *>(ctrl))
00189         processDeauthenticateCommand((Ieee80211Prim_DeauthenticateRequest *)ctrl);
00190     else if (dynamic_cast<Ieee80211Prim_AssociateRequest *>(ctrl))
00191         processAssociateCommand((Ieee80211Prim_AssociateRequest *)ctrl);
00192     else if (dynamic_cast<Ieee80211Prim_ReassociateRequest *>(ctrl))
00193         processReassociateCommand((Ieee80211Prim_ReassociateRequest *)ctrl);
00194     else if (dynamic_cast<Ieee80211Prim_DisassociateRequest *>(ctrl))
00195         processDisassociateCommand((Ieee80211Prim_DisassociateRequest *)ctrl);
00196     else if (ctrl)
00197         error("handleCommand(): unrecognized control info class `%s'", ctrl->className());
00198     else
00199         error("handleCommand(): control info is NULL");
00200     delete ctrl;
00201 }

void Ieee80211MgmtSTA::handleDataFrame ( Ieee80211DataFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00554 {
00555     sendUp(decapsulate(frame));
00556 }

void Ieee80211MgmtSTA::handleDeauthenticationFrame ( Ieee80211DeauthenticationFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00638 {
00639     EV << "Received Deauthentication frame\n";
00640     const MACAddress& address = frame->getAddress3();  // source address
00641     APInfo *ap = lookupAP(address);
00642     if (!ap || !ap->isAuthenticated)
00643     {
00644         EV << "Unknown AP, or not authenticated with that AP -- ignoring frame\n";
00645         delete frame;
00646         return;
00647     }
00648     if (ap->authTimeoutMsg)
00649     {
00650         delete cancelEvent(ap->authTimeoutMsg);
00651         ap->authTimeoutMsg = NULL;
00652         EV << "Cancelling pending authentication\n";
00653         delete frame;
00654         return;
00655     }
00656 
00657     EV << "Setting isAuthenticated flag for that AP to false\n";
00658     ap->isAuthenticated = false;
00659 }

void Ieee80211MgmtSTA::handleDisassociationFrame ( Ieee80211DisassociationFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00735 {
00736     EV << "Received Disassociation frame\n";
00737     const MACAddress& address = frame->getAddress3();  // source address
00738 
00739     if (assocTimeoutMsg)
00740     {
00741         // pending association
00742         delete cancelEvent(assocTimeoutMsg);
00743         assocTimeoutMsg = NULL;
00744     }
00745     if (!isAssociated || address!=assocAP.address)
00746     {
00747         EV << "Not associated with that AP -- ignoring frame\n";
00748         delete frame;
00749         return;
00750     }
00751 
00752     EV << "Setting isAssociated flag to false\n";
00753     isAssociated = false;
00754     delete cancelEvent(assocAP.beaconTimeoutMsg);
00755     assocAP.beaconTimeoutMsg = NULL;
00756 }

void Ieee80211MgmtSTA::handleProbeRequestFrame ( Ieee80211ProbeRequestFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00779 {
00780     dropManagementFrame(frame);
00781 }

void Ieee80211MgmtSTA::handleProbeResponseFrame ( Ieee80211ProbeResponseFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00784 {
00785     EV << "Received Probe Response frame\n";
00786     storeAPInfo(frame->getTransmitterAddress(), frame->getBody());
00787     delete frame;
00788 }

void Ieee80211MgmtSTA::handleReassociationRequestFrame ( Ieee80211ReassociationRequestFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00724 {
00725     dropManagementFrame(frame);
00726 }

void Ieee80211MgmtSTA::handleReassociationResponseFrame ( Ieee80211ReassociationResponseFrame frame  )  [protected, virtual]

Implements Ieee80211MgmtBase.

00729 {
00730     EV << "Received Reassociation Response frame\n";
00731     //TBD handle with the same code as Association Response?
00732 }

void Ieee80211MgmtSTA::handleTimer ( cMessage *  msg  )  [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

00112 {
00113     if (msg->kind()==MK_AUTH_TIMEOUT)
00114     {
00115         // authentication timed out
00116         APInfo *ap = (APInfo *)msg->contextPointer();
00117         EV << "Authentication timed out, AP address = " << ap->address << "\n";
00118 
00119         // send back failure report to agent
00120         sendAuthenticationConfirm(ap, PRC_TIMEOUT);
00121     }
00122     else if (msg->kind()==MK_ASSOC_TIMEOUT)
00123     {
00124         // association timed out
00125         APInfo *ap = (APInfo *)msg->contextPointer();
00126         EV << "Association timed out, AP address = " << ap->address << "\n";
00127 
00128         // send back failure report to agent
00129         sendAssociationConfirm(ap, PRC_TIMEOUT);
00130     }
00131     else if (msg->kind()==MK_SCAN_MAXCHANNELTIME)
00132     {
00133         // go to next channel during scanning
00134         bool done = scanNextChannel();
00135         if (done)
00136             sendScanConfirm(); // send back response to agents' "scan" command
00137         delete msg;
00138     }
00139     else if (msg->kind()==MK_SCAN_SENDPROBE)
00140     {
00141         // Active Scan: send a probe request, then wait for minChannelTime (11.1.3.2.2)
00142         delete msg;
00143         sendProbeRequest();
00144         cMessage *timerMsg = new cMessage("minChannelTime", MK_SCAN_MINCHANNELTIME);
00145         scheduleAt(simTime()+scanning.minChannelTime, timerMsg); //XXX actually, we should start waiting after ProbeReq actually got transmitted
00146     }
00147     else if (msg->kind()==MK_SCAN_MINCHANNELTIME)
00148     {
00149         // Active Scan: after minChannelTime, possibly listen for the remaining time until maxChannelTime
00150         delete msg;
00151         if (scanning.busyChannelDetected)
00152         {
00153             EV << "Busy channel detected during minChannelTime, continuing listening until maxChannelTime elapses\n";
00154             cMessage *timerMsg = new cMessage("maxChannelTime", MK_SCAN_MAXCHANNELTIME);
00155             scheduleAt(simTime()+scanning.maxChannelTime - scanning.minChannelTime, timerMsg);
00156         }
00157         else
00158         {
00159             EV << "Channel was empty during minChannelTime, going to next channel\n";
00160             bool done = scanNextChannel();
00161             if (done)
00162                 sendScanConfirm(); // send back response to agents' "scan" command
00163         }
00164     }
00165     else if (msg->kind()==MK_BEACON_TIMEOUT)
00166     {
00167         // missed a few consecutive beacons
00168         beaconLost();
00169     }
00170     else
00171     {
00172         error("internal error: unrecognized timer '%s'", msg->name());
00173     }
00174 }

void Ieee80211MgmtSTA::handleUpperMessage ( cMessage *  msg  )  [protected, virtual]

Implements abstract Ieee80211MgmtBase method

Implements Ieee80211MgmtBase.

00177 {
00178     Ieee80211DataFrame *frame = encapsulate(msg);
00179     sendOrEnqueue(frame);
00180 }

void Ieee80211MgmtSTA::initialize ( int   )  [protected, virtual]

Reimplemented from Ieee80211MgmtBase.

00085 {
00086     Ieee80211MgmtBase::initialize(stage);
00087     if (stage==0)
00088     {
00089         isScanning = false;
00090         isAssociated = false;
00091         assocTimeoutMsg = NULL;
00092 
00093         nb = NotificationBoardAccess().get();
00094 
00095         // determine numChannels (needed when we're told to scan "all" channels)
00096         //XXX find a better way than directly accessing channelControl
00097         cModule *cc = simulation.moduleByPath("channelcontrol");
00098         if (cc == NULL)
00099             error("cannot not find ChannelControl module");
00100         numChannels = cc->par("numChannels");
00101 
00102         WATCH(isScanning);
00103         WATCH(isAssociated);
00104 
00105         WATCH(scanning);
00106         WATCH(assocAP);
00107         WATCH_LIST(apList);
00108     }
00109 }

Ieee80211MgmtSTA::APInfo * Ieee80211MgmtSTA::lookupAP ( const MACAddress address  )  [protected]

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

00223 {
00224     for (AccessPointList::iterator it=apList.begin(); it!=apList.end(); ++it)
00225         if (it->address == address)
00226             return &(*it);
00227     return NULL;
00228 }

virtual int Ieee80211MgmtSTA::numInitStages (  )  const [inline, protected, virtual]

Reimplemented from Ieee80211MgmtBase.

00107 {return 2;}

void Ieee80211MgmtSTA::processAssociateCommand ( Ieee80211Prim_AssociateRequest ctrl  )  [protected, virtual]

00482 {
00483     const MACAddress& address = ctrl->getAddress();
00484     APInfo *ap = lookupAP(address);
00485     if (!ap)
00486         error("processAssociateCommand: AP not known: address = %s", address.str().c_str());
00487     startAssociation(ap, ctrl->getTimeout());
00488 }

void Ieee80211MgmtSTA::processAuthenticateCommand ( Ieee80211Prim_AuthenticateRequest ctrl  )  [protected, virtual]

00447 {
00448     const MACAddress& address = ctrl->getAddress();
00449     APInfo *ap = lookupAP(address);
00450     if (!ap)
00451         error("processAuthenticateCommand: AP not known: address = %s", address.str().c_str());
00452     startAuthentication(ap, ctrl->getTimeout());
00453 }

void Ieee80211MgmtSTA::processDeauthenticateCommand ( Ieee80211Prim_DeauthenticateRequest ctrl  )  [protected, virtual]

00456 {
00457     const MACAddress& address = ctrl->getAddress();
00458     APInfo *ap = lookupAP(address);
00459     if (!ap)
00460         error("processDeauthenticateCommand: AP not known: address = %s", address.str().c_str());
00461 
00462     if (isAssociated && assocAP.address==address)
00463         disassociate();
00464 
00465     if (ap->isAuthenticated)
00466         ap->isAuthenticated = false;
00467 
00468     // cancel possible pending authentication timer
00469     if (ap->authTimeoutMsg)
00470     {
00471         delete cancelEvent(ap->authTimeoutMsg);
00472         ap->authTimeoutMsg = NULL;
00473     }
00474 
00475     // create and send deauthentication request
00476     Ieee80211DeauthenticationFrame *frame = new Ieee80211DeauthenticationFrame("Deauth");
00477     frame->getBody().setReasonCode(ctrl->getReasonCode());
00478     sendManagementFrame(frame, address);
00479 }

void Ieee80211MgmtSTA::processDisassociateCommand ( Ieee80211Prim_DisassociateRequest ctrl  )  [protected, virtual]

00498 {
00499     const MACAddress& address = ctrl->getAddress();
00500 
00501     if (isAssociated && address==assocAP.address)
00502     {
00503         disassociate();
00504     }
00505     else if (assocTimeoutMsg)
00506     {
00507         // pending association
00508         delete cancelEvent(assocTimeoutMsg);
00509         assocTimeoutMsg = NULL;
00510     }
00511 
00512     // create and send disassociation request
00513     Ieee80211DisassociationFrame *frame = new Ieee80211DisassociationFrame("Disass");
00514     frame->getBody().setReasonCode(ctrl->getReasonCode());
00515     sendManagementFrame(frame, address);
00516 }

void Ieee80211MgmtSTA::processReassociateCommand ( Ieee80211Prim_ReassociateRequest ctrl  )  [protected, virtual]

00491 {
00492     // treat the same way as association
00493     //XXX refine
00494     processAssociateCommand(ctrl);
00495 }

void Ieee80211MgmtSTA::processScanCommand ( Ieee80211Prim_ScanRequest ctrl  )  [protected, virtual]

00336 {
00337     EV << "Received Scan Request from agent, clearing AP list and starting scanning...\n";
00338 
00339     if (isScanning)
00340         error("processScanCommand: scanning already in progress");
00341     if (isAssociated)
00342     {
00343         disassociate();
00344     }
00345     else if (assocTimeoutMsg)
00346     {
00347         EV << "Cancelling ongoing association process\n";
00348         delete cancelEvent(assocTimeoutMsg);
00349         assocTimeoutMsg = NULL;
00350     }
00351 
00352     // clear existing AP list (and cancel any pending authentications) -- we want to start with a clean page
00353     clearAPList();
00354 
00355     // fill in scanning state
00356     ASSERT(ctrl->getBSSType()==BSSTYPE_INFRASTRUCTURE);
00357     scanning.bssid = ctrl->getBSSID().isUnspecified() ? MACAddress::BROADCAST_ADDRESS : ctrl->getBSSID();
00358     scanning.ssid = ctrl->getSSID();
00359     scanning.activeScan = ctrl->getActiveScan();
00360     scanning.probeDelay = ctrl->getProbeDelay();
00361     scanning.channelList.clear();
00362     scanning.minChannelTime = ctrl->getMinChannelTime();
00363     scanning.maxChannelTime = ctrl->getMaxChannelTime();
00364     ASSERT(scanning.minChannelTime <= scanning.maxChannelTime);
00365 
00366     // channel list to scan (default: all channels)
00367     for (int i=0; i<ctrl->getChannelListArraySize(); i++)
00368         scanning.channelList.push_back(ctrl->getChannelList(i));
00369     if (scanning.channelList.empty())
00370         for (int i=0; i<numChannels; i++)
00371             scanning.channelList.push_back(i);
00372 
00373     // start scanning
00374     if (scanning.activeScan)
00375         nb->subscribe(this, NF_RADIOSTATE_CHANGED);
00376     scanning.currentChannelIndex = -1; // so we'll start with index==0
00377     isScanning = true;
00378     scanNextChannel();
00379 }

void Ieee80211MgmtSTA::receiveChangeNotification ( int  category,
cPolymorphic *  details 
) [protected, virtual]

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

Implements INotifiable.

00319 {
00320     Enter_Method_Silent();
00321     printNotificationBanner(category, details);
00322 
00323     // Note that we are only subscribed during scanning!
00324     if (category==NF_RADIOSTATE_CHANGED)
00325     {
00326         RadioState::State radioState = check_and_cast<RadioState *>(details)->getState();
00327         if (radioState==RadioState::RECV)
00328         {
00329             EV << "busy radio channel detected during scanning\n";
00330             scanning.busyChannelDetected = true;
00331         }
00332     }
00333 }

bool Ieee80211MgmtSTA::scanNextChannel (  )  [protected]

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

00382 {
00383     // if we're already at the last channel, we're through
00384     if (scanning.currentChannelIndex==scanning.channelList.size()-1)
00385     {
00386         EV << "Finished scanning last channel\n";
00387         if (scanning.activeScan)
00388             nb->unsubscribe(this, NF_RADIOSTATE_CHANGED);
00389         isScanning = false;
00390         return true; // we're done
00391     }
00392 
00393     // tune to next channel
00394     int newChannel = scanning.channelList[++scanning.currentChannelIndex];
00395     changeChannel(newChannel);
00396     scanning.busyChannelDetected = false;
00397 
00398     if (scanning.activeScan)
00399     {
00400         // Active Scan: first wait probeDelay, then send a probe. Listening
00401         // for minChannelTime or maxChannelTime takes place after that. (11.1.3.2)
00402         scheduleAt(simTime()+scanning.probeDelay, new cMessage("sendProbe", MK_SCAN_SENDPROBE));
00403     }
00404     else
00405     {
00406         // Passive Scan: spend maxChannelTime on the channel (11.1.3.1)
00407         cMessage *timerMsg = new cMessage("maxChannelTime", MK_SCAN_MAXCHANNELTIME);
00408         scheduleAt(simTime()+scanning.maxChannelTime, timerMsg);
00409     }
00410 
00411     return false;
00412 }

void Ieee80211MgmtSTA::sendAssociationConfirm ( APInfo ap,
int  resultCode 
) [protected]

Sends back result of association to the agent

00536 {
00537     sendConfirm(new Ieee80211Prim_AssociateConfirm(), resultCode);
00538 }

void Ieee80211MgmtSTA::sendAuthenticationConfirm ( APInfo ap,
int  resultCode 
) [protected]

Sends back result of authentication to the agent

00529 {
00530     Ieee80211Prim_AuthenticateConfirm *confirm = new Ieee80211Prim_AuthenticateConfirm();
00531     confirm->setAddress(ap->address);
00532     sendConfirm(confirm, resultCode);
00533 }

void Ieee80211MgmtSTA::sendConfirm ( Ieee80211PrimConfirm confirm,
int  resultCode 
) [protected]

Utility function: sends a confirmation to the agent

00541 {
00542     confirm->setResultCode(resultCode);
00543     cMessage *msg = new cMessage(confirm->className());
00544     msg->setControlInfo(confirm);
00545     send(msg, "agentOut");
00546 }

void Ieee80211MgmtSTA::sendManagementFrame ( Ieee80211ManagementFrame frame,
const MACAddress address 
) [protected]

Utility function: sends a management frame

00257 {
00258     // frame goes to the specified AP
00259     frame->setToDS(true);
00260     frame->setReceiverAddress(address);
00261     //XXX set sequenceNumber?
00262 
00263     sendOrEnqueue(frame);
00264 }

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

Broadcasts a Probe Request

00415 {
00416     EV << "Sending Probe Request, BSSID=" << scanning.bssid << ", SSID=\"" << scanning.ssid << "\"\n";
00417     Ieee80211ProbeRequestFrame *frame = new Ieee80211ProbeRequestFrame("ProbeReq");
00418     frame->getBody().setSSID(scanning.ssid.c_str());
00419     sendManagementFrame(frame, scanning.bssid);
00420 }

void Ieee80211MgmtSTA::sendScanConfirm (  )  [protected]

Sends back result of scanning to the agent

00423 {
00424     EV << "Scanning complete, found " << apList.size() << " APs, sending confirmation to agent\n";
00425 
00426     // copy apList contents into a ScanConfirm primitive and send it back
00427     int n = apList.size();
00428     Ieee80211Prim_ScanConfirm *confirm = new Ieee80211Prim_ScanConfirm();
00429     confirm->setBssListArraySize(n);
00430     AccessPointList::iterator it = apList.begin();
00431     //XXX filter for req'd bssid and ssid
00432     for (int i=0; i<n; i++, it++)
00433     {
00434         APInfo *ap = &(*it);
00435         Ieee80211Prim_BSSDescription& bss = confirm->getBssList(i);
00436         bss.setChannelNumber(ap->channel);
00437         bss.setBSSID(ap->address);
00438         bss.setSSID(ap->ssid.c_str());
00439         bss.setSupportedRates(ap->supportedRates);
00440         bss.setBeaconInterval(ap->beaconInterval);
00441         bss.setRxPower(ap->rxPower);
00442     }
00443     sendConfirm(confirm, PRC_SUCCESS);
00444 }

void Ieee80211MgmtSTA::startAssociation ( APInfo ap,
double  timeout 
) [protected, virtual]

Utility function: sends association request

00293 {
00294     if (isAssociated || assocTimeoutMsg)
00295         error("startAssociation: already associated or association currently in progress");
00296     if (!ap->isAuthenticated)
00297         error("startAssociation: not yet authenticated with AP address=", ap->address.str().c_str());
00298 
00299     // switch to that channel
00300     changeChannel(ap->channel);
00301 
00302     // create and send association request
00303     Ieee80211AssociationRequestFrame *frame = new Ieee80211AssociationRequestFrame("Assoc");
00304 
00305     //XXX set the following too?
00306     // string SSID
00307     // Ieee80211SupportedRatesElement supportedRates;
00308 
00309     sendManagementFrame(frame, ap->address);
00310 
00311     // schedule timeout
00312     ASSERT(assocTimeoutMsg==NULL);
00313     assocTimeoutMsg = new cMessage("assocTimeout", MK_ASSOC_TIMEOUT);
00314     assocTimeoutMsg->setContextPointer(ap);
00315     scheduleAt(simTime()+timeout, assocTimeoutMsg);
00316 }

void Ieee80211MgmtSTA::startAuthentication ( APInfo ap,
double  timeout 
) [protected, virtual]

Utility function: sends authentication request

00267 {
00268     if (ap->authTimeoutMsg)
00269         error("startAuthentication: authentication currently in progress with AP address=", ap->address.str().c_str());
00270     if (ap->isAuthenticated)
00271         error("startAuthentication: already authenticated with AP address=", ap->address.str().c_str());
00272 
00273     changeChannel(ap->channel);
00274 
00275     EV << "Sending initial Authentication frame with seqNum=1\n";
00276 
00277     // create and send first authentication frame
00278     Ieee80211AuthenticationFrame *frame = new Ieee80211AuthenticationFrame("Auth");
00279     frame->getBody().setSequenceNumber(1);
00280     //XXX frame length could be increased to account for challenge text length etc.
00281     sendManagementFrame(frame, ap->address);
00282 
00283     ap->authSeqExpected = 2;
00284 
00285     // schedule timeout
00286     ASSERT(ap->authTimeoutMsg==NULL);
00287     ap->authTimeoutMsg = new cMessage("authTimeout", MK_AUTH_TIMEOUT);
00288     ap->authTimeoutMsg->setContextPointer(ap);
00289     scheduleAt(simTime()+timeout, ap->authTimeoutMsg);
00290 }

int Ieee80211MgmtSTA::statusCodeToPrimResultCode ( int  statusCode  )  [protected, virtual]

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

00549 {
00550     return statusCode==SC_SUCCESSFUL ? PRC_SUCCESS : PRC_REFUSED;
00551 }

void Ieee80211MgmtSTA::storeAPInfo ( const MACAddress address,
const Ieee80211BeaconFrameBody body 
) [protected]

Stores AP info received in a beacon or probe response

00791 {
00792     APInfo *ap = lookupAP(address);
00793     if (ap)
00794     {
00795         EV << "AP address=" << address << ", SSID=" << body.getSSID() << " already in our AP list, refreshing the info\n";
00796     }
00797     else
00798     {
00799         EV << "Inserting AP address=" << address << ", SSID=" << body.getSSID() << " into our AP list\n";
00800         apList.push_back(APInfo());
00801         ap = &apList.back();
00802     }
00803 
00804     ap->channel = body.getChannelNumber();
00805     ap->address = address;
00806     ap->ssid = body.getSSID();
00807     ap->supportedRates = body.getSupportedRates();
00808     ap->beaconInterval = body.getBeaconInterval();
00809 
00810     //XXX where to get this from?
00811     //ap->rxPower = ...
00812 }


Member Data Documentation

AccessPointList Ieee80211MgmtSTA::apList [protected]

AssociatedAPInfo Ieee80211MgmtSTA::assocAP [protected]

cMessage* Ieee80211MgmtSTA::assocTimeoutMsg [protected]

bool Ieee80211MgmtSTA::isAssociated [protected]

bool Ieee80211MgmtSTA::isScanning [protected]

NotificationBoard* Ieee80211MgmtSTA::nb [protected]

int Ieee80211MgmtSTA::numChannels [protected]

ScanningInfo Ieee80211MgmtSTA::scanning [protected]


The documentation for this class was generated from the following files:
Generated on Wed Apr 4 13:20:20 2007 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.7