New method to get the network interface IP address
authorGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Tue, 8 Nov 2011 10:02:12 +0000 (08:02 -0200)
committerGuilherme Maciel Ferreira <guilherme.maciel.ferreira@gmail.com>
Tue, 8 Nov 2011 10:03:26 +0000 (08:03 -0200)
- Using Boost.Asio objects instead of a primitive data type (under development).

src/host/networkinterface.hpp

index 95bf1de..f50fd92 100644 (file)
 #define NETWORK_INTERFACE_HPP
 
 #include <errno.h>
-#include <net/if.h>
 #include <string.h>
-#include <sys/ioctl.h>
+
+#include <arpa/inet.h>
+#include <ifaddrs.h>
+#include <netinet/in.h>
+#include <net/if.h>
 #include <sys/socket.h>
 
 #include <string>
@@ -32,6 +35,9 @@
 #include <boost/assert.hpp>
 #include <boost/asio/basic_socket.hpp>
 #include <boost/asio/basic_raw_socket.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/address_v4.hpp>
+#include <boost/asio/ip/address_v6.hpp>
 
 #include <logfunc.hpp>
 
@@ -56,7 +62,7 @@ public:
 
     std::string get_name() const;
 
-    uint32_t get_address();
+    boost::asio::ip::address get_address(bool is_ip4) const;
 
 private:
     /// The network interface name which the socket is attached
@@ -122,15 +128,18 @@ std::string NetworkInterface<SocketType>::get_name() const
     return Name;
 }
 
+#include <iostream>
+
 /**
  * @brief This method gets the local address of network interface.
  *
- * @return The integer IP representing the local address of the network
+ * @return The integer IPv4 representing the local address of the network
  * interface.
  */
 template<typename SocketType>
-uint32_t NetworkInterface<SocketType>::get_address()
+boost::asio::ip::address NetworkInterface<SocketType>::get_address(bool is_ip4) const
 {
+#if 0
     struct ifreq ifr;
     memset( &ifr, 0, sizeof(ifr) );
 
@@ -145,7 +154,7 @@ uint32_t NetworkInterface<SocketType>::get_address()
     }
 
     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
+    ifr.ifr_addr.sa_family = AF_INET6; // TODO change to AF_INET6 when IPv6 -> NAO FUNCIONOU, USAR O addr6.cpp
 
     int ioctl_resp = ioctl( Socket.native(), SIOCGIFADDR, &ifr );
     if ( ioctl_resp != 0)
@@ -159,7 +168,61 @@ uint32_t NetworkInterface<SocketType>::get_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 )
+    {
+        for ( ifa_current = ifa_first; ifa_current != NULL; ifa_current = ifa_current->ifa_next )
+        {
+            if ( ifa_current->ifa_addr->sa_data == NULL)
+            {
+                continue;
+            }
+
+            char *interface_name = ifa_current->ifa_name;
+            if ( Name == interface_name )
+            {
+                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 ) );
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    freeifaddrs( ifa_first );
 }
 
 #endif // NETWORK_INTERFACE_HPP