Pr/slaac utility (#698)

* Provide utility for IPv6 SLAAC (#651)

* Semantically Opaque Interface Identifier with IPv6 SLAAC (#651)
This commit is contained in:
Hubert Miś
2016-09-29 17:37:10 +02:00
committed by Jonathan Hui
parent 537f0fdac8
commit aeba71b1a1
15 changed files with 599 additions and 97 deletions
+2
View File
@@ -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>
+1 -1
View File
@@ -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)
+23
View File
@@ -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
*
+64
View File
@@ -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
View File
@@ -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
View File
@@ -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;
};
+2
View File
@@ -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
+17
View File
@@ -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;
+27
View File
@@ -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.
*
+27
View File
@@ -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);
+244
View File
@@ -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
+162
View File
@@ -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_