|
INET Framework for OMNeT++/OMNEST
|
00001 // 00002 // Copyright (C) 2006 Andras Varga 00003 // 00004 // This program is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public License 00006 // as published by the Free Software Foundation; either version 2 00007 // of the License, or (at your option) any later version. 00008 // 00009 // This program is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 // GNU Lesser General Public License for more details. 00013 // 00014 // You should have received a copy of the GNU Lesser General Public License 00015 // along with this program; if not, see <http://www.gnu.org/licenses/>. 00016 // 00017 00018 00019 #include "Ieee80211MgmtAP.h" 00020 #include "Ieee802Ctrl_m.h" 00021 #include "EtherFrame_m.h" 00022 #include "NotifierConsts.h" 00023 #include "RadioState.h" 00024 00025 00026 Define_Module(Ieee80211MgmtAP); 00027 00028 static std::ostream& operator<< (std::ostream& os, const Ieee80211MgmtAP::STAInfo& sta) 00029 { 00030 os << "state:" << sta.status; 00031 return os; 00032 } 00033 00034 void Ieee80211MgmtAP::initialize(int stage) 00035 { 00036 Ieee80211MgmtAPBase::initialize(stage); 00037 00038 if (stage==0) 00039 { 00040 // read params and init vars 00041 ssid = par("ssid").stringValue(); 00042 beaconInterval = par("beaconInterval"); 00043 numAuthSteps = par("numAuthSteps"); 00044 if (numAuthSteps!=2 && numAuthSteps!=4) 00045 error("parameter 'numAuthSteps' (number of frames exchanged during authentication) must be 2 or 4, not %d", numAuthSteps); 00046 channelNumber = -1; // value will arrive from physical layer in receiveChangeNotification() 00047 WATCH(ssid); 00048 WATCH(channelNumber); 00049 WATCH(beaconInterval); 00050 WATCH(numAuthSteps); 00051 WATCH_MAP(staList); 00052 00053 //TBD fill in supportedRates 00054 00055 // subscribe for notifications 00056 NotificationBoard *nb = NotificationBoardAccess().get(); 00057 nb->subscribe(this, NF_RADIO_CHANNEL_CHANGED); 00058 00059 // start beacon timer (randomize startup time) 00060 beaconTimer = new cMessage("beaconTimer"); 00061 scheduleAt(simTime()+uniform(0,beaconInterval), beaconTimer); 00062 } 00063 } 00064 00065 void Ieee80211MgmtAP::handleTimer(cMessage *msg) 00066 { 00067 if (msg==beaconTimer) 00068 { 00069 sendBeacon(); 00070 scheduleAt(simTime()+beaconInterval, beaconTimer); 00071 } 00072 else 00073 { 00074 error("internal error: unrecognized timer '%s'", msg->getName()); 00075 } 00076 } 00077 00078 void Ieee80211MgmtAP::handleUpperMessage(cPacket *msg) 00079 { 00080 // must be an EtherFrame frame arriving from MACRelayUnit, that is, 00081 // bridged from another interface of the AP (probably Ethernet). 00082 EtherFrame *etherframe = check_and_cast<EtherFrame *>(msg); 00083 00084 // check we really have a STA with that dest address 00085 STAList::iterator it = staList.find(etherframe->getDest()); 00086 if (it==staList.end() || it->second.status!=ASSOCIATED) 00087 { 00088 EV << "STA with MAC address " << etherframe->getDest() << " not associated with this AP, dropping frame\n"; 00089 delete etherframe; // XXX count drops? 00090 return; 00091 } 00092 00093 // convert Ethernet frame 00094 Ieee80211DataFrame *frame = convertFromEtherFrame(etherframe); 00095 sendOrEnqueue(frame); 00096 } 00097 00098 void Ieee80211MgmtAP::handleCommand(int msgkind, cPolymorphic *ctrl) 00099 { 00100 error("handleCommand(): no commands supported"); 00101 } 00102 00103 void Ieee80211MgmtAP::receiveChangeNotification(int category, const cPolymorphic *details) 00104 { 00105 Enter_Method_Silent(); 00106 printNotificationBanner(category, details); 00107 00108 if (category == NF_RADIO_CHANNEL_CHANGED) 00109 { 00110 EV << "updating channel number\n"; 00111 channelNumber = check_and_cast<RadioState *>(details)->getChannelNumber(); 00112 } 00113 } 00114 00115 Ieee80211MgmtAP::STAInfo *Ieee80211MgmtAP::lookupSenderSTA(Ieee80211ManagementFrame *frame) 00116 { 00117 STAList::iterator it = staList.find(frame->getTransmitterAddress()); 00118 return it==staList.end() ? NULL : &(it->second); 00119 } 00120 00121 void Ieee80211MgmtAP::sendManagementFrame(Ieee80211ManagementFrame *frame, const MACAddress& destAddr) 00122 { 00123 frame->setFromDS(true); 00124 frame->setReceiverAddress(destAddr); 00125 frame->setAddress3(myAddress); 00126 sendOrEnqueue(frame); 00127 } 00128 00129 void Ieee80211MgmtAP::sendBeacon() 00130 { 00131 EV << "Sending beacon\n"; 00132 Ieee80211BeaconFrame *frame = new Ieee80211BeaconFrame("Beacon"); 00133 Ieee80211BeaconFrameBody& body = frame->getBody(); 00134 body.setSSID(ssid.c_str()); 00135 body.setSupportedRates(supportedRates); 00136 body.setBeaconInterval(beaconInterval); 00137 body.setChannelNumber(channelNumber); 00138 00139 frame->setReceiverAddress(MACAddress::BROADCAST_ADDRESS); 00140 frame->setFromDS(true); 00141 00142 sendOrEnqueue(frame); 00143 } 00144 00145 void Ieee80211MgmtAP::handleDataFrame(Ieee80211DataFrame *frame) 00146 { 00147 // check toDS bit 00148 if (!frame->getToDS()) 00149 { 00150 // looks like this is not for us - discard 00151 EV << "Frame is not for us (toDS=false) -- discarding\n"; 00152 delete frame; 00153 return; 00154 } 00155 00156 // handle broadcast frames 00157 if (frame->getAddress3().isBroadcast()) 00158 { 00159 EV << "Handling broadcast frame\n"; 00160 if (hasRelayUnit) 00161 send(convertToEtherFrame((Ieee80211DataFrame *)frame->dup()), "uppergateOut"); 00162 distributeReceivedDataFrame(frame); 00163 return; 00164 } 00165 00166 // look up destination address in our STA list 00167 STAList::iterator it = staList.find(frame->getAddress3()); 00168 if (it==staList.end()) 00169 { 00170 // not our STA -- pass up frame to relayUnit for LAN bridging if we have one 00171 if (hasRelayUnit) 00172 send(convertToEtherFrame(frame), "uppergateOut"); 00173 else { 00174 EV << "Frame's destination address is not in our STA list -- dropping frame\n"; 00175 delete frame; 00176 } 00177 } 00178 else 00179 { 00180 // dest address is our STA, but is it already associated? 00181 if (it->second.status == ASSOCIATED) 00182 distributeReceivedDataFrame(frame); // send it out to the destination STA 00183 else { 00184 EV << "Frame's destination STA is not in associated state -- dropping frame\n"; 00185 delete frame; 00186 } 00187 } 00188 } 00189 00190 void Ieee80211MgmtAP::handleAuthenticationFrame(Ieee80211AuthenticationFrame *frame) 00191 { 00192 int frameAuthSeq = frame->getBody().getSequenceNumber(); 00193 EV << "Processing Authentication frame, seqNum=" << frameAuthSeq << "\n"; 00194 00195 // create STA entry if needed 00196 STAInfo *sta = lookupSenderSTA(frame); 00197 if (!sta) 00198 { 00199 MACAddress staAddress = frame->getTransmitterAddress(); 00200 sta = &staList[staAddress]; // this implicitly creates a new entry 00201 sta->address = staAddress; 00202 sta->status = NOT_AUTHENTICATED; 00203 sta->authSeqExpected = 1; 00204 } 00205 00206 // check authentication sequence number is OK 00207 if (frameAuthSeq != sta->authSeqExpected) 00208 { 00209 // wrong sequence number: send error and return 00210 EV << "Wrong sequence number, " << sta->authSeqExpected << " expected\n"; 00211 Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame("Auth-ERROR"); 00212 resp->getBody().setStatusCode(SC_AUTH_OUT_OF_SEQ); 00213 sendManagementFrame(resp, frame->getTransmitterAddress()); 00214 delete frame; 00215 sta->authSeqExpected = 1; // go back to start square 00216 return; 00217 } 00218 00219 // station is authenticated if it made it through the required number of steps 00220 bool isLast = (frameAuthSeq+1 == numAuthSteps); 00221 00222 // send OK response (we don't model the cryptography part, just assume 00223 // successful authentication every time) 00224 EV << "Sending Authentication frame, seqNum=" << (frameAuthSeq+1) << "\n"; 00225 Ieee80211AuthenticationFrame *resp = new Ieee80211AuthenticationFrame(isLast ? "Auth-OK" : "Auth"); 00226 resp->getBody().setSequenceNumber(frameAuthSeq+1); 00227 resp->getBody().setStatusCode(SC_SUCCESSFUL); 00228 resp->getBody().setIsLast(isLast); 00229 // XXX frame length could be increased to account for challenge text length etc. 00230 sendManagementFrame(resp, frame->getTransmitterAddress()); 00231 00232 delete frame; 00233 00234 // update status 00235 if (isLast) 00236 { 00237 sta->status = AUTHENTICATED; // XXX only when ACK of this frame arrives 00238 EV << "STA authenticated\n"; 00239 } 00240 else 00241 { 00242 sta->authSeqExpected += 2; 00243 EV << "Expecting Authentication frame " << sta->authSeqExpected << "\n"; 00244 } 00245 } 00246 00247 void Ieee80211MgmtAP::handleDeauthenticationFrame(Ieee80211DeauthenticationFrame *frame) 00248 { 00249 EV << "Processing Deauthentication frame\n"; 00250 00251 STAInfo *sta = lookupSenderSTA(frame); 00252 delete frame; 00253 00254 if (sta) 00255 { 00256 // mark STA as not authenticated; alternatively, it could also be removed from staList 00257 sta->status = NOT_AUTHENTICATED; 00258 sta->authSeqExpected = 1; 00259 } 00260 } 00261 00262 void Ieee80211MgmtAP::handleAssociationRequestFrame(Ieee80211AssociationRequestFrame *frame) 00263 { 00264 EV << "Processing AssociationRequest frame\n"; 00265 00266 // "11.3.2 AP association procedures" 00267 STAInfo *sta = lookupSenderSTA(frame); 00268 if (!sta || sta->status==NOT_AUTHENTICATED) 00269 { 00270 // STA not authenticated: send error and return 00271 Ieee80211DeauthenticationFrame *resp = new Ieee80211DeauthenticationFrame("Deauth"); 00272 resp->getBody().setReasonCode(RC_NONAUTH_ASS_REQUEST); 00273 sendManagementFrame(resp, frame->getTransmitterAddress()); 00274 delete frame; 00275 return; 00276 } 00277 00278 delete frame; 00279 00280 // mark STA as associated 00281 sta->status = ASSOCIATED; // XXX this should only take place when MAC receives the ACK for the response 00282 00283 // send OK response 00284 Ieee80211AssociationResponseFrame *resp = new Ieee80211AssociationResponseFrame("AssocResp-OK"); 00285 Ieee80211AssociationResponseFrameBody& body = resp->getBody(); 00286 body.setStatusCode(SC_SUCCESSFUL); 00287 body.setAid(0); //XXX 00288 body.setSupportedRates(supportedRates); 00289 sendManagementFrame(resp, sta->address); 00290 } 00291 00292 void Ieee80211MgmtAP::handleAssociationResponseFrame(Ieee80211AssociationResponseFrame *frame) 00293 { 00294 dropManagementFrame(frame); 00295 } 00296 00297 void Ieee80211MgmtAP::handleReassociationRequestFrame(Ieee80211ReassociationRequestFrame *frame) 00298 { 00299 EV << "Processing ReassociationRequest frame\n"; 00300 00301 // "11.3.4 AP reassociation procedures" -- almost the same as AssociationRequest processing 00302 STAInfo *sta = lookupSenderSTA(frame); 00303 if (!sta || sta->status==NOT_AUTHENTICATED) 00304 { 00305 // STA not authenticated: send error and return 00306 Ieee80211DeauthenticationFrame *resp = new Ieee80211DeauthenticationFrame("Deauth"); 00307 resp->getBody().setReasonCode(RC_NONAUTH_ASS_REQUEST); 00308 sendManagementFrame(resp, frame->getTransmitterAddress()); 00309 delete frame; 00310 return; 00311 } 00312 00313 delete frame; 00314 00315 // mark STA as associated 00316 sta->status = ASSOCIATED; // XXX this should only take place when MAC receives the ACK for the response 00317 00318 // send OK response 00319 Ieee80211ReassociationResponseFrame *resp = new Ieee80211ReassociationResponseFrame("ReassocResp-OK"); 00320 Ieee80211ReassociationResponseFrameBody& body = resp->getBody(); 00321 body.setStatusCode(SC_SUCCESSFUL); 00322 body.setAid(0); //XXX 00323 body.setSupportedRates(supportedRates); 00324 sendManagementFrame(resp, sta->address); 00325 } 00326 00327 void Ieee80211MgmtAP::handleReassociationResponseFrame(Ieee80211ReassociationResponseFrame *frame) 00328 { 00329 dropManagementFrame(frame); 00330 } 00331 00332 void Ieee80211MgmtAP::handleDisassociationFrame(Ieee80211DisassociationFrame *frame) 00333 { 00334 STAInfo *sta = lookupSenderSTA(frame); 00335 delete frame; 00336 00337 if (sta) 00338 { 00339 sta->status = AUTHENTICATED; 00340 } 00341 } 00342 00343 void Ieee80211MgmtAP::handleBeaconFrame(Ieee80211BeaconFrame *frame) 00344 { 00345 dropManagementFrame(frame); 00346 } 00347 00348 void Ieee80211MgmtAP::handleProbeRequestFrame(Ieee80211ProbeRequestFrame *frame) 00349 { 00350 EV << "Processing ProbeRequest frame\n"; 00351 00352 if (strcmp(frame->getBody().getSSID(),"")!=0 && strcmp(frame->getBody().getSSID(), ssid.c_str())!=0) 00353 { 00354 EV << "SSID `" << frame->getBody().getSSID() << "' does not match, ignoring frame\n"; 00355 dropManagementFrame(frame); 00356 return; 00357 } 00358 00359 MACAddress staAddress = frame->getTransmitterAddress(); 00360 delete frame; 00361 00362 EV << "Sending ProbeResponse frame\n"; 00363 Ieee80211ProbeResponseFrame *resp = new Ieee80211ProbeResponseFrame("ProbeResp"); 00364 Ieee80211ProbeResponseFrameBody& body = resp->getBody(); 00365 body.setSSID(ssid.c_str()); 00366 body.setSupportedRates(supportedRates); 00367 body.setBeaconInterval(beaconInterval); 00368 body.setChannelNumber(channelNumber); 00369 sendManagementFrame(resp, staAddress); 00370 } 00371 00372 void Ieee80211MgmtAP::handleProbeResponseFrame(Ieee80211ProbeResponseFrame *frame) 00373 { 00374 dropManagementFrame(frame); 00375 } 00376 00377