src/filtration/pcap/network_interfaces.h (200 lines of code) (raw):

//------------------------------------------------------------------------------ // Author: Pavel Karneliuk // Description: Enumerates list of network devices, available to use in libpcap. // Copyright (c) 2013 EPAM Systems //------------------------------------------------------------------------------ /* This file is part of Nfstrace. Nfstrace is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2 of the License. Nfstrace is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Nfstrace. If not, see <http://www.gnu.org/licenses/>. */ //------------------------------------------------------------------------------ #ifndef NETWORK_INTERFACES_H #define NETWORK_INTERFACES_H //------------------------------------------------------------------------------ #include <arpa/inet.h> #include <netinet/in.h> #include <pcap/pcap.h> #include <sys/socket.h> #include "filtration/pcap/pcap_error.h" #include "utils/noncopyable.h" //------------------------------------------------------------------------------ namespace NST { namespace filtration { namespace pcap { class NetworkInterfaces final : utils::noncopyable { public: class Interface; class Address final { friend class Interface; public: inline sockaddr* address() const noexcept { return addr->addr; } inline sockaddr* netmask() const noexcept { return addr->netmask; } inline sockaddr* broadaddr() const noexcept { return addr->broadaddr; } inline sockaddr* destaddr() const noexcept { return addr->dstaddr; } Address& operator=(const Address&) = delete; void operator&() = delete; void* operator new(size_t) = delete; void operator delete(void*) = delete; inline operator bool() const noexcept { return addr != nullptr; } inline void operator++() noexcept { addr = addr->next; } inline bool operator!=(const Address& a) const noexcept { return addr != a.addr; } inline const Address operator*() const noexcept { return *this; } Address(const Address& a) : addr{a.addr} { } private: Address(pcap_addr_t* a) : addr{a} { } pcap_addr_t* addr; }; class Interface final { friend class NetworkInterfaces; public: inline const char* name() const noexcept { return ptr->name; } inline const char* dscr() const noexcept { return ptr->description; } inline bool is_loopback() const noexcept { return ptr->flags & PCAP_IF_LOOPBACK; } Interface& operator=(const Interface&) = delete; void operator&() = delete; void* operator new(size_t) = delete; void operator delete(void*) = delete; inline operator bool() const noexcept { return ptr != nullptr; } inline void operator++() noexcept { ptr = ptr->next; } inline bool operator!=(const Interface& i) const noexcept { return ptr != i.ptr; } inline const Interface operator*() const noexcept { return *this; } Interface(const Interface& i) : ptr{i.ptr} { } const Address begin() const noexcept { return Address{ptr->addresses}; } const Address end() const noexcept { return Address{nullptr}; } private: Interface(pcap_if_t* p) : ptr{p} { } pcap_if_t* ptr; }; inline NetworkInterfaces() : interfaces{nullptr} { char errbuf[PCAP_ERRBUF_SIZE]; if(pcap_findalldevs(&interfaces, errbuf) == -1) { throw PcapError("pcap_findalldevs", errbuf); } } inline ~NetworkInterfaces() noexcept { pcap_freealldevs(interfaces); } inline static std::string default_device() { NST::filtration::pcap::NetworkInterfaces interfaces; for(const auto& interface : interfaces) { for(const auto& address : interface) { // Do not compare string for appropriate IP4/IP6 address. // If pointer to address is not null expect it has valid address. if(address.address() != nullptr) { return interface.name(); } } } throw std::runtime_error{"No suitable device found.\n Note: reading an ip address of a network device may require special privileges."}; } void operator&() = delete; void* operator new(size_t) = delete; void operator delete(void*) = delete; const Interface begin() const noexcept { return Interface{interfaces}; } const Interface end() const noexcept { return Interface{nullptr}; } private: pcap_if_t* interfaces; }; std::ostream& operator<<(std::ostream& out, const NetworkInterfaces::Interface& i) { out.width(8); out << std::left << i.name(); const char* dscr{i.dscr()}; if(dscr) { out << '(' << dscr << ')'; } if(i.is_loopback()) { out << "(loopback)"; } return out; } std::ostream& operator<<(std::ostream& out, const NetworkInterfaces::Address& a) { sockaddr* s_address{a.address()}; sockaddr* s_netmask{a.netmask()}; if(s_address) { switch(s_address->sa_family) { case AF_INET: { char ip[INET_ADDRSTRLEN]{}; char netmask[INET_ADDRSTRLEN]{}; inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(s_address)->sin_addr), ip, sizeof(ip)); out << "inet " << ip; inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(s_netmask)->sin_addr), netmask, sizeof(netmask)); out << " netmask " << netmask; sockaddr* s_broadaddr{a.broadaddr()}; if(s_broadaddr) { char broadaddr[INET_ADDRSTRLEN]{}; inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(s_broadaddr)->sin_addr), broadaddr, sizeof(broadaddr)); out << " broadcast " << broadaddr; } sockaddr* s_destaddr{a.destaddr()}; if(s_destaddr) { char destaddr[INET_ADDRSTRLEN]{}; inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(s_destaddr)->sin_addr), destaddr, sizeof(destaddr)); out << " destadrr " << destaddr; } break; } case AF_INET6: { char ip6[INET6_ADDRSTRLEN]{}; char netmask6[INET6_ADDRSTRLEN]{}; inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(s_address)->sin6_addr), ip6, sizeof(ip6)); out << "inet6 " << ip6; out << " scopeid " << std::showbase << std::hex << reinterpret_cast<sockaddr_in6*>(s_address)->sin6_scope_id << std::dec; inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(s_netmask)->sin6_addr), netmask6, sizeof(netmask6)); out << " netmask " << netmask6; break; } default: { out << "Unsupported address family(" << static_cast<uint32_t>(s_address->sa_family) << ')'; } } } return out; } } // namespace pcap } // namespace filtration } // namespace NST //------------------------------------------------------------------------------ #endif // NETWORK_INTERFACES_H //------------------------------------------------------------------------------