#include <logfunc.hpp>
+#include "host/networkinterfacelist.h"
+
+typedef const struct sockaddr* const_sockaddr_ptr_t;
+typedef const struct sockaddr_in* const_sockaddr_in_ptr_t;
+typedef const struct sockaddr_in6* const_sockaddr_in6_ptr_t;
+
//-----------------------------------------------------------------------------
// NetworkInterface
//-----------------------------------------------------------------------------
/**
* @brief This class represents a local network interface.
*/
-template<typename SocketType>
+template<typename SocketType, typename Protocol>
class NetworkInterface
{
public:
std::string get_name() const;
- boost::asio::ip::address get_address(bool is_ip4) const;
+ boost::asio::ip::address get_address( Protocol protocol ) const;
+
+ const uint8_t* get_address_bytes( const_sockaddr_ptr_t ifa_addr ) const;
private:
/// The network interface name which the socket is attached
// NetworkInterface
//-----------------------------------------------------------------------------
-template<typename SocketType>
-NetworkInterface<SocketType>::NetworkInterface(
+template<typename SocketType, typename Protocol>
+NetworkInterface<SocketType, Protocol>::NetworkInterface(
const std::string &nic_name,
SocketType &boost_socket
) :
*
* @return true if the bind was successfully, and false if the bind failed.
*/
-template<typename SocketType>
-bool NetworkInterface<SocketType>::bind()
+template<typename SocketType, typename Protocol>
+bool NetworkInterface<SocketType, Protocol>::bind()
{
BOOST_ASSERT( !Name.empty() );
*
* @return A string representing the name of the network interface.
*/
-template<typename SocketType>
-std::string NetworkInterface<SocketType>::get_name() const
+template<typename SocketType, typename Protocol>
+std::string NetworkInterface<SocketType, Protocol>::get_name() const
{
+ BOOST_ASSERT( !Name.empty() );
+
return Name;
}
-#include <iostream>
-
/**
* @brief This method gets the local address of network interface.
*
- * @return The integer IPv4 representing the local address of the network
- * interface.
+ * @return The @c boost::asio::ip::address representing the local address of
+ * the network interface.
*/
-template<typename SocketType>
-boost::asio::ip::address NetworkInterface<SocketType>::get_address(bool is_ip4) const
+template<typename SocketType, typename Protocol>
+boost::asio::ip::address NetworkInterface<SocketType, Protocol>::get_address(
+ Protocol protocol
+) const
{
-#if 0
- 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;
- }
+ BOOST_ASSERT( (protocol.family() == PF_INET) || (protocol.family() == PF_INET6) );
- strncpy( ifr.ifr_name, Name.c_str(), network_interface_name_limit );
- ifr.ifr_addr.sa_family = AF_INET6; // TODO change to AF_INET6 when IPv6 -> NAO FUNCIONOU, USAR O addr6.cpp
+ NetworkInterfaceList nic_list;
- int ioctl_resp = ioctl( Socket.native(), SIOCGIFADDR, &ifr );
- if ( ioctl_resp != 0)
+ const sa_family_t addr_type = static_cast<sa_family_t>( protocol.family() );
+ const struct ifaddrs *ifa_entry = nic_list.find_interface( get_name(), addr_type );
+ if ( ifa_entry == NULL )
{
- I2n::Logger::GlobalLogger.error()
- << "Error: could not retrieve IP address from network interface"
- << std::endl;
- return 0;
+ return boost::asio::ip::address();
}
- 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 );
-
- std::cout << source_ipv4_address << std::endl;
-
- return source_ipv4_address;
-#endif
-
- struct ifaddrs *ifa_first = NULL;
- struct ifaddrs *ifa_current = NULL;
- int rc = 0;
- char addr_string[ INET6_ADDRSTRLEN ];
-
- rc = getifaddrs( &ifa_first );
- if ( rc == 0 )
+ const uint8_t *addr_bytes = get_address_bytes( ifa_entry->ifa_addr );
+ if ( addr_bytes != NULL )
{
- for ( ifa_current = ifa_first; ifa_current != NULL; ifa_current = ifa_current->ifa_next )
+ BOOST_ASSERT( ifa_entry->ifa_addr->sa_family == addr_type );
+
+ char addr_buffer_string[ INET6_ADDRSTRLEN ];
+ volatile const char *addr_ret_string = inet_ntop( addr_type, addr_bytes, addr_buffer_string, sizeof(addr_buffer_string) );
+ if ( addr_ret_string != NULL )
{
- if ( ifa_current->ifa_addr->sa_data == NULL)
+ if ( PF_INET == addr_type )
{
- continue;
+ return boost::asio::ip::address_v4::from_string( std::string( addr_buffer_string ) );
}
-
- char *interface_name = ifa_current->ifa_name;
- if ( Name == interface_name )
+ else if ( PF_INET6 == addr_type )
{
- sa_family_t addr_type = ifa_current->ifa_addr->sa_family;
- void *addr_bytes = NULL;
-
- if ( AF_INET == addr_type )
- {
- addr_bytes = &((struct sockaddr_in *) ifa_current->ifa_addr)->sin_addr;
- }
- else if ( AF_INET6 == addr_type )
- {
- addr_bytes = &((struct sockaddr_in6 *) ifa_current->ifa_addr)->sin6_addr;
- }
-
- if ( addr_bytes != NULL )
- {
- const char *a = inet_ntop( addr_type, addr_bytes, addr_string, sizeof(addr_string) );
- if ( a != NULL )
- {
- if ( AF_INET == addr_type )
- {
- return boost::asio::ip::address_v4::from_string( std::string( a ) );
- }
- else if ( AF_INET6 == addr_type )
- {
- return boost::asio::ip::address_v6::from_string( std::string( a ) );
- }
- }
- }
+ return boost::asio::ip::address_v6::from_string( std::string( addr_buffer_string ) );
}
}
}
- freeifaddrs( ifa_first );
+ return boost::asio::ip::address();
+}
+
+/**
+ * @brief Converts @c sockaddr into a sequence of bytes.
+ *
+ * @param ifa_addr A @c sockaddr structure.
+ *
+ * @return A sequence of bytes representing the interface address.
+ */
+template<typename SocketType, typename Protocol>
+const uint8_t* NetworkInterface<SocketType, Protocol>::get_address_bytes(
+ const_sockaddr_ptr_t ifa_addr
+) const
+{
+ BOOST_ASSERT( ifa_addr != NULL );
+
+ sa_family_t addr_type = ifa_addr->sa_family;
+ const uint8_t *addr_bytes = NULL;
+
+ if ( PF_INET == addr_type )
+ {
+ const_sockaddr_in_ptr_t sockaddr = reinterpret_cast<const_sockaddr_in_ptr_t>( ifa_addr );
+ addr_bytes = reinterpret_cast<const uint8_t*>( & (sockaddr->sin_addr) );
+ }
+ else if ( PF_INET6 == addr_type )
+ {
+ const_sockaddr_in6_ptr_t sockaddr = reinterpret_cast<const_sockaddr_in6_ptr_t>( ifa_addr );
+ addr_bytes = reinterpret_cast<const uint8_t*>( & (sockaddr->sin6_addr) );
+ }
+
+ return addr_bytes;
}
#endif // NETWORK_INTERFACE_HPP