Implement known missing OpenThread APIs needed for NCP support. (#122)

This change adds the following APIs:
* otGetLeaderRloc
* otGetMeshLocalEid
* otGetMeshLocalPrefix
* otSetMeshLocalPrefix
* otGetNetworkDataLeader
* otGetNetworkDataLocal
* otGetShortAddress
* otSetRawIp6ReceivedCallback
* otSendRawIp6
diff --git a/include/openthread-types.h b/include/openthread-types.h
index 2bccd7d..ba1bc20 100644
--- a/include/openthread-types.h
+++ b/include/openthread-types.h
@@ -75,6 +75,11 @@
      */
     kThreadError_ChannelAccessFailure = 17,
 
+    /**
+     * Not currently attached to a Thread Partition.
+     */
+    kThreadError_Detached = 18,
+
     kThreadError_Error = 255,
 } ThreadError;
 
diff --git a/include/openthread.h b/include/openthread.h
index 19b0b4d..b01a4fd 100644
--- a/include/openthread.h
+++ b/include/openthread.h
@@ -56,6 +56,7 @@
  * @defgroup config Configuration
  * @defgroup diags Diagnostics
  * @defgroup messages Message Buffers
+ * @defgroup ip6 IPv6
  * @defgroup udp UDP
  *
  * @}
@@ -278,6 +279,18 @@
 void otSetExtendedPanId(const uint8_t *aExtendedPanId);
 
 /**
+ * This function returns a pointer to the Leader's RLOC.
+ *
+ * @param[out]  aLeaderRloc  A pointer to where the Leader's RLOC will be written.
+ *
+ * @retval kThreadError_None         The Leader's RLOC was successfully written to @p aLeaderRloc.
+ * @retval kThreadError_InvalidArgs  @p aLeaderRloc was NULL.
+ * @retval kThreadError_Detached     Not currently attached to a Thread Partition.
+ *
+ */
+ThreadError otGetLeaderRloc(otIp6Address *aLeaderRloc);
+
+/**
  * Get the MLE Link Mode configuration.
  *
  * @returns The MLE Link Mode configuration.
@@ -323,6 +336,52 @@
 ThreadError otSetMasterKey(const uint8_t *aKey, uint8_t aKeyLength);
 
 /**
+ * This function returns a pointer to the Mesh Local EID.
+ *
+ * @returns A pointer to the Mesh Local EID.
+ *
+ */
+const otIp6Address *otGetMeshLocalEid(void);
+
+/**
+ * This function returns a pointer to the Mesh Local Prefix.
+ *
+ * @returns A pointer to the Mesh Local Prefix.
+ *
+ */
+const uint8_t *otGetMeshLocalPrefix(void);
+
+/**
+ * This function sets the Mesh Local Prefix.
+ *
+ * @param[in]  aMeshLocalPrefix  A pointer to the Mesh Local Prefix.
+ *
+ * @retval kThreadError_None  Successfully set the Mesh Local Prefix.
+ *
+ */
+ThreadError otSetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix);
+
+/**
+ * This method provides a full or stable copy of the Leader's Thread Network Data.
+ *
+ * @param[in]     aStable      TRUE when copying the stable version, FALSE when copying the full version.
+ * @param[out]    aData        A pointer to the data buffer.
+ * @param[inout]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
+ *                             On exit, number of copied bytes.
+ */
+ThreadError otGetNetworkDataLeader(bool aStable, uint8_t *aData, uint8_t *aDataLength);
+
+/**
+ * This method provides a full or stable copy of the local Thread Network Data.
+ *
+ * @param[in]     aStable      TRUE when copying the stable version, FALSE when copying the full version.
+ * @param[out]    aData        A pointer to the data buffer.
+ * @param[inout]  aDataLength  On entry, size of the data buffer pointed to by @p aData.
+ *                             On exit, number of copied bytes.
+ */
+ThreadError otGetNetworkDataLocal(bool aStable, uint8_t *aData, uint8_t *aDataLength);
+
+/**
  * Get the Thread Network Name.
  *
  * @returns A pointer to the Thread Network Name.
@@ -364,6 +423,13 @@
 ThreadError otSetPanId(otPanId aPanId);
 
 /**
+ * Get the IEEE 802.15.4 Short Address.
+ *
+ * @returns A pointer to the IEEE 802.15.4 Short Address.
+ */
+otShortAddress otGetShortAddress(void);
+
+/**
  * Get the list of IPv6 addresses assigned to the Thread interface.
  *
  * @returns A pointer to the first Network Inteface Address.
@@ -995,6 +1061,46 @@
  */
 
 /**
+ * @addtogroup ip6  IPv6
+ *
+ * @brief
+ *   This module includes functions that control IPv6 communication.
+ *
+ * @{
+ *
+ */
+
+/**
+ * This function pointer is called when an IPv6 datagram is received.
+ *
+ * @param[in]  aMessage  A pointer to the message buffer containing the received IPv6 datagram.
+ *
+ */
+typedef void (*otReceiveIp6DatagramCallback)(otMessage aMessage);
+
+/**
+ * This function registers a callback to provide received IPv6 datagrams.
+ *
+ * @param[in]  aCallback  A pointer to a function that is called when an IPv6 datagram is received or NULL to disable
+ *                        the callback.
+ *
+ */
+void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback);
+
+/**
+ * This function sends an IPv6 datagram via the Thread interface.
+ *
+ * @param[in]  aMessage  A pointer to the message buffer containing the IPv6 datagram.
+ *
+ */
+ThreadError otSendIp6Datagram(otMessage aMessage);
+
+/**
+ * @}
+ *
+ */
+
+/**
  * @addtogroup udp  UDP
  *
  * @brief
diff --git a/src/core/net/ip6.cpp b/src/core/net/ip6.cpp
index e2c3e63..d5b2a0e 100644
--- a/src/core/net/ip6.cpp
+++ b/src/core/net/ip6.cpp
@@ -47,8 +47,7 @@
 namespace Ip6 {
 
 static Mpl sMpl;
-static Ip6::NcpReceivedDatagramHandler sNcpReceivedHandler = NULL;
-static void *sNcpReceivedHandlerContext = NULL;
+static otReceiveIp6DatagramCallback sReceiveIp6DatagramCallback = NULL;
 
 static ThreadError ForwardMessage(Message &message, MessageInfo &messageInfo);
 
@@ -93,10 +92,9 @@
     return checksum;
 }
 
-void Ip6::SetNcpReceivedHandler(NcpReceivedDatagramHandler handler, void *context)
+void Ip6::SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback)
 {
-    sNcpReceivedHandler = handler;
-    sNcpReceivedHandlerContext = context;
+    sReceiveIp6DatagramCallback = aCallback;
 }
 
 ThreadError AddMplOption(Message &message, Header &header, IpProto nextHeader, uint16_t payloadLength)
@@ -307,7 +305,7 @@
 }
 
 ThreadError Ip6::HandleDatagram(Message &message, Netif *netif, uint8_t interfaceId, const void *linkMessageInfo,
-                                bool fromNcpHost)
+                                bool fromLocalHost)
 {
     ThreadError error = kThreadError_Drop;
     MessageInfo messageInfo;
@@ -387,9 +385,9 @@
     {
         SuccessOrExit(HandlePayload(message, messageInfo, nextHeader));
 
-        if (sNcpReceivedHandler != NULL && fromNcpHost == false)
+        if (sReceiveIp6DatagramCallback != NULL && fromLocalHost == false)
         {
-            sNcpReceivedHandler(sNcpReceivedHandlerContext, message);
+            sReceiveIp6DatagramCallback(&message);
             ExitNow(error = kThreadError_None);
         }
     }
diff --git a/src/core/net/ip6.hpp b/src/core/net/ip6.hpp
index edd06e3..c309a1f 100644
--- a/src/core/net/ip6.hpp
+++ b/src/core/net/ip6.hpp
@@ -563,22 +563,13 @@
                                                 uint16_t aLength, IpProto aProto);
 
     /**
-     * This function pointer is called when an IPv6 message is received.
+     * This function registers a callback to provide receivd raw IPv6 datagrams.
      *
-     * @param[in]  aContext  A pointer to arbitrary context information.
-     * @param[in]  aMessage  A reference to the IPv6 message.
+     * @param[in]  aCallback  A pointer to a function that is called when an IPv6 datagram is received or NULL to disable
+     *                        the callback.
      *
      */
-    typedef void (*NcpReceivedDatagramHandler)(void *aContext, Message &aMessage);
-
-    /**
-     * This method sets the NCP receive handler.
-     *
-     * @param[in]  aHandler  A pointer to a function that is called when IPv6 messages are received.
-     * @param[in]  aContext  A pointer to arbitrary context information.
-     *
-     */
-    static void SetNcpReceivedHandler(NcpReceivedDatagramHandler aHandler, void *aContext);
+    static void SetReceiveDatagramCallback(otReceiveIp6DatagramCallback aCallback);
 
 };
 
diff --git a/src/core/openthread.cpp b/src/core/openthread.cpp
index 2fe1eba..8f25f0b 100644
--- a/src/core/openthread.cpp
+++ b/src/core/openthread.cpp
@@ -110,6 +110,18 @@
     sThreadNetif->GetMle().SetMeshLocalPrefix(aExtendedPanId);
 }
 
+ThreadError otGetLeaderRloc(otIp6Address *aAddress)
+{
+    ThreadError error;
+
+    VerifyOrExit(aAddress != NULL, error = kThreadError_InvalidArgs);
+
+    error = sThreadNetif->GetMle().GetLeaderAddress(*static_cast<Ip6::Address *>(aAddress));
+
+exit:
+    return error;
+}
+
 otLinkModeConfig otGetLinkMode(void)
 {
     otLinkModeConfig config = {};
@@ -175,6 +187,45 @@
     return sThreadNetif->GetKeyManager().SetMasterKey(aKey, aKeyLength);
 }
 
+const otIp6Address *otGetMeshLocalEid(void)
+{
+    return sThreadNetif->GetMle().GetMeshLocal64();
+}
+
+const uint8_t *otGetMeshLocalPrefix(void)
+{
+    return sThreadNetif->GetMle().GetMeshLocalPrefix();
+}
+
+ThreadError otSetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix)
+{
+    return sThreadNetif->GetMle().SetMeshLocalPrefix(aMeshLocalPrefix);
+}
+
+ThreadError otGetNetworkDataLeader(bool aStable, uint8_t *aData, uint8_t *aDataLength)
+{
+    ThreadError error = kThreadError_None;
+
+    VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs);
+
+    sThreadNetif->GetNetworkDataLeader().GetNetworkData(aStable, aData, *aDataLength);
+
+exit:
+    return error;
+}
+
+ThreadError otGetNetworkDataLocal(bool aStable, uint8_t *aData, uint8_t *aDataLength)
+{
+    ThreadError error = kThreadError_None;
+
+    VerifyOrExit(aData != NULL && aDataLength != NULL, error = kThreadError_InvalidArgs);
+
+    sThreadNetif->GetNetworkDataLocal().GetNetworkData(aStable, aData, *aDataLength);
+
+exit:
+    return error;
+}
+
 const char *otGetNetworkName(void)
 {
     return sThreadNetif->GetMac().GetNetworkName();
@@ -195,6 +246,11 @@
     return sThreadNetif->GetMac().SetPanId(aPanId);
 }
 
+otShortAddress otGetShortAddress(void)
+{
+    return sThreadNetif->GetMac().GetShortAddress();
+}
+
 uint8_t otGetLocalLeaderWeight(void)
 {
     return sThreadNetif->GetMle().GetLeaderWeight();
@@ -523,6 +579,17 @@
     return;
 }
 
+void otSetReceiveIp6DatagramCallback(otReceiveIp6DatagramCallback aCallback)
+{
+    Ip6::Ip6::SetReceiveDatagramCallback(aCallback);
+}
+
+ThreadError otSendIp6Datagram(otMessage aMessage)
+{
+    return Ip6::Ip6::HandleDatagram(*static_cast<Message *>(aMessage), NULL, sThreadNetif->GetInterfaceId(),
+                                    NULL, true);
+}
+
 otMessage otNewUdpMessage(void)
 {
     return Ip6::Udp::NewMessage(0);
diff --git a/src/core/thread/mle.cpp b/src/core/thread/mle.cpp
index fa60cb8..731edd5 100644
--- a/src/core/thread/mle.cpp
+++ b/src/core/thread/mle.cpp
@@ -97,6 +97,13 @@
     mLinkLocal16.mPreferredLifetime = 0xffffffff;
     mLinkLocal16.mValidLifetime = 0xffffffff;
 
+    // initialize Mesh Local Prefix
+    mMeshLocal64.GetAddress().m8[0] = 0xfd;
+    memcpy(mMeshLocal64.GetAddress().m8 + 1, mMac.GetExtendedPanId(), 5);
+    mMeshLocal64.GetAddress().m8[6] = 0x00;
+    mMeshLocal64.GetAddress().m8[7] = 0x00;
+    SetMeshLocalPrefix(mMeshLocal64.GetAddress().m8);
+
     // mesh-local 64
     for (int i = 8; i < 16; i++)
     {
@@ -128,8 +135,6 @@
     mRealmLocalAllThreadNodes.GetAddress().m16[7] = HostSwap16(0x0001);
     mNetif.SubscribeMulticast(mRealmLocalAllThreadNodes);
 
-    SetMeshLocalPrefix(mMac.GetExtendedPanId());
-
     mNetif.RegisterHandler(mNetifHandler);
 }
 
@@ -326,20 +331,16 @@
     return mMeshLocal16.GetAddress().m8;
 }
 
-ThreadError Mle::SetMeshLocalPrefix(const uint8_t *aExtendedPanId)
+ThreadError Mle::SetMeshLocalPrefix(const uint8_t *aMeshLocalPrefix)
 {
-    mMeshLocal64.GetAddress().m8[0] = 0xfd;
-    memcpy(mMeshLocal64.GetAddress().m8 + 1, aExtendedPanId, 5);
-    mMeshLocal64.GetAddress().m8[6] = 0x00;
-    mMeshLocal64.GetAddress().m8[7] = 0x00;
-
-    memcpy(&mMeshLocal16.GetAddress(), &mMeshLocal64.GetAddress(), 8);
+    memcpy(mMeshLocal64.GetAddress().m8, aMeshLocalPrefix, 8);
+    memcpy(mMeshLocal16.GetAddress().m8, mMeshLocal64.GetAddress().m8, 8);
 
     mLinkLocalAllThreadNodes.GetAddress().m8[3] = 64;
-    memcpy(mLinkLocalAllThreadNodes.GetAddress().m8 + 4, &mMeshLocal64.GetAddress(), 8);
+    memcpy(mLinkLocalAllThreadNodes.GetAddress().m8 + 4, mMeshLocal64.GetAddress().m8, 8);
 
     mRealmLocalAllThreadNodes.GetAddress().m8[3] = 64;
-    memcpy(mRealmLocalAllThreadNodes.GetAddress().m8 + 4, &mMeshLocal64.GetAddress(), 8);
+    memcpy(mRealmLocalAllThreadNodes.GetAddress().m8 + 4, mMeshLocal64.GetAddress().m8, 8);
 
     return kThreadError_None;
 }
@@ -416,7 +417,7 @@
 {
     ThreadError error = kThreadError_None;
 
-    VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kThreadError_Error);
+    VerifyOrExit(GetRloc16() != Mac::kShortAddrInvalid, error = kThreadError_Detached);
 
     memcpy(&aAddress, &mMeshLocal16.GetAddress(), 8);
     aAddress.m16[4] = HostSwap16(0x0000);
diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp
index 2052c7e..92cea3a 100644
--- a/src/ncp/ncp_base.cpp
+++ b/src/ncp/ncp_base.cpp
@@ -42,6 +42,8 @@
 
 extern ThreadNetif *sThreadNetif;
 
+static NcpBase *sNcpContext = NULL;
+
 // ----------------------------------------------------------------------------
 // MARK: Command/Property Jump Tables
 // ----------------------------------------------------------------------------
@@ -228,20 +230,20 @@
     mSupportedChannelMask = (0xFFFF << 11); // Default to 2.4GHz 802.15.4 channels.
     mChannelMask = mSupportedChannelMask;
     mScanPeriod = 200; // ms
+    sNcpContext = this;
 
     assert(sThreadNetif != NULL);
     sThreadNetif->RegisterHandler(mNetifHandler);
-    Ip6::Ip6::SetNcpReceivedHandler(&HandleDatagramFromStack, this);
+    otSetReceiveIp6DatagramCallback(&HandleDatagramFromStack);
 }
 
 // ----------------------------------------------------------------------------
 // MARK: Outbound Datagram Handling
 // ----------------------------------------------------------------------------
 
-void NcpBase::HandleDatagramFromStack(void *context, Message &message)
+void NcpBase::HandleDatagramFromStack(otMessage message)
 {
-    NcpBase *obj = reinterpret_cast<NcpBase *>(context);
-    obj->HandleDatagramFromStack(message);
+    sNcpContext->HandleDatagramFromStack(*static_cast<Message *>(message));
 }
 
 void NcpBase::HandleDatagramFromStack(Message &message)
@@ -1138,7 +1140,7 @@
         SPINEL_CMD_PROP_VALUE_IS,
         key,
         SPINEL_DATATYPE_UINT16_S,
-        sThreadNetif->GetMac().GetShortAddress()
+        otGetShortAddress()
     );
 }
 
@@ -1313,10 +1315,10 @@
 
     if (errorCode == kThreadError_None)
     {
-        sThreadNetif->GetNetworkDataLocal().GetNetworkData(
+        otGetNetworkDataLocal(
             false, // Stable?
             network_data,
-            network_data_len
+            &network_data_len
         );
 
         errorCode = OutboundFrameFeedData(network_data, network_data_len);
@@ -1346,10 +1348,10 @@
 
     if (errorCode == kThreadError_None)
     {
-        sThreadNetif->GetNetworkDataLocal().GetNetworkData(
+        otGetNetworkDataLocal(
             true, // Stable?
             network_data,
-            network_data_len
+            &network_data_len
         );
 
         errorCode = OutboundFrameFeedData(network_data, network_data_len);
@@ -1402,8 +1404,8 @@
 void NcpBase::GetPropertyHandler_THREAD_LEADER_ADDR(uint8_t header, spinel_prop_key_t key)
 {
     ThreadError errorCode;
-    Ip6::Address address;
-    errorCode = sThreadNetif->GetMle().GetLeaderAddress(address);
+    otIp6Address address;
+    errorCode = otGetLeaderRloc(&address);
 
     if (errorCode == kThreadError_None)
     {
@@ -1423,7 +1425,7 @@
 
 void NcpBase::GetPropertyHandler_IPV6_ML_PREFIX(uint8_t header, spinel_prop_key_t key)
 {
-    const uint8_t *ml_prefix = sThreadNetif->GetMle().GetMeshLocalPrefix();
+    const uint8_t *ml_prefix = otGetMeshLocalPrefix();
 
     if (ml_prefix)
     {
@@ -1456,7 +1458,7 @@
 
 void NcpBase::GetPropertyHandler_IPV6_ML_ADDR(uint8_t header, spinel_prop_key_t key)
 {
-    const Ip6::Address *ml64 = sThreadNetif->GetMle().GetMeshLocal64();
+    const otIp6Address *ml64 = otGetMeshLocalEid();
 
     if (ml64)
     {
@@ -2186,7 +2188,7 @@
 
     if (errorCode == kThreadError_None)
     {
-        errorCode = Ip6::Ip6::HandleDatagram(*message, NULL, sThreadNetif->GetInterfaceId(), NULL, true);
+        errorCode = otSendIp6Datagram(message);
     }
 
     if (errorCode == kThreadError_None)
@@ -2244,7 +2246,7 @@
 
     if (errorCode == kThreadError_None)
     {
-        errorCode = Ip6::Ip6::HandleDatagram(*message, NULL, sThreadNetif->GetInterfaceId(), NULL, true);
+        errorCode = otSendIp6Datagram(message);
     }
 
     if (errorCode == kThreadError_None)
@@ -2269,7 +2271,7 @@
 
     if (value_len >= 8)
     {
-        errorCode = sThreadNetif->GetMle().SetMeshLocalPrefix(value_ptr);
+        errorCode = otSetMeshLocalPrefix(value_ptr);
         HandleCommandPropertyGet(header, key);
     }
     else
diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp
index 1b01759..2ff05bc 100644
--- a/src/ncp/ncp_base.hpp
+++ b/src/ncp/ncp_base.hpp
@@ -76,7 +76,7 @@
     /**
      * Trampoline for HandleDatagramFromStack().
      */
-    static void HandleDatagramFromStack(void *context, Message &message);
+    static void HandleDatagramFromStack(otMessage message);
 
     void HandleDatagramFromStack(Message &message);