Access point configuration from clean.

This commit is contained in:
Robin Davies
2021-09-01 05:38:34 -04:00
parent 6cb1300cc9
commit 90b8a93c93
6 changed files with 302 additions and 95 deletions
+116 -22
View File
@@ -26,31 +26,46 @@
using namespace pipedal;
#define IP_RANGE "172.22.0"
#define PIPEDAL_IP IP_RANGE ".1"
#define PIPEDAL_NETWORK PIPEDAL_IP "/24"
#define SYSTEMCTL_BIN "/usr/bin/systemctl"
void pipedal::SetWifiConfig(const WifiConfigSettings&settings)
{
char band;
if (!settings.enable_)
{
SysExec("/usr/bin/systemctl stop hostapd");
SysExec("/usr/bin/systemctl disable hostapd");
SysExec(SYSTEMCTL_BIN " stop hostapd");
SysExec(SYSTEMCTL_BIN " disable hostapd");
SysExec("/usr/bin/systemctl enable wpa_supplicant");
SysExec("/usr/bin/systemctl start wpa_supplicant");
SysExec(SYSTEMCTL_BIN " enable wpa_supplicant");
SysExec(SYSTEMCTL_BIN " start wpa_supplicant");
} else {
boost::filesystem::path path("/etc/hostapd/hostapd.conf");
SystemConfigFile apdConfig(path);
apdConfig.Set("ieee80211n","1",false);
apdConfig.Set("ieee80211d","1",false);
apdConfig.Set("ieee80211ac","1",false);
apdConfig.Set("ieee80211d","1",false);
apdConfig.Set("ht_capab","[HT40][SHORT-GI-20][DSSS_CCK-40]",false);
apdConfig.Set("rsn_pairwise","CCMP",false);
std::filesystem::path path("/etc/hostapd/hostapd.conf");
SystemConfigFile apdConfig;
if (std::filesystem::exists(path))
{
apdConfig.Load(path);
}
apdConfig.Set("interface","wlan0");
apdConfig.Set("driver","nl80211");
apdConfig.Set("country_code",settings.countryCode_);
apdConfig.Set("wmm_enabled","1");
apdConfig.Set("ieee80211n","1","Wi-Fi features");
apdConfig.SetDefault("ieee80211d","1");
apdConfig.SetDefault("ieee80211ac","1");
apdConfig.SetDefault("ieee80211d","1");
apdConfig.Set("ht_capab","[HT40][SHORT-GI-20][DSSS_CCK-40]");
apdConfig.Set("wmm_enabled","1","Authentication options");
apdConfig.Set("auth_algs","1");
apdConfig.Set("wpa","2");
apdConfig.SetDefault("wpa_pairwise","TKIP CCMP");
apdConfig.SetDefault("wpa_ptk_rekey","600");
apdConfig.SetDefault("rsn_pairwise","CCMP");
std::string hwMode = "g";
if (settings.channel_.length() > 0 && settings.channel_[0] == 'a') {
@@ -72,22 +87,94 @@ void pipedal::SetWifiConfig(const WifiConfigSettings&settings)
}
}
apdConfig.Set("ssid",settings.hotspotName_,"Access point configuration");
if (settings.password_.length() != 0)
{
apdConfig.Set("wpa_passphrase",settings.password_);
}
apdConfig.Set("ssid",settings.hotspotName_);
apdConfig.Set("country_code",settings.countryCode_);
apdConfig.Set("hw_mode",hwMode);
apdConfig.Set("channel",channel);
apdConfig.Save();
SysExec("/usr/bin/systemctl daemon-reload");
// ******************** dsnmasq ******
std::filesystem::path dnsMasqPath("/etc/dnsmasq.conf");
SystemConfigFile dnsMasq;
try {
dnsMasq.Load(dnsMasqPath);
} catch (const std::exception &)
{
// ignore.
}
SysExec("/usr/bin/systemctl mask wpa_supplicant");
SysExec("/usr/bin/systemctl stop wpa_supplicant");
dnsMasq.Set("interface","wlan0","Name of the Wi-Fi interface");
dnsMasq.Set("listen-address",PIPEDAL_IP);
if (SysExec("/usr/bin/systemctl restart hostapd") != 0)
dnsMasq.SetDefault("dhcp-range", IP_RANGE ".3," IP_RANGE ".127,12h","dhcp configuration");
dnsMasq.SetDefault("domain","local");
std::stringstream sAddress;
sAddress << "/" << settings.mdnsName_ << ".local/" IP_RANGE << ".1";
dnsMasq.Set("address",sAddress.str());
// ****** dhcpd.conf ***/
std::filesystem::path dhcpcdConfig("/etc/dhcpcd.conf");
if (std::filesystem::exists(dhcpcdConfig))
{
SystemConfigFile dhcpcd(dhcpcdConfig);
int line = dhcpcd.GetLineThatStartsWith("hostname");
std::string hostNameLine;
if (settings.mdnsName_ != "")
{
hostNameLine = "hostname " + settings.mdnsName_;
} else {
hostNameLine = "hostname"; // the default value.
}
if (line != -1) {
dhcpcd.SetLineValue(line,hostNameLine);
} else {
dhcpcd.AppendLine(hostNameLine);
}
line = dhcpcd.GetLineNumber("interface wlan0");
if (line != -1) {
dhcpcd.EraseLine(line);
while (line < dhcpcd.GetLineCount())
{
const std::string &lineValue = dhcpcd.GetLineValue(line);
if (lineValue.length() > 0 && (lineValue[0] == ' ' || lineValue[0] == '\t'))
{
dhcpcd.EraseLine(line);
} else {
break;
}
}
}
if (line == -1) {
dhcpcd.AppendLine("");
line = dhcpcd.GetLineCount();
}
dhcpcd.InsertLine(line++,"interface wlan0");
dhcpcd.InsertLine(line++," static ip_address=" PIPEDAL_NETWORK);
dhcpcd.InsertLine(line++," nohook wpa_supplicant");
dhcpcd.Save(dhcpcdConfig);
}
// ***** save the config files ***
apdConfig.Save(path);
dnsMasq.Save(dnsMasqPath);
// **************** start services ************
SysExec("rfkill unblock wlan");
SysExec(SYSTEMCTL_BIN " daemon-reload");
SysExec(SYSTEMCTL_BIN " mask wpa_supplicant");
SysExec(SYSTEMCTL_BIN " stop wpa_supplicant");
SysExec(SYSTEMCTL_BIN " unmask hostapd");
if (SysExec(SYSTEMCTL_BIN " restart hostapd") != 0)
{
throw PiPedalException("Unable to start the access point.");
@@ -96,8 +183,15 @@ void pipedal::SetWifiConfig(const WifiConfigSettings&settings)
{
throw PiPedalException("Unable to start the access point.");
}
SysExec("/usr/bin/systemctl enable hostapd");
SysExec(SYSTEMCTL_BIN " enable hostapd");
SysExec(SYSTEMCTL_BIN " stop wpa_supplicant");
SysExec(SYSTEMCTL_BIN " mask wpa_supplicant");
SysExec(SYSTEMCTL_BIN " restart dnsmasq");
SysExec(SYSTEMCTL_BIN " enable dnsmasq");
}
}
+165 -65
View File
@@ -27,7 +27,22 @@
using namespace pipedal;
using namespace std;
void SystemConfigFile::Load(const boost::filesystem::path&path)
static std::string makeLine(const std::string &key, const std::string &value)
{
stringstream s;
if (value.length() == 0)
{
s << key;
}
else
{
s << key << "=" << value;
}
return s.str();
}
void SystemConfigFile::Load(const std::filesystem::path &path)
{
this->lines.clear();
@@ -42,7 +57,7 @@ void SystemConfigFile::Load(const boost::filesystem::path&path)
while (true)
{
std::string line;
std::getline(f,line);
std::getline(f, line);
if (f.fail())
{
break;
@@ -50,107 +65,130 @@ void SystemConfigFile::Load(const boost::filesystem::path&path)
lines.push_back(line);
}
this->currentPath = path;
}
int64_t SystemConfigFile::GetLine(const std::string &key) const
{
for (size_t i = 0; i < lines.size(); ++i)
{
if (LineMatches(lines[i],key))
if (LineMatches(lines[i], key))
{
return i;
}
}
std::string commentedKey = "#" + key;
for (size_t i = 0; i < lines.size(); ++i)
{
if (LineMatches(lines[i], commentedKey))
{
return i;
}
}
return -1;
}
bool SystemConfigFile::HasValue(const std::string&key) const
bool SystemConfigFile::HasValue(const std::string &key) const
{
return GetLine(key) != -1;
int line = GetLine(key);
if (line == -1)
return false;
return lines[line][0] != '#';
}
static inline std::string ValuePart(const std::string &line)
{
auto pos = line.find('=');
if (pos == std::string::npos) throw PiPedalException("Value not found.");
return line.substr(pos+1);
if (pos == std::string::npos)
throw PiPedalException("Value not found.");
return line.substr(pos + 1);
}
std::string SystemConfigFile::Get(const std::string&key) const
std::string SystemConfigFile::Get(const std::string &key) const
{
int64_t lineIndex = GetLine(key);
if (lineIndex == -1) throw PiPedalArgumentException("Not found.");
if (lineIndex == -1)
throw PiPedalArgumentException("Not found.");
return ValuePart(lines[lineIndex]);
}
bool SystemConfigFile::Get(const std::string&key,std::string*pResult) const
bool SystemConfigFile::Get(const std::string &key, std::string *pResult) const
{
int64_t lineIndex = GetLine(key);
if (lineIndex == -1) return false;
if (lineIndex == -1)
return false;
*pResult = ValuePart(lines[lineIndex]);
return true;
}
void SystemConfigFile::Set(const std::string&key,const std::string &value)
void SystemConfigFile::Set(const std::string &key, const std::string &value)
{
stringstream s;
s << key << "=" << value;
std::string line = s.str();
std::string line = makeLine(key, value);
int lineIndex = GetLine(key);
if (lineIndex != -1) {
if (lineIndex != -1)
{
lines[lineIndex] = line;
} else {
}
else
{
lines.push_back(line);
}
}
void SystemConfigFile::SetDefault(const std::string &key, const std::string &value)
{
int lineIndex = GetLine(key);
if (lineIndex == -1)
{
lines.push_back(makeLine(key, value));
} else if (lines[lineIndex][0] != '#') {
lines[lineIndex] = makeLine(key,value);
}
}
bool SystemConfigFile::Erase(const std::string&key)
bool SystemConfigFile::Erase(const std::string &key)
{
bool matched = false;
for (size_t i = 0; i < lines.size(); ++i)
{
if (LineMatches(lines[i],key))
if (LineMatches(lines[i], key))
{
matched = true;
lines.erase(lines.begin()+i);
lines.erase(lines.begin() + i);
--i;
}
}
return matched;
}
static std::string makeLine(const std::string&key, const std::string&value) {
stringstream s;
s << key << "=" << value;
return s.str();
}
int64_t SystemConfigFile::Insert(int64_t position, const std::string&key, const std::string&value)
int64_t SystemConfigFile::Insert(int64_t position, const std::string &key, const std::string &value)
{
if (position < 0 || position >= lines.size())
{
lines.push_back(makeLine(key,value));
lines.push_back(makeLine(key, value));
return (int64_t)lines.size();
} else {
lines.insert(lines.begin()+position,makeLine(key,value));
return position+1;
}
else
{
lines.insert(lines.begin() + position, makeLine(key, value));
return position + 1;
}
}
int64_t SystemConfigFile::Insert(int64_t position, const std::string&line)
int64_t SystemConfigFile::Insert(int64_t position, const std::string &line)
{
if (position < 0 || position >= lines.size())
{
lines.push_back(line);
return (int64_t)lines.size();
} else {
lines.insert(lines.begin()+position,line);
return position+1;
}
else
{
lines.insert(lines.begin() + position, line);
return position + 1;
}
}
bool SystemConfigFile::LineMatches(const std::string &line, const std::string&key) const
inline bool SystemConfigFile::LineMatches(const std::string &line, const std::string &key) const
{
// (very permissive interpretation)
int pos = 0;
@@ -158,46 +196,61 @@ bool SystemConfigFile::LineMatches(const std::string &line, const std::string&ke
{
++pos;
}
if (line.compare(pos,pos+key.length(),key) != 0) return false;
pos += key.length();\
if (line.compare(pos, pos + key.length(), key) != 0)
return false;
pos += key.length();
while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t'))
{
++pos;
}
if (pos == line.length())
return true;
return pos < line.length() && line[pos] == '=';
}
void SystemConfigFile::SetLine(int64_t lineIndex,const std::string&key,const std::string &value )
void SystemConfigFile::SetLine(int64_t lineIndex, const std::string &key, const std::string &value)
{
stringstream s;
s << key << "=" << value;
std::string line = makeLine(key, value);
if (lineIndex >= 0 && lineIndex < this->lines.size())
{
this->lines[lineIndex] = s.str();
} else {
this->lines.push_back(s.str());
this->lines[lineIndex] = line;
}
else
{
this->lines.push_back(line);
}
}
void SystemConfigFile::Set(const std::string&key,const std::string &value, bool overwrite)
{
if (!overwrite)
{
if (HasValue(key)) return;
}
Set(key,value);
}
void SystemConfigFile::Set(const std::string&key,const std::string &value, const std::string&comment)
void SystemConfigFile::SetDefault(const std::string &key, const std::string &value, const std::string &comment)
{
uint64_t lineIndex = GetLine(key);
if (lineIndex != -1)
int lineIndex = GetLine(key);
if (lineIndex == -1)
{
SetLine(lineIndex, key, value);
} else {
lines.push_back("");
lines.push_back("# " + comment);
SetLine(-1,key,value);
lines.push_back(makeLine(key, value));
} else {
if (lines[lineIndex][0] == '#')
{
lines[lineIndex] = makeLine(key,value);
}
}
}
void SystemConfigFile::Set(const std::string &key, const std::string &value, const std::string &comment)
{
auto lineIndex = GetLine(key);
if (lineIndex != -1)
{
SetLine(lineIndex, key, value);
}
else
{
lines.push_back("");
lines.push_back("# " + comment);
SetLine(-1, key, value);
}
}
@@ -207,13 +260,13 @@ void SystemConfigFile::Save(std::ostream &os)
{
os << lines[i] << std::endl;
}
}
void SystemConfigFile::Save(const boost::filesystem::path&path)
void SystemConfigFile::Save(const std::filesystem::path &path)
{
ofstream f(path);
if (!f.is_open()) {
if (!f.is_open())
{
stringstream s;
s << "Unable to write to " << path;
throw PiPedalException(s.str());
@@ -230,3 +283,50 @@ void SystemConfigFile::Save()
{
Save(this->currentPath);
}
int SystemConfigFile::GetLineNumber(const std::string &line) const {
for (int i = 0; i < lines.size(); ++i)
{
if (lines[i] == line)
{
return i;
}
}
return -1;
}
void SystemConfigFile::EraseLine(int i)
{
if (i < 0 || i >= lines.size()) throw PiPedalArgumentException("Range error.");
lines.erase(lines.begin()+i);
}
bool SystemConfigFile::EraseLine(const std::string &line)
{
int lineNumber = GetLineNumber(line);
if (lineNumber == -1) return false;
lines.erase(lines.begin() + lineNumber);
return true;
}
void SystemConfigFile::InsertLine(int position, const std::string&line)
{
this->lines.insert(lines.begin()+position,line);
}
int SystemConfigFile::GetLineThatStartsWith(const std::string&text) const
{
for (size_t i = 0; i < lines.size(); ++i)
{
if (lines[i].rfind(text,0) != std::string::npos) {
return (int)i;
}
}
return -1;
}
void SystemConfigFile::AppendLine(const std::string &line)
{
lines.push_back(line);
}
+18 -7
View File
@@ -18,12 +18,12 @@
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#pragma once
#include <boost/filesystem.hpp>
#include <filesystem>
namespace pipedal {
class SystemConfigFile {
boost::filesystem::path currentPath;
std::filesystem::path currentPath;
std::vector<std::string> lines;
void SetLine(int64_t lineIndex,const std::string&key,const std::string &value );
bool LineMatches(const std::string &line, const std::string&key) const;
@@ -31,15 +31,15 @@ public:
SystemConfigFile() {
}
SystemConfigFile(const boost::filesystem::path& path)
SystemConfigFile(const std::filesystem::path& path)
{
Load(path);
}
void Load(const boost::filesystem::path&path);
void Load(const std::filesystem::path&path);
void Save(std::ostream &os);
void Save(const boost::filesystem::path&path);
void Save(const std::filesystem::path&path);
void Save();
int64_t GetLine(const std::string &key) const;
@@ -47,12 +47,23 @@ public:
bool Get(const std::string&key,std::string*pResult) const;
std::string Get(const std::string&key) const;
void Set(const std::string&key,const std::string &value);
void Set(const std::string&key,const std::string &value, bool overwrite);
void Set(const std::string&key,const std::string &value, const std::string&comment);
void SetDefault(const std::string&key, const std::string &value);
void SetDefault(const std::string&key,const std::string &value, const std::string &comment);
bool Erase(const std::string&key);
int64_t Insert(int64_t position, const std::string&key, const std::string&value);
int64_t Insert(int64_t position, const std::string&line);
int GetLineNumber(const std::string&line) const;
bool HasLine(const std::string&line) const { return GetLineNumber(line) != -1; }
void EraseLine(int i);
int GetLineThatStartsWith(const std::string&text) const;
int GetLineCount() const { return (int)lines.size();}
const std::string & GetLineValue(int line) const { return lines[line]; }
bool EraseLine(const std::string&line);
void InsertLine(int position, const std::string&line);
void AppendLine(const std::string&line);
void SetLineValue(int index, const std::string&line) { lines[index] = line; }
};
};
+1 -1
View File
@@ -33,7 +33,7 @@ using namespace pipedal;
TEST_CASE( "SystemConfigFile Test", "[system_config_file_test]" ) {
boost::filesystem::path path("/etc/hostapd/hostapd.conf");
std::filesystem::path path("/etc/hostapd/hostapd.conf");
SystemConfigFile file(path);
std::string driverName;
+1
View File
@@ -28,6 +28,7 @@ JSON_MAP_BEGIN(WifiConfigSettings)
JSON_MAP_REFERENCE(WifiConfigSettings,rebootRequired)
JSON_MAP_REFERENCE(WifiConfigSettings,enable)
JSON_MAP_REFERENCE(WifiConfigSettings,hotspotName)
JSON_MAP_REFERENCE(WifiConfigSettings,mdnsName)
JSON_MAP_REFERENCE(WifiConfigSettings,hasPassword)
JSON_MAP_REFERENCE(WifiConfigSettings,password)
JSON_MAP_REFERENCE(WifiConfigSettings,countryCode)
+1
View File
@@ -31,6 +31,7 @@ namespace pipedal {
bool enable_ = false;
std::string countryCode_ = "US"; // iso 3661
std::string hotspotName_ = "pipedal";
std::string mdnsName_ = "pipedal";
bool hasPassword_ = false;
std::string password_;
std::string channel_ = "g6";