Implement ethernet address determination

This commit is contained in:
RipleyTom 2020-10-11 05:02:33 +02:00 committed by Ivan
parent 1393bb2caf
commit 9e14d240a8
6 changed files with 118 additions and 7 deletions

View file

@ -16,14 +16,21 @@
#ifdef _WIN32
#include <winsock2.h>
#include <WS2tcpip.h>
#include <iphlpapi.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#endif
#ifdef __FreeBSD__
#include <ifaddrs.h>
#include <net/if_dl.h>
#endif
LOG_CHANNEL(sys_net);
LOG_CHANNEL(sceNp2);
LOG_CHANNEL(sceNp);
@ -47,6 +54,13 @@ np_handler::np_handler()
is_psn_active = false;
}
if (!discover_ether_address())
{
nph_log.error("Failed to discover ethernet address!");
is_connected = false;
is_psn_active = false;
}
// Convert dns address
// TODO: recover actual user dns through OS specific API
in_addr conv{};
@ -113,9 +127,97 @@ bool np_handler::discover_ip_address()
// Set public address to local discovered address for now, may be updated later;
public_ip_addr = local_ip_addr;
nph_log.notice("IP was determined to be %s", ip_to_string(local_ip_addr));
return true;
}
bool np_handler::discover_ether_address()
{
#ifdef __FreeBSD__
ifaddrs* ifap;
if (getifaddrs(&ifap) == 0)
{
ifaddrs* p;
for (p = ifap; p; p = p->ifa_next)
{
if (p->ifa_addr->sa_family == AF_LINK)
{
sockaddr_dl* sdp = reinterpret_cast<sockaddr_dl*>(p->ifa_addr);
memcpy(ether_address.data(), sdp->sdl_data + sdp->sdl_nlen, 6);
freeifaddrs(ifap);
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
return true;
}
}
freeifaddrs(ifap);
}
#elif defined(_WIN32)
std::vector<u8> adapter_infos(sizeof(IP_ADAPTER_INFO));
ULONG size_infos = sizeof(IP_ADAPTER_INFO);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == ERROR_BUFFER_OVERFLOW)
adapter_infos.resize(size_infos);
if (GetAdaptersInfo(reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data()), &size_infos) == NO_ERROR && size_infos)
{
PIP_ADAPTER_INFO info = reinterpret_cast<PIP_ADAPTER_INFO>(adapter_infos.data());
memcpy(ether_address.data(), info[0].Address, 6);
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
return true;
}
#else
ifreq ifr;
ifconf ifc;
char buf[1024];
int success = 0;
int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_IP);
if (sock == -1)
return false;
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, &ifc) == -1)
return false;
ifreq* it = ifc.ifc_req;
const ifreq* const end = it + (ifc.ifc_len / sizeof(ifreq));
for (; it != end; ++it)
{
strcpy(ifr.ifr_name, it->ifr_name);
if (ioctl(sock, SIOCGIFFLAGS, &ifr) == 0)
{
if (!(ifr.ifr_flags & IFF_LOOPBACK))
{
if (ioctl(sock, SIOCGIFHWADDR, &ifr) == 0)
{
success = 1;
break;
}
}
}
}
if (success)
{
memcpy(ether_address.data(), ifr.ifr_hwaddr.sa_data, 6);
nph_log.notice("Determined Ethernet address to be %s", ether_to_string(ether_address));
return true;
}
#endif
return false;
}
const std::array<u8, 6>& np_handler::get_ether_addr() const
{
return ether_address;
}
u32 np_handler::get_local_ip_addr() const
{
return local_ip_addr;
@ -172,6 +274,11 @@ std::string np_handler::ip_to_string(u32 ip_addr)
return result;
}
std::string np_handler::ether_to_string(std::array<u8, 6>& ether)
{
return fmt::format("%02X:%02X:%02X:%02X:%02X:%02X", ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
}
void np_handler::string_to_npid(const char* str, SceNpId* npid)
{
strncpy(npid->handle.data, str, sizeof(npid->handle.data));