mirror of
https://github.com/espressif/openthread.git
synced 2026-06-06 05:24:51 +00:00
Pr/slaac utility (#698)
* Provide utility for IPv6 SLAAC (#651) * Semantically Opaque Interface Identifier with IPv6 SLAAC (#651)
This commit is contained in:
@@ -71,6 +71,7 @@
|
||||
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\thread_netif.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\thread_tlvs.cpp" />
|
||||
<ClCompile Include="..\..\src\core\utils\global_address.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\core\coap\coap_header.hpp" />
|
||||
@@ -135,6 +136,7 @@
|
||||
<ClInclude Include="..\..\src\core\thread\thread_tlvs.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\thread_uris.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\topology.hpp" />
|
||||
<ClInclude Include="..\..\src\core\utils\global_address.hpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{DD5018BE-54C6-4FD4-9F8D-08D52FC0CD40}</ProjectGuid>
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
<Filter Include="Header Files\meshcop">
|
||||
<UniqueIdentifier>{635aaabf-80f0-40e2-9218-22ff75bc0e32}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\utils">
|
||||
<UniqueIdentifier>{A0D2E990-DC5E-4B56-A552-888F97214A17}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\utils">
|
||||
<UniqueIdentifier>{5ac96cb9-6257-4387-9238-27649915463a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\core\coap\coap_header.cpp">
|
||||
@@ -207,6 +213,9 @@
|
||||
<ClCompile Include="..\..\src\core\crypto\sha256.cpp">
|
||||
<Filter>Source Files\crypto</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\utils\global_address.cpp">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\core\openthreadcontext.h">
|
||||
@@ -395,5 +404,8 @@
|
||||
<ClInclude Include="..\..\src\core\crypto\sha256.hpp">
|
||||
<Filter>Header Files\crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\utils\global_address.hpp">
|
||||
<Filter>Header Files\utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -71,6 +71,7 @@
|
||||
<ClCompile Include="..\..\src\core\thread\panid_query_server.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\thread_netif.cpp" />
|
||||
<ClCompile Include="..\..\src\core\thread\thread_tlvs.cpp" />
|
||||
<ClCompile Include="..\..\src\core\utils\global_address.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\core\coap\coap_header.hpp" />
|
||||
@@ -135,6 +136,7 @@
|
||||
<ClInclude Include="..\..\src\core\thread\thread_tlvs.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\thread_uris.hpp" />
|
||||
<ClInclude Include="..\..\src\core\thread\topology.hpp" />
|
||||
<ClInclude Include="..\..\src\core\utils\global_address.hpp" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9B33C190-5D07-40BF-9536-68843DC5D7AF}</ProjectGuid>
|
||||
|
||||
@@ -49,6 +49,12 @@
|
||||
<Filter Include="Header Files\meshcop">
|
||||
<UniqueIdentifier>{8f54e8b3-d8fb-4fed-88ce-42b39f171d0b}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\utils">
|
||||
<UniqueIdentifier>{A0D2E990-DC5E-4B56-A552-888F97214A17}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Header Files\utils">
|
||||
<UniqueIdentifier>{5ac96cb9-6257-4387-9238-27649915463a}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\src\core\coap\coap_header.cpp">
|
||||
@@ -207,6 +213,9 @@
|
||||
<ClCompile Include="..\..\src\core\crypto\sha256.cpp">
|
||||
<Filter>Source Files\crypto</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\core\utils\global_address.cpp">
|
||||
<Filter>Source Files\utils</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\core\openthreadcontext.h">
|
||||
@@ -395,5 +404,8 @@
|
||||
<ClInclude Include="..\..\src\core\crypto\sha256.hpp">
|
||||
<Filter>Header Files\crypto</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\core\utils\global_address.hpp">
|
||||
<Filter>Header Files\utils</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -39,8 +39,8 @@ ot_cli_CPPFLAGS = \
|
||||
$(NULL)
|
||||
|
||||
ot_cli_LDADD = \
|
||||
$(top_builddir)/src/core/libopenthread.a \
|
||||
$(top_builddir)/src/cli/libopenthread-cli.a \
|
||||
$(top_builddir)/src/core/libopenthread.a \
|
||||
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
|
||||
$(NULL)
|
||||
|
||||
|
||||
@@ -132,6 +132,11 @@ typedef enum ThreadError
|
||||
*/
|
||||
kThreadError_BlacklistFiltered = 27,
|
||||
|
||||
/**
|
||||
* The creation of IPv6 address failed.
|
||||
*/
|
||||
kThreadError_Ipv6AddressCreationFailure = 28,
|
||||
|
||||
kThreadError_Error = 255,
|
||||
} ThreadError;
|
||||
|
||||
@@ -807,6 +812,24 @@ typedef struct otNetifAddress
|
||||
struct otNetifAddress *mNext; ///< A pointer to the next network interface address.
|
||||
} otNetifAddress;
|
||||
|
||||
/**
|
||||
* This structure represents data used by Semantically Opaque IID Generator.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *mInterfaceId; ///< String of bytes representing interface ID. Like "eth0" or "wlan0".
|
||||
uint8_t mInterfaceIdLength; ///< Length of interface ID string.
|
||||
|
||||
uint8_t *mNetworkId; ///< Network ID (or name). Can be null if mNetworkIdLength is 0.
|
||||
uint8_t mNetworkIdLength; ///< Length of Network ID string.
|
||||
|
||||
uint8_t mDadCounter; ///< Duplicate address detection counter.
|
||||
|
||||
uint8_t *mSecretKey; ///< Secret key used to create IID. Cannot be null.
|
||||
uint16_t mSecretKeyLength; ///< Secret key length in bytes. Should be at least 16 bytes == 128 bits.
|
||||
} otSemanticallyOpaqueIidGeneratorData;
|
||||
|
||||
/**
|
||||
* @addtogroup messages Message Buffers
|
||||
*
|
||||
|
||||
@@ -83,6 +83,7 @@ extern "C" {
|
||||
*
|
||||
* @defgroup core-6lowpan 6LoWPAN
|
||||
* @defgroup core-coap CoAP
|
||||
* @defgroup core-global-address Global IPv6 Address
|
||||
* @defgroup core-ipv6 IPv6
|
||||
* @defgroup core-mac MAC
|
||||
* @defgroup core-mesh-forwarding Mesh Forwarding
|
||||
@@ -786,6 +787,69 @@ ThreadError otAddUnicastAddress(otInstance *aInstance, const otNetifAddress *aAd
|
||||
*/
|
||||
ThreadError otRemoveUnicastAddress(otInstance *aInstance, const otIp6Address *aAddress);
|
||||
|
||||
/**
|
||||
* This function pointer is called to create IPv6 IID during SLAAC procedure.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[inout] aContext A pointer to creator-specific context.
|
||||
*
|
||||
* @retval kThreadError_None Created valid IID for given IPv6 address.
|
||||
* @retval kThreadError_Ipv6AddressCreationFailure Creation of valid IID for given IPv6 address failed.
|
||||
*
|
||||
*/
|
||||
typedef ThreadError(*otSlaacIidCreate)(otInstance *aInstance, otNetifAddress *aAddress, void *aContext);
|
||||
|
||||
/**
|
||||
* Update all automatically created IPv6 addresses for prefixes from current Network Data with SLAAC procedure.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddresses A pointer to an array of automatically created IPv6 addresses.
|
||||
* @param[in] aNumAddresses The number of slots in aAddresses array.
|
||||
* @param[in] aIidCreate A pointer to a function that is called to create IPv6 IIDs.
|
||||
* @param[in] aContext A pointer to data passed to aIidCreate function.
|
||||
*
|
||||
*/
|
||||
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
||||
otSlaacIidCreate aIidCreate, void *aContext);
|
||||
|
||||
/**
|
||||
* Create random IID for given IPv6 address.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[in] aContext A pointer to unused data.
|
||||
*
|
||||
* @retval kThreadError_None Created valid IID for given IPv6 address.
|
||||
*
|
||||
*/
|
||||
ThreadError otCreateRandomIid(otInstance *aInstance, otNetifAddress *aAddresses, void *aContext);
|
||||
|
||||
/**
|
||||
* Create IID for given IPv6 address using extended MAC address.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[in] aContext A pointer to unused data.
|
||||
*
|
||||
* @retval kThreadError_None Created valid IID for given IPv6 address.
|
||||
*
|
||||
*/
|
||||
ThreadError otCreateMacIid(otInstance *aInstance, otNetifAddress *aAddresses, void *aContext);
|
||||
|
||||
/**
|
||||
* Create semantically opaque IID for given IPv6 address.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[inout] aContext A pointer to a otSemanticallyOpaqueIidGeneratorData structure.
|
||||
*
|
||||
* @retval kThreadError_None Created valid IID for given IPv6 address.
|
||||
* @retval kThreadError_Ipv6AddressCreationFailure Could not create valid IID for given IPv6 address.
|
||||
*
|
||||
*/
|
||||
ThreadError otCreateSemanticallyOpaqueIid(otInstance *aInstance, otNetifAddress *aAddresses, void *aContext);
|
||||
|
||||
/**
|
||||
* This function pointer is called to notify certain configuration or state changes within OpenThread.
|
||||
*
|
||||
|
||||
+2
-95
@@ -52,7 +52,6 @@
|
||||
#include <common/encoding.hpp>
|
||||
#include <common/new.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
#include <platform/random.h>
|
||||
#include <platform/uart.h>
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
@@ -2389,102 +2388,10 @@ void Interpreter::s_HandleNetifStateChanged(uint32_t aFlags, void *aContext)
|
||||
|
||||
void Interpreter::HandleNetifStateChanged(uint32_t aFlags)
|
||||
{
|
||||
otNetworkDataIterator iterator;
|
||||
otBorderRouterConfig config;
|
||||
|
||||
VerifyOrExit((aFlags & OT_THREAD_NETDATA_UPDATED) != 0, ;);
|
||||
|
||||
// remove addresses
|
||||
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
|
||||
{
|
||||
otNetifAddress *address = &sAutoAddresses[i];
|
||||
bool found = false;
|
||||
|
||||
if (address->mValidLifetime == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
while (otGetNextOnMeshPrefix(mInstance, false, &iterator, &config) == kThreadError_None)
|
||||
{
|
||||
if (config.mSlaac == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
|
||||
config.mPrefix.mLength == address->mPrefixLength)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
otRemoveUnicastAddress(mInstance, &address->mAddress);
|
||||
address->mValidLifetime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// add addresses
|
||||
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
while (otGetNextOnMeshPrefix(mInstance, false, &iterator, &config) == kThreadError_None)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (config.mSlaac == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
|
||||
{
|
||||
otNetifAddress *address = &sAutoAddresses[i];
|
||||
|
||||
if (address->mValidLifetime == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
|
||||
config.mPrefix.mLength == address->mPrefixLength)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
for (size_t i = 0; i < sizeof(sAutoAddresses) / sizeof(sAutoAddresses[0]); i++)
|
||||
{
|
||||
otNetifAddress *address = &sAutoAddresses[i];
|
||||
|
||||
if (address->mValidLifetime != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(address, 0, sizeof(*address));
|
||||
memcpy(&address->mAddress, &config.mPrefix.mPrefix, 8);
|
||||
|
||||
for (size_t j = 8; j < sizeof(address->mAddress); j++)
|
||||
{
|
||||
address->mAddress.mFields.m8[j] = (uint8_t)otPlatRandomGet();
|
||||
}
|
||||
|
||||
address->mPrefixLength = config.mPrefix.mLength;
|
||||
address->mPreferredLifetime = config.mPreferred ? 0xffffffff : 0;
|
||||
address->mValidLifetime = 0xffffffff;
|
||||
otAddUnicastAddress(mInstance, address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
otSlaacUpdate(mInstance, mAutoAddresses, sizeof(mAutoAddresses) / sizeof(mAutoAddresses[0]), otCreateRandomIid,
|
||||
NULL);
|
||||
|
||||
exit:
|
||||
return;
|
||||
|
||||
+2
-1
@@ -131,6 +131,7 @@ private:
|
||||
enum
|
||||
{
|
||||
kMaxArgs = 32,
|
||||
kMaxAutoAddresses = 8,
|
||||
};
|
||||
|
||||
void AppendResult(ThreadError error);
|
||||
@@ -232,7 +233,7 @@ private:
|
||||
uint32_t sInterval;
|
||||
Timer sPingTimer;
|
||||
|
||||
otNetifAddress sAutoAddresses[8];
|
||||
otNetifAddress mAutoAddresses[kMaxAutoAddresses];
|
||||
|
||||
otInstance *mInstance;
|
||||
};
|
||||
|
||||
@@ -83,6 +83,7 @@ libopenthread_a_SOURCES = \
|
||||
thread/network_diag_tlvs.cpp \
|
||||
thread/thread_netif.cpp \
|
||||
thread/thread_tlvs.cpp \
|
||||
utils/global_address.cpp \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
@@ -171,6 +172,7 @@ noinst_HEADERS = \
|
||||
thread/thread_tlvs.hpp \
|
||||
thread/thread_uris.hpp \
|
||||
thread/topology.hpp \
|
||||
utils/global_address.hpp \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
|
||||
@@ -111,6 +111,23 @@ bool Address::IsRoutingLocator(void) const
|
||||
mFields.m16[6] == HostSwap16(0xfe00));
|
||||
}
|
||||
|
||||
bool Address::IsSubnetRouterAnycast(void) const
|
||||
{
|
||||
return (mFields.m32[2] == 0 && mFields.m32[3] == 0);
|
||||
}
|
||||
|
||||
bool Address::IsReservedSubnetAnycast(void) const
|
||||
{
|
||||
return (mFields.m32[2] == HostSwap32(0xfdffffff) && mFields.m16[6] == 0xffff && mFields.m8[14] == 0xff &&
|
||||
mFields.m8[15] >= 0x80);
|
||||
}
|
||||
|
||||
bool Address::IsIidReserved(void) const
|
||||
{
|
||||
return IsSubnetRouterAnycast() || IsReservedSubnetAnycast();
|
||||
}
|
||||
|
||||
|
||||
const uint8_t *Address::GetIid(void) const
|
||||
{
|
||||
return mFields.m8 + kInterfaceIdentifierOffset;
|
||||
|
||||
@@ -188,6 +188,33 @@ public:
|
||||
*/
|
||||
bool IsRoutingLocator(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is Subnet-Router Anycast (RFC 4291),
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a Subnet-Router Anycast address.
|
||||
* @retval FALSE If the IPv6 address is not a Subnet-Router Anycast address.
|
||||
*
|
||||
*/
|
||||
bool IsSubnetRouterAnycast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address is Reserved Subnet Anycast (RFC 2526),
|
||||
*
|
||||
* @retval TRUE If the IPv6 address is a Reserved Subnet Anycast address.
|
||||
* @retval FALSE If the IPv6 address is not a Reserved Subnet Anycast address.
|
||||
*
|
||||
*/
|
||||
bool IsReservedSubnetAnycast(void) const;
|
||||
|
||||
/**
|
||||
* This method indicates whether or not the IPv6 address contains Reserved IPv6 IID (RFC 5453),
|
||||
*
|
||||
* @retval TRUE If the IPv6 address contains a reserved IPv6 IID.
|
||||
* @retval FALSE If the IPv6 address does not contain a reserved IPv6 IID.
|
||||
*
|
||||
*/
|
||||
bool IsIidReserved(void) const;
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the Interface Identifier.
|
||||
*
|
||||
|
||||
@@ -48,10 +48,12 @@
|
||||
#include <crypto/mbedtls.hpp>
|
||||
#include <net/icmp6.hpp>
|
||||
#include <net/ip6.hpp>
|
||||
#include <platform/radio.h>
|
||||
#include <platform/random.h>
|
||||
#include <platform/misc.h>
|
||||
#include <thread/thread_netif.hpp>
|
||||
#include <thread/thread_uris.hpp>
|
||||
#include <utils/global_address.hpp>
|
||||
|
||||
// Temporary definition
|
||||
typedef struct otInstance
|
||||
@@ -906,6 +908,31 @@ ThreadError otRemoveUnicastAddress(otInstance *, const otIp6Address *address)
|
||||
return sThreadNetif->RemoveExternalUnicastAddress(*static_cast<const Ip6::Address *>(address));
|
||||
}
|
||||
|
||||
void otSlaacUpdate(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
||||
otSlaacIidCreate aIidCreate, void *aContext)
|
||||
{
|
||||
Utils::Slaac::UpdateAddresses(aInstance, aAddresses, aNumAddresses, aIidCreate, aContext);
|
||||
}
|
||||
|
||||
ThreadError otCreateRandomIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext)
|
||||
{
|
||||
return Utils::Slaac::CreateRandomIid(aInstance, aAddress, aContext);
|
||||
}
|
||||
|
||||
ThreadError otCreateMacIid(otInstance *, otNetifAddress *aAddress, void *)
|
||||
{
|
||||
memcpy(&aAddress->mAddress.mFields.m8[OT_IP6_ADDRESS_SIZE - OT_IP6_IID_SIZE],
|
||||
sThreadNetif->GetMac().GetExtAddress(), OT_IP6_IID_SIZE);
|
||||
aAddress->mAddress.mFields.m8[OT_IP6_ADDRESS_SIZE - OT_IP6_IID_SIZE] ^= 0x02;
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError otCreateSemanticallyOpaqueIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext)
|
||||
{
|
||||
return static_cast<Utils::SemanticallyOpaqueIidGenerator *>(aContext)->CreateIid(aInstance, aAddress);
|
||||
}
|
||||
|
||||
void otSetStateChangedCallback(otInstance *, otStateChangedCallback aCallback, void *aCallbackContext)
|
||||
{
|
||||
sNetifCallback.Set(aCallback, aCallbackContext);
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file implements the Thread IPv6 global addresses configuration utilities.
|
||||
*/
|
||||
|
||||
#ifdef OPENTHREAD_CONFIG_FILE
|
||||
#include OPENTHREAD_CONFIG_FILE
|
||||
#else
|
||||
#include <openthread-config.h>
|
||||
#endif
|
||||
|
||||
#include <openthread.h>
|
||||
#include <openthread-types.h>
|
||||
#include <common/code_utils.hpp>
|
||||
#include <crypto/sha256.hpp>
|
||||
#include <mac/mac.hpp>
|
||||
#include <net/ip6_address.hpp>
|
||||
#include <utils/global_address.hpp>
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Utils {
|
||||
|
||||
void Slaac::UpdateAddresses(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
||||
IidCreator aIidCreator, void *aContext)
|
||||
{
|
||||
otNetworkDataIterator iterator;
|
||||
otBorderRouterConfig config;
|
||||
|
||||
// remove addresses
|
||||
for (size_t i = 0; i < aNumAddresses; i++)
|
||||
{
|
||||
otNetifAddress *address = &aAddresses[i];
|
||||
bool found = false;
|
||||
|
||||
if (address->mValidLifetime == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
while (otGetNextOnMeshPrefix(aInstance, false, &iterator, &config) == kThreadError_None)
|
||||
{
|
||||
if (config.mSlaac == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
|
||||
config.mPrefix.mLength == address->mPrefixLength)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
otRemoveUnicastAddress(aInstance, &address->mAddress);
|
||||
address->mValidLifetime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// add addresses
|
||||
iterator = OT_NETWORK_DATA_ITERATOR_INIT;
|
||||
|
||||
while (otGetNextOnMeshPrefix(aInstance, false, &iterator, &config) == kThreadError_None)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
if (config.mSlaac == false)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < aNumAddresses; i++)
|
||||
{
|
||||
otNetifAddress *address = &aAddresses[i];
|
||||
|
||||
if (address->mValidLifetime == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (otIp6PrefixMatch(&config.mPrefix.mPrefix, &address->mAddress) >= config.mPrefix.mLength &&
|
||||
config.mPrefix.mLength == address->mPrefixLength)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
for (size_t i = 0; i < aNumAddresses; i++)
|
||||
{
|
||||
otNetifAddress *address = &aAddresses[i];
|
||||
|
||||
if (address->mValidLifetime != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(address, 0, sizeof(*address));
|
||||
memcpy(&address->mAddress, &config.mPrefix.mPrefix, 8);
|
||||
|
||||
address->mPrefixLength = config.mPrefix.mLength;
|
||||
address->mPreferredLifetime = config.mPreferred ? 0xffffffff : 0;
|
||||
address->mValidLifetime = 0xffffffff;
|
||||
|
||||
if (aIidCreator(aInstance, address, aContext) != kThreadError_None)
|
||||
{
|
||||
CreateRandomIid(aInstance, address, aContext);
|
||||
}
|
||||
|
||||
otAddUnicastAddress(aInstance, address);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError Slaac::CreateRandomIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext)
|
||||
{
|
||||
(void) aInstance;
|
||||
(void) aContext;
|
||||
|
||||
for (size_t i = sizeof(aAddress[i].mAddress) - OT_IP6_IID_SIZE; i < sizeof(aAddress[i].mAddress); i++)
|
||||
{
|
||||
aAddress->mAddress.mFields.m8[i] = static_cast<uint8_t>(otPlatRandomGet());
|
||||
}
|
||||
|
||||
return kThreadError_None;
|
||||
}
|
||||
|
||||
ThreadError SemanticallyOpaqueIidGenerator::CreateIid(otInstance *aInstance, otNetifAddress *aAddress)
|
||||
{
|
||||
(void) aInstance;
|
||||
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
for (uint32_t i = 0; i <= kMaxRetries; i++)
|
||||
{
|
||||
error = CreateIidOnce(aInstance, aAddress);
|
||||
VerifyOrExit(error == kThreadError_Ipv6AddressCreationFailure,);
|
||||
|
||||
mDadCounter++;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError SemanticallyOpaqueIidGenerator::CreateIidOnce(otInstance *aInstance, otNetifAddress *aAddress)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
Crypto::Sha256 sha256;
|
||||
uint8_t hash[Crypto::Sha256::kHashSize];
|
||||
Ip6::Address *address = static_cast<Ip6::Address *>(&aAddress->mAddress);
|
||||
|
||||
sha256.Start();
|
||||
|
||||
sha256.Update(aAddress->mAddress.mFields.m8, aAddress->mPrefixLength / 8);
|
||||
|
||||
VerifyOrExit(mInterfaceId != NULL, error = kThreadError_InvalidArgs);
|
||||
sha256.Update(mInterfaceId, mInterfaceIdLength);
|
||||
|
||||
if (mNetworkIdLength)
|
||||
{
|
||||
VerifyOrExit(mNetworkId != NULL, error = kThreadError_InvalidArgs);
|
||||
sha256.Update(mNetworkId, mNetworkIdLength);
|
||||
}
|
||||
|
||||
sha256.Update(static_cast<uint8_t *>(&mDadCounter), sizeof(mDadCounter));
|
||||
|
||||
VerifyOrExit(mSecretKey != NULL, error = kThreadError_InvalidArgs);
|
||||
sha256.Update(mSecretKey, mSecretKeyLength);
|
||||
|
||||
sha256.Finish(hash);
|
||||
|
||||
memcpy(&aAddress->mAddress.mFields.m8[OT_IP6_ADDRESS_SIZE - OT_IP6_IID_SIZE],
|
||||
&hash[sizeof(hash) - OT_IP6_IID_SIZE], OT_IP6_IID_SIZE);
|
||||
|
||||
VerifyOrExit(!IsAddressRegistered(aInstance, aAddress), error = kThreadError_Ipv6AddressCreationFailure);
|
||||
VerifyOrExit(!address->IsIidReserved(), error = kThreadError_Ipv6AddressCreationFailure);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
bool SemanticallyOpaqueIidGenerator::IsAddressRegistered(otInstance *aInstance, otNetifAddress *aCreatedAddress)
|
||||
{
|
||||
bool result = false;
|
||||
const otNetifAddress *address = otGetUnicastAddresses(aInstance);
|
||||
|
||||
while (address != NULL)
|
||||
{
|
||||
if (0 == memcmp(aCreatedAddress->mAddress.mFields.m8, address->mAddress.mFields.m8,
|
||||
sizeof(address->mAddress.mFields)))
|
||||
{
|
||||
ExitNow(result = true);
|
||||
}
|
||||
|
||||
address = address->mNext;
|
||||
}
|
||||
|
||||
exit:
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} // namespace Slaac
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright (c) 2016, The OpenThread Authors.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the copyright holder nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file includes definitions for Thread global IPv6 address configuration with SLAAC.
|
||||
*/
|
||||
|
||||
#ifndef GLOBAL_ADDRESS_HPP_
|
||||
#define GLOBAL_ADDRESS_HPP_
|
||||
|
||||
#include <openthread-types.h>
|
||||
#include <platform/random.h>
|
||||
|
||||
namespace Thread {
|
||||
namespace Utils {
|
||||
|
||||
/**
|
||||
* @addtogroup core-global-address
|
||||
*
|
||||
* @brief
|
||||
* This module includes definitions for Thread global IPv6 address configuration with SLAAC.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class implements the SLAAC utility for Thread protocol.
|
||||
*
|
||||
*/
|
||||
class Slaac
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This function pointer is called when SLAAC creates global address.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[in] aContext A pointer to creator-specific context.
|
||||
*
|
||||
* @retval kThreadError_None if generated valid IID.
|
||||
* @retval kThreadError_Failed if creating IID failed.
|
||||
*
|
||||
*/
|
||||
typedef ThreadError(*IidCreator)(otInstance *aInstance, otNetifAddress *aAddress, void *aContext);
|
||||
|
||||
/**
|
||||
* This function update addresses that shall be automatically created using SLAAC.
|
||||
*
|
||||
* @param[in] aInstance A pointer to openThread instance.
|
||||
* @param[inout] aAddresses A pointer to an array containing addresses created by this module.
|
||||
* @param[in] aNumAddresses The number of elements in aAddresses array.
|
||||
* @param[in] aIidCreator A pointer to function that will be used to create IID for IPv6 addresses.
|
||||
* @param[in] aContext A pointer to IID creator-specific context data.
|
||||
*
|
||||
*/
|
||||
static void UpdateAddresses(otInstance *aInstance, otNetifAddress *aAddresses, uint32_t aNumAddresses,
|
||||
IidCreator aIidCreator, void *aContext);
|
||||
|
||||
/**
|
||||
* This function creates randomly generated IPv6 IID for given IPv6 address.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
* @param[in] aContext Unused pointer.
|
||||
*
|
||||
* @retval kThreadError_None Generated valid IID.
|
||||
*/
|
||||
static ThreadError CreateRandomIid(otInstance *aInstance, otNetifAddress *aAddress, void *aContext);
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the Method for Generating Semantically Opaque IIDs with IPv6 SLAAC (RFC 7217).
|
||||
*
|
||||
*/
|
||||
class SemanticallyOpaqueIidGenerator: public otSemanticallyOpaqueIidGeneratorData
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This function creates semantically opaque IID for given IPv6 address and context.
|
||||
*
|
||||
* The generator starts with DAD counter provided as a class member field. The DAD counter is automatically
|
||||
* incremented at most kMaxRetries times if creation of valid IPv6 address fails.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
*
|
||||
* @retval kThreadError_None Generated valid IID.
|
||||
* @retval kThreadError_InvalidArgs Any given parameter is invalid.
|
||||
* @retval kThreadError_Ipv6AddressCreationFailure Could not generate IID due to RFC 7217 restrictions.
|
||||
*
|
||||
*/
|
||||
ThreadError CreateIid(otInstance *aInstance, otNetifAddress *aAddress);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxRetries = 255,
|
||||
};
|
||||
|
||||
/**
|
||||
* This function creates semantically opaque IID for given arguments.
|
||||
*
|
||||
* This function creates IID only for given DAD counter value.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[inout] aAddress A pointer to structure containing IPv6 address for which IID is being created.
|
||||
*
|
||||
* @retval kThreadError_None Generated valid IID.
|
||||
* @retval kThreadError_InvalidArgs Any given parameter is invalid.
|
||||
* @retval kThreadError_Ipv6AddressCreationFailure Could not generate IID due to RFC 7217 restrictions.
|
||||
*
|
||||
*/
|
||||
ThreadError CreateIidOnce(otInstance *aInstance, otNetifAddress *aAddress);
|
||||
|
||||
/**
|
||||
* This function checks if created IPv6 address is already registered in the Thread interface.
|
||||
*
|
||||
* @param[in] aInstance A pointer to an OpenThread instance.
|
||||
* @param[in] aCreatedAddress A pointer to created IPv6 address.
|
||||
*
|
||||
* @retval true Given address is present in the address list.
|
||||
* @retval false Given address is missing in the address list.
|
||||
*
|
||||
*/
|
||||
bool IsAddressRegistered(otInstance *aInstance, otNetifAddress *aCreatedAddress);
|
||||
};
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
} // namespace Slaac
|
||||
} // namespace Thread
|
||||
|
||||
#endif // GLOBAL_ADDRESS_HPP_
|
||||
|
||||
Reference in New Issue
Block a user