mirror of
https://github.com/mfontanini/libtins
synced 2026-01-23 02:35:57 +01:00
Add Utils::route6_entries
This commit is contained in:
@@ -108,6 +108,7 @@ private:
|
|||||||
|
|
||||||
void skip_line(std::istream& input);
|
void skip_line(std::istream& input);
|
||||||
bool from_hex(const std::string& str, uint32_t& result);
|
bool from_hex(const std::string& str, uint32_t& result);
|
||||||
|
bool from_hex(const std::string& str, std::string& result);
|
||||||
|
|
||||||
template<bool, typename T = void>
|
template<bool, typename T = void>
|
||||||
struct enable_if {
|
struct enable_if {
|
||||||
|
|||||||
@@ -55,6 +55,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
typedef const uint8_t* const_iterator;
|
typedef const uint8_t* const_iterator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Constructs an IPv6 address from a prefix length
|
||||||
|
*
|
||||||
|
* \param prefix_length The length of the prefix
|
||||||
|
*/
|
||||||
|
static IPv6Address from_prefix_length(uint32_t prefix_length);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Default constructor.
|
* \brief Default constructor.
|
||||||
* Initializes this IPv6 address to "::"
|
* Initializes this IPv6 address to "::"
|
||||||
|
|||||||
@@ -36,6 +36,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "ip_address.h"
|
#include "ip_address.h"
|
||||||
|
#include "ipv6_address.h"
|
||||||
#include "internals.h"
|
#include "internals.h"
|
||||||
|
|
||||||
// Fix for Windows interface define on combaseapi.h
|
// Fix for Windows interface define on combaseapi.h
|
||||||
@@ -89,6 +90,36 @@ struct RouteEntry {
|
|||||||
int metric;
|
int metric;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct that represents an entry the IPv6 routing table
|
||||||
|
*/
|
||||||
|
struct Route6Entry {
|
||||||
|
/**
|
||||||
|
* This interface's name.
|
||||||
|
*/
|
||||||
|
std::string interface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route entry's destination.
|
||||||
|
*/
|
||||||
|
IPv6Address destination;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route entry's subnet mask.
|
||||||
|
*/
|
||||||
|
IPv6Address mask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route entry's next hop.
|
||||||
|
*/
|
||||||
|
IPv6Address next_hop;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This route entry's metric.
|
||||||
|
*/
|
||||||
|
int metric;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Resolves a domain name and returns its corresponding ip address.
|
* \brief Resolves a domain name and returns its corresponding ip address.
|
||||||
*
|
*
|
||||||
@@ -176,6 +207,13 @@ void route_entries(ForwardIterator output);
|
|||||||
*/
|
*/
|
||||||
TINS_API std::vector<RouteEntry> route_entries();
|
TINS_API std::vector<RouteEntry> route_entries();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Retrieves entries in the routing table.
|
||||||
|
*
|
||||||
|
* \return a vector which contains all of the route entries.
|
||||||
|
*/
|
||||||
|
TINS_API std::vector<Route6Entry> route6_entries();
|
||||||
|
|
||||||
/** \brief Returns the 32 bit crc of the given buffer.
|
/** \brief Returns the 32 bit crc of the given buffer.
|
||||||
*
|
*
|
||||||
* \param data The input buffer.
|
* \param data The input buffer.
|
||||||
|
|||||||
@@ -49,15 +49,7 @@ IPv6Range operator/(const IPv6Address& addr, int mask) {
|
|||||||
if (mask > 128) {
|
if (mask > 128) {
|
||||||
throw std::logic_error("Prefix length cannot exceed 128");
|
throw std::logic_error("Prefix length cannot exceed 128");
|
||||||
}
|
}
|
||||||
IPv6Address last_addr;
|
return IPv6Range::from_mask(addr, IPv6Address::from_prefix_length(mask));
|
||||||
IPv6Address::iterator it = last_addr.begin();
|
|
||||||
while (mask > 8) {
|
|
||||||
*it = 0xff;
|
|
||||||
++it;
|
|
||||||
mask -= 8;
|
|
||||||
}
|
|
||||||
*it = 0xff << (8 - mask);
|
|
||||||
return IPv6Range::from_mask(addr, last_addr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // Tins
|
} // Tins
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace Tins {
|
|||||||
namespace Internals {
|
namespace Internals {
|
||||||
|
|
||||||
bool from_hex(const string& str, uint32_t& result) {
|
bool from_hex(const string& str, uint32_t& result) {
|
||||||
unsigned i(0);
|
size_t i = 0;
|
||||||
result = 0;
|
result = 0;
|
||||||
while (i < str.size()) {
|
while (i < str.size()) {
|
||||||
uint8_t tmp;
|
uint8_t tmp;
|
||||||
@@ -82,6 +82,29 @@ bool from_hex(const string& str, uint32_t& result) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool from_hex(const string& str, string& result) {
|
||||||
|
result = "";
|
||||||
|
for (size_t i = 0; i < str.size(); i+= 2) {
|
||||||
|
uint8_t value = 0;
|
||||||
|
for (size_t j = i; j < i + 2 && j < str.size(); ++j) {
|
||||||
|
if (str[j] >= 'A' && str[j] <= 'F') {
|
||||||
|
value = (value << 4) | (str[j] - 'A' + 10);
|
||||||
|
}
|
||||||
|
else if (str[j] >= 'a' && str[j] <= 'f') {
|
||||||
|
value = (value << 4) | (str[j] - 'a' + 10);
|
||||||
|
}
|
||||||
|
else if (str[j] >= '0' && str[j] <= '9') {
|
||||||
|
value = (value << 4) | (str[j] - '0');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.push_back(value);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void skip_line(std::istream& input) {
|
void skip_line(std::istream& input) {
|
||||||
int c = 0;
|
int c = 0;
|
||||||
while (c != '\n' && input) {
|
while (c != '\n' && input) {
|
||||||
|
|||||||
@@ -52,6 +52,18 @@ namespace Tins {
|
|||||||
const IPv6Address loopback_address = "::1";
|
const IPv6Address loopback_address = "::1";
|
||||||
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
const AddressRange<IPv6Address> multicast_range = IPv6Address("ff00::") / 8;
|
||||||
|
|
||||||
|
IPv6Address IPv6Address::from_prefix_length(uint32_t prefix_length) {
|
||||||
|
IPv6Address address;
|
||||||
|
IPv6Address::iterator it = address.begin();
|
||||||
|
while (prefix_length > 8) {
|
||||||
|
*it = 0xff;
|
||||||
|
++it;
|
||||||
|
prefix_length -= 8;
|
||||||
|
}
|
||||||
|
*it = 0xff << (8 - prefix_length);
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
IPv6Address::IPv6Address() {
|
IPv6Address::IPv6Address() {
|
||||||
fill(address_, address_ + address_size, 0);
|
fill(address_, address_ + address_size, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,8 +54,8 @@
|
|||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <iphlpapi.h>
|
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
#include <iphlpapi.h>
|
||||||
#undef interface
|
#undef interface
|
||||||
#endif
|
#endif
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
@@ -191,6 +191,7 @@ HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||||
|
|
||||||
vector<RouteEntry> route_entries() {
|
vector<RouteEntry> route_entries() {
|
||||||
vector<RouteEntry> output;
|
vector<RouteEntry> output;
|
||||||
vector<char> buffer = query_route_table();
|
vector<char> buffer = query_route_table();
|
||||||
@@ -219,15 +220,14 @@ vector<RouteEntry> route_entries() {
|
|||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
|
|
||||||
vector<RouteEntry> route_entries() {
|
vector<RouteEntry> route_entries() {
|
||||||
vector<RouteEntry> output;
|
vector<RouteEntry> output;
|
||||||
MIB_IPFORWARDTABLE* table;
|
MIB_IPFORWARDTABLE table;
|
||||||
ULONG size = 0;
|
ULONG size = 0;
|
||||||
GetIpForwardTable(0, &size, 0);
|
GetIpForwardTable(AF_INET6, &table);
|
||||||
vector<uint8_t> buffer(size);
|
|
||||||
table = (MIB_IPFORWARDTABLE*)&buffer[0];
|
|
||||||
GetIpForwardTable(table, &size, 0);
|
|
||||||
|
|
||||||
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||||
MIB_IPFORWARDROW* row = &table->table[i];
|
MIB_IPFORWARDROW* row = &table->table[i];
|
||||||
@@ -244,7 +244,34 @@ vector<RouteEntry> route_entries() {
|
|||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
vector<Route6Entry> route6_entries() {
|
||||||
|
vector<Route6Entry> output;
|
||||||
|
MIB_IPFORWARD_TABLE2* table;
|
||||||
|
GetIpForwardTable2(AF_INET6, &table);
|
||||||
|
for (ULONG i = 0; i < table->NumEntries; i++) {
|
||||||
|
MIB_IPFORWARD_ROW2* row = &table->Table[i];
|
||||||
|
if (true) {
|
||||||
|
try {
|
||||||
|
Route6Entry entry;
|
||||||
|
entry.interface = NetworkInterface::from_index(row->InterfaceIndex).name();
|
||||||
|
entry.destination = IPv6Address(row->DestinationPrefix.Prefix.Ipv6.sin6_addr.s6_addr);
|
||||||
|
entry.mask = IPv6Address::from_prefix_length(row->DestinationPrefix.PrefixLength);
|
||||||
|
entry.next_hop = IPv6Address(row->NextHop.Ipv6.sin6_addr.s6_addr);
|
||||||
|
entry.metric = row->Metric;
|
||||||
|
output.push_back(entry);
|
||||||
|
}
|
||||||
|
catch (invalid_interface&) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FreeMibTable(table);
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else // GNU/LINUX
|
||||||
|
|
||||||
vector<RouteEntry> route_entries() {
|
vector<RouteEntry> route_entries() {
|
||||||
using namespace Tins::Internals;
|
using namespace Tins::Internals;
|
||||||
vector<RouteEntry> output;
|
vector<RouteEntry> output;
|
||||||
@@ -271,6 +298,44 @@ vector<RouteEntry> route_entries() {
|
|||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<Route6Entry> route6_entries() {
|
||||||
|
using namespace Tins::Internals;
|
||||||
|
vector<Route6Entry> output;
|
||||||
|
ifstream input("/proc/net/ipv6_route");
|
||||||
|
string destination, mask_length, metric, next_hop, dummy, flags;
|
||||||
|
Route6Entry entry;
|
||||||
|
while (input >> destination >> mask_length) {
|
||||||
|
string temporary;
|
||||||
|
uint32_t temporary_int;
|
||||||
|
for (unsigned i(0); i < 2; ++i) {
|
||||||
|
input >> dummy;
|
||||||
|
}
|
||||||
|
input >> next_hop;
|
||||||
|
input >> metric;
|
||||||
|
for (unsigned i(0); i < 2; ++i) {
|
||||||
|
input >> dummy;
|
||||||
|
}
|
||||||
|
input >> flags >> entry.interface;
|
||||||
|
from_hex(destination, temporary);
|
||||||
|
entry.destination = IPv6Address((const uint8_t*)&temporary[0]);
|
||||||
|
from_hex(mask_length, temporary_int);
|
||||||
|
entry.mask = IPv6Address::from_prefix_length(temporary_int);
|
||||||
|
from_hex(next_hop, temporary);
|
||||||
|
entry.next_hop = IPv6Address((const uint8_t*)&temporary[0]);
|
||||||
|
from_hex(metric, temporary_int);
|
||||||
|
entry.metric = temporary_int;
|
||||||
|
// Process flags
|
||||||
|
from_hex(flags, temporary_int);
|
||||||
|
// Skip:
|
||||||
|
// * 0x01000000 -> cache entries
|
||||||
|
if ((temporary_int & 0x01000000) == 0) {
|
||||||
|
output.push_back(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
|
bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
|
||||||
|
|||||||
@@ -100,3 +100,9 @@ TEST(IPv6AddressTest, IsMulticast) {
|
|||||||
EXPECT_FALSE(IPv6Address("feaa::dead").is_multicast());
|
EXPECT_FALSE(IPv6Address("feaa::dead").is_multicast());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IPv6AddressTest, FromPrefixLength) {
|
||||||
|
EXPECT_EQ(IPv6Address("ffff:fe00::"), IPv6Address::from_prefix_length(23));
|
||||||
|
EXPECT_EQ(IPv6Address("ffff::"), IPv6Address::from_prefix_length(16));
|
||||||
|
EXPECT_EQ(IPv6Address("ffff:ffff::"), IPv6Address::from_prefix_length(32));
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user