--- /dev/null
+/*
+ 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 <errno.h>
+#include <net/if.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <string>
+
+#include <boost/assert.hpp>
+#include <boost/asio/basic_socket.hpp>
+#include <boost/asio/basic_raw_socket.hpp>
+
+#include <logfunc.hpp>
+
+//-----------------------------------------------------------------------------
+// NetworkInterface
+//-----------------------------------------------------------------------------
+
+/**
+ * @brief This class represents a local network interface.
+ */
+template<typename SocketType>
+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<typename SocketType>
+NetworkInterface<SocketType>::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<typename SocketType>
+bool NetworkInterface<SocketType>::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<typename SocketType>
+std::string NetworkInterface<SocketType>::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<typename SocketType>
+uint32_t NetworkInterface<SocketType>::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<const sockaddr_in *>( &ifr.ifr_addr );
+ uint32_t source_ipv4_address = htonl( source_sockaddr->sin_addr.s_addr );
+
+ return source_ipv4_address;
+}
+
+#endif // NETWORK_INTERFACE_HPP