Skip to content

Commit

Permalink
Support for Ubuntu iwlN wifi devices.
Browse files Browse the repository at this point in the history
  • Loading branch information
rerdavies committed Nov 25, 2024
1 parent 8787073 commit 7651bc9
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 65 deletions.
2 changes: 1 addition & 1 deletion src/HotspotManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,7 +383,7 @@ void HotspotManagerImpl::onStartMonitoring()
wlanDevice = GetDevice(NM_DEVICE_TYPE_WIFI);
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());

Expand Down
182 changes: 126 additions & 56 deletions src/Ipv6Helpers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@
#include <regex>
#include "ss.hpp"
#include "Finally.hpp"
#include <boost/asio.hpp>

using namespace pipedal;


static bool IsIpv4MappedAddress(const struct in6_addr &inetAddr6)
{
return IN6_IS_ADDR_V4MAPPED(&inetAddr6) != 0;
Expand Down Expand Up @@ -62,6 +62,71 @@ static bool ipv6NetmaskCompare(const struct in6_addr &left, const struct in6_add
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)
{
bool result = false;
Expand Down Expand Up @@ -267,16 +332,17 @@ bool pipedal::IsOnLocalSubnet(const std::string &fromAddress)
return result;
}


static bool isEthernetAddress(const char*ifName)
static bool isEthernetAddress(const char *ifName)
{
// either ethN (classic),
if (strncmp(ifName,"eth",3) == 0) return true;
// either ethN (classic),
if (strncmp(ifName, "eth", 3) == 0)
return true;
// 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;

struct ifaddrs *ifap = nullptr;
Expand All @@ -289,15 +355,12 @@ std::vector<std::string> pipedal::GetEthernetIpv4Addresses() {
{
if (p->ifa_addr->sa_family == AF_INET && p->ifa_addr != nullptr && p->ifa_netmask != nullptr)
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(
((ifAddr >> 24) & 0xFF) <<
'.' << ((ifAddr >> 16) & 0xFF) <<
'.' << ((ifAddr >> 8) & 0xFF) <<
'.' << ((ifAddr) & 0xFF)
);
((ifAddr >> 24) & 0xFF) << '.' << ((ifAddr >> 16) & 0xFF) << '.' << ((ifAddr >> 8) & 0xFF) << '.' << ((ifAddr) & 0xFF));
result.push_back(std::move(name));
}
}
Expand Down Expand Up @@ -365,9 +428,10 @@ static std::string GetNonLinkLocalAddress(const boost::asio::ip::address_v6 &ipV
if (getifaddrs(&ifap) != 0)
throw std::runtime_error("No networks available.");

Finally f{[ifap]() {
freeifaddrs(ifap);
}};
Finally f{[ifap]()
{
freeifaddrs(ifap);
}};

std::string result;

Expand Down Expand Up @@ -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 (strcmp(p->ifa_name,targetInterfaceName) == 0)
if (strcmp(p->ifa_name, targetInterfaceName) == 0)
{
constexpr int BUFSIZE = 128;
char host[BUFSIZE];
Expand All @@ -421,14 +485,13 @@ static std::string GetNonLinkLocalAddress(const boost::asio::ip::address_v6 &ipV
{
char buffer[128];
inet_ntop(AF_INET6, &(pAddr->sin6_addr),
buffer,sizeof(buffer));
buffer, sizeof(buffer));
return SS('[' << buffer << ']');
}
}
}
// probably network address settling after the hotspot comes up. :-/
throw std::runtime_error("Not ready. Try again later.");

}

static std::string GetNonLinkLocalAddressForInterface(const std::string &name)
Expand Down Expand Up @@ -583,7 +646,6 @@ static std::string GetNonLinkLocalAddressForIp4Interface(const std::string &name
// else
// {


// std::string interfaceName = GetInterfaceForIp6Address(inetAddr6);
// result = GetNonLinkLocalAddressForInterface(interfaceName);
// }
Expand All @@ -596,7 +658,6 @@ static std::string GetNonLinkLocalAddressForIp4Interface(const std::string &name
// return result;
// }


std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
{
std::string address = fromAddress;
Expand All @@ -612,12 +673,11 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
throw std::invalid_argument("Bad address.");
address = address.substr(1, address.length() - 2);

auto nPos = address.find('%') ;
auto nPos = address.find('%');
if (nPos != std::string::npos)
{
std::string ifName = address.substr(nPos+1);
std::string ifName = address.substr(nPos + 1);
return GetNonLinkLocalAddressForInterface(ifName);

}
struct in6_addr inetAddr6;
memset(&inetAddr6, 0, sizeof(inetAddr6));
Expand All @@ -639,9 +699,8 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
else
{


std::string interfaceName = GetInterfaceForIp6Address(inetAddr6);
result = GetNonLinkLocalAddressForInterface(interfaceName);
result = GetNonLinkLocalAddressForInterface(interfaceName);
}
}
}
Expand All @@ -652,13 +711,11 @@ std::string pipedal::GetNonLinkLocalAddress(const std::string &fromAddress)
return result;
}

std::string pipedal::GetInterfaceIpv4Address(const std::string& interfaceName)
std::string pipedal::GetInterfaceIpv4Address(const std::string &interfaceName)
{
return GetNonLinkLocalAddressForIp4Interface(interfaceName);
}



// std::string getNonLinkLocalAddress(const std::string&address, const std::string&interface)
// {
// if (!interface.empty())
Expand All @@ -669,15 +726,16 @@ 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 end = url.end();

// proto:
while (true)
{
if (iter == end) return false;
if (iter == end)
return false;
if (*iter == ':')
{
++iter;
Expand All @@ -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;
if (iter == end || *iter != '/') return false;
if (iter == end || *iter != '/')
return false;
++iter;


// (user@)? of id: http://user@[::1]/
if (*iter != '[') {
if (*iter != '[')
{
while (true)
{
if (iter == end || *iter == '/') return false;
if (iter == end || *iter == '/')
return false;
if (*iter == '@')
{
++iter;
Expand All @@ -715,62 +776,71 @@ static bool parseForLinkLocalUrl(const std::string&url,std::string*prefix, std::
++iter;

// fe80: ...
if (iter == end || !(*iter == 'f' || *iter == 'F')) return false;
if (iter == end || !(*iter == 'f' || *iter == 'F'))
return false;
++iter;
if (iter == end || !(*iter == 'e' || *iter == 'E')) return false;
if (iter == end || !(*iter == 'e' || *iter == 'E'))
return false;
++iter;
if (iter == end || *iter != '8' ) return false;
if (iter == end || *iter != '8')
return false;
++iter;
if (iter == end || *iter != '0' ) return false;
if (iter == end || *iter != '0')
return false;
++iter;
if (iter == end || *iter != ':' ) return false;
if (iter == end || *iter != ':')
return false;
++iter;

while (true)
{
if (iter == end) break;
if (iter == end)
break;
char c = *iter;
bool valid = (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') || c >= '0' && c <= '9' || c == ':';
if (!valid) break;
if (!valid)
break;
++iter;
}
// potentially a scope ID
// [::1%wlan0]
auto endOfAddress = iter;
if (iter != end && *iter == '%')
{
while (true) {
if (iter == end) return false;
if (*iter == ']') break;
while (true)
{
if (iter == end)
return false;
if (*iter == ']')
break;
++iter;
}
}
// made it!
if (iter == end || *iter != ']') return false;
if (iter == end || *iter != ']')
return false;
++iter;

auto startOfRest = iter;

*prefix = std::string(url.begin(),endOfPrefix);
*suffix = std::string(startOfRest,url.end());
*prefix = std::string(url.begin(), endOfPrefix);
*suffix = std::string(startOfRest, url.end());
return true;

}
bool pipedal::RemapLinkLocalUrl(
const boost::asio::ip::address &boostAddress,
const std::string&url,std::string*outputUrl)
const std::string &url, std::string *outputUrl)
{

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();

std::string directAddress;
directAddress = ::GetNonLinkLocalAddress(addressV6);

*outputUrl = SS(prefix << directAddress << suffix);
*outputUrl = SS(prefix << directAddress << suffix);
return true;
}


Loading

0 comments on commit 7651bc9

Please sign in to comment.