-
Notifications
You must be signed in to change notification settings - Fork 8
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #30 from microsoft/wpactrlsettings
Add hostapd interaction interface: define and implement basic commands
- Loading branch information
Showing
21 changed files
with
1,031 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
|
||
#include <format> | ||
#include <optional> | ||
|
||
#include <notstd/Exceptions.hxx> | ||
|
||
#include <Wpa/Hostapd.hxx> | ||
#include <Wpa/ProtocolHostapd.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
Hostapd::Hostapd(std::string_view interfaceName) : | ||
m_interface(interfaceName), | ||
m_controller(interfaceName, WpaType::Hostapd) | ||
{ | ||
} | ||
|
||
std::string_view Hostapd::GetInterface() | ||
{ | ||
return m_interface; | ||
} | ||
|
||
bool Hostapd::Ping() | ||
{ | ||
static constexpr WpaCommand PingCommand(ProtocolHostapd::CommandPayloadPing); | ||
|
||
const auto response = m_controller.SendCommand(PingCommand); | ||
if (!response) | ||
{ | ||
throw HostapdException("Failed to ping hostapd"); | ||
} | ||
|
||
return response->Payload.starts_with(ProtocolHostapd::ResponsePayloadPing); | ||
} | ||
|
||
HostapdStatus Hostapd::GetStatus() | ||
{ | ||
static constexpr WpaCommand StatusCommand(ProtocolHostapd::CommandPayloadStatus); | ||
|
||
auto response = m_controller.SendCommand(StatusCommand); | ||
if (!response) | ||
{ | ||
throw HostapdException("Failed to send hostapd 'status' command"); | ||
} | ||
|
||
HostapdStatus hostapdStatus{}; | ||
|
||
// Parse the response for the state field. Note that this code will later be | ||
// replaced by proper generic response parsing code, so this is quick-and-dirty. | ||
static constexpr std::string_view StateKey = "state="; | ||
|
||
// Find interface state string in payload. | ||
auto keyPosition = response->Payload.find(StateKey); | ||
if (keyPosition == response->Payload.npos) | ||
{ | ||
// The response should always have this field and not much can be done without it. | ||
throw HostapdException("hostapd 'status' command response missing state field"); | ||
} | ||
|
||
// Convert value string to corresponding enum value. | ||
const auto valuePosition = keyPosition + std::size(StateKey); | ||
const auto* value = std::data(response->Payload) + valuePosition; | ||
hostapdStatus.State = HostapdInterfaceStateFromString(value); | ||
|
||
return hostapdStatus; | ||
} | ||
|
||
bool Hostapd::Enable() | ||
{ | ||
static constexpr WpaCommand EnableCommand(ProtocolHostapd::CommandPayloadEnable); | ||
|
||
const auto response = m_controller.SendCommand(EnableCommand); | ||
if (!response) | ||
{ | ||
throw HostapdException("Failed to send hostapd 'enable' command"); | ||
} | ||
else if (response->IsOk()) | ||
{ | ||
return true; | ||
} | ||
|
||
// The response will indicate failure if the interface is already enabled. | ||
// Check if this is the case by validating the interface status. | ||
// This is only done if the 'enable' command fails since the GetStatus() | ||
// command is fairly heavy-weight in terms of its payload. | ||
const auto status = GetStatus(); | ||
return IsHostapdStateOperational(status.State); | ||
} | ||
|
||
bool Hostapd::Disable() | ||
{ | ||
static constexpr WpaCommand DisableCommand(ProtocolHostapd::CommandPayloadDisable); | ||
|
||
const auto response = m_controller.SendCommand(DisableCommand); | ||
if (!response) | ||
{ | ||
throw HostapdException("Failed to send hostapd 'disable' command"); | ||
} | ||
else if (response->IsOk()) | ||
{ | ||
return true; | ||
} | ||
|
||
// The response will indicate failure if the interface is already disabled. | ||
// Check if this is the case by validating the interface status. | ||
// This is only done if the 'disable' command fails since the GetStatus() | ||
// command is fairly heavy-weight in terms of its payload. | ||
const auto status = GetStatus(); | ||
return !IsHostapdStateOperational(status.State); | ||
} | ||
|
||
bool Hostapd::Terminate() | ||
{ | ||
static constexpr WpaCommand TerminateCommand(ProtocolHostapd::CommandPayloadTerminate); | ||
|
||
const auto response = m_controller.SendCommand(TerminateCommand); | ||
if (!response) | ||
{ | ||
throw HostapdException("Failed to send hostapd 'terminate' command"); | ||
} | ||
|
||
return response->IsOk(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
|
||
#include <Wpa/ProtocolHostapd.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
HostapdInterfaceState Wpa::HostapdInterfaceStateFromString(std::string_view state) noexcept | ||
{ | ||
// Implementation uses starts_with() instead of equals() to accommodate | ||
// unparsed payloads from command responses. | ||
if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusUninitialized)) | ||
{ | ||
return HostapdInterfaceState::Uninitialized; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusDisabled)) | ||
{ | ||
return HostapdInterfaceState::Disabled; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusEnabled)) | ||
{ | ||
return HostapdInterfaceState::Enabled; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusCountryUpdate)) | ||
{ | ||
return HostapdInterfaceState::CountryUpdate; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusAcs)) | ||
{ | ||
return HostapdInterfaceState::Acs; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusHtScan)) | ||
{ | ||
return HostapdInterfaceState::HtScan; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusDfs)) | ||
{ | ||
return HostapdInterfaceState::Dfs; | ||
} | ||
else if (state.starts_with(ProtocolHostapd::ResponsePayloadStatusNoIr)) | ||
{ | ||
return HostapdInterfaceState::NoIr; | ||
} | ||
|
||
return HostapdInterfaceState::Unknown; | ||
} | ||
|
||
bool Wpa::IsHostapdStateOperational(HostapdInterfaceState state) noexcept | ||
{ | ||
switch (state) | ||
{ | ||
case HostapdInterfaceState::Enabled: | ||
case HostapdInterfaceState::CountryUpdate: | ||
case HostapdInterfaceState::Acs: | ||
case HostapdInterfaceState::HtScan: | ||
case HostapdInterfaceState::Dfs: | ||
case HostapdInterfaceState::NoIr: | ||
return true; | ||
case HostapdInterfaceState::Uninitialized: | ||
case HostapdInterfaceState::Disabled: | ||
case HostapdInterfaceState::Unknown: | ||
default: | ||
return false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
#include <Wpa/ProtocolWpa.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
/* static */ | ||
bool ProtocolWpa::IsResponseOk(std::string_view response) | ||
{ | ||
return (response.starts_with(ResponsePayloadOk)); | ||
} | ||
|
||
/* static */ | ||
bool ProtocolWpa::IsResponseFail(std::string_view response) | ||
{ | ||
return (response.starts_with(ResponsePayloadFail)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,3 @@ | |
#include <Wpa/WpaCommand.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
WpaCommand::WpaCommand(std::string_view data) : | ||
Data(data) | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
#include <Wpa/WpaCommandStatus.hxx> | ||
#include <Wpa/ProtocolWpa.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
constexpr WpaCommandStatus::WpaCommandStatus() : | ||
WpaCommand(ProtocolWpa::CommandPayloadStatus) | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,26 @@ | ||
|
||
#include <Wpa/WpaResponse.hxx> | ||
#include <Wpa/ProtocolWpa.hxx> | ||
|
||
using namespace Wpa; | ||
|
||
WpaResponse::WpaResponse(std::string_view payload) : | ||
Payload(payload) | ||
m_payload(payload), | ||
Payload(m_payload) | ||
{ | ||
} | ||
|
||
WpaResponse::operator bool() const | ||
{ | ||
return IsOk(); | ||
} | ||
|
||
bool WpaResponse::IsOk() const | ||
{ | ||
return (ProtocolWpa::IsResponseOk(Payload)); | ||
} | ||
|
||
bool WpaResponse::Failed() const | ||
{ | ||
return (ProtocolWpa::IsResponseFail(Payload)); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
|
||
#ifndef HOSTAPD_HXX | ||
#define HOSTAPD_HXX | ||
|
||
#include <string_view> | ||
#include <string> | ||
|
||
#include <Wpa/IHostapd.hxx> | ||
#include <Wpa/WpaController.hxx> | ||
|
||
namespace Wpa | ||
{ | ||
/** | ||
* @brief Concrete implementation of the IHostapd interface. | ||
*/ | ||
struct Hostapd : | ||
public IHostapd | ||
{ | ||
/** | ||
* @brief Construct a new Hostapd object. | ||
* | ||
* @param interfaceName The name of the intrerface to control. Eg. wlan1. | ||
*/ | ||
Hostapd(std::string_view interfaceName); | ||
|
||
/** | ||
* @brief Get the name of the interface hostapd is managing. | ||
* | ||
* @return std::string_view | ||
*/ | ||
std::string_view GetInterface() override; | ||
|
||
/** | ||
* @brief Checks connectivity to the hostapd daemon. | ||
*/ | ||
bool Ping() override; | ||
|
||
/** | ||
* @brief Get the status for the interface. | ||
* | ||
* @return HostapdStatus | ||
*/ | ||
HostapdStatus GetStatus() override; | ||
|
||
/** | ||
* @brief Enables the interface for use. | ||
* | ||
* @return true | ||
* @return false | ||
*/ | ||
bool Enable() override; | ||
|
||
/** | ||
* @brief Disables the interface for use. | ||
* | ||
* @return true | ||
* @return false | ||
*/ | ||
bool Disable() override; | ||
|
||
/** | ||
* @brief Terminates the process hosting the daemon. | ||
* | ||
* @return true | ||
* @return false | ||
*/ | ||
bool Terminate() override; | ||
|
||
private: | ||
const std::string m_interface; | ||
WpaController m_controller; | ||
}; | ||
} // namespace Wpa | ||
|
||
#endif // HOSTAPD_HXX |
Oops, something went wrong.