1
0
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:
Matias Fontanini
2016-03-06 19:18:33 -08:00
parent c082dfad67
commit 4dcef0f15d
8 changed files with 161 additions and 17 deletions

View File

@@ -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 {

View File

@@ -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 "::"

View File

@@ -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.

View File

@@ -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

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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));
}