face: Implementing ip::address::is_loopback method for Boost <1.47

boost::ip::address::is_loopback method appeared only in Boost 1.47.
This commit enables the same functionality for earlier versions of
boost, based on implementation in 1.55.

Change-Id: I571408fc7db44eebd14405e7b7a9810b5d061802
diff --git a/daemon/face/tcp-face.hpp b/daemon/face/tcp-face.hpp
index dfd6028..21b13f2 100644
--- a/daemon/face/tcp-face.hpp
+++ b/daemon/face/tcp-face.hpp
@@ -27,26 +27,6 @@
 
 //
 
-/** \brief Class validating use of TcpLocalFace
- */
-template<>
-struct StreamFaceValidator<boost::asio::ip::tcp, LocalFace>
-{
-  /** Check that local endpoint is loopback
-   *
-   *  @throws Face::Error if validation failed
-   */
-  static void
-  validateSocket(boost::asio::ip::tcp::socket& socket)
-  {
-    if (!socket.local_endpoint().address().is_loopback() ||
-        !socket.remote_endpoint().address().is_loopback())
-      {
-        throw Face::Error("TcpLocalFace can be created only on loopback interface");
-      }
-  }
-};
-
 /**
  * \brief Implementation of Face abstraction that uses TCP
  *        as underlying transport mechanism and is used for
@@ -61,6 +41,53 @@
   TcpLocalFace(const shared_ptr<protocol::socket>& socket);
 };
 
+//
+
+inline bool
+is_loopback(const boost::asio::ip::address& address)
+{
+#if BOOST_VERSION < 104700
+  if (address.is_v4())
+    {
+      return (address.to_v4().to_ulong() & 0xFF000000) == 0x7F000000;
+    }
+  else
+    {
+      boost::asio::ip::address_v6::bytes_type v6_addr = address.to_v6().to_bytes();
+      return ((v6_addr[0] == 0) && (v6_addr[1] == 0)
+              && (v6_addr[2] == 0) && (v6_addr[3] == 0)
+              && (v6_addr[4] == 0) && (v6_addr[5] == 0)
+              && (v6_addr[6] == 0) && (v6_addr[7] == 0)
+              && (v6_addr[8] == 0) && (v6_addr[9] == 0)
+              && (v6_addr[10] == 0) && (v6_addr[11] == 0)
+              && (v6_addr[12] == 0) && (v6_addr[13] == 0)
+              && (v6_addr[14] == 0) && (v6_addr[15] == 1));
+    }
+#else
+  return address.is_loopback();
+#endif
+}
+
+/** \brief Class validating use of TcpLocalFace
+ */
+template<>
+struct StreamFaceValidator<boost::asio::ip::tcp, LocalFace>
+{
+  /** Check that local endpoint is loopback
+   *
+   *  @throws Face::Error if validation failed
+   */
+  static void
+  validateSocket(boost::asio::ip::tcp::socket& socket)
+  {
+    if (!is_loopback(socket.local_endpoint().address()) ||
+        !is_loopback(socket.remote_endpoint().address()))
+      {
+        throw Face::Error("TcpLocalFace can be created only on loopback interface");
+      }
+  }
+};
+
 
 } // namespace nfd