diff --git a/include/tins/hw_address.h b/include/tins/hw_address.h index 240e7df..5715f8b 100644 --- a/include/tins/hw_address.h +++ b/include/tins/hw_address.h @@ -59,6 +59,9 @@ TINS_API bool hw_address_equal_compare(const uint8_t* start1, const uint8_t* end TINS_API bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1, const uint8_t* start2, const uint8_t* end2); +TINS_API bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1, + const uint8_t* start2, const uint8_t* end2); + /** * \endcond */ @@ -268,6 +271,39 @@ public: return Internals::hw_address_lt_compare(begin(), end(), rhs.begin(), rhs.end()); } + /** + * \brief Compares this HWAddress for less-than equality. + * + * \param rhs The HWAddress to be compared to. + * + * \return bool indicating whether this address is equal or less-than rhs. + */ + bool operator<=(const HWAddress& rhs) const { + return !operator>(rhs); + } + + /** + * \brief Compares this HWAddress for greater-than inequality. + * + * \param rhs The HWAddress to be compared to. + * + * \return bool indicating whether this address is greater-than rhs. + */ + bool operator>(const HWAddress& rhs) const { + return Internals::hw_address_gt_compare(begin(), end(), rhs.begin(), rhs.end()); + } + + /** + * \brief Compares this HWAddress for greater-than equality. + * + * \param rhs The HWAddress to be compared to. + * + * \return bool indicating whether this address is equal or greater-than rhs. + */ + bool operator>=(const HWAddress& rhs) const { + return !operator<(rhs); + } + /** * \brief Apply a mask to this address * @@ -281,7 +317,33 @@ public: } return output; } - + + /** + * \brief Apply a mask to this address + * + * \param mask The mask to be applied + * \return The result of applying the mask to this address + */ + HWAddress operator|(const HWAddress& mask) const { + HWAddress output = *this; + for (size_t i = 0; i < n; ++i) { + output[i] = output[i] | mask[i]; + } + return output; + } + + /** + * \brief not operator + * \return The result of applying the mask to this address + */ + HWAddress operator~() const { + HWAddress output = *this; + for (size_t i = 0; i < n; ++i) { + output[i] = ~output[i]; + } + return output; + } + /** * \brief Retrieves the size of this address. * diff --git a/include/tins/ip_address.h b/include/tins/ip_address.h index 8db32ec..5e6f6d1 100644 --- a/include/tins/ip_address.h +++ b/include/tins/ip_address.h @@ -135,6 +135,38 @@ public: return ip_addr_ < rhs.ip_addr_; } + /** + * \brief Compares this address for less-than equality. + * + * \param rhs The address to be compared to. + * + * \return bool indicating whether this address is equal or less-than rhs. + */ + bool operator<=(const IPv4Address& rhs) const { + return !operator>(rhs); + } + + /** + * \brief Compare this IPv4Address for greater-than inequality. + * + * \param rhs The address to be compared. + * \return bool indicating whether this address is greater-than rhs. + */ + bool operator>(const IPv4Address& rhs) const { + return ip_addr_ > rhs.ip_addr_; + } + + /** + * \brief Compares this address for greater-than equality. + * + * \param rhs The address to be compared to. + * + * \return bool indicating whether this address is equal or greater-than rhs. + */ + bool operator>=(const IPv4Address& rhs) const { + return !operator<(rhs); + } + /** * \brief Apply a mask to this address * @@ -142,6 +174,19 @@ public: * \return The result of applying the mask to this address */ IPv4Address operator&(const IPv4Address& mask) const; + + /** + * \brief Apply a mask to this address + * + * \param mask The mask to be applied + * \return The result of applying the mask to this address + */ + IPv4Address operator|(const IPv4Address& mask) const; + + /** + * not operator (invert) + */ + IPv4Address operator~() const; /** * \brief Returns true if this is a private IPv4 address. diff --git a/include/tins/ipv6_address.h b/include/tins/ipv6_address.h index 43d4995..553e38e 100644 --- a/include/tins/ipv6_address.h +++ b/include/tins/ipv6_address.h @@ -160,7 +160,40 @@ public: bool operator<(const IPv6Address& rhs) const { return std::lexicographical_compare(begin(), end(), rhs.begin(), rhs.end()); } - + + /** + * \brief Compares this address for less-than equality. + * + * \param rhs The address to be compared to. + * + * \return bool indicating whether this address is equal or less-than rhs. + */ + bool operator<=(const IPv6Address& rhs) const { + return !operator>(rhs); + } + + /** + * \brief Compares this address for greater-than inequality. + * + * \param rhs The address to be compared to. + * + * \return bool indicating whether this address is greater-than rhs. + */ + bool operator>(const IPv6Address& rhs) const { + return std::lexicographical_compare(rhs.begin(), rhs.end(), begin(), end()); + } + + /** + * \brief Compares this address for greater-than equality. + * + * \param rhs The address to be compared to. + * + * \return bool indicating whether this address is equal or greater-than rhs. + */ + bool operator>=(const IPv6Address& rhs) const { + return !operator<(rhs); + } + /** * \brief Helper function which copies the address into an output * iterator. @@ -218,7 +251,17 @@ public: /** * Applies a mask to an address */ - TINS_API friend IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs); + IPv6Address operator&(const IPv6Address& rhs) const; + + /** + * or a mask to an address + */ + IPv6Address operator|(const IPv6Address& rhs) const; + + /** + * not operator (invert) + */ + IPv6Address operator~() const ; private: void init(const char* addr); diff --git a/include/tins/network_interface.h b/include/tins/network_interface.h index 678ad4d..365000c 100644 --- a/include/tins/network_interface.h +++ b/include/tins/network_interface.h @@ -118,6 +118,17 @@ public: * \param ip The ip address being looked up. */ NetworkInterface(IPv4Address ip); + + + /** + * \brief Constructs a NetworkInterface from an ipv6 address. + * + * This abstracted interface will be the one that would be the gateway + * when sending a packet to the given ip. + * + * \param ip The ipv6 address being looked up. + */ + NetworkInterface(IPv6Address ipv6); /** * \brief Getter for this interface's identifier. diff --git a/include/tins/utils/routing_utils.h b/include/tins/utils/routing_utils.h index 199f363..9852d7e 100644 --- a/include/tins/utils/routing_utils.h +++ b/include/tins/utils/routing_utils.h @@ -110,6 +110,14 @@ struct Route6Entry { template void route_entries(ForwardIterator output); +/** + * \brief Retrieves entries in the routing table. + * + * \brief output ForwardIterator in which entries will be stored. + */ +template +void route6_entries(ForwardIterator output); + /** * \brief Retrieves entries in the routing table. * @@ -117,6 +125,7 @@ void route_entries(ForwardIterator output); */ TINS_API std::vector route_entries(); + /** * \brief Retrieves entries in the routing table. * @@ -146,6 +155,19 @@ TINS_API std::set network_interfaces(); */ TINS_API bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr); +/** + * \brief Finds the gateway's IP address for the given IP + * address. + * + * \param ip The IP address for which the default gateway will + * be searched. + * \param gw_addr This parameter will contain the gateway's IP + * address in case it is found. + * + * \return bool indicating whether the lookup was successfull. + */ +TINS_API bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr); + } // Utils } // Tins @@ -158,4 +180,13 @@ void Tins::Utils::route_entries(ForwardIterator output) { } } +template +void Tins::Utils::route6_entries(ForwardIterator output) { + std::vector entries = route6_entries(); + for (size_t i = 0; i < entries.size(); ++i) { + *output = entries[i]; + ++output; + } +} + #endif // TINS_ROUTING_UTILS_H diff --git a/src/hw_address.cpp b/src/hw_address.cpp index ce59d9a..9573f4b 100644 --- a/src/hw_address.cpp +++ b/src/hw_address.cpp @@ -113,5 +113,10 @@ bool hw_address_lt_compare(const uint8_t* start1, const uint8_t* end1, return lexicographical_compare(start1, end1, start2, end2); } +bool hw_address_gt_compare(const uint8_t* start1, const uint8_t* end1, + const uint8_t* start2, const uint8_t* end2) { + return lexicographical_compare(start2, end2, start1, end1); +} + } // Internals } // Tins diff --git a/src/ip_address.cpp b/src/ip_address.cpp index b5c2b23..a091429 100644 --- a/src/ip_address.cpp +++ b/src/ip_address.cpp @@ -153,4 +153,12 @@ IPv4Address IPv4Address::operator&(const IPv4Address& mask) const { return IPv4Address(Endian::be_to_host(ip_addr_ & mask.ip_addr_)); } +IPv4Address IPv4Address::operator|(const IPv4Address& mask) const { + return IPv4Address(Endian::be_to_host(ip_addr_ | mask.ip_addr_)); +} + +IPv4Address IPv4Address::operator~() const { + return IPv4Address(Endian::be_to_host(~ip_addr_)); +} + } // Tins diff --git a/src/ipv6_address.cpp b/src/ipv6_address.cpp index b28ba4f..cd2d7a3 100644 --- a/src/ipv6_address.cpp +++ b/src/ipv6_address.cpp @@ -142,13 +142,33 @@ ostream& operator<<(ostream& os, const IPv6Address& addr) { return os << addr.to_string(); } -IPv6Address operator&(const IPv6Address& lhs, const IPv6Address& rhs) { - IPv6Address output = lhs; - IPv6Address::iterator addr_iter = output.begin(); +IPv6Address IPv6Address::operator&(const IPv6Address& rhs) const { + IPv6Address result = *this; + IPv6Address::iterator addr_iter = result.begin(); for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) { *addr_iter = *addr_iter & *it; } - return output; + + return result; +} + +IPv6Address IPv6Address::operator|(const IPv6Address& rhs) const { + IPv6Address result = *this; + IPv6Address::iterator addr_iter = result.begin(); + for (IPv6Address::const_iterator it = rhs.begin(); it != rhs.end(); ++it, ++addr_iter) { + *addr_iter = *addr_iter | *it; + } + + return result; +} + +IPv6Address IPv6Address::operator~() const { + IPv6Address result = *this; + for (IPv6Address::iterator addr_iter = result.begin(); addr_iter != result.end(); ++addr_iter) { + *addr_iter = ~*addr_iter; + } + + return result; } } // Tins diff --git a/src/network_interface.cpp b/src/network_interface.cpp index 6ab5220..f48e522 100644 --- a/src/network_interface.cpp +++ b/src/network_interface.cpp @@ -257,6 +257,35 @@ NetworkInterface::NetworkInterface(IPv4Address ip) } } +NetworkInterface::NetworkInterface(IPv6Address ipv6) +: iface_id_(0) { + typedef vector entries_type; + + if (ipv6 == "::1") { + #if defined(BSD) || defined(__FreeBSD_kernel__) + iface_id_ = resolve_index("lo0"); + #else + iface_id_ = resolve_index("lo"); + #endif + } + else { + const Utils::Route6Entry* best_match = 0; + entries_type entries; + Utils::route6_entries(std::back_inserter(entries)); + for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) { + if ((ipv6 & it->mask) == it->destination) { + if (!best_match || it->mask > best_match->mask || it->metric < best_match->metric) { + best_match = &*it; + } + } + } + if (!best_match) { + throw invalid_interface(); + } + iface_id_ = resolve_index(best_match->interface.c_str()); + } +} + string NetworkInterface::name() const { #ifndef _WIN32 char iface_name[IF_NAMESIZE]; diff --git a/src/utils/routing_utils.cpp b/src/utils/routing_utils.cpp index a233bca..d107de8 100644 --- a/src/utils/routing_utils.cpp +++ b/src/utils/routing_utils.cpp @@ -439,5 +439,17 @@ bool gateway_from_ip(IPv4Address ip, IPv4Address& gw_addr) { return false; } +bool gateway_from_ip(IPv6Address ip, IPv6Address& gw_addr) { + typedef vector entries_type; + entries_type entries =route6_entries(); + for (entries_type::const_iterator it(entries.begin()); it != entries.end(); ++it) { + if ((ip & it->mask) == it->destination) { + gw_addr = it->gateway; + return true; + } + } + return false; +} + } // Utils } // Tins diff --git a/tests/src/hw_address_test.cpp b/tests/src/hw_address_test.cpp index 86b82cd..d924430 100644 --- a/tests/src/hw_address_test.cpp +++ b/tests/src/hw_address_test.cpp @@ -52,6 +52,7 @@ TEST_F(HWAddressTest, LessThanOperator) { HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff"; EXPECT_LT(addr2, addr1); EXPECT_LT(addr2, bcast); + EXPECT_LE(addr1, addr1); std::map, int> dict; dict[addr1] = 12; dict[addr2] = 15; @@ -59,6 +60,20 @@ TEST_F(HWAddressTest, LessThanOperator) { EXPECT_EQ(dict[addr2], 15); } +TEST_F(HWAddressTest, GreaterThanOperator) { + HWAddress<6> addr1(byte_address), addr2(empty_addr); + HWAddress<6> bcast = "ff:ff:ff:ff:ff:ff"; + EXPECT_GT(addr1, addr2); + EXPECT_GT(bcast, addr2); + EXPECT_GE(addr1, addr1); + std::map, int> dict; + dict[addr1] = 12; + dict[addr2] = 15; + EXPECT_EQ(dict[addr1], 12); + EXPECT_EQ(dict[addr2], 15); +} + + TEST_F(HWAddressTest, CopyConstructor) { HWAddress<6> addr1(byte_address), addr2(addr1); @@ -115,3 +130,18 @@ TEST_F(HWAddressTest, Mask) { address_type("de:ad:be:ef:00:00") & address_type("ff:ff:ff:f0:00:00") ); } + +TEST_F(HWAddressTest, OrMask) { + typedef HWAddress<6> address_type; + EXPECT_EQ( + address_type("ff:ff:ff:ff:fe:be"), + address_type("de:ad:be:ef:fe:be") | address_type("ff:ff:ff:f0:00:00") + ); +} + +TEST_F(HWAddressTest, NotMask) { + typedef HWAddress<6> address_type; + EXPECT_EQ( + address_type("00:00:00:0f:ff:ff"), ~address_type("ff:ff:ff:f0:00:00") + ); +} diff --git a/tests/src/ip_address_test.cpp b/tests/src/ip_address_test.cpp index 2be5701..db68666 100644 --- a/tests/src/ip_address_test.cpp +++ b/tests/src/ip_address_test.cpp @@ -47,8 +47,19 @@ TEST(IPAddressTest, LessThanOperator) { EXPECT_LT(addr1, "192.168.1.2"); EXPECT_LT(addr1, "192.168.0.226"); EXPECT_LT(addr1, "193.0.0.0"); + EXPECT_LE(addr1, addr2); } +TEST(IPAddressTest, GreaterThanOperator) { + IPv4Address addr1(ip_string), addr2(ip_string); + EXPECT_FALSE(addr1 < addr2); + EXPECT_GT(addr1, "192.167.1.2"); + EXPECT_GT(addr1, "192.167.0.226"); + EXPECT_GT(addr1, "191.0.0.0"); + EXPECT_GE(addr1, addr2); +} + + TEST(IPAddressTest, IsPrivate) { EXPECT_TRUE(IPv4Address("192.168.0.1").is_private()); EXPECT_TRUE(IPv4Address("192.168.133.7").is_private()); @@ -112,6 +123,26 @@ TEST(IPAddressTest, Mask) { ); } +TEST(IPAddressTest, OrMask) { + EXPECT_EQ( + IPv4Address("255.255.255.1"), + IPv4Address("192.168.100.1") | IPv4Address("255.255.255.0") + ); + EXPECT_EQ( + IPv4Address("255.255.1.2"), + IPv4Address("192.255.1.2") | IPv4Address("255.128.0.0") + ); +} + +TEST(IPAddressTest, NotMask) { + EXPECT_EQ( + IPv4Address("0.0.0.255"), ~IPv4Address("255.255.255.0") + ); + EXPECT_EQ( + IPv4Address("0.127.255.255"),~IPv4Address("255.128.0.0") + ); +} + TEST(IPv4AddressTest, Size) { EXPECT_EQ(4UL, IPv4Address("127.0.0.1").size()); EXPECT_EQ(4UL, IPv4Address().size()); diff --git a/tests/src/ipv6_address_test.cpp b/tests/src/ipv6_address_test.cpp index 5f8fa16..92d4791 100644 --- a/tests/src/ipv6_address_test.cpp +++ b/tests/src/ipv6_address_test.cpp @@ -70,6 +70,14 @@ TEST(IPv6AddressTest, LessThanOperator) { EXPECT_LT(IPv6Address("17f8::1"), IPv6Address("17f8:0::0:5")); EXPECT_LT(IPv6Address("::1"), IPv6Address("::5")); EXPECT_LT(IPv6Address("1::"), IPv6Address("2::")); + EXPECT_LE(IPv6Address("1::"), IPv6Address("1::")); +} + +TEST(IPv6AddressTest, GreaterThanOperator) { + EXPECT_GT(IPv6Address("17f8:0::0:5"), IPv6Address("17f8::1")); + EXPECT_GT(IPv6Address("::5"), IPv6Address("::1")); + EXPECT_GT(IPv6Address("2::"), IPv6Address("1::")); + EXPECT_GE(IPv6Address("2::"), IPv6Address("2::")); } TEST(IPv6AddressTest, OutputOperator) { @@ -124,6 +132,33 @@ TEST(IPv6AddressTest, MaskAddress) { ); } + +TEST(IPv6AddressTest, OrMaskAddress) { + EXPECT_EQ( + IPv6Address("ffff:ffff:adad:beef::"), + IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ffff::") + ); + EXPECT_EQ( + IPv6Address("ffff:ffef:adad:beef::"), + IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:ff00::") + ); + EXPECT_EQ( + IPv6Address("ffff:feef:adad:beef::"), + IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:f000::") + ); + EXPECT_EQ( + IPv6Address("ffff:feef:adad:beef::"), + IPv6Address("deaf:beef:adad:beef::") | IPv6Address("ffff:e000::") + ); +} + +TEST(IPv6AddressTest, NotMaskAddress) { + EXPECT_EQ(IPv6Address("::ffff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff::")); + EXPECT_EQ(IPv6Address("::ff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:ff00::")); + EXPECT_EQ(IPv6Address("::fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:f000::")); + EXPECT_EQ(IPv6Address("::1fff:ffff:ffff:ffff:ffff:ffff"),~IPv6Address("ffff:ffff:e000::")); +} + TEST(IPv6AddressTest, Size) { EXPECT_EQ(16UL, IPv6Address("dead:beef::1").size()); EXPECT_EQ(16UL, IPv6Address().size()); diff --git a/tests/src/network_interface_test.cpp b/tests/src/network_interface_test.cpp index ee0f21f..84b7e16 100644 --- a/tests/src/network_interface_test.cpp +++ b/tests/src/network_interface_test.cpp @@ -37,6 +37,8 @@ TEST_F(NetworkInterfaceTest, ConstructorFromString) { TEST_F(NetworkInterfaceTest, ConstructorFromIp) { NetworkInterface iface(IPv4Address("127.0.0.1")); EXPECT_EQ(iface.name(), iface_name); + NetworkInterface i6face(IPv6Address("::1")); + EXPECT_EQ(i6face.name(), iface_name); } TEST_F(NetworkInterfaceTest, Id) {