From: Guilherme Maciel Ferreira Date: Sat, 20 Aug 2011 04:16:50 +0000 (-0300) Subject: Bring aboard the Network Interface template class. X-Git-Tag: v1.1^2~12 X-Git-Url: http://developer.intra2net.com/git/?a=commitdiff_plain;h=bca40e6dbf405d11cdce3c62be93ffbfcbc25417;p=pingcheck Bring aboard the Network Interface template class. - It is a template because it uses the generic socket type, to avoid inheritances. - This template class hides much of the low level socket handling. --- diff --git a/src/host/networkinterface.hpp b/src/host/networkinterface.hpp new file mode 100644 index 0000000..53b543d --- /dev/null +++ b/src/host/networkinterface.hpp @@ -0,0 +1,165 @@ +/* + The software in this package is distributed under the GNU General + Public License version 2 (with a special exception described below). + + A copy of GNU General Public License (GPL) is included in this distribution, + in the file COPYING.GPL. + + As a special exception, if other files instantiate templates or use macros + or inline functions from this file, or you compile this file and link it + with other works to produce a work based on this file, this file + does not by itself cause the resulting work to be covered + by the GNU General Public License. + + However the source code for this file must still be made available + in accordance with section (3) of the GNU General Public License. + + This exception does not invalidate any other reasons why a work based + on this file might be covered by the GNU General Public License. + */ + +#ifndef NETWORK_INTERFACE_HPP +#define NETWORK_INTERFACE_HPP + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +#include + +//----------------------------------------------------------------------------- +// NetworkInterface +//----------------------------------------------------------------------------- + +/** + * @brief This class represents a local network interface. + */ +template +class NetworkInterface +{ +public: + + NetworkInterface( + const std::string &nic_name, + SocketType &socket + ); + + bool bind(); + + std::string get_name() const; + + uint32_t get_address(); + +private: + /// The network interface name which the socket is attached + const std::string Name; + /// The native socket descriptor + SocketType &Socket; + +}; + + +//----------------------------------------------------------------------------- +// NetworkInterface +//----------------------------------------------------------------------------- + +template +NetworkInterface::NetworkInterface( + const std::string &nic_name, + SocketType &socket +) : + Name( nic_name ), + Socket( socket ) +{ + BOOST_ASSERT( !nic_name.empty() ); +} + +/** + * @brief Avoid the socket to drop to another network interface if the + * destination is unreachable through the binded interface. Packets are + * sent only from this interface. + * + * @return true if the bind was successfully, and false if the bind failed. + */ +template +bool NetworkInterface::bind() +{ + BOOST_ASSERT( !Name.empty() ); + + int ret = ::setsockopt( + Socket.native(), + SOL_SOCKET, + SO_BINDTODEVICE, + Name.c_str(), + Name.size() + ); + if ( ret == -1 ) + { + I2n::Logger::GlobalLogger.error() + << "Error: could not bind pinger to interface " << Name << std::endl; + return false; + } + + return true; +} + +/** + * @brief Get the network interface name. + * + * @return A string representing the name of the network interface. + */ +template +std::string NetworkInterface::get_name() const +{ + return Name; +} + +/** + * @brief This method gets the local address of network interface. + * + * @return The integer IP representing the local address of the network + * interface. + */ +template +uint32_t NetworkInterface::get_address() +{ + struct ifreq ifr; + memset( &ifr, 0, sizeof(ifr) ); + + // make sure the ifr.ifr_name has enough room to receive the network + // interface name + size_t network_interface_name_limit = sizeof(ifr.ifr_name); + if ( network_interface_name_limit <= Name.size() ) + { + I2n::Logger::GlobalLogger.error() + << "Error: network interface name truncated" << std::endl; + return 0; + } + + strncpy( ifr.ifr_name, Name.c_str(), network_interface_name_limit ); + ifr.ifr_addr.sa_family = AF_INET; // TODO change to AF_INET6 when IPv6 + + int ioctl_resp = ioctl( Socket.native(), SIOCGIFADDR, &ifr ); + if ( ioctl_resp != 0) + { + I2n::Logger::GlobalLogger.error() + << "Error: could not retrieve IP address from network interface" + << std::endl; + return 0; + } + + const sockaddr_in *source_sockaddr = reinterpret_cast( &ifr.ifr_addr ); + uint32_t source_ipv4_address = htonl( source_sockaddr->sin_addr.s_addr ); + + return source_ipv4_address; +} + +#endif // NETWORK_INTERFACE_HPP