1
0
mirror of https://github.com/mfontanini/libtins synced 2026-01-23 02:35:57 +01:00

Add IPv6 addresses to NetworkInterface::Info

This commit is contained in:
Matias Fontanini
2016-03-02 21:13:50 -08:00
parent 186d23c920
commit ad71158268
3 changed files with 90 additions and 35 deletions

View File

@@ -29,12 +29,14 @@
#include <string>
#include <iostream>
#include <sstream>
#include <tins/network_interface.h>
using std::cout;
using std::wcout;
using std::endl;
using std::string;
using std::ostringstream;
using namespace Tins;
@@ -59,11 +61,27 @@ int main() {
#endif // _WIN32
cout << ": " << endl;
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
string ipv6_string;
if (info.ipv6_addrs.empty()) {
ipv6_string = "(none)";
}
else {
ostringstream oss;
for (size_t i = 0; i < info.ipv6_addrs.size(); ++i) {
const NetworkInterface::IPv6AddressPrefix& prefix = info.ipv6_addrs[i];
if (i > 0) {
oss << ", ";
}
oss << prefix.address << "/" << prefix.prefix_length;
}
ipv6_string = oss.str();
}
cout << " HW address: " << info.hw_addr << endl
<< " IP address: " << info.ip_addr << endl
<< " IPv6 addresses: " << ipv6_string << endl
<< " Netmask: " << info.netmask << endl
<< " Broadcast: " << info.bcast_addr << endl
<< " Iface index: " << iface.id() << endl
<< " Status: " << "interface " << status << endl << endl;
}
}

View File

@@ -36,6 +36,7 @@
#include "macros.h"
#include "hw_address.h"
#include "ip_address.h"
#include "ipv6_address.h"
namespace Tins {
@@ -55,11 +56,20 @@ public:
*/
typedef HWAddress<6> address_type;
/**
*
*/
struct IPv6AddressPrefix {
IPv6Address address;
uint32_t prefix_length;
};
/**
* \brief Struct that holds an interface's addresses.
*/
struct Info {
IPv4Address ip_addr, netmask, bcast_addr;
std::vector<IPv6AddressPrefix> ipv6_addrs;
address_type hw_addr;
bool is_up;
};

View File

@@ -45,6 +45,7 @@
#include <net/if.h>
#else
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#undef interface
#endif
@@ -75,37 +76,32 @@ struct InterfaceInfoCollector {
using Tins::Endian::host_to_be;
using Tins::IPv4Address;
#if defined(BSD) || defined(__FreeBSD_kernel__)
#define TINS_BROADCAST_ADDR(addr) (addr->ifa_dstaddr)
const struct sockaddr_dl* addr_ptr = ((struct sockaddr_dl*)addr->ifa_addr);
if (addr->ifa_addr->sa_family == AF_LINK && addr_ptr->sdl_index == iface_id) {
info->hw_addr = (const uint8_t*)LLADDR(addr_ptr);
found_hw = true;
}
else if (addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
if ((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT))) {
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_dstaddr)->sin_addr.s_addr);
}
else {
info->bcast_addr = 0;
}
info->is_up = (addr->ifa_flags & IFF_UP);
found_ip = true;
}
#else
#define TINS_BROADCAST_ADDR(addr) (addr->ifa_broadaddr)
const struct sockaddr_ll* addr_ptr = ((struct sockaddr_ll*)addr->ifa_addr);
if (addr->ifa_addr) {
if (addr->ifa_addr->sa_family == AF_PACKET && addr_ptr->sll_ifindex == iface_id) {
info->hw_addr = addr_ptr->sll_addr;
found_hw = true;
}
else if (addr->ifa_addr->sa_family == AF_INET && !std::strcmp(addr->ifa_name, iface_name)) {
if (!addr->ifa_addr) {
return false;
}
if (addr->ifa_addr->sa_family == AF_PACKET && addr_ptr->sll_ifindex == iface_id) {
info->hw_addr = addr_ptr->sll_addr;
found_hw = true;
}
#endif
else if (!std::strcmp(addr->ifa_name, iface_name)) {
if (addr->ifa_addr->sa_family == AF_INET) {
info->ip_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_addr)->sin_addr.s_addr);
info->netmask = IPv4Address(((struct sockaddr_in *)addr->ifa_netmask)->sin_addr.s_addr);
if ((addr->ifa_flags & (IFF_BROADCAST | IFF_POINTOPOINT))) {
info->bcast_addr = IPv4Address(((struct sockaddr_in *)addr->ifa_broadaddr)->sin_addr.s_addr);
info->bcast_addr = IPv4Address(
((struct sockaddr_in *)TINS_BROADCAST_ADDR(addr))->sin_addr.s_addr);
}
else {
info->bcast_addr = 0;
@@ -113,9 +109,29 @@ struct InterfaceInfoCollector {
info->is_up = (addr->ifa_flags & IFF_UP);
found_ip = true;
}
else if (addr->ifa_addr->sa_family == AF_INET6) {
Tins::NetworkInterface::IPv6AddressPrefix prefix;
prefix.address = ((struct sockaddr_in6 *)addr->ifa_addr)->sin6_addr.s6_addr;
Tins::IPv6Address mask = ((struct sockaddr_in6 *)addr->ifa_netmask)->sin6_addr.s6_addr;
prefix.prefix_length = 0;
for (Tins::IPv6Address::iterator iter = mask.begin(); iter != mask.end(); ++iter) {
if (*iter == 255) {
prefix.prefix_length += 8;
}
else {
uint8_t current_value = 128;
while (*iter > 0) {
prefix.prefix_length += 1;
*iter &= ~current_value;
current_value /= 2;
}
break;
}
}
info->ipv6_addrs.push_back(prefix);
}
}
#endif
#undef TINS_BROADCAST_ADDR
return found_ip && found_hw;
}
#else // _WIN32
@@ -124,14 +140,25 @@ struct InterfaceInfoCollector {
using Tins::Endian::host_to_be;
if (iface_id == uint32_t(iface->IfIndex)) {
copy(iface->PhysicalAddress, iface->PhysicalAddress + 6, info->hw_addr.begin());
const IP_ADAPTER_UNICAST_ADDRESS* unicast = iface->FirstUnicastAddress;
if (unicast) {
info->ip_addr = IPv4Address(((const struct sockaddr_in *)unicast->Address.lpSockaddr)->sin_addr.s_addr);
info->netmask = IPv4Address(host_to_be<uint32_t>(0xffffffff << (32 - unicast->OnLinkPrefixLength)));
info->bcast_addr = IPv4Address((info->ip_addr & info->netmask) | ~info->netmask);
info->is_up = (iface->Flags & IP_ADAPTER_IPV4_ENABLED) != 0;
found_ip = true;
found_hw = true;
found_hw = true;
IP_ADAPTER_UNICAST_ADDRESS* unicast = iface->FirstUnicastAddress;
while (unicast) {
int family = ((const struct sockaddr*)unicast->Address.lpSockaddr)->sa_family;
if (family == AF_INET) {
info->ip_addr = IPv4Address(((const struct sockaddr_in *)unicast->Address.lpSockaddr)->sin_addr.s_addr);
info->netmask = IPv4Address(host_to_be<uint32_t>(0xffffffff << (32 - unicast->OnLinkPrefixLength)));
info->bcast_addr = IPv4Address((info->ip_addr & info->netmask) | ~info->netmask);
info->is_up = (iface->Flags & IP_ADAPTER_IPV4_ENABLED) != 0;
found_ip = true;
}
else if (family == AF_INET6) {
Tins::NetworkInterface::IPv6AddressPrefix prefix;
prefix.address = ((const struct sockaddr_in6 *)unicast->Address.lpSockaddr)->sin6_addr.s6_addr;
prefix.prefix_length = unicast->OnLinkPrefixLength;
info->ipv6_addrs.push_back(prefix);
found_ip = true;
}
unicast = unicast->Next;
}
}
return found_ip && found_hw;