Support for Ubuntu iwlN wifi devices.

This commit is contained in:
Robin E. R. Davies
2024-11-25 18:14:32 -05:00
parent 8787073338
commit 7651bc97a2
5 changed files with 155 additions and 66 deletions
+1 -1
View File
@@ -383,7 +383,7 @@ void HotspotManagerImpl::onStartMonitoring()
wlanDevice = GetDevice(NM_DEVICE_TYPE_WIFI); wlanDevice = GetDevice(NM_DEVICE_TYPE_WIFI);
if (!wlanDevice) if (!wlanDevice)
{ {
throw std::runtime_error("wlan0 device not found."); throw std::runtime_error("Wi-Fi device not found.");
} }
wlanWirelessDevice = DeviceWireless::Create(dbusDispatcher, wlanDevice->getObjectPath()); wlanWirelessDevice = DeviceWireless::Create(dbusDispatcher, wlanDevice->getObjectPath());
+120 -50
View File
@@ -30,10 +30,10 @@
#include <regex> #include <regex>
#include "ss.hpp" #include "ss.hpp"
#include "Finally.hpp" #include "Finally.hpp"
#include <boost/asio.hpp>
using namespace pipedal; using namespace pipedal;
static bool IsIpv4MappedAddress(const struct in6_addr &inetAddr6) static bool IsIpv4MappedAddress(const struct in6_addr &inetAddr6)
{ {
return IN6_IS_ADDR_V4MAPPED(&inetAddr6) != 0; return IN6_IS_ADDR_V4MAPPED(&inetAddr6) != 0;
@@ -62,6 +62,71 @@ static bool ipv6NetmaskCompare(const struct in6_addr &left, const struct in6_add
return true; return true;
} }
NetworkInterfaceType pipedal::GetNetworkInterfaceType(const char *interfaceName)
{
// stock linux.
if (strncmp(interfaceName, "eth", 3) == 0)
{
return NetworkInterfaceType::Ethernet;
}
if (strncmp(interfaceName, "wlan", 4) == 0)
{
return NetworkInterfaceType::WiFi;
}
if (strncmp(interfaceName, "lo", 2) == 0)
{
return NetworkInterfaceType::Loopback;
}
// ubuntu-style names.
if (strncmp(interfaceName, "en", 2) == 0)
{
return NetworkInterfaceType::Ethernet;
}
if (strncmp(interfaceName, "wl", 2) == 0)
{
return NetworkInterfaceType::WiFi;
}
return NetworkInterfaceType::Other;
}
std::optional<std::string> pipedal::GetWlanInterfaceName()
{
struct ifaddrs *ifap = nullptr;
if (getifaddrs(&ifap) != 0)
throw std::runtime_error("No networks available.");
Finally f{[ifap]()
{
freeifaddrs(ifap);
}};
for (struct ifaddrs *p = ifap; p != nullptr; p = p->ifa_next)
{
if (GetNetworkInterfaceType(p->ifa_name) == NetworkInterfaceType::WiFi)
{
return std::string(p->ifa_name);
}
}
return std::optional<std::string>();
}
std::optional<std::string> pipedal::GetWlanIpv4Address()
{
auto wlanAddress = GetWlanInterfaceName();
if (wlanAddress)
{
auto result = GetInterfaceIpv4Address(*wlanAddress);
if (result.length() != 0)
{
return result;
}
}
return std::optional<std::string>();
}
static bool IsIpv4OnLocalSubnet(uint32_t ipv4Addres) static bool IsIpv4OnLocalSubnet(uint32_t ipv4Addres)
{ {
bool result = false; bool result = false;
@@ -267,16 +332,17 @@ bool pipedal::IsOnLocalSubnet(const std::string &fromAddress)
return result; return result;
} }
static bool isEthernetAddress(const char *ifName)
static bool isEthernetAddress(const char*ifName)
{ {
// either ethN (classic), // either ethN (classic),
if (strncmp(ifName,"eth",3) == 0) return true; if (strncmp(ifName, "eth", 3) == 0)
return true;
// or "enpNNsNN" (ubuntu) // or "enpNNsNN" (ubuntu)
return (ifName[0] == 'e' && ifName[1] == 'n' && ifName[2] == 'p'); return (ifName[0] == 'e' && ifName[1] == 'n');
} }
std::vector<std::string> pipedal::GetEthernetIpv4Addresses() { std::vector<std::string> pipedal::GetEthernetIpv4Addresses()
{
std::vector<std::string> result; std::vector<std::string> result;
struct ifaddrs *ifap = nullptr; struct ifaddrs *ifap = nullptr;
@@ -291,13 +357,10 @@ std::vector<std::string> pipedal::GetEthernetIpv4Addresses() {
uint32_t netmask = htonl(((sockaddr_in *)(p->ifa_netmask))->sin_addr.s_addr); uint32_t netmask = htonl(((sockaddr_in *)(p->ifa_netmask))->sin_addr.s_addr);
uint32_t ifAddr = htonl(((sockaddr_in *)(p->ifa_addr))->sin_addr.s_addr); uint32_t ifAddr = htonl(((sockaddr_in *)(p->ifa_addr))->sin_addr.s_addr);
{ {
if (ifAddr & 0xFF) { // has an actual bound IP address. if (ifAddr & 0xFF)
{ // has an actual bound IP address.
std::string name = SS( std::string name = SS(
((ifAddr >> 24) & 0xFF) << ((ifAddr >> 24) & 0xFF) << '.' << ((ifAddr >> 16) & 0xFF) << '.' << ((ifAddr >> 8) & 0xFF) << '.' << ((ifAddr) & 0xFF));
'.' << ((ifAddr >> 16) & 0xFF) <<
'.' << ((ifAddr >> 8) & 0xFF) <<
'.' << ((ifAddr) & 0xFF)
);
result.push_back(std::move(name)); result.push_back(std::move(name));
} }
} }
@@ -365,7 +428,8 @@ static std::string GetNonLinkLocalAddress(const boost::asio::ip::address_v6 &ipV
if (getifaddrs(&ifap) != 0) if (getifaddrs(&ifap) != 0)
throw std::runtime_error("No networks available."); throw std::runtime_error("No networks available.");
Finally f{[ifap]() { Finally f{[ifap]()
{
freeifaddrs(ifap); freeifaddrs(ifap);
}}; }};
@@ -397,7 +461,7 @@ static std::string GetNonLinkLocalAddress(const boost::asio::ip::address_v6 &ipV
{ {
if (p->ifa_addr->sa_family == AF_INET && p->ifa_addr != nullptr && p->ifa_netmask != nullptr) if (p->ifa_addr->sa_family == AF_INET && p->ifa_addr != nullptr && p->ifa_netmask != nullptr)
{ {
if (strcmp(p->ifa_name,targetInterfaceName) == 0) if (strcmp(p->ifa_name, targetInterfaceName) == 0)
{ {
constexpr int BUFSIZE = 128; constexpr int BUFSIZE = 128;
char host[BUFSIZE]; char host[BUFSIZE];
@@ -421,14 +485,13 @@ static std::string GetNonLinkLocalAddress(const boost::asio::ip::address_v6 &ipV
{ {
char buffer[128]; char buffer[128];
inet_ntop(AF_INET6, &(pAddr->sin6_addr), inet_ntop(AF_INET6, &(pAddr->sin6_addr),
buffer,sizeof(buffer)); buffer, sizeof(buffer));
return SS('[' << buffer << ']'); return SS('[' << buffer << ']');
} }
} }
} }
// probably network address settling after the hotspot comes up. :-/ // probably network address settling after the hotspot comes up. :-/
throw std::runtime_error("Not ready. Try again later."); throw std::runtime_error("Not ready. Try again later.");
} }
static std::string GetNonLinkLocalAddressForInterface(const std::string &name) static std::string GetNonLinkLocalAddressForInterface(const std::string &name)
@@ -583,7 +646,6 @@ static std::string GetNonLinkLocalAddressForIp4Interface(const std::string &name
// else // else
// { // {
// std::string interfaceName = GetInterfaceForIp6Address(inetAddr6); // std::string interfaceName = GetInterfaceForIp6Address(inetAddr6);
// result = GetNonLinkLocalAddressForInterface(interfaceName); // result = GetNonLinkLocalAddressForInterface(interfaceName);
// } // }
@@ -596,7 +658,6 @@ static std::string GetNonLinkLocalAddressForIp4Interface(const std::string &name
// return result; // return result;
// } // }
std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress) std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
{ {
std::string address = fromAddress; std::string address = fromAddress;
@@ -612,12 +673,11 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
throw std::invalid_argument("Bad address."); throw std::invalid_argument("Bad address.");
address = address.substr(1, address.length() - 2); address = address.substr(1, address.length() - 2);
auto nPos = address.find('%') ; auto nPos = address.find('%');
if (nPos != std::string::npos) if (nPos != std::string::npos)
{ {
std::string ifName = address.substr(nPos+1); std::string ifName = address.substr(nPos + 1);
return GetNonLinkLocalAddressForInterface(ifName); return GetNonLinkLocalAddressForInterface(ifName);
} }
struct in6_addr inetAddr6; struct in6_addr inetAddr6;
memset(&inetAddr6, 0, sizeof(inetAddr6)); memset(&inetAddr6, 0, sizeof(inetAddr6));
@@ -639,7 +699,6 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
else else
{ {
std::string interfaceName = GetInterfaceForIp6Address(inetAddr6); std::string interfaceName = GetInterfaceForIp6Address(inetAddr6);
result = GetNonLinkLocalAddressForInterface(interfaceName); result = GetNonLinkLocalAddressForInterface(interfaceName);
} }
@@ -652,13 +711,11 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
return result; return result;
} }
std::string pipedal::GetInterfaceIpv4Address(const std::string& interfaceName) std::string pipedal::GetInterfaceIpv4Address(const std::string &interfaceName)
{ {
return GetNonLinkLocalAddressForIp4Interface(interfaceName); return GetNonLinkLocalAddressForIp4Interface(interfaceName);
} }
// std::string getNonLinkLocalAddress(const std::string&address, const std::string&interface) // std::string getNonLinkLocalAddress(const std::string&address, const std::string&interface)
// { // {
// if (!interface.empty()) // if (!interface.empty())
@@ -669,7 +726,7 @@ std::string pipedal::GetInterfaceIpv4Address(const std::string& interfaceName)
// } // }
static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::string *suffix) static bool parseForLinkLocalUrl(const std::string &url, std::string *prefix, std::string *suffix)
{ {
auto iter = url.begin(); auto iter = url.begin();
auto end = url.end(); auto end = url.end();
@@ -677,7 +734,8 @@ static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::
// proto: // proto:
while (true) while (true)
{ {
if (iter == end) return false; if (iter == end)
return false;
if (*iter == ':') if (*iter == ':')
{ {
++iter; ++iter;
@@ -687,17 +745,20 @@ static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::
} }
// // // //
if (iter == end || *iter != '/') return false; if (iter == end || *iter != '/')
return false;
++iter; ++iter;
if (iter == end || *iter != '/') return false; if (iter == end || *iter != '/')
return false;
++iter; ++iter;
// (user@)? of id: http://user@[::1]/ // (user@)? of id: http://user@[::1]/
if (*iter != '[') { if (*iter != '[')
{
while (true) while (true)
{ {
if (iter == end || *iter == '/') return false; if (iter == end || *iter == '/')
return false;
if (*iter == '@') if (*iter == '@')
{ {
++iter; ++iter;
@@ -715,23 +776,30 @@ static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::
++iter; ++iter;
// fe80: ... // fe80: ...
if (iter == end || !(*iter == 'f' || *iter == 'F')) return false; if (iter == end || !(*iter == 'f' || *iter == 'F'))
return false;
++iter; ++iter;
if (iter == end || !(*iter == 'e' || *iter == 'E')) return false; if (iter == end || !(*iter == 'e' || *iter == 'E'))
return false;
++iter; ++iter;
if (iter == end || *iter != '8' ) return false; if (iter == end || *iter != '8')
return false;
++iter; ++iter;
if (iter == end || *iter != '0' ) return false; if (iter == end || *iter != '0')
return false;
++iter; ++iter;
if (iter == end || *iter != ':' ) return false; if (iter == end || *iter != ':')
return false;
++iter; ++iter;
while (true) while (true)
{ {
if (iter == end) break; if (iter == end)
break;
char c = *iter; char c = *iter;
bool valid = (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c >= '0' && c <= '9' || c == ':'; bool valid = (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c >= '0' && c <= '9' || c == ':';
if (!valid) break; if (!valid)
break;
++iter; ++iter;
} }
// potentially a scope ID // potentially a scope ID
@@ -739,30 +807,34 @@ static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::
auto endOfAddress = iter; auto endOfAddress = iter;
if (iter != end && *iter == '%') if (iter != end && *iter == '%')
{ {
while (true) { while (true)
if (iter == end) return false; {
if (*iter == ']') break; if (iter == end)
return false;
if (*iter == ']')
break;
++iter; ++iter;
} }
} }
// made it! // made it!
if (iter == end || *iter != ']') return false; if (iter == end || *iter != ']')
return false;
++iter; ++iter;
auto startOfRest = iter; auto startOfRest = iter;
*prefix = std::string(url.begin(),endOfPrefix); *prefix = std::string(url.begin(), endOfPrefix);
*suffix = std::string(startOfRest,url.end()); *suffix = std::string(startOfRest, url.end());
return true; return true;
} }
bool pipedal::RemapLinkLocalUrl( bool pipedal::RemapLinkLocalUrl(
const boost::asio::ip::address &boostAddress, const boost::asio::ip::address &boostAddress,
const std::string&url,std::string*outputUrl) const std::string &url, std::string *outputUrl)
{ {
std::string prefix, suffix; std::string prefix, suffix;
if (!parseForLinkLocalUrl(url,&prefix,&suffix)) return false; if (!parseForLinkLocalUrl(url, &prefix, &suffix))
return false;
boost::asio::ip::address_v6 addressV6 = boostAddress.to_v6(); boost::asio::ip::address_v6 addressV6 = boostAddress.to_v6();
@@ -772,5 +844,3 @@ bool pipedal::RemapLinkLocalUrl(
*outputUrl = SS(prefix << directAddress << suffix); *outputUrl = SS(prefix << directAddress << suffix);
return true; return true;
} }
+20 -1
View File
@@ -22,13 +22,32 @@
#include <string> #include <string>
#include <utility> #include <utility>
#include <boost/asio.hpp> #include <boost/asio.hpp>
namespace pipedal {
namespace pipedal {
enum class NetworkInterfaceType {
Loopback,
Ethernet,
WiFi,
WiFiDirect,
Other,
};
NetworkInterfaceType GetNetworkInterfaceType(const char*interfaceName);
inline NetworkInterfaceType GetNetworkInterfaceType(const std::string&interfaceName)
{
return GetNetworkInterfaceType(interfaceName.c_str());
}
std::string GetInterfaceIpv4Address(const std::string& interfaceName); std::string GetInterfaceIpv4Address(const std::string& interfaceName);
std::optional<std::string> GetWlanInterfaceName();
std::optional<std::string> GetWlanIpv4Address();
std::vector<std::string> GetEthernetIpv4Addresses(); std::vector<std::string> GetEthernetIpv4Addresses();
// bool IsLinkLocalAddress(const std::string &fromAddress); // bool IsLinkLocalAddress(const std::string &fromAddress);
std::string GetNonLinkLocalAddress(const std::string& fromAddress); std::string GetNonLinkLocalAddress(const std::string& fromAddress);
+3 -3
View File
@@ -100,10 +100,10 @@ PiPedalVersion::PiPedalVersion(PiPedalModel&model)
this->webAddresses_.push_back(MakeWebAddress(ethAddress,port)); this->webAddresses_.push_back(MakeWebAddress(ethAddress,port));
} }
// yyx: fix this for ubuntu. // yyx: fix this for ubuntu.
std::string wlanAddr = GetInterfaceIpv4Address("wlan0"); auto wlanAddr = GetWlanIpv4Address();
if (wlanAddr.length() != 0) if (wlanAddr)
{ {
this->webAddresses_.push_back(MakeWebAddress(wlanAddr,port)); this->webAddresses_.push_back(MakeWebAddress(*wlanAddr,port));
} }
std::string p2pAddr = GetInterfaceIpv4Address("p2p-wlan0-0"); std::string p2pAddr = GetInterfaceIpv4Address("p2p-wlan0-0");
+5 -5
View File
@@ -1419,16 +1419,16 @@ void WebServerImpl::DisplayIpAddresses()
Lv2Log::info(SS("Listening on " << ethAddress << ":" << this->port)); Lv2Log::info(SS("Listening on " << ethAddress << ":" << this->port));
} }
std::string wifiAddress = getIpv4Address("wlan0"); auto wifiAddress = GetWlanIpv4Address();
if (wifiAddress.length() != 0) if (wifiAddress)
{ {
if (wifiAddress == "10.42.0.1") if (*wifiAddress == "10.42.0.1")
{ {
Lv2Log::info(SS("Listening on Wi-Fi hotspot address " << wifiAddress << ":" << this->port)); Lv2Log::info(SS("Listening on Wi-Fi hotspot address " << *wifiAddress << ":" << this->port));
} }
else else
{ {
Lv2Log::info(SS("Listening on Wi-Fi address " << wifiAddress << ":" << this->port)); Lv2Log::info(SS("Listening on Wi-Fi address " << *wifiAddress << ":" << this->port));
} }
} }
} }