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);
|
||||
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>
|
||||
struct enable_if {
|
||||
|
||||
@@ -55,6 +55,13 @@ public:
|
||||
*/
|
||||
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.
|
||||
* Initializes this IPv6 address to "::"
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <vector>
|
||||
#include <stdint.h>
|
||||
#include "ip_address.h"
|
||||
#include "ipv6_address.h"
|
||||
#include "internals.h"
|
||||
|
||||
// Fix for Windows interface define on combaseapi.h
|
||||
@@ -89,6 +90,36 @@ struct RouteEntry {
|
||||
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.
|
||||
*
|
||||
@@ -176,6 +207,13 @@ void route_entries(ForwardIterator output);
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* \param data The input buffer.
|
||||
|
||||
@@ -49,15 +49,7 @@ IPv6Range operator/(const IPv6Address& addr, int mask) {
|
||||
if (mask > 128) {
|
||||
throw std::logic_error("Prefix length cannot exceed 128");
|
||||
}
|
||||
IPv6Address last_addr;
|
||||
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);
|
||||
return IPv6Range::from_mask(addr, IPv6Address::from_prefix_length(mask));
|
||||
}
|
||||
|
||||
} // Tins
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace Tins {
|
||||
namespace Internals {
|
||||
|
||||
bool from_hex(const string& str, uint32_t& result) {
|
||||
unsigned i(0);
|
||||
size_t i = 0;
|
||||
result = 0;
|
||||
while (i < str.size()) {
|
||||
uint8_t tmp;
|
||||
@@ -82,6 +82,29 @@ bool from_hex(const string& str, uint32_t& result) {
|
||||
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) {
|
||||
int c = 0;
|
||||
while (c != '\n' && input) {
|
||||
|
||||
@@ -52,6 +52,18 @@ namespace Tins {
|
||||
const IPv6Address loopback_address = "::1";
|
||||
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() {
|
||||
fill(address_, address_ + address_size, 0);
|
||||
}
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
#endif
|
||||
#else
|
||||
#include <winsock2.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#undef interface
|
||||
#endif
|
||||
#include "utils.h"
|
||||
@@ -191,6 +191,7 @@ HWAddress<6> resolve_hwaddr(IPv4Address ip, PacketSender& sender) {
|
||||
}
|
||||
|
||||
#if defined(BSD) || defined(__FreeBSD_kernel__)
|
||||
|
||||
vector<RouteEntry> route_entries() {
|
||||
vector<RouteEntry> output;
|
||||
vector<char> buffer = query_route_table();
|
||||
@@ -219,15 +220,14 @@ vector<RouteEntry> route_entries() {
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
vector<RouteEntry> route_entries() {
|
||||
vector<RouteEntry> output;
|
||||
MIB_IPFORWARDTABLE* table;
|
||||
MIB_IPFORWARDTABLE table;
|
||||
ULONG size = 0;
|
||||
GetIpForwardTable(0, &size, 0);
|
||||
vector<uint8_t> buffer(size);
|
||||
table = (MIB_IPFORWARDTABLE*)&buffer[0];
|
||||
GetIpForwardTable(table, &size, 0);
|
||||
GetIpForwardTable(AF_INET6, &table);
|
||||
|
||||
for (DWORD i = 0; i < table->dwNumEntries; i++) {
|
||||
MIB_IPFORWARDROW* row = &table->table[i];
|
||||
@@ -244,7 +244,34 @@ vector<RouteEntry> route_entries() {
|
||||
}
|
||||
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() {
|
||||
using namespace Tins::Internals;
|
||||
vector<RouteEntry> output;
|
||||
@@ -271,6 +298,44 @@ vector<RouteEntry> route_entries() {
|
||||
}
|
||||
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
|
||||
|
||||
bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) {
|
||||
|
||||
@@ -100,3 +100,9 @@ TEST(IPv6AddressTest, IsMulticast) {
|
||||
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