/* Copyright (c) 2017, Andrei Kurushin Copyright (c) 2005-2007, 2009-2010, 2013, 2015-2017, 2019-2020, Arvid Norberg Copyright (c) 2016-2018, 2020, Alden Torres All rights reserved. You may use, distribute and modify this code under the terms of the BSD license, see LICENSE file. */ #ifndef TORRENT_IP_FILTER_HPP #define TORRENT_IP_FILTER_HPP #include "libtorrent/config.hpp" #include #include #include #include #include #include "libtorrent/address.hpp" namespace libtorrent { template struct ip_range { Addr first; Addr last; std::uint32_t flags; friend bool operator==(ip_range const& lhs, ip_range const& rhs) { return lhs.first == rhs.first && lhs.last == rhs.last && lhs.flags == rhs.flags; } }; namespace aux { template TORRENT_EXTRA_EXPORT Addr zero(); template TORRENT_EXTRA_EXPORT Addr plus_one(Addr const& a); template TORRENT_EXTRA_EXPORT Addr minus_one(Addr const& a); template TORRENT_EXTRA_EXPORT Addr max_addr(); extern template address_v4::bytes_type minus_one(address_v4::bytes_type const&); extern template address_v6::bytes_type minus_one(address_v6::bytes_type const&); extern template address_v4::bytes_type plus_one(address_v4::bytes_type const&); extern template address_v6::bytes_type plus_one(address_v6::bytes_type const&); extern template address_v4::bytes_type zero(); extern template address_v6::bytes_type zero(); extern template address_v4::bytes_type max_addr(); extern template address_v6::bytes_type max_addr(); inline std::uint16_t plus_one(std::uint16_t val) { return val + 1; } inline std::uint16_t minus_one(std::uint16_t val) { return val - 1; } template<> inline std::uint16_t zero() { return 0; } template<> inline std::uint16_t max_addr() { return (std::numeric_limits::max)(); } // this is the generic implementation of // a filter for a specific address type. // it works with IPv4 and IPv6 template class filter_impl { public: filter_impl(); bool empty() const; void add_rule(Addr first, Addr last, std::uint32_t flags); std::uint32_t access(Addr const& addr) const; template std::vector> export_filter() const; private: struct range { range(Addr addr, std::uint32_t a = 0) : start(addr), access(a) {} // NOLINT bool operator<(range const& r) const { return start < r.start; } bool operator<(Addr const& a) const { return start < a; } Addr start; // the end of the range is implicit // and given by the next entry in the set std::uint32_t access; friend bool operator==(range const& lhs, range const& rhs) { return lhs.start == rhs.start && lhs.access == rhs.access; } }; std::set m_access_list; }; extern template class filter_impl; extern template class filter_impl; extern template class filter_impl; extern template std::vector> filter_impl::export_filter() const; extern template std::vector> filter_impl::export_filter() const; extern template std::vector> filter_impl::export_filter() const; } // The ``ip_filter`` class is a set of rules that uniquely categorizes all // ip addresses as allowed or disallowed. The default constructor creates // a single rule that allows all addresses (0.0.0.0 - 255.255.255.255 for // the IPv4 range, and the equivalent range covering all addresses for the // IPv6 range). // // A default constructed ip_filter does not filter any address. struct TORRENT_EXPORT ip_filter { ip_filter(); ip_filter(ip_filter const&); ip_filter(ip_filter&&) noexcept; ip_filter& operator=(ip_filter const&); ip_filter& operator=(ip_filter&&) noexcept; ~ip_filter(); // the flags defined for an IP range enum access_flags { // indicates that IPs in this range should not be connected // to nor accepted as incoming connections blocked = 1 }; // returns true if the filter does not contain any rules bool empty() const; // Adds a rule to the filter. ``first`` and ``last`` defines a range of // ip addresses that will be marked with the given flags. The ``flags`` // can currently be 0, which means allowed, or ``ip_filter::blocked``, which // means disallowed. // // precondition: // ``first.is_v4() == last.is_v4() && first.is_v6() == last.is_v6()`` // // postcondition: // ``access(x) == flags`` for every ``x`` in the range [``first``, ``last``] // // This means that in a case of overlapping ranges, the last one applied takes // precedence. void add_rule(address const& first, address const& last, std::uint32_t flags); // Returns the access permissions for the given address (``addr``). The permission // can currently be 0 or ``ip_filter::blocked``. The complexity of this operation // is O(``log`` n), where n is the minimum number of non-overlapping ranges to describe // the current filter. std::uint32_t access(address const& addr) const; using filter_tuple_t = std::tuple> , std::vector>>; // This function will return the current state of the filter in the minimum number of // ranges possible. They are sorted from ranges in low addresses to high addresses. Each // entry in the returned vector is a range with the access control specified in its // ``flags`` field. // // The return value is a tuple containing two range-lists. One for IPv4 addresses // and one for IPv6 addresses. filter_tuple_t export_filter() const; private: aux::filter_impl m_filter4; aux::filter_impl m_filter6; }; // the port filter maps non-overlapping port ranges to flags. This // is primarily used to indicate whether a range of ports should // be connected to or not. The default is to have the full port // range (0-65535) set to flag 0. class TORRENT_EXPORT port_filter { public: port_filter(); port_filter(port_filter const&); port_filter(port_filter&&); port_filter& operator=(port_filter const&); port_filter& operator=(port_filter&&); ~port_filter(); // the defined flags for a port range enum access_flags { // this flag indicates that destination ports in the // range should not be connected to blocked = 1 }; // set the flags for the specified port range (``first``, ``last``) to // ``flags`` overwriting any existing rule for those ports. The range // is inclusive, i.e. the port ``last`` also has the flag set on it. void add_rule(std::uint16_t first, std::uint16_t last, std::uint32_t flags); // test the specified port (``port``) for whether it is blocked // or not. The returned value is the flags set for this port. // see access_flags. std::uint32_t access(std::uint16_t port) const; private: aux::filter_impl m_filter; }; } #endif