|
INET Framework for OMNeT++/OMNEST
|
#include <Ieee80211MgmtAP.h>
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 STAInfo * | lookupSenderSTA (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 |
Used in 802.11 infrastructure mode: handles management frames for an access point (AP). See corresponding NED file for a detailed description.
| typedef std::map<MACAddress,STAInfo, MAC_compare> Ieee80211MgmtAP::STAList |
State of a STA
| 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().
| 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);
}
simtime_t Ieee80211MgmtAP::beaconInterval [protected] |
Referenced by handleProbeRequestFrame(), handleTimer(), initialize(), and sendBeacon().
cMessage* Ieee80211MgmtAP::beaconTimer [protected] |
Referenced by handleTimer(), and initialize().
int Ieee80211MgmtAP::channelNumber [protected] |
Referenced by handleProbeRequestFrame(), initialize(), receiveChangeNotification(), and sendBeacon().
int Ieee80211MgmtAP::numAuthSteps [protected] |
Referenced by handleAuthenticationFrame(), and initialize().
std::string Ieee80211MgmtAP::ssid [protected] |
Referenced by handleProbeRequestFrame(), initialize(), and sendBeacon().
STAList Ieee80211MgmtAP::staList [protected] |
list of STAs
Referenced by handleAuthenticationFrame(), handleDataFrame(), handleUpperMessage(), initialize(), and lookupSenderSTA().
Ieee80211SupportedRatesElement Ieee80211MgmtAP::supportedRates [protected] |