diff --git a/examples/wireless/handover/omnetpp.ini b/examples/wireless/handover/omnetpp.ini index 15b7551ad22..1b5cccab3da 100644 --- a/examples/wireless/handover/omnetpp.ini +++ b/examples/wireless/handover/omnetpp.ini @@ -18,7 +18,7 @@ network = HandoverNetwork **.ap1.wlan[*].mgmt.ssid = "AP1" **.ap2.wlan[*].mgmt.ssid = "AP2" **.ap*.wlan[*].mgmt.beaconInterval = 100ms -**.wlan[*].mgmt.numAuthSteps = 4 +**.wlan[*].mgmt.numAuthSteps = 2 # mobility **.mobility.initFromDisplayString = true diff --git a/src/inet/linklayer/ieee80211/mac/Ieee80211BssidReq.msg b/src/inet/linklayer/ieee80211/mac/Ieee80211BssidReq.msg new file mode 100644 index 00000000000..ee4094c13ee --- /dev/null +++ b/src/inet/linklayer/ieee80211/mac/Ieee80211BssidReq.msg @@ -0,0 +1,16 @@ +// +// SPDX-License-Identifier: LGPL-3.0-or-later +// + +import inet.common.INETDefs; +import inet.common.TagBase; +import inet.linklayer.common.MacAddress; + +namespace inet; + +// The management procedure's BSSID for Address3 of an outgoing management frame. +// It is independent of the receiver address and survives queuing/state changes. +class Ieee80211BssidReq extends TagBase +{ + MacAddress bssid; +} diff --git a/src/inet/linklayer/ieee80211/mac/Ieee80211Mac.cc b/src/inet/linklayer/ieee80211/mac/Ieee80211Mac.cc index d87f581231f..8528a05aeef 100644 --- a/src/inet/linklayer/ieee80211/mac/Ieee80211Mac.cc +++ b/src/inet/linklayer/ieee80211/mac/Ieee80211Mac.cc @@ -6,6 +6,7 @@ #include "inet/linklayer/ieee80211/mac/Ieee80211Mac.h" +#include "inet/linklayer/ieee80211/mac/Ieee80211BssidReq_m.h" #include @@ -164,7 +165,10 @@ void Ieee80211Mac::handleMgmtPacket(Packet *packet) const auto& header = makeShared(); header->setType((Ieee80211FrameType)packet->getTag()->getSubtype()); header->setReceiverAddress(packet->getTag()->getDestAddress()); - if (mib->mode == Ieee80211Mib::INFRASTRUCTURE && mib->bssStationData.stationType == Ieee80211Mib::ACCESS_POINT) + // IEEE Std 802.11-2024, 9.3.3.1: management supplies its intended BSSID. + if (auto bssid = packet->findTag()) + header->setAddress3(bssid->getBssid()); + else if (mib->mode == Ieee80211Mib::INFRASTRUCTURE && mib->bssStationData.stationType == Ieee80211Mib::ACCESS_POINT) header->setAddress3(mib->bssData.bssid); packet->insertAtFront(header); packet->insertAtBack(makeShared()); diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc index 1b52306987e..16e5fb2da38 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.cc @@ -50,8 +50,8 @@ void Ieee80211MgmtAp::initialize(int stage) ssid = par("ssid").stdstringValue(); beaconInterval = normalizeIeee80211BeaconInterval(par("beaconInterval")); numAuthSteps = par("numAuthSteps"); - if (numAuthSteps != 2 && numAuthSteps != 4) - throw cRuntimeError("parameter 'numAuthSteps' (number of frames exchanged during authentication) must be 2 or 4, not %d", numAuthSteps); + if (numAuthSteps != 2) + throw cRuntimeError("Open System authentication requires numAuthSteps=2; unsupported value %d", numAuthSteps); WATCH(ssid); WATCH(beaconInterval); WATCH(numAuthSteps); @@ -226,7 +226,17 @@ void Ieee80211MgmtAp::handleAuthenticationFrame(Packet *packet, const PtrpeekData(); int frameAuthSeq = requestBody->getSequenceNumber(); - EV << "Processing Authentication frame, seqNum=" << frameAuthSeq << "\n"; + // IEEE Std 802.11-2024, 12.3.3.2: Open System is exactly two messages. + // Reject unsupported inputs before creating or downgrading peer state. + if (requestBody->getAlgorithmNumber() != 0 || frameAuthSeq != 1) { + const auto& body = makeShared(); + body->setAlgorithmNumber(requestBody->getAlgorithmNumber()); + body->setSequenceNumber(2); + body->setStatusCode(requestBody->getAlgorithmNumber() != 0 ? SC_AUTH_ALG0_UNSUP : SC_AUTH_OUT_OF_SEQ); + sendManagementFrame("Auth-ERROR", body, ST_AUTHENTICATION, header->getTransmitterAddress()); + delete packet; + return; + } // create STA entry if needed StaInfo *sta = lookupSenderSTA(header); @@ -260,48 +270,15 @@ void Ieee80211MgmtAp::handleAuthenticationFrame(Packet *packet, const Ptraddress); } - // 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"; - const auto& body = makeShared(); - body->setStatusCode(SC_AUTH_OUT_OF_SEQ); - sendManagementFrame("Auth-ERROR", body, ST_AUTHENTICATION, header->getTransmitterAddress()); - delete packet; - 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"; const auto& body = makeShared(); - body->setSequenceNumber(frameAuthSeq + 1); + body->setAlgorithmNumber(0); + body->setSequenceNumber(2); body->setStatusCode(SC_SUCCESSFUL); - body->setIsLast(isLast); - // TODO frame length could be increased to account for challenge text length etc. - sendManagementFrame(isLast ? "Auth-OK" : "Auth", body, ST_AUTHENTICATION, header->getTransmitterAddress()); - + sendManagementFrame("Auth-OK", body, ST_AUTHENTICATION, header->getTransmitterAddress()); delete packet; - - // update status - if (isLast) { - bool wasAssociated = mib->bssAccessPointData.stations[sta->address] == Ieee80211Mib::ASSOCIATED; - if (wasAssociated) - mib->releaseAssociationId(sta->address); - mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::AUTHENTICATED; // TODO only when ACK of this frame arrives - mib->removePeerHtCapabilities(sta->address); - if (wasAssociated) - sendDisAssocNotification(sta->address); - EV << "STA authenticated\n"; - } - else { - sta->authSeqExpected += 2; - EV << "Expecting Authentication frame " << sta->authSeqExpected << "\n"; - } + mib->bssAccessPointData.stations[sta->address] = Ieee80211Mib::AUTHENTICATED; // TODO commit when response ACK arrives + mib->removePeerHtCapabilities(sta->address); + sta->authSeqExpected = 1; } void Ieee80211MgmtAp::handleDeauthenticationFrame(Packet *packet, const Ptr& header) diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.ned b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.ned index 95397135f3b..f72e84fcba0 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.ned +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.ned @@ -26,7 +26,7 @@ simple Ieee80211MgmtAp extends SimpleModule like IIeee80211Mgmt @class(Ieee80211MgmtAp); string ssid = default("SSID"); double beaconInterval @unit(s) = default(100ms); // 1..65535 TUs; rounded down to whole 1024 us TUs for scheduling and advertisement - int numAuthSteps = default(4); // Use 2 for Open System auth, 4 for WEP + int numAuthSteps = default(2); // Open System authentication; only 2 is supported string interfaceTableModule; string radioModule = default("^.radio"); // The path to the Radio module //FIXME remove default value string mibModule; diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrame.msg b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrame.msg index 4725c5e1110..de7bdee7cf8 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrame.msg +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrame.msg @@ -202,19 +202,15 @@ class Ieee80211MgmtFrame extends FieldsChunk // // Authentication frame body format. // -// Note: the "isLast" field is not part of the standard. -// The authentication procedure is simulated by this model by exchanging -// a number of "dummy" authentication frames without real contents; -// the "isLast" field gets set by the AP to signal the STA that -// the authentication procedure has completed and it does not need to -// send any more Authentication frames. +// Open System uses wire transaction numbers 1 and 2 (IEEE 802.11-2024, 12.3.3.2). // class Ieee80211AuthenticationFrame extends Ieee80211MgmtFrame { chunkLength = B(6); // add 2+len bytes for challenge text if present + uint16_t algorithmNumber = 0; // Open System; preserve unsupported wire values for rejection unsigned short sequenceNumber; Ieee80211StatusCode statusCode; - bool isLast; // not part of the standard; see above + bool isLast; // deprecated compatibility field, not serialized or used by management } // diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrameSerializer.cc b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrameSerializer.cc index 5fb46ae01ad..efd89b742cf 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrameSerializer.cc +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrameSerializer.cc @@ -636,7 +636,7 @@ void Ieee80211MgmtFrameSerializer::serializeFields(MemoryOutputStream& stream, c if (auto authenticationFrame = dynamicPtrCast(chunk)) { // type = ST_AUTHENTICATION; // 1 Authentication algorithm number - stream.writeUint16Le(0); + stream.writeUint16Le(authenticationFrame->getAlgorithmNumber()); // 2 Authentication transaction sequence number stream.writeUint16Le(authenticationFrame->getSequenceNumber()); // 3 Status code The status code information is reserved in certain Authentication frames as defined in Table 7-17. @@ -838,7 +838,7 @@ const Ptr Ieee80211MgmtFrameSerializer::deserializeFields(MemoryInputStre { if (typeInfo == typeid(Ieee80211AuthenticationFrame)) { auto frame = makeShared(); - stream.readUint16Le(); + frame->setAlgorithmNumber(stream.readUint16Le()); frame->setSequenceNumber(stream.readUint16Le()); frame->setStatusCode((Ieee80211StatusCode)stream.readUint16Le()); readHtElements(stream, frame, HT_ELEMENT_NONE, 0); diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc index 859a5c108ea..1ec225d33d1 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.cc @@ -14,6 +14,7 @@ #include "inet/common/packet/Message.h" #include "inet/linklayer/common/MacAddressTag_m.h" #include "inet/linklayer/ieee80211/mac/Ieee80211SubtypeTag_m.h" +#include "inet/linklayer/ieee80211/mac/Ieee80211BssidReq_m.h" #include "inet/networklayer/common/NetworkInterface.h" #include "inet/physicallayer/wireless/common/contract/packetlevel/IRadioMedium.h" #include "inet/physicallayer/wireless/common/contract/packetlevel/RadioControlInfo_m.h" @@ -319,6 +320,8 @@ void Ieee80211MgmtSta::sendManagementFrame(const char *name, const PtraddTag()->setDestAddress(address); + // IEEE Std 802.11-2024, 9.3.3.1: use the target AP, including before association. + packet->addTag()->setBssid(address); packet->addTag()->setSubtype(subtype); packet->insertAtBack(body); sendDown(packet); @@ -738,48 +741,14 @@ void Ieee80211MgmtSta::handleAuthenticationFrame(Packet *packet, const PtrauthSeqExpected) { - // wrong sequence number: send error and return - EV << "Wrong sequence number, " << ap->authSeqExpected << " expected\n"; - const auto& body = makeShared(); - body->setStatusCode(SC_AUTH_OUT_OF_SEQ); - sendManagementFrame("Auth-ERROR", body, ST_AUTHENTICATION, header->getTransmitterAddress()); - delete packet; - - // cancel timeout, send error to agent - cancelAndDelete(ap->authTimeoutMsg); - ap->authTimeoutMsg = nullptr; - sendAuthenticationConfirm(ap, PRC_REFUSED); // TODO or what resultCode? - return; - } - - // check if more exchanges are needed for auth to be complete + // IEEE Std 802.11-2024, 12.3.3.2: wire algorithm/transaction fields + // determine completion, never the old model-only isLast flag. + bool validResponse = requestBody->getAlgorithmNumber() == 0 && frameAuthSeq == 2; int statusCode = requestBody->getStatusCode(); - - if (statusCode == SC_SUCCESSFUL && !requestBody->isLast()) { - EV << "More steps required, sending another Authentication frame\n"; - - // more steps required, send another Authentication frame - const auto& body = makeShared(); - body->setSequenceNumber(frameAuthSeq + 1); - body->setStatusCode(SC_SUCCESSFUL); - // TODO frame length could be increased to account for challenge text length etc. - sendManagementFrame("Auth", body, ST_AUTHENTICATION, 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); - cancelAndDelete(ap->authTimeoutMsg); - ap->authTimeoutMsg = nullptr; - sendAuthenticationConfirm(ap, statusCodeToPrimResultCode(statusCode)); - } + ap->isAuthenticated = validResponse && statusCode == SC_SUCCESSFUL; + cancelAndDelete(ap->authTimeoutMsg); + ap->authTimeoutMsg = nullptr; + sendAuthenticationConfirm(ap, validResponse ? statusCodeToPrimResultCode(statusCode) : PRC_REFUSED); delete packet; } diff --git a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h index 326c7638644..285270bba08 100644 --- a/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h +++ b/src/inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h @@ -85,7 +85,7 @@ class INET_API Ieee80211MgmtSta : public Ieee80211MgmtBase double rxPower; bool isAuthenticated; - int authSeqExpected; // valid while authenticating; values: 1,3,5... + int authSeqExpected; // Open System response transaction: 2 cMessage *authTimeoutMsg; // if non-nullptr: authentication is in progress ApInfo() diff --git a/templates/NewWirelessHandoverSimulationWizard/omnetpp.ini.ftl b/templates/NewWirelessHandoverSimulationWizard/omnetpp.ini.ftl index 96ccb33ca3e..8aa05a9970d 100644 --- a/templates/NewWirelessHandoverSimulationWizard/omnetpp.ini.ftl +++ b/templates/NewWirelessHandoverSimulationWizard/omnetpp.ini.ftl @@ -25,7 +25,7 @@ tkenv-plugin-path = ../../../etc/plugins **.ap${i}.wlan[*].radio.channelNumber = ${i+1} **.ap*.wlan[*].mgmt.beaconInterval = 100ms -**.wlan[*].mgmt.numAuthSteps = 4 +**.wlan[*].mgmt.numAuthSteps = 2 **.mgmt.frameCapacity = 10 diff --git a/tests/module/Ieee80211OpenSystemAuthentication_1.test b/tests/module/Ieee80211OpenSystemAuthentication_1.test new file mode 100644 index 00000000000..a4c92a7d70e --- /dev/null +++ b/tests/module/Ieee80211OpenSystemAuthentication_1.test @@ -0,0 +1,117 @@ +%description: +Open System rejects unsupported algorithm/transaction inputs without authenticating +peers. STA completes using wire fields, independent of deprecated isLast metadata. + +%file: TestAuthentication.cc +#include +#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtAp.h" +#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtSta.h" +namespace inet { namespace ieee80211 { +class TestAuthenticationAp : public Ieee80211MgmtAp { + protected: + Ptr response; + virtual void sendManagementFrame(const char *, const Ptr& body, int subtype, const MacAddress&, uint64_t = 0) override { + if (subtype == ST_AUTHENTICATION) response = dynamicPtrCast(body); + } + virtual void initialize(int stage) override { + Ieee80211MgmtAp::initialize(stage); + if (stage != INITSTAGE_LAST) return; + const MacAddress peer("02:00:00:00:00:99"); + for (auto input : {std::pair(1,1), {0,3}, {0,1}}) { + auto packet = new Packet("auth"); + auto body = makeShared(); + body->setAlgorithmNumber(input.first); + body->setSequenceNumber(input.second); + packet->insertAtBack(body); + auto header = makeShared(); + header->setType(ST_AUTHENTICATION); + header->setTransmitterAddress(peer); + header->setReceiverAddress(mib->address); + handleAuthenticationFrame(packet, header); + ASSERT(response && response->getAlgorithmNumber() == input.first && response->getSequenceNumber() == 2); + auto status = input.first != 0 ? SC_AUTH_ALG0_UNSUP : input.second != 1 ? SC_AUTH_OUT_OF_SEQ : SC_SUCCESSFUL; + ASSERT(response->getStatusCode() == status); + if (status != SC_SUCCESSFUL) + ASSERT(mib->bssAccessPointData.stations.count(peer) == 0); + else + ASSERT(mib->bssAccessPointData.stations.at(peer) == Ieee80211Mib::AUTHENTICATED); + } + std::cout << "AP accepts only Open System transaction1 and responds with transaction2.\n"; + } +}; +Define_Module(TestAuthenticationAp); +class TestAuthenticationSta : public Ieee80211MgmtSta { + protected: + Ieee80211PrimResultCode result = PRC_SUCCESS; + virtual void sendAuthenticationConfirm(ApInfo *, Ieee80211PrimResultCode code) override { result = code; } + virtual void initialize(int stage) override { + Ieee80211MgmtSta::initialize(stage); + if (stage != INITSTAGE_LAST) return; + const MacAddress peer("02:00:00:00:00:98"); + apList.emplace_back(); + auto& ap = apList.back(); + ap.address = peer; + for (int variant = 0; variant < 4; variant++) { + ap.isAuthenticated = false; + ap.authSeqExpected = 2; + ap.authTimeoutMsg = new cMessage("authTimeout"); + scheduleAfter(1, ap.authTimeoutMsg); + auto packet = new Packet("auth-response"); + auto body = makeShared(); + body->setAlgorithmNumber(variant == 0 ? 1 : 0); + body->setSequenceNumber(variant == 1 ? 4 : 2); + body->setStatusCode(variant == 2 ? SC_UNSPECIFIED : SC_SUCCESSFUL); + body->setIsLast(false); // Must not trigger a third frame. + packet->insertAtBack(body); + auto header = makeShared(); + header->setType(ST_AUTHENTICATION); + header->setTransmitterAddress(peer); + handleAuthenticationFrame(packet, header); + ASSERT(ap.isAuthenticated == (variant == 3)); + ASSERT(ap.authTimeoutMsg == nullptr); + ASSERT((result == PRC_SUCCESS) == (variant == 3)); + } + std::cout << "STA completion requires successful algorithm0 transaction2, without isLast.\n"; + } +}; +Define_Module(TestAuthenticationSta); +}} + +%file: test.ned +import inet.linklayer.ieee80211.mgmt.Ieee80211MgmtAp; +import inet.linklayer.ieee80211.mgmt.Ieee80211MgmtSta; +import inet.node.wireless.AccessPoint; +import inet.node.inet.WirelessHost; +import inet.physicallayer.wireless.ieee80211.packetlevel.Ieee80211ScalarRadioMedium; +simple TestAuthenticationAp extends Ieee80211MgmtAp { parameters: @class(::inet::ieee80211::TestAuthenticationAp); } +simple TestAuthenticationSta extends Ieee80211MgmtSta { parameters: @class(::inet::ieee80211::TestAuthenticationSta); } +network AuthenticationNetwork { + submodules: + radioMedium: Ieee80211ScalarRadioMedium; + ap: AccessPoint; + sta: WirelessHost; +} + +%inifile: omnetpp.ini +[General] +network = AuthenticationNetwork +ned-path = .;../../../../src;../../lib +sim-time-limit = 1ms +seed-set = 0 +record-vector-results = false +record-scalar-results = false +*.ap.wlan[0].mgmt.typename = "TestAuthenticationAp" +*.sta.wlan[0].mgmt.typename = "TestAuthenticationSta" +*.sta.wlan[0].agent.startingTime = 2s +**.opMode = "g(erp)" +**.bitrate = 6Mbps +**.mobility.initFromDisplayString = false +**.mobility.initialX = 0m +**.mobility.initialY = 0m +**.mobility.initialZ = 0m + +%contains: stdout +AP accepts only Open System transaction1 and responds with transaction2. + +%contains: stdout +STA completion requires successful algorithm0 transaction2, without isLast. diff --git a/tests/module/Ieee80211StaMgmtBssid_1.test b/tests/module/Ieee80211StaMgmtBssid_1.test new file mode 100644 index 00000000000..9e9a5d0d005 --- /dev/null +++ b/tests/module/Ieee80211StaMgmtBssid_1.test @@ -0,0 +1,73 @@ +%description: +Infrastructure STA management packets retain the target BSSID at the real MAC +header construction boundary, including wildcard scans before association. + +%file: TestStaMgmtBssid.cc +#include +#include "inet/linklayer/ieee80211/mac/Ieee80211Mac.h" +#include "inet/linklayer/ieee80211/mgmt/Ieee80211MgmtFrame_m.h" +namespace inet { namespace ieee80211 { +class TestStaMgmtBssid : public Ieee80211Mac +{ + protected: + int probes = 0, authentications = 0, associations = 0; + virtual void processUpperFrame(Packet *packet, const Ptr& header) override { + if (dynamicPtrCast(header)) { + ASSERT(header->getAddress3() == header->getReceiverAddress()); + if (header->getType() == ST_PROBEREQUEST) probes++; + if (header->getType() == ST_AUTHENTICATION) { + auto body = packet->peekDataAt(header->getChunkLength()); + ASSERT(body->getAlgorithmNumber() == 0 && body->getSequenceNumber() == 1); + authentications++; + } + if (header->getType() == ST_ASSOCIATIONREQUEST) associations++; + } + Ieee80211Mac::processUpperFrame(packet, header); + } + virtual void finish() override { + ASSERT(probes > 0 && authentications == 1 && associations > 0); + std::cout << "STA scan, authentication and association headers carry their target BSSID.\n"; + } +}; +Define_Module(TestStaMgmtBssid); +}} + +%file: test.ned +import inet.linklayer.ieee80211.mac.Ieee80211Mac; +import inet.node.wireless.AccessPoint; +import inet.node.inet.WirelessHost; +import inet.physicallayer.wireless.ieee80211.packetlevel.Ieee80211ScalarRadioMedium; +module TestStaMgmtBssid extends Ieee80211Mac { + parameters: + @class(::inet::ieee80211::TestStaMgmtBssid); +} +network StaMgmtBssidNetwork { + submodules: + radioMedium: Ieee80211ScalarRadioMedium; + ap: AccessPoint; + sta: WirelessHost; +} + +%inifile: omnetpp.ini +[General] +network = StaMgmtBssidNetwork +ned-path = .;../../../../src;../../lib +sim-time-limit = 1s +seed-set = 0 +cmdenv-express-mode = true +record-vector-results = false +record-scalar-results = false +*.sta.wlan[0].mac.typename = "TestStaMgmtBssid" +*.ap.wlan[0].mgmt.ssid = "test" +*.sta.wlan[0].agent.defaultSsid = "test" +*.sta.wlan[0].agent.channelsToScan = "0" +**.opMode = "g(erp)" +**.bitrate = 6Mbps +**.mobility.initFromDisplayString = false +*.ap.mobility.initialX = 0m +*.sta.mobility.initialX = 10m +**.mobility.initialY = 0m +**.mobility.initialZ = 0m + +%contains: stdout +STA scan, authentication and association headers carry their target BSSID. diff --git a/tests/module/MIPv6_binding_refresh.test b/tests/module/MIPv6_binding_refresh.test index 3240ce8f44e..8c85492e1a8 100644 --- a/tests/module/MIPv6_binding_refresh.test +++ b/tests/module/MIPv6_binding_refresh.test @@ -43,7 +43,7 @@ num-rngs = 3 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_early_route_optimization.test b/tests/module/MIPv6_early_route_optimization.test index 37c79697957..2d7136f6a05 100644 --- a/tests/module/MIPv6_early_route_optimization.test +++ b/tests/module/MIPv6_early_route_optimization.test @@ -42,7 +42,7 @@ num-rngs = 3 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_handover.test b/tests/module/MIPv6_handover.test index 03a0583451f..50a92fa1b08 100644 --- a/tests/module/MIPv6_handover.test +++ b/tests/module/MIPv6_handover.test @@ -38,7 +38,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_movement_detection.test b/tests/module/MIPv6_movement_detection.test index 1a6552cde9b..ab9842f2b72 100644 --- a/tests/module/MIPv6_movement_detection.test +++ b/tests/module/MIPv6_movement_detection.test @@ -44,7 +44,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_return_home.test b/tests/module/MIPv6_return_home.test index 446192a9b76..49c55b2dcad 100644 --- a/tests/module/MIPv6_return_home.test +++ b/tests/module/MIPv6_return_home.test @@ -39,7 +39,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_return_home_route_optimization.test b/tests/module/MIPv6_return_home_route_optimization.test index 07269e2f3c3..1e4263e6fb2 100644 --- a/tests/module/MIPv6_return_home_route_optimization.test +++ b/tests/module/MIPv6_return_home_route_optimization.test @@ -45,7 +45,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minReceptionPower = -82dBm *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 **.AP*.wlan*.mgmt.beaconInterval = 0.1s **.AP_Home.wlan*.mgmt.ssid = "HOME" **.AP_Home.wlan*.address = "10:AA:00:00:00:01" diff --git a/tests/module/MIPv6_roaming_two_handovers.test b/tests/module/MIPv6_roaming_two_handovers.test index 4c3e2a0f264..5a5b3c4a519 100644 --- a/tests/module/MIPv6_roaming_two_handovers.test +++ b/tests/module/MIPv6_roaming_two_handovers.test @@ -42,7 +42,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minReceptionPower = -82dBm *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 **.AP*.wlan*.mgmt.beaconInterval = 0.1s **.AP_Home.wlan*.mgmt.ssid = "HOME" **.AP_Home.wlan*.address = "10:AA:00:00:00:01" diff --git a/tests/module/MIPv6_route_optimization.test b/tests/module/MIPv6_route_optimization.test index d354fe169aa..ea54bf8ce8b 100644 --- a/tests/module/MIPv6_route_optimization.test +++ b/tests/module/MIPv6_route_optimization.test @@ -40,7 +40,7 @@ num-rngs = 3 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_route_optimization_two_cns.test b/tests/module/MIPv6_route_optimization_two_cns.test index 42bd3ee2628..198537fa892 100644 --- a/tests/module/MIPv6_route_optimization_two_cns.test +++ b/tests/module/MIPv6_route_optimization_two_cns.test @@ -40,7 +40,7 @@ num-rngs = 3 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_tcp_handover.test b/tests/module/MIPv6_tcp_handover.test index d335e686362..ee4407101be 100644 --- a/tests/module/MIPv6_tcp_handover.test +++ b/tests/module/MIPv6_tcp_handover.test @@ -42,7 +42,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm # access point -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 # ALL APs common parameters **.AP*.wlan*.mgmt.beaconInterval = 0.1s diff --git a/tests/module/MIPv6_two_mobile_nodes.test b/tests/module/MIPv6_two_mobile_nodes.test index b01d30d69ed..309d0d69832 100644 --- a/tests/module/MIPv6_two_mobile_nodes.test +++ b/tests/module/MIPv6_two_mobile_nodes.test @@ -32,7 +32,7 @@ seed-set = 1 *.radioMedium.mediumLimitCache.minReceptionPower = -82dBm *.radioMedium.mediumLimitCache.minInterferencePower = -82dBm -**.wlan*.mgmt.numAuthSteps = 4 +**.wlan*.mgmt.numAuthSteps = 2 **.AP*.wlan*.mgmt.beaconInterval = 0.1s **.AP_Home.wlan*.mgmt.ssid = "HOME" **.AP_Home.wlan*.address = "10:AA:00:00:00:01" diff --git a/tests/protocol/wifi/common/WifiAuthOpen.test b/tests/protocol/wifi/common/WifiAuthOpen.test index ef1a2ed3d69..64c51fa032e 100644 --- a/tests/protocol/wifi/common/WifiAuthOpen.test +++ b/tests/protocol/wifi/common/WifiAuthOpen.test @@ -13,9 +13,11 @@ Define_ProtocolTest(wifi_auth_open) return ProtocolTest("wifi_auth_open") .once(on("sta1.wlan[0].mac").signal("packetSentToLower") .filterPacket("ieee80211mac.type == 11") + .assertPacket("Ieee80211AuthenticationFrame.algorithmNumber == 0 && Ieee80211AuthenticationFrame.sequenceNumber == 1") .describe("an Authentication request from STA").within(2.0)) .once(on("sta1.wlan[0].mac").signal("packetReceivedFromLower") .filterPacket("ieee80211mac.type == 11") + .assertPacket("Ieee80211AuthenticationFrame.algorithmNumber == 0 && Ieee80211AuthenticationFrame.sequenceNumber == 2 && Ieee80211AuthenticationFrame.statusCode == 0") .describe("an Authentication response from AP").within(2.0)); } diff --git a/tests/serializer/lib/fillers/ChunkFillers_ieee80211.cc b/tests/serializer/lib/fillers/ChunkFillers_ieee80211.cc index 158b12c5620..246fe526640 100644 --- a/tests/serializer/lib/fillers/ChunkFillers_ieee80211.cc +++ b/tests/serializer/lib/fillers/ChunkFillers_ieee80211.cc @@ -520,6 +520,7 @@ void addFillers_ieee80211(std::vector& fillers) fillers.push_back({"inet::ieee80211::Ieee80211AuthenticationFrame", "", [](Chunk *c) { auto p = check_and_cast(c); FillValues v; + p->setAlgorithmNumber(v.u16()); p->setSequenceNumber(v.u16()); p->setStatusCode(SC_AUTH_ALG0_UNSUP); // isLast is explicitly not part of the standard (see the .msg comment) and is diff --git a/tests/unit/Ieee80211MgmtFrameSerializer_1.test b/tests/unit/Ieee80211MgmtFrameSerializer_1.test index 18e3638f495..bab917a8e5c 100644 --- a/tests/unit/Ieee80211MgmtFrameSerializer_1.test +++ b/tests/unit/Ieee80211MgmtFrameSerializer_1.test @@ -173,6 +173,15 @@ static void checkMalformedSupportedRates(const std::vector& prefix) } %activity: +for (uint16_t algorithm : {0, 1, 0xffff}) { + auto auth = makeShared(); + auth->setAlgorithmNumber(algorithm); + auth->setSequenceNumber(2); + auth->setStatusCode(SC_SUCCESSFUL); + std::vector expected = {uint8_t(algorithm), uint8_t(algorithm >> 8), 2, 0, 0, 0}; + assertSerializedBody(auth, expected); + ASSERT(deserializeBody(expected)->getAlgorithmNumber() == algorithm); +} { const std::vector body = {0x00, 0x00, 0x34, 0x12, 0x0E, 0x00};